From 7095409d15937bfe85419d42f64a452b7b72afcb Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Thu, 4 Jan 2024 21:34:27 +0300 Subject: [PATCH 1/6] document the new ambiguous identifier resolution refs #23123 --- doc/manual.md | 22 +++++++++++++++++++--- tests/lookups/mambsym3.nim | 4 ++++ tests/lookups/mambsym4.nim | 4 ++++ tests/lookups/tambsymmanual.nim | 21 +++++++++++++++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 tests/lookups/mambsym3.nim create mode 100644 tests/lookups/mambsym4.nim create mode 100644 tests/lookups/tambsymmanual.nim diff --git a/doc/manual.md b/doc/manual.md index 0e167be042024..2c1577604c258 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -6956,25 +6956,41 @@ All identifiers of a module are valid from the point of declaration until the end of the module. Identifiers from indirectly dependent modules are *not* available. The `system`:idx: module is automatically imported in every module. -If a module imports an identifier by two different modules, each occurrence of -the identifier has to be qualified unless it is an overloaded procedure or -iterator in which case the overloading resolution takes place: +If a module imports the same identifier from two different modules, the +identifier must be disambiguated in one of the following ways: + +* Calling it as a routine, in which case overload resolution will take place + (but can still fail due to ambiguity). +* Using type inference to match only one symbol against the expected type, + which can fail if multiple symbols match the expected type equally strongly. +* Qualifying it in the form `module.identifier`. ```nim # Module A var x*: string + proc foo*(a: string) = + echo "A: ", a ``` ```nim # Module B var x*: int + proc foo*(b: int) = + echo "B: ", b ``` ```nim # Module C import A, B + + foo("abc") # A: abc + foo(123) # B: 123 + write(stdout, x) # error: x is ambiguous write(stdout, A.x) # no error: qualifier used + + proc bar(a: int): int = a + 1 + assert bar(x) == x + 1 # no error: only A.x of type int matches var x = 4 write(stdout, x) # not ambiguous: uses the module C's x diff --git a/tests/lookups/mambsym3.nim b/tests/lookups/mambsym3.nim new file mode 100644 index 0000000000000..946a5ff294960 --- /dev/null +++ b/tests/lookups/mambsym3.nim @@ -0,0 +1,4 @@ +# Module A +var x*: string +proc foo*(a: string) = + echo "A: ", a diff --git a/tests/lookups/mambsym4.nim b/tests/lookups/mambsym4.nim new file mode 100644 index 0000000000000..ed66cc16d9d1f --- /dev/null +++ b/tests/lookups/mambsym4.nim @@ -0,0 +1,4 @@ +# Module B +var x*: int +proc foo*(b: int) = + echo "B: ", b diff --git a/tests/lookups/tambsymmanual.nim b/tests/lookups/tambsymmanual.nim new file mode 100644 index 0000000000000..1ce5d850637a5 --- /dev/null +++ b/tests/lookups/tambsymmanual.nim @@ -0,0 +1,21 @@ +discard """ + output: ''' +A: abc +B: 123 +4 +''' +""" +# Module C +import mambsym3, mambsym4 + +foo("abc") # A: abc +foo(123) # B: 123 + +doAssert not compiles(write(stdout, x)) # error: x is ambiguous +write(stdout, mambsym3.x) # no error: qualifier used + +proc bar(a: int): int = a + 1 +doAssert bar(x) == x + 1 # no error: only A.x of type int matches + +var x = 4 +write(stdout, x) # not ambiguous: uses the module C's x From a6c9b47df6d8c49ab9eabc370c47317d589652ec Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Fri, 5 Jan 2024 09:48:32 +0300 Subject: [PATCH 2/6] fix output for megatest --- tests/lookups/tambsymmanual.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/lookups/tambsymmanual.nim b/tests/lookups/tambsymmanual.nim index 1ce5d850637a5..ecffd4d44afd1 100644 --- a/tests/lookups/tambsymmanual.nim +++ b/tests/lookups/tambsymmanual.nim @@ -19,3 +19,4 @@ doAssert bar(x) == x + 1 # no error: only A.x of type int matches var x = 4 write(stdout, x) # not ambiguous: uses the module C's x +write(stdout, '\n') From 266ba367c86f18473cc5180c2b38f52451dfdb13 Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Fri, 5 Jan 2024 10:50:00 +0300 Subject: [PATCH 3/6] fix again --- tests/lookups/tambsymmanual.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lookups/tambsymmanual.nim b/tests/lookups/tambsymmanual.nim index ecffd4d44afd1..a8b32e9ee7537 100644 --- a/tests/lookups/tambsymmanual.nim +++ b/tests/lookups/tambsymmanual.nim @@ -19,4 +19,4 @@ doAssert bar(x) == x + 1 # no error: only A.x of type int matches var x = 4 write(stdout, x) # not ambiguous: uses the module C's x -write(stdout, '\n') +echo() # for test output From 6d3f696430e78b7158bc506f8a6766d0d2dd9189 Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Sat, 6 Jan 2024 14:48:15 +0300 Subject: [PATCH 4/6] hopefully clearer docs, add new type inference example --- doc/manual.md | 18 ++++++++++++------ tests/lookups/tambsymmanual.nim | 3 +++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/doc/manual.md b/doc/manual.md index 2c1577604c258..57ed61c1ceb1b 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -6957,13 +6957,17 @@ the end of the module. Identifiers from indirectly dependent modules are *not* available. The `system`:idx: module is automatically imported in every module. If a module imports the same identifier from two different modules, the -identifier must be disambiguated in one of the following ways: +identifier is considered ambiguous, which is resolved in the following ways: -* Calling it as a routine, in which case overload resolution will take place - (but can still fail due to ambiguity). -* Using type inference to match only one symbol against the expected type, - which can fail if multiple symbols match the expected type equally strongly. -* Qualifying it in the form `module.identifier`. +* Qualifying the identifier as `module.identifier` resolves ambiguity + between modules. (See below for the case that the module name itself + is ambiguous.) +* Calling the identifier as a routine makes overload resolution take place, + which resolves ambiguity in the case that one overload matches stronger + than the others. +* Using the identifier in a context where the compiler can infer the type + of the identifier resolves ambiguity in the case that one definition + matches the type stronger than the others. ```nim # Module A @@ -6985,6 +6989,8 @@ identifier must be disambiguated in one of the following ways: foo("abc") # A: abc foo(123) # B: 123 + let inferred: proc (x: string) = foo + foo("def") # A: def write(stdout, x) # error: x is ambiguous write(stdout, A.x) # no error: qualifier used diff --git a/tests/lookups/tambsymmanual.nim b/tests/lookups/tambsymmanual.nim index a8b32e9ee7537..3ad91b8cc721d 100644 --- a/tests/lookups/tambsymmanual.nim +++ b/tests/lookups/tambsymmanual.nim @@ -2,6 +2,7 @@ discard """ output: ''' A: abc B: 123 +A: def 4 ''' """ @@ -10,6 +11,8 @@ import mambsym3, mambsym4 foo("abc") # A: abc foo(123) # B: 123 +let inferred: proc (x: string) = foo +foo("def") # A: def doAssert not compiles(write(stdout, x)) # error: x is ambiguous write(stdout, mambsym3.x) # no error: qualifier used From 87c9b7cd5c19a6c24a2e7b414a65734cfcb7f106 Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Sat, 6 Jan 2024 14:49:12 +0300 Subject: [PATCH 5/6] minor wording change --- doc/manual.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual.md b/doc/manual.md index 57ed61c1ceb1b..eb8f503afab78 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -6957,7 +6957,7 @@ the end of the module. Identifiers from indirectly dependent modules are *not* available. The `system`:idx: module is automatically imported in every module. If a module imports the same identifier from two different modules, the -identifier is considered ambiguous, which is resolved in the following ways: +identifier is considered ambiguous, which can be resolved in the following ways: * Qualifying the identifier as `module.identifier` resolves ambiguity between modules. (See below for the case that the module name itself From 60ef371cc4d09922d2d71074f4a81636f9b3cc3c Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Sat, 6 Jan 2024 14:50:47 +0300 Subject: [PATCH 6/6] fix error message example for ambiguous module --- doc/manual.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual.md b/doc/manual.md index eb8f503afab78..db82d851b1625 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -7020,7 +7020,7 @@ proc fb* = echo "buzz" import A/C import B/C -C.fb() # Error: ambiguous identifier: 'fb' +C.fb() # Error: ambiguous identifier: 'C' ```