tokiwa-software / fuzion

The Fuzion Language Implementation
https://fuzion-lang.dev
GNU General Public License v3.0
47 stars 11 forks source link

Actual type parameters not checked sufficiently strictly resulting in crashes #3773

Open fridis opened 2 months ago

fridis commented 2 months ago

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.
michaellilltokiwa commented 1 month ago

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;