Skip to content

Commit

Permalink
only bind known type parameters to monomorphs in definition mode (#11658
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Simn authored May 9, 2024
1 parent bcc3c93 commit 9d2007b
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 5 deletions.
18 changes: 13 additions & 5 deletions src/core/tUnification.ml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type eq_kind =
| EqStricter

type type_param_unification_context = {
known_type_params : typed_type_param list;
mutable type_param_pairs : (typed_type_param * typed_type_param) list;
}

Expand Down Expand Up @@ -328,14 +329,21 @@ let rec follow_and_close t = match follow t with
| t ->
t

let link e a b =
let link uctx e a b =
(* tell if setting a == b will create a type-loop *)
let rec loop t =
if t == a then
true
else match t with
| TMono t -> (match t.tm_type with None -> false | Some t -> loop t)
| TEnum (_,tl) -> List.exists loop tl
| TInst ({cl_kind = KTypeParameter ttp}, tl) ->
begin match uctx.type_param_mode with
| TpDefault ->
List.exists loop tl
| TpDefinition tctx ->
not (List.memq ttp tctx.known_type_params)
end
| TInst (_,tl) | TType (_,tl) | TAbstract (_,tl) -> List.exists loop tl
| TFun (tl,t) -> List.exists (fun (_,_,t) -> loop t) tl || loop t
| TDynamic None ->
Expand Down Expand Up @@ -554,11 +562,11 @@ let rec type_eq uctx a b =
| _ , TLazy f -> type_eq uctx a (lazy_type f)
| TMono t , _ ->
(match t.tm_type with
| None -> if param = EqCoreType || param = EqStricter || not (link t a b) then error [cannot_unify a b]
| None -> if param = EqCoreType || param = EqStricter || not (link uctx t a b) then error [cannot_unify a b]
| Some t -> type_eq uctx t b)
| _ , TMono t ->
(match t.tm_type with
| None -> if param = EqCoreType || param = EqStricter || not (link t b a) then error [cannot_unify a b]
| None -> if param = EqCoreType || param = EqStricter || not (link uctx t b a) then error [cannot_unify a b]
| Some t -> type_eq uctx a t)
| TDynamic None, TDynamic None ->
()
Expand Down Expand Up @@ -714,11 +722,11 @@ let rec unify (uctx : unification_context) a b =
| _ , TLazy f -> unify uctx a (lazy_type f)
| TMono t , _ ->
(match t.tm_type with
| None -> if uctx.equality_kind = EqStricter || not (link t a b) then error [cannot_unify a b]
| None -> if uctx.equality_kind = EqStricter || not (link uctx t a b) then error [cannot_unify a b]
| Some t -> unify uctx t b)
| _ , TMono t ->
(match t.tm_type with
| None -> if uctx.equality_kind = EqStricter || not (link t b a) then error [cannot_unify a b]
| None -> if uctx.equality_kind = EqStricter || not (link uctx t b a) then error [cannot_unify a b]
| Some t -> unify uctx a t)
| TType (t,tl) , _ ->
rec_stack unify_stack (a,b)
Expand Down
1 change: 1 addition & 0 deletions src/typing/typeloadCheck.ml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ let is_generic_parameter ctx c =
let valid_redefinition map1 map2 f1 t1 f2 t2 = (* child, parent *)
let tctx = {
type_param_pairs = [];
known_type_params = f1.cf_params
} in
let uctx = {default_unification_context with type_param_mode = TpDefinition tctx} in
let valid t1 t2 =
Expand Down
9 changes: 9 additions & 0 deletions tests/misc/projects/Issue11624/MainBar.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
interface Foo {
function bar<T>():T;
}

class Bar implements Foo {
public function bar<T>() return null; // Error: write_full_path hxb writer failure
}

function main() {}
9 changes: 9 additions & 0 deletions tests/misc/projects/Issue11624/MainBaz.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
interface Foo {
function baz<T>():T;
}

class Bar implements Foo {
public function baz<T>():T return null; // this is fine
}

function main() {}
9 changes: 9 additions & 0 deletions tests/misc/projects/Issue11624/MainFoo.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
interface Foo {
function foo<T>():T;
}

class Bar implements Foo {
public function foo() return null; // Warning: Unbound type parameter foo.T
}

function main() {}
2 changes: 2 additions & 0 deletions tests/misc/projects/Issue11624/compile-bar-fail.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--main MainBar
--interp
5 changes: 5 additions & 0 deletions tests/misc/projects/Issue11624/compile-bar-fail.hxml.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MainBar.hx:6: characters 18-21 : Field bar has different type than in Foo
MainBar.hx:2: characters 11-14 : ... Interface field is defined here
MainBar.hx:6: characters 18-21 : ... error: Null<Unknown<0>> should be bar.T
MainBar.hx:6: characters 18-21 : ... have: (...) -> Null<...>
MainBar.hx:6: characters 18-21 : ... want: (...) -> bar.T
2 changes: 2 additions & 0 deletions tests/misc/projects/Issue11624/compile-baz.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--main MainBaz
--interp
2 changes: 2 additions & 0 deletions tests/misc/projects/Issue11624/compile-foo-fail.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--main MainFoo
--interp
5 changes: 5 additions & 0 deletions tests/misc/projects/Issue11624/compile-foo-fail.hxml.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MainFoo.hx:6: characters 18-21 : Field foo has different type than in Foo
MainFoo.hx:2: characters 11-14 : ... Interface field is defined here
MainFoo.hx:6: characters 18-21 : ... error: Null<Unknown<0>> should be foo.T
MainFoo.hx:6: characters 18-21 : ... have: (...) -> Null<...>
MainFoo.hx:6: characters 18-21 : ... want: (...) -> foo.T

0 comments on commit 9d2007b

Please sign in to comment.