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
|
||||
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]
|
||||
...)] has no good reading: taken as written it is a parameter called [i64],
|
||||
which shadows nothing but confuses everything, and the likelier intent is a
|
||||
pair written backwards. Refusing here costs a rename in the one program that
|
||||
meant it and closes the one place where this rule could still hand somebody
|
||||
a signature they did not write. *)
|
||||
A name that *is* a type name pairs only when a type follows it: [[str str]]
|
||||
has one reading. [(defn f [i64 x] ...)] has two — a dyn parameter called
|
||||
[i64], or a pair written backwards — so it is refused rather than handed
|
||||
back as a signature nobody wrote. *)
|
||||
let is_type_name env n =
|
||||
Types.ikind_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
|
||||
"a parameter's name was expected here, and this is a type. Parameters \
|
||||
are [name Type ...]"
|
||||
| Ast.Pname (n, loc) :: rest when is_type_name env n ->
|
||||
ignore rest;
|
||||
(* A parameter may share a type's name — [str] is a common name for text —
|
||||
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
|
||||
"%s names a type, so it cannot also be this parameter's name. Write \
|
||||
[name %s], or rename the parameter" n n
|
||||
"%s names a type, and no type follows this parameter called %s. Give \
|
||||
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. *)
|
||||
| Ast.Pname (n, _) :: Ast.Pname ("_", 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.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
|
||||
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
|
||||
@ -10440,6 +10459,7 @@ and vec_new_elem ctx ~want loc args =
|
||||
(match want with
|
||||
| Some (Types.Vec t) -> t, args
|
||||
| _ ->
|
||||
shadowed_type_arg ctx loc "vec-new" args;
|
||||
fail loc
|
||||
"nothing here says what (vec-new) is a Vec of — write the element \
|
||||
type, as (vec-new i32)")
|
||||
@ -10530,6 +10550,7 @@ and map_new_types ctx ~want loc args =
|
||||
(match want with
|
||||
| Some (Types.Map (k, v)) -> k, v, args
|
||||
| _ ->
|
||||
shadowed_type_arg ctx loc "map-new" args;
|
||||
fail loc
|
||||
"nothing here says what (map-new) maps — write the key and value \
|
||||
types, as (map-new str i32)")
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
(import agent "vendor:agent")
|
||||
|
||||
(defn find-match [text str pattern str] i32
|
||||
(dotimes [i (length text)]
|
||||
(defn find-match [str str pattern str] i32
|
||||
(dotimes [i (length str)]
|
||||
(let [matched true]
|
||||
(dotimes [j (length pattern)]
|
||||
(when (!= (at text (+ i j)) (at pattern j))
|
||||
(when (!= (at str (+ i j)) (at pattern j))
|
||||
(set matched false)))
|
||||
(when matched
|
||||
(return i))))
|
||||
@ -41,11 +41,11 @@
|
||||
(comment
|
||||
(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))
|
||||
(let [text (bytes "INSERTIONSORT")]
|
||||
(insertion-sort text)
|
||||
(println text))
|
||||
(let [text (bytes "SELECTIONSORT")]
|
||||
(selection-sort text)
|
||||
(println text))
|
||||
(let [str (bytes "INSERTIONSORT")]
|
||||
(insertion-sort str)
|
||||
(println str))
|
||||
(let [str (bytes "SELECTIONSORT")]
|
||||
(selection-sort str)
|
||||
(println str))
|
||||
(find-match "aababba" "abba")
|
||||
:-)
|
||||
|
||||
@ -3,11 +3,11 @@
|
||||
|
||||
import agent "vendor:agent"
|
||||
|
||||
fn find-match(text: str, pattern: str) -> i32
|
||||
for i in range(length(text))
|
||||
fn find-match(str: str, pattern: str) -> i32
|
||||
for i in range(length(str))
|
||||
let matched = true
|
||||
for j in range(length(pattern))
|
||||
if text[i + j] != pattern[j]
|
||||
if str[i + j] != pattern[j]
|
||||
matched = false
|
||||
if matched
|
||||
return i
|
||||
@ -42,11 +42,11 @@ fn main() -> i32 = 0
|
||||
comment():
|
||||
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))
|
||||
let text = bytes("INSERTIONSORT")
|
||||
insertion-sort(text)
|
||||
println(text)
|
||||
let text = bytes("SELECTIONSORT")
|
||||
selection-sort(text)
|
||||
println(text)
|
||||
let str = bytes("INSERTIONSORT")
|
||||
insertion-sort(str)
|
||||
println(str)
|
||||
let str = bytes("SELECTIONSORT")
|
||||
selection-sort(str)
|
||||
println(str)
|
||||
find-match("aababba", "abba")
|
||||
:-
|
||||
|
||||
@ -1479,11 +1479,21 @@ let () =
|
||||
|
||||
(* ── 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
|
||||
reading — taken as written it is a parameter called [i64] — and the
|
||||
likelier intent is a pair the wrong way round, which the message names. *)
|
||||
(* The pairing rule's own refusal. A type-named parameter with no type after
|
||||
it is a dyn parameter or a pair the wrong way round; 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] ())"
|
||||
~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
|
||||
a fixed array with an i64/f64/bool element now crosses as a VIEW rather
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user