Skip to content

Commit 2ca2f09

Browse files
authored
Avoid duplicate nested modules in Trie. (#14756)
1 parent 4247eb9 commit 2ca2f09

File tree

2 files changed

+188
-3
lines changed

2 files changed

+188
-3
lines changed

src/Compiler/Driver/GraphChecking/TrieMapping.fs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ let mkDictFromKeyValuePairs (items: KeyValuePair<'TKey, 'TValue> list) =
100100
let dict = Dictionary(Seq.length items)
101101

102102
for KeyValue (k, v) in items do
103-
dict.Add(k, v)
103+
if not (dict.ContainsKey(k)) then
104+
dict.Add(k, v)
104105

105106
dict
106107

@@ -188,8 +189,7 @@ let processSynModuleOrNamespace<'Decl>
188189
mkSingletonDict name { Current = current; Children = node } |> continuation)
189190
tail
190191

191-
if List.isEmpty name then
192-
// This can happen for a namespace global.
192+
if kind = SynModuleOrNamespaceKind.AnonModule then
193193
// We collect the child nodes from the decls
194194
decls |> List.choose (mkTrieForDeclaration idx) |> mkDictFromKeyValuePairs
195195
else

tests/FSharp.Compiler.ComponentTests/TypeChecks/Graph/TrieMappingTests.fs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,188 @@ let _ = ()
313313
Assert.AreEqual(1, trie.Children.Count)
314314
let aNode = trie.Children.["A"]
315315
Assert.AreEqual(set [| 0 |], aNode.Files)
316+
317+
[<Test>]
318+
let ``Two nested modules with the same name, in named namespace`` () =
319+
let trie =
320+
TrieMapping.mkTrie
321+
[|
322+
{
323+
Idx = 0
324+
FileName = "A.fs"
325+
ParsedInput =
326+
parseSourceCode (
327+
"A.fs",
328+
"""
329+
namespace N
330+
331+
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
332+
module ``module`` =
333+
let f x = x + 1
334+
module ``module`` =
335+
let g x = x + 1
336+
""" )
337+
}
338+
|]
339+
340+
Assert.AreEqual(1, trie.Children.Count)
341+
let node = trie.Children.["N"]
342+
Assert.AreEqual(1, node.Children.Count)
343+
344+
[<Test>]
345+
let ``Two nested modules with the same name, in namespace global`` () =
346+
let trie =
347+
TrieMapping.mkTrie
348+
[|
349+
{
350+
Idx = 0
351+
FileName = "A.fs"
352+
ParsedInput =
353+
parseSourceCode (
354+
"A.fs",
355+
"""
356+
namespace global
357+
358+
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
359+
module ``module`` =
360+
let f x = x + 1
361+
module ``module`` =
362+
let g x = x + 1
363+
""" )
364+
}
365+
|]
366+
367+
// namespace global leads to a Root entry, no further processing will be done.
368+
Assert.AreEqual(set [| 0 |], trie.Files)
369+
370+
[<Test>]
371+
let ``Two nested modules with the same name, in anonymous module`` () =
372+
let trie =
373+
TrieMapping.mkTrie
374+
[|
375+
{
376+
Idx = 1
377+
FileName = "Program.fs"
378+
ParsedInput =
379+
parseSourceCode (
380+
"Program.fs",
381+
"""
382+
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
383+
module ``module`` =
384+
let f x = x + 1
385+
module ``module`` =
386+
let g x = x + 1
387+
""" )
388+
}
389+
|]
390+
391+
Assert.AreEqual(1, trie.Children.Count)
392+
Assert.True(trie.Children.ContainsKey("module"))
393+
394+
[<Test>]
395+
let ``Two nested modules with the same name, in nested module`` () =
396+
let trie =
397+
TrieMapping.mkTrie
398+
[|
399+
{
400+
Idx = 0
401+
FileName = "A.fs"
402+
ParsedInput =
403+
parseSourceCode (
404+
"A.fs",
405+
"""
406+
namespace A
407+
408+
module B =
409+
410+
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
411+
module ``module`` =
412+
let f x = x + 1
413+
module ``module`` =
414+
let g x = x + 1
415+
""" )
416+
}
417+
|]
418+
419+
let bNode = trie.Children["A"].Children["B"]
420+
Assert.AreEqual(1, bNode.Children.Count)
421+
Assert.True(bNode.Children.ContainsKey("module"))
422+
423+
[<Test>]
424+
let ``Two nested modules with the same name, in nested module in signature file`` () =
425+
let trie =
426+
TrieMapping.mkTrie
427+
[|
428+
{
429+
Idx = 0
430+
FileName = "A.fsi"
431+
ParsedInput =
432+
parseSourceCode (
433+
"A.fsi",
434+
"""
435+
namespace A
436+
437+
module B =
438+
439+
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
440+
module ``module`` = begin end
441+
module ``module`` = begin end
442+
""" )
443+
}
444+
|]
445+
446+
let bNode = trie.Children["A"].Children["B"]
447+
Assert.AreEqual(1, bNode.Children.Count)
448+
Assert.True(bNode.Children.ContainsKey("module"))
449+
450+
[<Test>]
451+
let ``Two namespaces with the same name in the same implementation file`` () =
452+
let trie =
453+
TrieMapping.mkTrie
454+
[|
455+
{
456+
Idx = 0
457+
FileName = "A.fs"
458+
ParsedInput =
459+
parseSourceCode (
460+
"A.fs",
461+
"""
462+
namespace A
463+
464+
module B = begin end
465+
466+
namespace A
467+
468+
module C = begin end
469+
""" )
470+
}
471+
|]
472+
473+
let aNode = trie.Children["A"]
474+
Assert.AreEqual(2, aNode.Children.Count)
475+
476+
[<Test>]
477+
let ``Two namespaces with the same name in the same signature file`` () =
478+
let trie =
479+
TrieMapping.mkTrie
480+
[|
481+
{
482+
Idx = 0
483+
FileName = "A.fsi"
484+
ParsedInput =
485+
parseSourceCode (
486+
"A.fsi",
487+
"""
488+
namespace A
489+
490+
module B = begin end
491+
492+
namespace A
493+
494+
module C = begin end
495+
""" )
496+
}
497+
|]
498+
499+
let aNode = trie.Children["A"]
500+
Assert.AreEqual(2, aNode.Children.Count)

0 commit comments

Comments
 (0)