usethesource / rascal

The implementation of the Rascal meta-programming language (including interpreter, type checker, parser generator, compiler and JVM based run-time system)
http://www.rascal-mpl.org
Other
407 stars 77 forks source link

"Expected set[void], but got set[int]" when assigning an empty set to an uninitialized variable #2045

Open arthurrump opened 1 month ago

arthurrump commented 1 month ago

Describe the bug

module Example

private set[int] numbers;

public void initialize() {
    numbers = {};
}

public void do() {
    numbers += { 5 };
}

public void main(list[str] args) {
    initialize();
    do();
}

results in the error |file:///.../Example.rsc|(127,1,<10,17>,<10,18>): Expected set[void], but got set[int]. It looks like the empty set in the initialize function is inferred to be a set[void] and this overrides the type of numbers.

Immediately initializing the numbers variable fixes the issue:

private set[int] numbers = {};

To Reproduce

Copy the module above to a file and run the main method.

Expected behavior

I expect this code to run without errors :) I found this in an old project, so I suppose it worked in some previous versions.

Stack traces

unexpected error: Expected set[void], but got set[int]
Advice: |https://www.rascal-mpl.org/docs/Rascal/Errors/CompileTimeErrors/UnexpectedType|
org.rascalmpl.interpreter.staticErrors.UnexpectedType: Expected set[void], but got set[int]
Advice: |https://www.rascal-mpl.org/docs/Rascal/Errors/CompileTimeErrors/UnexpectedType|
        at Example.?(/.../src/main/rascal/Example.rsc:10)
        at org.rascalmpl.interpreter.AssignableEvaluator.newResult(AssignableEvaluator.java:143)
        at org.rascalmpl.semantics.dynamic.Assignable$Variable.assignment(Assignable.java:1002)
        at org.rascalmpl.semantics.dynamic.Statement$Assignment.interpret(Statement.java:209)
        at org.rascalmpl.interpreter.result.RascalFunction.runBody(RascalFunction.java:385)
        at org.rascalmpl.interpreter.result.RascalFunction.call(RascalFunction.java:294)
        at org.rascalmpl.semantics.dynamic.Expression$CallOrTree.interpret(Expression.java:540)
        at org.rascalmpl.semantics.dynamic.Statement$Expression.interpret(Statement.java:365)
        at org.rascalmpl.interpreter.result.RascalFunction.runBody(RascalFunction.java:385)
        at org.rascalmpl.interpreter.result.RascalFunction.call(RascalFunction.java:326)
        at org.rascalmpl.interpreter.result.AbstractFunction.call(AbstractFunction.java:199)
        at org.rascalmpl.interpreter.Evaluator.main(Evaluator.java:595)
        at org.rascalmpl.shell.ModuleRunner.run(ModuleRunner.java:33)
        at org.rascalmpl.shell.RascalShell.main(RascalShell.java:69)

Desktop (please complete the following information):

jurgenvinju commented 1 month ago

Thanks for this concise report and the analysis @arthurrump ; we'll look into this. To me it seems like the dynamic type is confused with the static type somewhere.

The interpreter does both an abstract interpretation and a concrete interpretation at the same time to simulate the behavior of the (then) future static checker to some degree. That sometimes led to confusion.