diff --git a/src/core/tUnification.ml b/src/core/tUnification.ml index 185abdfb870..e372c151b15 100644 --- a/src/core/tUnification.ml +++ b/src/core/tUnification.ml @@ -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; } @@ -328,7 +329,7 @@ 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 @@ -336,6 +337,13 @@ let link e a b = 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 -> @@ -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 -> () @@ -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) diff --git a/src/typing/typeloadCheck.ml b/src/typing/typeloadCheck.ml index 56adc1e7db8..c6c8a87dba6 100644 --- a/src/typing/typeloadCheck.ml +++ b/src/typing/typeloadCheck.ml @@ -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 = diff --git a/tests/misc/projects/Issue11624/MainBar.hx b/tests/misc/projects/Issue11624/MainBar.hx new file mode 100644 index 00000000000..da534b41b8a --- /dev/null +++ b/tests/misc/projects/Issue11624/MainBar.hx @@ -0,0 +1,9 @@ +interface Foo { + function bar():T; +} + +class Bar implements Foo { + public function bar() return null; // Error: write_full_path hxb writer failure +} + +function main() {} \ No newline at end of file diff --git a/tests/misc/projects/Issue11624/MainBaz.hx b/tests/misc/projects/Issue11624/MainBaz.hx new file mode 100644 index 00000000000..347e5ce4fc9 --- /dev/null +++ b/tests/misc/projects/Issue11624/MainBaz.hx @@ -0,0 +1,9 @@ +interface Foo { + function baz():T; +} + +class Bar implements Foo { + public function baz():T return null; // this is fine +} + +function main() {} \ No newline at end of file diff --git a/tests/misc/projects/Issue11624/MainFoo.hx b/tests/misc/projects/Issue11624/MainFoo.hx new file mode 100644 index 00000000000..21dc6655ed8 --- /dev/null +++ b/tests/misc/projects/Issue11624/MainFoo.hx @@ -0,0 +1,9 @@ +interface Foo { + function foo():T; +} + +class Bar implements Foo { + public function foo() return null; // Warning: Unbound type parameter foo.T +} + +function main() {} \ No newline at end of file diff --git a/tests/misc/projects/Issue11624/compile-bar-fail.hxml b/tests/misc/projects/Issue11624/compile-bar-fail.hxml new file mode 100644 index 00000000000..300cea8e45f --- /dev/null +++ b/tests/misc/projects/Issue11624/compile-bar-fail.hxml @@ -0,0 +1,2 @@ +--main MainBar +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue11624/compile-bar-fail.hxml.stderr b/tests/misc/projects/Issue11624/compile-bar-fail.hxml.stderr new file mode 100644 index 00000000000..c6897cde922 --- /dev/null +++ b/tests/misc/projects/Issue11624/compile-bar-fail.hxml.stderr @@ -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> should be bar.T +MainBar.hx:6: characters 18-21 : ... have: (...) -> Null<...> +MainBar.hx:6: characters 18-21 : ... want: (...) -> bar.T \ No newline at end of file diff --git a/tests/misc/projects/Issue11624/compile-baz.hxml b/tests/misc/projects/Issue11624/compile-baz.hxml new file mode 100644 index 00000000000..b726e0230b3 --- /dev/null +++ b/tests/misc/projects/Issue11624/compile-baz.hxml @@ -0,0 +1,2 @@ +--main MainBaz +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue11624/compile-foo-fail.hxml b/tests/misc/projects/Issue11624/compile-foo-fail.hxml new file mode 100644 index 00000000000..70c6af854f0 --- /dev/null +++ b/tests/misc/projects/Issue11624/compile-foo-fail.hxml @@ -0,0 +1,2 @@ +--main MainFoo +--interp \ No newline at end of file diff --git a/tests/misc/projects/Issue11624/compile-foo-fail.hxml.stderr b/tests/misc/projects/Issue11624/compile-foo-fail.hxml.stderr new file mode 100644 index 00000000000..2fcec0f75db --- /dev/null +++ b/tests/misc/projects/Issue11624/compile-foo-fail.hxml.stderr @@ -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> should be foo.T +MainFoo.hx:6: characters 18-21 : ... have: (...) -> Null<...> +MainFoo.hx:6: characters 18-21 : ... want: (...) -> foo.T \ No newline at end of file