A refused dyn view of a parameter names its declaration as the fix
This commit is contained in:
parent
4f060bb648
commit
d16fe79b79
35
lib/check.ml
35
lib/check.ml
@ -3456,6 +3456,10 @@ let view_elem_lit loc (k : int64) =
|
|||||||
says which one the reader is looking at. *)
|
says which one the reader is looking at. *)
|
||||||
let fln_source (loc : Loc.t) = Filename.check_suffix loc.Loc.file ".fln"
|
let fln_source (loc : Loc.t) = Filename.check_suffix loc.Loc.file ".fln"
|
||||||
|
|
||||||
|
(* The function being checked and its parameters, by slot. A stack because
|
||||||
|
a generic's copy is checked from inside the body that called it. *)
|
||||||
|
let grow_params : (ctx * (int * Ast.field) list) list ref = ref []
|
||||||
|
|
||||||
(* The two refusals below share their subject and their fix. The subject is
|
(* The two refusals below share their subject and their fix. The subject is
|
||||||
the name as written when the refused value is a bare name, so the message
|
the name as written when the refused value is a bare name, so the message
|
||||||
can say [a is a [4 i64]]; anything longer is "this". The fix is the one
|
can say [a is a [4 i64]]; anything longer is "this". The fix is the one
|
||||||
@ -3467,7 +3471,7 @@ let view_subject (e : Tast.expr) =
|
|||||||
| Some s
|
| Some s
|
||||||
when s <> ""
|
when s <> ""
|
||||||
&& String.for_all
|
&& String.for_all
|
||||||
(fun c -> not (List.mem c [ ' '; '('; ')'; '['; ']'; '{'; '}'; '"' ]))
|
(fun c -> not (List.mem c [ ' '; '('; ')'; '['; ']'; '{'; '}'; '"'; '.'; ',' ]))
|
||||||
s ->
|
s ->
|
||||||
Some s
|
Some s
|
||||||
| _ -> None
|
| _ -> None
|
||||||
@ -3475,14 +3479,29 @@ let view_subject (e : Tast.expr) =
|
|||||||
let view_refusal kind loc (e : Tast.expr) reason =
|
let view_refusal kind loc (e : Tast.expr) reason =
|
||||||
let ty = Types.to_string e.Tast.ty in
|
let ty = Types.to_string e.Tast.ty in
|
||||||
let fln = fln_source loc in
|
let fln = fln_source loc in
|
||||||
|
(* A parameter is made by the caller, so its fix is its declaration. The
|
||||||
|
name is compared as well as the slot: a closure numbers its slots from
|
||||||
|
zero too, and is checked while its enclosing function is on the stack. *)
|
||||||
|
let param =
|
||||||
|
match e.Tast.e, view_subject e, !grow_params with
|
||||||
|
| Tast.Local s, Some n, (ctx, ps) :: _ ->
|
||||||
|
(match List.assoc_opt s ps with
|
||||||
|
| Some (p : Ast.field) when p.Ast.fname = n -> Some (ctx.owner, n)
|
||||||
|
| _ -> None)
|
||||||
|
| _ -> None
|
||||||
|
in
|
||||||
let subject, fix =
|
let subject, fix =
|
||||||
match view_subject e with
|
match param, view_subject e with
|
||||||
| Some n ->
|
| Some (f, n), _ ->
|
||||||
|
( Printf.sprintf "%s is a %s parameter" n ty,
|
||||||
|
Printf.sprintf "Declare %s as dyn in %s's parameters: %s%s" n f n
|
||||||
|
(if fln then ": dyn" else " dyn") )
|
||||||
|
| None, Some n ->
|
||||||
( Printf.sprintf "%s is a %s" n ty,
|
( Printf.sprintf "%s is a %s" n ty,
|
||||||
Printf.sprintf "Build %s as a dyn value where it is made, as in %s" n
|
Printf.sprintf "Build %s as a dyn value where it is made, as in %s" n
|
||||||
(if fln then Printf.sprintf "let %s: dyn = [...]" n
|
(if fln then Printf.sprintf "let %s: dyn = [...]" n
|
||||||
else Printf.sprintf "(let [%s (the dyn [...])] ...)" n) )
|
else Printf.sprintf "(let [%s (the dyn [...])] ...)" n) )
|
||||||
| None ->
|
| None, None ->
|
||||||
( Printf.sprintf "This is a %s" ty,
|
( Printf.sprintf "This is a %s" ty,
|
||||||
Printf.sprintf "Build it as a dyn value where it is made, as in %s"
|
Printf.sprintf "Build it as a dyn value where it is made, as in %s"
|
||||||
(if fln then "the(dyn, [...])" else "(the dyn [...])") )
|
(if fln then "the(dyn, [...])" else "(the dyn [...])") )
|
||||||
@ -5153,11 +5172,9 @@ let if_depth = ref 0
|
|||||||
|
|
||||||
(* A Vec or a Map parameter is a copy of the caller's header — Odin's rule —
|
(* A Vec or a Map parameter is a copy of the caller's header — Odin's rule —
|
||||||
so growing it reallocates a block only this function's copy points at, and
|
so growing it reallocates a block only this function's copy points at, and
|
||||||
the caller's container never sees the elements. The function being checked
|
the caller's container never sees the elements. The warnings found so far,
|
||||||
and its container parameters, by slot, and the warnings found so far, one
|
one per parameter, printed by [build_program]; the parameters themselves
|
||||||
per parameter, printed by [build_program]. A stack because a generic's copy
|
are [grow_params], above [view_refusal], which reads them too. *)
|
||||||
is checked from inside the body that called it. *)
|
|
||||||
let grow_params : (ctx * (int * Ast.field) list) list ref = ref []
|
|
||||||
let grow_warnings : Loc.diag list ref = ref []
|
let grow_warnings : Loc.diag list ref = ref []
|
||||||
|
|
||||||
let note_grown ctx op loc (target : Tast.expr) =
|
let note_grown ctx op loc (target : Tast.expr) =
|
||||||
|
|||||||
@ -589,6 +589,18 @@ let () =
|
|||||||
(poke_fln ^ "fn main() -> ()\n let d = [6 2 4 9]\n poke(d)\n")
|
(poke_fln ^ "fn main() -> ()\n let d = [6 2 4 9]\n poke(d)\n")
|
||||||
[ "d is a [4 i32]"; "only when its elements are i64, f64 or bool, and these are i32";
|
[ "d is a [4 i32]"; "only when its elements are i64, f64 or bool, and these are i32";
|
||||||
"as in let d: dyn = [...]" ];
|
"as in let d: dyn = [...]" ];
|
||||||
|
(* A parameter is made by the caller, so its fix is its declaration. *)
|
||||||
|
refused "view-param.fln"
|
||||||
|
"fn take(d) -> i32 = 1\n\nfn give(n: i32, v: [4 i64]) -> i32\n take(v)\n\n\
|
||||||
|
fn main() -> i32 = 0\n"
|
||||||
|
[ "v is a [4 i64] parameter"; "Declare v as dyn in give's parameters: v: dyn" ];
|
||||||
|
refused "view-param.flan"
|
||||||
|
"(defn take [d dyn] i32 1)\n(defn give [n i32 v (Vec i64)] i32 (take v))\n\
|
||||||
|
(defn main [] i32 0)\n"
|
||||||
|
[ "v is a (Vec i64) parameter"; "Declare v as dyn in give's parameters: v dyn" ];
|
||||||
|
checks "view-param-fix.fln"
|
||||||
|
"fn take(d) -> i32 = 1\n\nfn give(n: i32, v: dyn) -> i32\n take(v)\n\n\
|
||||||
|
fn main() -> i32 = 0\n";
|
||||||
(* The fix both of them name. *)
|
(* The fix both of them name. *)
|
||||||
checks "view-fix.fln"
|
checks "view-fix.fln"
|
||||||
(poke_fln ^ "fn main() -> ()\n let d: dyn = [6 2 4 9]\n poke(d)\n poke(the(dyn, [1 2]))\n");
|
(poke_fln ^ "fn main() -> ()\n let d: dyn = [6 2 4 9]\n poke(d)\n poke(the(dyn, [1 2]))\n");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user