A parameter, local or field may be named str or any other type name when a type follows it, and a type-named parameter with no type after it is refused with both fixes.
This commit is contained in:
parent
267db2cd91
commit
b92e91bcaa
41
lib/check.ml
41
lib/check.ml
@ -2077,12 +2077,10 @@ and array_len env loc = function
|
|||||||
another name that is not a type, or by nothing, takes one and is [dyn]. That
|
another name that is not a type, or by nothing, takes one and is [dyn]. That
|
||||||
is the whole rule, and it reads the way the vector reads.
|
is the whole rule, and it reads the way the vector reads.
|
||||||
|
|
||||||
A name that *is* a type name is refused rather than paired. [(defn f [i64 x]
|
A name that *is* a type name pairs only when a type follows it: [[str str]]
|
||||||
...)] has no good reading: taken as written it is a parameter called [i64],
|
has one reading. [(defn f [i64 x] ...)] has two — a dyn parameter called
|
||||||
which shadows nothing but confuses everything, and the likelier intent is a
|
[i64], or a pair written backwards — so it is refused rather than handed
|
||||||
pair written backwards. Refusing here costs a rename in the one program that
|
back as a signature nobody wrote. *)
|
||||||
meant it and closes the one place where this rule could still hand somebody
|
|
||||||
a signature they did not write. *)
|
|
||||||
let is_type_name env n =
|
let is_type_name env n =
|
||||||
Types.ikind_of_name n <> None
|
Types.ikind_of_name n <> None
|
||||||
|| Types.fkind_of_name n <> None
|
|| Types.fkind_of_name n <> None
|
||||||
@ -2255,11 +2253,20 @@ let pair_params ?(also = fun _ -> false) ?(declared = fun _ -> None)
|
|||||||
Loc.failk "check/parameter-name-expected" t.Ast.tloc
|
Loc.failk "check/parameter-name-expected" t.Ast.tloc
|
||||||
"a parameter's name was expected here, and this is a type. Parameters \
|
"a parameter's name was expected here, and this is a type. Parameters \
|
||||||
are [name Type ...]"
|
are [name Type ...]"
|
||||||
| Ast.Pname (n, loc) :: rest when is_type_name env n ->
|
(* A parameter may share a type's name — [str] is a common name for text —
|
||||||
ignore rest;
|
when a type follows it: [[str str]] and [str: str] can only be a name
|
||||||
|
then a type. Without a type after it, [[i64 x]] is a pair written
|
||||||
|
backwards as likely as a dyn parameter called [i64], so that one is
|
||||||
|
refused with both fixes. *)
|
||||||
|
| Ast.Pname (n, loc) :: Ast.Ptype t :: rest when is_type_name env n ->
|
||||||
|
{ Ast.fname = n; fty = t; floc = loc } :: go rest
|
||||||
|
| Ast.Pname (n, loc) :: Ast.Pname (t, tloc) :: rest
|
||||||
|
when is_type_name env n && is_type_name env t ->
|
||||||
|
{ Ast.fname = n; fty = { Ast.t = Ast.Tname t; tloc }; floc = loc } :: go rest
|
||||||
|
| Ast.Pname (n, loc) :: _ when is_type_name env n ->
|
||||||
Loc.failk "check/parameter-named-type" loc
|
Loc.failk "check/parameter-named-type" loc
|
||||||
"%s names a type, so it cannot also be this parameter's name. Write \
|
"%s names a type, and no type follows this parameter called %s. Give \
|
||||||
[name %s], or rename the parameter" n n
|
it one, as [%s %s], or if the pair is backwards write [name %s]" n n n n n
|
||||||
(* [_] reads a type off a body, and a parameter has none to read. *)
|
(* [_] reads a type off a body, and a parameter has none to read. *)
|
||||||
| Ast.Pname (n, _) :: Ast.Pname ("_", tloc) :: _ ->
|
| Ast.Pname (n, _) :: Ast.Pname ("_", tloc) :: _ ->
|
||||||
Loc.failk "check/infer-misplaced" tloc
|
Loc.failk "check/infer-misplaced" tloc
|
||||||
@ -10416,6 +10423,18 @@ and type_named ctx n =
|
|||||||
|| Hashtbl.mem ctx.env.enums n
|
|| Hashtbl.mem ctx.env.enums n
|
||||||
|| Hashtbl.mem ctx.env.aliases n
|
|| Hashtbl.mem ctx.env.aliases n
|
||||||
|
|
||||||
|
(* A local or global that shares a type's name — [str] is a common name for
|
||||||
|
text — is the binding in (vec-new str), and then nothing names the type.
|
||||||
|
Said here so the refusal names the binding rather than a missing type. *)
|
||||||
|
and shadowed_type_arg ctx loc what args =
|
||||||
|
match args with
|
||||||
|
| { Ast.e = Ast.Var n; _ } :: _
|
||||||
|
when type_named ctx n && (lookup ctx n <> None || global_value ctx n) ->
|
||||||
|
fail loc
|
||||||
|
"%s here is the value named %s and not the type, so nothing says what \
|
||||||
|
(%s) makes — rename that binding to write the type" n n what
|
||||||
|
| _ -> ()
|
||||||
|
|
||||||
(* The element type for [vec-new]: a leading bare symbol naming a type, a
|
(* The element type for [vec-new]: a leading bare symbol naming a type, a
|
||||||
leading type expression — [(vec-new [u8])], [(vec-new (Ptr Cell))], which
|
leading type expression — [(vec-new [u8])], [(vec-new (Ptr Cell))], which
|
||||||
Parse has already read as one — or the expectation at the site. A bare
|
Parse has already read as one — or the expectation at the site. A bare
|
||||||
@ -10440,6 +10459,7 @@ and vec_new_elem ctx ~want loc args =
|
|||||||
(match want with
|
(match want with
|
||||||
| Some (Types.Vec t) -> t, args
|
| Some (Types.Vec t) -> t, args
|
||||||
| _ ->
|
| _ ->
|
||||||
|
shadowed_type_arg ctx loc "vec-new" args;
|
||||||
fail loc
|
fail loc
|
||||||
"nothing here says what (vec-new) is a Vec of — write the element \
|
"nothing here says what (vec-new) is a Vec of — write the element \
|
||||||
type, as (vec-new i32)")
|
type, as (vec-new i32)")
|
||||||
@ -10530,6 +10550,7 @@ and map_new_types ctx ~want loc args =
|
|||||||
(match want with
|
(match want with
|
||||||
| Some (Types.Map (k, v)) -> k, v, args
|
| Some (Types.Map (k, v)) -> k, v, args
|
||||||
| _ ->
|
| _ ->
|
||||||
|
shadowed_type_arg ctx loc "map-new" args;
|
||||||
fail loc
|
fail loc
|
||||||
"nothing here says what (map-new) maps — write the key and value \
|
"nothing here says what (map-new) maps — write the key and value \
|
||||||
types, as (map-new str i32)")
|
types, as (map-new str i32)")
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
(import agent "vendor:agent")
|
(import agent "vendor:agent")
|
||||||
|
|
||||||
(defn find-match [text str pattern str] i32
|
(defn find-match [str str pattern str] i32
|
||||||
(dotimes [i (length text)]
|
(dotimes [i (length str)]
|
||||||
(let [matched true]
|
(let [matched true]
|
||||||
(dotimes [j (length pattern)]
|
(dotimes [j (length pattern)]
|
||||||
(when (!= (at text (+ i j)) (at pattern j))
|
(when (!= (at str (+ i j)) (at pattern j))
|
||||||
(set matched false)))
|
(set matched false)))
|
||||||
(when matched
|
(when matched
|
||||||
(return i))))
|
(return i))))
|
||||||
@ -41,11 +41,11 @@
|
|||||||
(comment
|
(comment
|
||||||
(insertion-sort [\I \N \S \E \R \T \I \O \N \S \O \R \T])
|
(insertion-sort [\I \N \S \E \R \T \I \O \N \S \O \R \T])
|
||||||
(insertion-sort (slice [6 2 4 9 1 9 4 5] 0 8))
|
(insertion-sort (slice [6 2 4 9 1 9 4 5] 0 8))
|
||||||
(let [text (bytes "INSERTIONSORT")]
|
(let [str (bytes "INSERTIONSORT")]
|
||||||
(insertion-sort text)
|
(insertion-sort str)
|
||||||
(println text))
|
(println str))
|
||||||
(let [text (bytes "SELECTIONSORT")]
|
(let [str (bytes "SELECTIONSORT")]
|
||||||
(selection-sort text)
|
(selection-sort str)
|
||||||
(println text))
|
(println str))
|
||||||
(find-match "aababba" "abba")
|
(find-match "aababba" "abba")
|
||||||
:-)
|
:-)
|
||||||
|
|||||||
@ -3,11 +3,11 @@
|
|||||||
|
|
||||||
import agent "vendor:agent"
|
import agent "vendor:agent"
|
||||||
|
|
||||||
fn find-match(text: str, pattern: str) -> i32
|
fn find-match(str: str, pattern: str) -> i32
|
||||||
for i in range(length(text))
|
for i in range(length(str))
|
||||||
let matched = true
|
let matched = true
|
||||||
for j in range(length(pattern))
|
for j in range(length(pattern))
|
||||||
if text[i + j] != pattern[j]
|
if str[i + j] != pattern[j]
|
||||||
matched = false
|
matched = false
|
||||||
if matched
|
if matched
|
||||||
return i
|
return i
|
||||||
@ -42,11 +42,11 @@ fn main() -> i32 = 0
|
|||||||
comment():
|
comment():
|
||||||
insertion-sort([\I \N \S \E \R \T \I \O \N \S \O \R \T])
|
insertion-sort([\I \N \S \E \R \T \I \O \N \S \O \R \T])
|
||||||
insertion-sort(slice([6 2 4 9 1 9 4 5], 0, 8))
|
insertion-sort(slice([6 2 4 9 1 9 4 5], 0, 8))
|
||||||
let text = bytes("INSERTIONSORT")
|
let str = bytes("INSERTIONSORT")
|
||||||
insertion-sort(text)
|
insertion-sort(str)
|
||||||
println(text)
|
println(str)
|
||||||
let text = bytes("SELECTIONSORT")
|
let str = bytes("SELECTIONSORT")
|
||||||
selection-sort(text)
|
selection-sort(str)
|
||||||
println(text)
|
println(str)
|
||||||
find-match("aababba", "abba")
|
find-match("aababba", "abba")
|
||||||
:-
|
:-
|
||||||
|
|||||||
@ -1479,11 +1479,21 @@ let () =
|
|||||||
|
|
||||||
(* ── dyn, and what it does not do yet ──────────────────────────── *)
|
(* ── dyn, and what it does not do yet ──────────────────────────── *)
|
||||||
|
|
||||||
(* The pairing rule's own refusal. A name that is also a type's has no good
|
(* The pairing rule's own refusal. A type-named parameter with no type after
|
||||||
reading — taken as written it is a parameter called [i64] — and the
|
it is a dyn parameter or a pair the wrong way round; the message names
|
||||||
likelier intent is a pair the wrong way round, which the message names. *)
|
both fixes. With a type after it there is one reading. *)
|
||||||
rejects_check "a parameter named after a type" "(defn f [i64 x] ())"
|
rejects_check "a parameter named after a type" "(defn f [i64 x] ())"
|
||||||
~needle:"cannot also be this parameter's name";
|
~needle:"no type follows this parameter called i64";
|
||||||
|
rejects_check "a last parameter named after a type" "(defn f [a i32 str] ())"
|
||||||
|
~needle:"Give it one, as [str str]";
|
||||||
|
accepts "a parameter named str with a type" "(defn f [str str] i32 (length str))";
|
||||||
|
accepts "a parameter named str of another type"
|
||||||
|
"(defn f [str [u8]] i32 (length str))";
|
||||||
|
accepts "a local named str" "(defn f [b [u8]] str (let [str (str b)] str))";
|
||||||
|
accepts "a field named str" "(defstruct P [str str]) (defn f [p P] str (.str p))";
|
||||||
|
rejects_check "a local named str is not the type at vec-new"
|
||||||
|
"(defn f [] i32 (let [str 1 v (vec-new str)] 0))"
|
||||||
|
~needle:"str here is the value named str and not the type";
|
||||||
|
|
||||||
(* M2 item 3 lifted the container-into-dyn refusal: a [(Vec T)], a slice or
|
(* M2 item 3 lifted the container-into-dyn refusal: a [(Vec T)], a slice or
|
||||||
a fixed array with an i64/f64/bool element now crosses as a VIEW rather
|
a fixed array with an i64/f64/bool element now crosses as a VIEW rather
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user