Skip to content

Commit

Permalink
[typer] don't consider @:structInit + @:from when inferring
Browse files Browse the repository at this point in the history
closes #11535
  • Loading branch information
Simn committed Feb 4, 2024
1 parent 61fae05 commit c55da75
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/typing/matcher/exprToPattern.ml
Expand Up @@ -315,7 +315,7 @@ let rec make pctx toplevel t e =
PatConstructor(con_array (List.length patterns) (pos e),patterns)
| TAbstract(a,tl) as t when not (List.exists (fun t' -> shallow_eq t t') seen) ->
begin match TyperBase.get_abstract_froms ctx a tl with
| [t2] -> pattern (t :: seen) t2
| [(_,t2)] -> pattern (t :: seen) t2
| _ -> fail()
end
| _ ->
Expand Down
30 changes: 13 additions & 17 deletions src/typing/typer.ml
Expand Up @@ -96,7 +96,7 @@ let maybe_type_against_enum ctx f with_type iscall p =
false,a.a_path,fields,TAbstractDecl a
| TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
begin match get_abstract_froms ctx a pl with
| [t2] ->
| [(_,t2)] ->
if (List.exists (shallow_eq t) stack) then raise Exit;
loop (t :: stack) t2
| _ -> raise Exit
Expand Down Expand Up @@ -782,14 +782,15 @@ and type_object_decl ctx fl with_type p =
let dynamic_parameter = ref None in
let a = (match with_type with
| WithType.WithType(t,_) ->
let rec loop seen t =
let rec loop had_cast seen t =
match follow t with
| TAnon a -> ODKWithStructure a
| TAnon a ->
ODKWithStructure a
| TAbstract (a,pl) as t
when not (Meta.has Meta.CoreType a.a_meta)
&& not (List.exists (fun t' -> shallow_eq t t') seen) ->
let froms = get_abstract_froms ctx a pl in
let fold = fun acc t' -> match loop (t :: seen) t' with ODKPlain -> acc | t -> t :: acc in
let fold = fun acc (fk,t') -> match loop (fk = FromField) (t :: seen) t' with ODKPlain -> acc | t -> t :: acc in
begin match List.fold_left fold [] froms with
| [] -> ODKPlain (* If the abstract has no casts in the first place, we can assume plain typing (issue #10730) *)
| [t] -> t
Expand All @@ -801,12 +802,12 @@ and type_object_decl ctx fl with_type p =
a_status = ref Closed;
a_fields = PMap.empty;
}
| TInst(c,tl) when Meta.has Meta.StructInit c.cl_meta ->
| TInst(c,tl) when not had_cast && Meta.has Meta.StructInit c.cl_meta ->
ODKWithClass(c,tl)
| _ ->
ODKPlain
in
loop [] t
loop false [] t
| _ ->
ODKPlain
) in
Expand Down Expand Up @@ -1296,14 +1297,14 @@ and type_local_function ctx kind f with_type p =
maybe_unify_ret tr
| TAbstract(a,tl) ->
begin match get_abstract_froms ctx a tl with
| [t2] ->
| [(_,t2)] ->
if not (List.exists (shallow_eq t) stack) then loop (t :: stack) t2
| l ->
(* For cases like nested EitherType, we want a flat list of all possible candidates.
This might be controversial because those could be considered transitive casts,
but it's unclear if that's a bad thing for this kind of inference (issue #10982). *)
let rec loop stack acc l = match l with
| t :: l ->
| (_,t) :: l ->
begin match follow t with
| TAbstract(a,tl) as t when not (List.exists (shallow_eq t) stack) ->
loop (t :: stack) acc (l @ get_abstract_froms ctx a tl)
Expand Down Expand Up @@ -1398,15 +1399,10 @@ and type_array_decl ctx el with_type p =
with Not_found ->
None)
| TAbstract (a,pl) as t when not (List.exists (fun t' -> shallow_eq t t') seen) ->
let types =
List.fold_left
(fun acc t' -> match loop (t :: seen) t' with
| None -> acc
| Some t -> t :: acc
)
[]
(get_abstract_froms ctx a pl)
in
let types = List.fold_left (fun acc (_,t') -> match loop (t :: seen) t' with
| None -> acc
| Some t -> t :: acc
) [] (get_abstract_froms ctx a pl) in
(match types with
| [t] -> Some t
| _ -> None)
Expand Down
8 changes: 6 additions & 2 deletions src/typing/typerBase.ml
Expand Up @@ -330,8 +330,12 @@ let unify_static_extension ctx e t p =
e
end

type from_kind =
| FromType
| FromField

let get_abstract_froms ctx a pl =
let l = List.map (apply_params a.a_params pl) a.a_from in
let l = List.map (fun t -> FromType,apply_params a.a_params pl t) a.a_from in
List.fold_left (fun acc (t,f) ->
(* We never want to use the @:from we're currently in because that's recursive (see #10604) *)
if f == ctx.f.curfield then
Expand All @@ -342,7 +346,7 @@ let get_abstract_froms ctx a pl =
| TFun ([_,_,v],t) ->
(try
ignore(type_eq EqStrict t (TAbstract(a,List.map duplicate pl))); (* unify fields monomorphs *)
v :: acc
(FromField,v) :: acc
with Unify_error _ ->
acc)
| _ ->
Expand Down
34 changes: 34 additions & 0 deletions tests/unit/src/unit/issues/Issue11535.hx
@@ -0,0 +1,34 @@
package unit.issues;

@:structInit
private class BarImpl {
public function new() {}
}

@:structInit
private class FooImpl {
public var x:Int;

public function new(x:Int) {
this.x = x;
}
}

@:forward
private abstract Foo(FooImpl) from FooImpl to FooImpl {
public function new(x:Int) {
this = new FooImpl(x);
}

@:from
static public function fromVec4(v:BarImpl):Foo {
return new Foo(1);
}
}

class Issue11535 extends Test {
function test() {
var v:Foo = {x: 2};
eq(2, v.x);
}
}

0 comments on commit c55da75

Please sign in to comment.