fuzion
fuzion copied to clipboard
Actual type parameters not checked sufficiently strictly resulting in crashes
This small example defines feature a that receives an argument of type S type : Sequence U, but if U is bool, then S might be Seqence i32:
a(U type,
S type : Sequence U,
s S) U => s[0]
say (a bool (Sequence i32) [42])
which causes a crash in DFA:
> ../clean/fuzion/build/bin/fz test_fun.fz
error 1: java.lang.Error: DFA encountered Unexpected value in match: class dev.flang.fuir.analysis.dfa.NumericValue 'i32:42' for match of type bool
at dev.flang.fuir.analysis.dfa.DFA$Analyze.matchSingleSubject(DFA.java:704)
at dev.flang.fuir.analysis.dfa.DFA$Analyze.match(DFA.java:645)
at dev.flang.fuir.analysis.dfa.DFA$Analyze.match(DFA.java:99)
A similar example with a function argument
a(U type,
F type : Function U,
f F) U => f.call
say (a bool B B)
B : Function (option i32) is
redef call option i32 => 32
causes an error only during execution
> ../clean/fuzion/build/bin/fz test_fun2.fz
error 1: java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
fzC_1a_bool_B.fzRoutine()Z @12: putfield
Reason:
Type 'fzC_option_i32' (current frame, stack[1]) is not assignable to integer
Current Frame:
bci: @12
flags: { }
locals: { 'fzC_1a_bool_B' }
stack: { 'fzC_1a_bool_B', 'fzC_option_i32' }
Bytecode:
0000000: bb00 0259 b700 104b 2ab8 0016 b500 182a
0000010: b400 18ac
Stackmap Table:
full_frame(@0,{},{})
at fzC_universe.fzRoutine(--builtin--:5)
at fzC_universe.fz_run(--builtin--)
at dev.flang.be.jvm.runtime.FuzionThread.lambda$new$1(FuzionThread.java:104)
at dev.flang.util.Errors.runAndExit(Errors.java:895)
at dev.flang.be.jvm.runtime.FuzionThread.lambda$new$2(FuzionThread.java:116)
at java.base/java.lang.Thread.run(Thread.java:1583)
*** fatal errors encountered, stopping.
one error.
the following patch does not seem to suffice:
diff --git a/src/dev/flang/ast/Call.java b/src/dev/flang/ast/Call.java
index 16496b9a6..97af04ff5 100644
--- a/src/dev/flang/ast/Call.java
+++ b/src/dev/flang/ast/Call.java
@@ -1341,6 +1341,19 @@ public class Call extends AbstractCall
Generic g = frmlT.genericArgument();
var frmlTs = g.replaceOpen(g.feature() == _calledFeature
? _generics
+ /* example where this applies:
+ *
+ * a(U type,
+ * F type : Function U,
+ * f F) U => f.call
+ *
+ * say (a bool B B)
+ *
+ * B : Function (option i32) is
+ * redef call option i32 => 32
+ */
+ : _target.type().isGenericArgument()
+ ? _target.type().genericArgument().constraint(context).generics()
: _target.type().generics());
addToResolvedFormalArgumentTypes(res, argnum + i, frmlTs.toArray(new AbstractType[frmlTs.size()]), frml);
i = i + frmlTs.size() - 1;