This PR refines several error error messages, mostly involving invalid
use of field notation, generalized field notation, and numeric
projection. Provides a new error explanation for field notation.
## Error message changes
In general:
- Uses a slightly different convention for expression-type pairs, where
the expression is always given `indentExpr` and the type is given
`inlineExpr` treatment. This is something of a workaround for the fact
that the `Format` type is awkward for embedding possibly-linebreaking
expressions in not-linebreaking text, which may be a separate issue
worth addressing.
- Tries to give slightly more "why" reasoning — the environment does not
contain `String.parse`, and _therefore you can't project `.parse` from a
`String`_.
Some specific examples:
### No such projection function
```lean4
#check "".parse
```
before:
```
error: Invalid field `parse`: The environment does not contain `String.parse`
""
has type
String
```
after:
```
error: Invalid field `parse`: The environment does not contain `String.parse`, so it is not possible to project the field `parse` from an expression
""
of type `String`
```
### Type does not have the correct form
```lean4
example (x : α) := (foo x).foo
```
before:
```
error: Invalid field notation: Type is not of the form `C ...` where C is a constant
foo x
has type
α
```
after:
```
error: Invalid field notation: Field projection operates on types of the form `C ...` where C is a constant. The expression
foo x
has type `α` which does not have the necessary form.
```
## Refactoring
Includes some refactoring changes as well:
- factors out multiple uses of number (1, 2, 3, 212, 222) to ordinal
("first", "second", "third", "212th", "222nd") conversion into
Lean.Elab.ErrorUtils
- significant refactoring of `resolveLValAux` in `Lean.Elab.App` — in
place of five helper functions, a special-case function case analysis,
and a case analysis on the projection type and structure, there's now a
single case analysis on the projection type and structure. This allows
several error messages to be more explicit (there were a number of cases
where index projection was being described as field projection in an
error messages) and gave the opportunity to slightly improve positining
for several errors: field *notation* errors should appear on `foo.bar`,
but field *projection* errors should appear only on the `bar` part of
`foo.bar`.
80 lines
2.5 KiB
Text
80 lines
2.5 KiB
Text
/-!
|
||
# Hints for invalid tuple projections
|
||
|
||
These tests assess hints for invalid projections that may be incorrectly attempting to project the
|
||
`n`th element from a tuple where `n > 2`.
|
||
-/
|
||
|
||
def p : Nat × Nat × Nat := (3, 4, 5)
|
||
/--
|
||
error: Invalid projection: Index `3` is invalid for this structure; it must be between 1 and 2
|
||
|
||
Note: The expression
|
||
p
|
||
has type `Nat × Nat × Nat` which has only 2 fields
|
||
|
||
Hint: n-tuples in Lean are actually nested pairs. To access the third component of this tuple, use the projection `.2.2` instead:
|
||
3̵2̲.̲2̲
|
||
-/
|
||
#guard_msgs in
|
||
#check p.3
|
||
|
||
/--
|
||
error: Invalid projection: Index `17` is invalid for this structure; it must be between 1 and 2
|
||
|
||
Note: The expression
|
||
p
|
||
has type `Nat × Nat × Nat` which has only 2 fields
|
||
|
||
Hint: n-tuples in Lean are actually nested pairs. For example, to access the "third" component of `(a, b, c)`, write `(a, b, c).2.2` instead of `(a, b, c).3`.
|
||
-/
|
||
#guard_msgs in
|
||
#check p.17
|
||
|
||
/--
|
||
error: Invalid projection: Index `3` is invalid for this structure; it must be between 1 and 2
|
||
|
||
Note: The expression
|
||
p
|
||
has type `Nat × Nat × Nat` which has only 2 fields
|
||
|
||
Hint: n-tuples in Lean are actually nested pairs. To access the third component of this tuple, use the projection `.2.2` instead:
|
||
3̵2̲.̲2̲
|
||
-/
|
||
#guard_msgs in
|
||
#check p.3.succ
|
||
|
||
/-
|
||
In prior versions of Lean, the below would erroneously produce two error messages: "structure type
|
||
expected" on the first lval resolution iteration (prior to unfolding `MyProd`), then (correctly)
|
||
"invalid index" on the second, post-unfolding iteration
|
||
-/
|
||
abbrev MyProd := Nat × Nat × Nat × Nat × Nat
|
||
def mp : MyProd := (1, 2, 3, 4, 5)
|
||
/--
|
||
error: Invalid projection: Index `4` is invalid for this structure; it must be between 1 and 2
|
||
|
||
Note: The expression
|
||
mp
|
||
has type `Nat × Nat × Nat × Nat × Nat` which has only 2 fields
|
||
|
||
Hint: n-tuples in Lean are actually nested pairs. To access the fourth component of this tuple, use the projection `.2.2.2.1` instead:
|
||
4̵2̲.̲2̲.̲2̲.̲1̲
|
||
-/
|
||
#guard_msgs in
|
||
#eval mp.4
|
||
|
||
-- Ensure we don't produce hints for synthetic syntax
|
||
macro "illegally_project_from_a_tuple" : term => `((true, true, false).3)
|
||
|
||
/--
|
||
error: Invalid projection: Index `3` is invalid for this structure; it must be between 1 and 2
|
||
|
||
Note: The expression
|
||
(true, true, false)
|
||
has type `Bool × Bool × Bool` which has only 2 fields
|
||
|
||
Hint: n-tuples in Lean are actually nested pairs. For example, to access the "third" component of `(a, b, c)`, write `(a, b, c).2.2` instead of `(a, b, c).3`.
|
||
-/
|
||
#guard_msgs in
|
||
#check illegally_project_from_a_tuple
|