A read-only slice's diagnostics name (clone v) wherever clone copies the element type
This commit is contained in:
parent
bb4705b7e0
commit
409c5f5c0d
24
lib/check.ml
24
lib/check.ml
@ -2419,12 +2419,11 @@ and const_steps ro (ty : Types.t) n =
|
|||||||
| _ -> ro
|
| _ -> ro
|
||||||
|
|
||||||
(* A copy of a read-only slice's elements that can be written, spelled so it
|
(* A copy of a read-only slice's elements that can be written, spelled so it
|
||||||
compiles. Only for elements that own nothing: an element holding a Vec or
|
compiles: [clone], for exactly the element types clone copies. It refuses
|
||||||
a Map — directly or inside a struct — would copy only its header, and the
|
elements that own storage — a copy would share their blocks — and
|
||||||
copy would share the original's block. *)
|
elements that hold a dyn, which its allocator storage cannot root. *)
|
||||||
let const_copy env (e : Types.t) =
|
let const_copy env (e : Types.t) =
|
||||||
if owning env e then None
|
if owning env e || holds_dyn env e then None else Some "(clone v)"
|
||||||
else Some (Printf.sprintf "(slice (into v (vec-new %s)))" (Types.to_string e))
|
|
||||||
|
|
||||||
(* A store through a read-only view: a [[const T]] or a (Ptr const T). *)
|
(* A store through a read-only view: a [[const T]] or a (Ptr const T). *)
|
||||||
let refuse_const_place env loc (view : Types.t) =
|
let refuse_const_place env loc (view : Types.t) =
|
||||||
@ -3348,19 +3347,12 @@ let numeric_note ~(want : Types.t) ~(got : Types.t) =
|
|||||||
(%s x)"
|
(%s x)"
|
||||||
(Types.to_string want)
|
(Types.to_string want)
|
||||||
|
|
||||||
(* The rest of the sentence when a read-only slice meets a writable one. Both
|
(* The rest of the sentence when a read-only slice meets a writable one. *)
|
||||||
copies it names compile today: [string] reads any byte slice and [bytes]
|
|
||||||
copies a string, and [into] pushes any slice's elements into a Vec that
|
|
||||||
[slice] then views. *)
|
|
||||||
let const_note env ~(want : Types.t) ~(got : Types.t) =
|
let const_note env ~(want : Types.t) ~(got : Types.t) =
|
||||||
match want, got with
|
match want, got with
|
||||||
| Types.Slice (Types.Mut, e), Types.Slice (Types.Const, e')
|
| Types.Slice (Types.Mut, e), Types.Slice (Types.Const, e')
|
||||||
when Types.equal e e' ->
|
when Types.equal e e' ->
|
||||||
let copy =
|
let copy = const_copy env e in
|
||||||
match e with
|
|
||||||
| Types.Int Types.U8 -> Some "(bytes (string v))"
|
|
||||||
| _ -> const_copy env e
|
|
||||||
in
|
|
||||||
Printf.sprintf
|
Printf.sprintf
|
||||||
" — a %s can only be read, and never becomes a %s that can be written \
|
" — a %s can only be read, and never becomes a %s that can be written \
|
||||||
through. %sWhere nothing writes through it, the %s can be declared %s \
|
through. %sWhere nothing writes through it, the %s can be declared %s \
|
||||||
@ -3989,8 +3981,8 @@ and refuse_owned_copy ctx (r : Tast.expr) =
|
|||||||
match r.Tast.ty with
|
match r.Tast.ty with
|
||||||
| (Types.Vec _ | Types.Map _) when not (region_only ctx.env r.Tast.ty) ->
|
| (Types.Vec _ | Types.Map _) when not (region_only ctx.env r.Tast.ty) ->
|
||||||
Printf.sprintf "(clone v) copies it into a %s of its own" t
|
Printf.sprintf "(clone v) copies it into a %s of its own" t
|
||||||
(* TODO.org, "(clone slice)": once clone copies any value that owns
|
(* Nothing copies an array, an Option or a struct that owns storage,
|
||||||
storage, this should say (clone v) too. *)
|
nor a container whose elements do: its address is the way to it. *)
|
||||||
| _ -> Printf.sprintf "(addr v) gives a (Ptr const %s) to read it through" t
|
| _ -> Printf.sprintf "(addr v) gives a (Ptr const %s) to read it through" t
|
||||||
in
|
in
|
||||||
Loc.failk "check/const-owned-copy" r.Tast.loc
|
Loc.failk "check/const-owned-copy" r.Tast.loc
|
||||||
|
|||||||
@ -2283,7 +2283,18 @@ let () =
|
|||||||
~needle:"expected [u8], found [const u8]";
|
~needle:"expected [u8], found [const u8]";
|
||||||
rejects_check "and the refusal names the copy"
|
rejects_check "and the refusal names the copy"
|
||||||
"(defn g [b [u8]] () (set (at b 0) 1)) (defn f [s [const u8]] () (g s))"
|
"(defn g [b [u8]] () (set (at b 0) 1)) (defn f [s [const u8]] () (g s))"
|
||||||
~needle:"(bytes (string v)) copies v";
|
~needle:"(clone v) copies v into a [u8] of its own";
|
||||||
|
accepts "and the copy it names compiles"
|
||||||
|
"(defn g [b [u8]] () (set (at b 0) 1)) (defn f [s [const u8]] () (g (clone s)))";
|
||||||
|
rejects_check "a store through a const slice names clone"
|
||||||
|
"(defstruct P [x i32]) (defn f [v [const P]] () (set (.x (at v 0)) 1))"
|
||||||
|
~needle:"(clone v) copies v's elements into one";
|
||||||
|
accepts "and that clone compiles"
|
||||||
|
"(defstruct P [x i32]) \
|
||||||
|
(defn f [v [const P]] () (let [w (clone v)] (set (.x (at w 0)) 1)))";
|
||||||
|
rejects_check "no clone named for elements clone refuses"
|
||||||
|
"(defn f [v [const dyn]] () (set (at v 0) 1))"
|
||||||
|
~needle:"take it as a [dyn] instead";
|
||||||
rejects_check "a generic writer does not take a const slice"
|
rejects_check "a generic writer does not take a const slice"
|
||||||
"(defn f [s [const i32]] () (sort s))"
|
"(defn f [s [const i32]] () (sort s))"
|
||||||
~needle:"sort takes a slice it may write through";
|
~needle:"sort takes a slice it may write through";
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user