Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### Fixed

* Report `FS0037 Duplicate definition of type or module` at type-check time when two sibling modules in a `module rec` / `namespace rec` group share a name, instead of letting the duplicate slip through to IL emit where it surfaced as the cryptic `FS2014: duplicate entry . in type index table`. ([Issue #6694](https://github.com/dotnet/fsharp/issues/6694), [PR #19913](https://github.com/dotnet/fsharp/pull/19913))
* Suppress hover/symbol resolution for wildcard `_` patterns inside `member _.…` bodies that incorrectly showed `val _: T` tooltip. ([PR #19760](https://github.com/dotnet/fsharp/pull/19760))
* Deduplicate format specifier locations in computation expressions so editor tooling no longer reports duplicate entries for the same `%` specifier. ([Issue #16419](https://github.com/dotnet/fsharp/issues/16419), [PR #19791](https://github.com/dotnet/fsharp/pull/19791))
* Reject non-function bindings for single-case and partial active pattern names with FS1209, matching the existing multi-case behavior. ([PR #19763](https://github.com/dotnet/fsharp/pull/19763))
Expand Down
5 changes: 5 additions & 0 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4095,6 +4095,11 @@ module EstablishTypeDefinitionCores =
let envTmp, withEnvs =
(envInitial, withEntities) ||> MutRecShapes.computeEnvs
(fun envAbove (MutRecDefnsPhase2DataForModule (moduleTyAcc, moduleEntity)) ->
// In recursive scopes all siblings build their entities in Phase1A against the same
// envInitial, so duplicate sibling-module names are not yet visible there. Detect
// them here at the publish point, where envAbove's accumulator already contains
// any earlier-published siblings. See https://github.com/dotnet/fsharp/issues/6694.
CheckForDuplicateModule envAbove moduleEntity.DemangledModuleOrNamespaceName moduleEntity.Range
PublishModuleDefn cenv envAbove moduleEntity
MakeInnerEnvWithAcc true envAbove moduleEntity.Id moduleTyAcc moduleEntity.ModuleOrNamespaceType.ModuleOrNamespaceKind)
(fun envAbove _ -> envAbove)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,100 @@ AutoOpen>] L1 = do ()
|> shouldFail
|> withDiagnostics [
Error 10, Line 3, Col 1, Line 3, Col 9, "Unexpected start of structured construct in attribute list"
]
]

[<Fact>]
let ``Recursive module with duplicate sibling modules emits FS0037`` () =
FSharp """
module rec A

module Foobar = let x = 1
module Foobar = let y = 2
Comment thread
abonie marked this conversation as resolved.
"""
|> typecheck
|> shouldFail
|> withErrorCode 37
|> withDiagnosticMessageMatches "Foobar"
|> ignore

[<Fact>]
let ``Recursive namespace with duplicate sibling modules emits FS0037`` () =
FSharp """
namespace rec N

module Foobar = let x = 1
module Foobar = let y = 2
"""
|> typecheck
|> shouldFail
|> withErrorCode 37
|> withDiagnosticMessageMatches "Foobar"
|> ignore

[<Fact>]
let ``Recursive module nested cousins with same name compile`` () =
FSharp """
module rec Outer

module A =
module Inner = let x = 1

module B =
module Inner = let y = 2
"""
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Recursive module nested siblings with duplicate name emit FS0037`` () =
FSharp """
module rec Outer

module Inner =
module Dup = let x = 1
module Dup = let y = 2
"""
|> typecheck
|> shouldFail
|> withErrorCode 37
|> withDiagnosticMessageMatches "Dup"
|> ignore

[<Fact>]
let ``Non-recursive module with duplicate sibling modules still emits FS0037`` () =
FSharp """
module A

module Foobar = let x = 1
module Foobar = let y = 2
"""
|> typecheck
|> shouldFail
|> withErrorCode 37
|> withDiagnosticMessageMatches "Foobar"
|> ignore

[<Fact>]
let ``Single file with two namespace fragments and different modules compiles`` () =
FSharp """
namespace N

module M = let x = 1

namespace N

module M2 = let y = 2
"""
|> typecheck
|> shouldSucceed

[<Fact>]
let ``Recursive module siblings differing only in case compile`` () =
FSharp """
module rec A

module Foobar = let x = 1
module FooBar = let y = 2
"""
|> typecheck
|> shouldSucceed
Loading