Skip to content

Commit 636136c

Browse files
Specific info message for equally named effect operations (#956)
## Enhance Reporting for Missing `do` Syntax in Effect Operations This pull request improves error messages for unresolved function calls in the presence of equally named effect operations, addressing issue [#950](#950). --- ## Summary This update enhances the info message in the `Namer` component of Effekt when an equally named effect operation exists but has not been invoked using the `do` syntax. It ensures the user is provided with a more descriptive information message, avoiding the generic `"Cannot find a function named _"`. --- ## Changes ### 1. **Improved Information in `Namer.scala`**: - Removed `lookupOverloaded` and with it the never issued information on fields and added `lookupOperation` to capture equally named effect operations the `resolveFunctionCallTarget` method. - When an equally named effect operation is found, an **information message** is provided to the user with the recommended syntax (`do {operationName}()`). ### 3. **Added Negative Tests**: - Introduced three new tests in `examples/neg/namer/issue950` to verify the following cases: - An info message is displayed when an effect operation is invoked without the `do` syntax. - The generic message is displayed when no valid function or operation matches the call. - Overloaded Effects all get captured by the `foreach` --- ## Example Behavior ### Before the Fix ```scala interface Greet { def sayHello(): Unit } def helloWorld() = try { sayHello() // [error] Cannot find a function named `sayHello`. } with Greet { def sayHello() = { println("Hello!"); resume(()) } } def main() = { helloWorld() // Generic error, not helpful } ``` ### After the Fix ```scala interface Greet { def sayHello(): Unit } def helloWorld() = try { sayHello() // [error] There is an equally named effect operation `sayHello` of interface `Greet`. Use syntax `do sayHello()` to call it. } with Greet { def sayHello() = { println("Hello!"); resume(()) } } def main() = { helloWorld() // Specific error with actionable advice } ``` --- ## Testing - **Negative Test 1**: Missing `do` for effect operation: - Confirms that invoking an effect operation without the `do` syntax triggers the improved error message. - **Negative Test 2**: Unresolved function call: - Ensures that the generic error message appears when no matches (operations, fields, or overloads) are found. - **Negative Test 3**: Overloaded effect operations: - Confirms that overloaded effect operations are all captured by the new foreach --------- Co-authored-by: Jiří Beneš <[email protected]>
1 parent faedca8 commit 636136c

File tree

6 files changed

+45
-6
lines changed

6 files changed

+45
-6
lines changed

effekt/shared/src/main/scala/effekt/Namer.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -921,14 +921,14 @@ trait NamerOps extends ContextOps { Context: Context =>
921921
assignSymbol(id, value)
922922
case Right(blocks) =>
923923
if (blocks.isEmpty) {
924-
val allSyms = scope.lookupOverloaded(id, term => true).flatten
924+
val ops = scope.lookupOperation(id.path, id.name).flatten
925925

926-
if (allSyms.exists { case o: Operation => true; case _ => false })
927-
info(pretty"There is an equally named effect operation. Use syntax `do ${id}() to call it.`")
928-
929-
if (allSyms.exists { case o: Field => true; case _ => false })
930-
info(pretty"There is an equally named field. Use syntax `obj.${id} to access it.`")
926+
// Provide specific info messages for operations
927+
ops.foreach { op =>
928+
info(pretty"There is an equally named effect operation ${op} of interface ${op.interface}. Use syntax `do ${id}()` to call it.")
929+
}
931930

931+
// Always abort with the generic message
932932
abort(pretty"Cannot find a function named `${id}`.")
933933
}
934934
assignSymbol(id, CallTarget(blocks))
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[info] examples/neg/namer/issue950/ambiguous_interfaces_overload.effekt:5:3: There is an equally named effect operation sayHello of interface Greet. Use syntax `do sayHello()` to call it.
2+
sayHello()
3+
^^^^^^^^
4+
[info] examples/neg/namer/issue950/ambiguous_interfaces_overload.effekt:5:3: There is an equally named effect operation sayHello of interface Welcome. Use syntax `do sayHello()` to call it.
5+
sayHello()
6+
^^^^^^^^
7+
[error] examples/neg/namer/issue950/ambiguous_interfaces_overload.effekt:5:3: Cannot find a function named `sayHello`.
8+
sayHello()
9+
^^^^^^^^
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
interface Greet { def sayHello(): Unit }
2+
interface Welcome { def sayHello(): Unit }
3+
4+
def helloWorld() = try {
5+
sayHello()
6+
} with Greet {
7+
def sayHello() = { println("Hello from Greet!"); resume(()) }
8+
}
9+
10+
def main() = {
11+
helloWorld()
12+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
def main() = doesNotExist() // ERROR Cannot find a function named `doesNotExist`.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[info] examples/neg/namer/issue950/effect_operation_with_same_name.effekt:4:3: There is an equally named effect operation sayHello of interface Greet. Use syntax `do sayHello()` to call it.
2+
sayHello()
3+
^^^^^^^^
4+
[error] examples/neg/namer/issue950/effect_operation_with_same_name.effekt:4:3: Cannot find a function named `sayHello`.
5+
sayHello()
6+
^^^^^^^^
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
interface Greet { def sayHello(): Unit }
2+
3+
def helloWorld() = try {
4+
sayHello()
5+
} with Greet {
6+
def sayHello() = { println("Hello!"); resume(()) }
7+
}
8+
9+
def main() = {
10+
helloWorld()
11+
}

0 commit comments

Comments
 (0)