lean4-htt/tests/lean/run/coinductive_syntax.lean
Robert J. Simmons 5326530383
feat: suggestions for ambiguous dotted identifiers (#11555)
This PR scans the environment for viable replacements for a dotted
identifier (like `.zero`) and suggests concrete alternatives as
replacements.

## Example

```
#example .zero
```

Error message:
```
Invalid dotted identifier notation: The expected type of `.cons` could not be determined
```

Additional hint added by this PR:
```
Hint: Using one of these would be unambiguous:
  [apply] `BitVec.cons`
  [apply] `List.cons`
  [apply] `List.Lex.cons`
  [apply] `List.Pairwise.cons`
  [apply] `List.Perm.cons`
  [apply] `List.Sublist.cons`
  [apply] `List.Lex.below.cons`
  [apply] `List.Pairwise.below.cons`
  [apply] `List.Perm.below.cons`
  [apply] `List.Sublist.below.cons`
  [apply] `Lean.Grind.AC.Seq.cons`
```

## Additional changes

This PR also brings several related error message descriptions and code
actions more in line with each other, changing several "Suggested
replacement: " code actions to the more common "Change to " wording, and
sorts suggestions obtained from searching the context by the default
sort for Names (which prefers names with fewer segments).
2025-12-09 17:27:22 +00:00

265 lines
7.9 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- set_option trace.Elab.coinductive true
set_option pp.proofs true
section
variable (α : Type)
/--
docstring
-/
coinductive infSeq (r : αα → Prop) : α → Prop where
| step : r a b → infSeq r b → infSeq r a
/--
info: infSeq.step (α : Type) (r : αα → Prop) {a b : α} : r a b → infSeq α r b → infSeq α r a
-/
#guard_msgs in
#check infSeq.step
theorem casesOnTest (r : αα → Prop) (a : α) : infSeq α r a → ∃ b, r a b := by
intro h
cases h
case step b _ hr => exists b
-- `match` support does not work yet
/--
error: Invalid pattern: Expected a constructor or constant marked with `[match_pattern]`
Hint: Using one of these would be valid:
[apply] `Nat.le.step`
[apply] `Nat.le.below.step`
[apply] `Lean.Order.iterates.below.step`
[apply] `Lean.Order.iterates.step`
[apply] `infSeq._functor.step`
---
error: Case tag `rhs` not found.
Note: There are no cases to select.
-/
#guard_msgs in
theorem casesOnTest' (r : αα → Prop) (a : α) : infSeq α r a → ∃ b, r a b := by
intro h
match h with
| step b _ hr => exists b
/--
info: infSeq.casesOn (α : Type) (r : αα → Prop) {motive : (a : α) → infSeq α r a → Prop} {a✝ : α} (t : infSeq α r a✝)
(step : ∀ {a b : α} (a_1 : r a b) (a_2 : infSeq α r b), motive a (infSeq.step α r a_1 a_2)) : motive a✝ t
-/
#guard_msgs in
#check infSeq.casesOn
/--
info: infSeq.functor_unfold (α : Type) (r : αα → Prop) (a✝ : α) : infSeq α r a✝ = infSeq._functor α r (infSeq α r) a✝
-/
#guard_msgs in
#check infSeq.functor_unfold
/-- info: infSeq (α : Type) (r : αα → Prop) : α → Prop -/
#guard_msgs in
#check infSeq
/--
info: inductive infSeq._functor : (α : Type) → (αα → Prop) → (α → Prop) → α → Prop
number of parameters: 3
constructors:
infSeq._functor.step : ∀ (α : Type) (r : αα → Prop) (infSeq._functor.call : α → Prop) {a b : α},
r a b → infSeq._functor.call b → infSeq._functor α r infSeq._functor.call a
-/
#guard_msgs in
#print infSeq._functor
/--
info: def infSeq._functor.existential : (α : Type) → (αα → Prop) → (α → Prop) → α → Prop :=
fun α r infSeq._functor.call a => ∃ b, r a b ∧ infSeq._functor.call b
-/
#guard_msgs in
#print infSeq._functor.existential
/--
info: infSeq._functor.existential_equiv (α : Type) (r : αα → Prop) (infSeq._functor.call : α → Prop) (a✝ : α) :
infSeq._functor α r infSeq._functor.call a✝ ↔ ∃ b, r a✝ b ∧ infSeq._functor.call b
-/
#guard_msgs in
#check infSeq._functor.existential_equiv
/--
info: infSeq.coinduct (α : Type) (r : αα → Prop) (pred : α → Prop) (hyp : ∀ (a : α), pred a → ∃ b, r a b ∧ pred b)
(a✝ : α) : pred a✝ → infSeq α r a✝
-/
#guard_msgs in
#check infSeq.coinduct
/--
info: infSeq.step (α : Type) (r : αα → Prop) {a b : α} : r a b → infSeq α r b → infSeq α r a
-/
#guard_msgs in
#check infSeq.step
end
section
mutual
coinductive tick : Prop where
| mk : ¬tock → tick
inductive tock : Prop where
| mk : ¬tick → tock
end
/--
info: tick._functor.casesOn {tick._functor.call tock._functor.call : Prop}
{motive_1 : tick._functor tick._functor.call tock._functor.call → Prop}
(t : tick._functor tick._functor.call tock._functor.call)
(mk : ∀ (a : ¬tock._functor.call), motive_1 (tick._functor.mk tick._functor.call tock._functor.call a)) : motive_1 t
-/
#guard_msgs in
#check tick._functor.casesOn
/-- info: tick.mk : ¬tock → tick -/
#guard_msgs in
#check tick.mk
/-- info: tock.mk : ¬tick → tock -/
#guard_msgs in
#check tock.mk
/-- info: tock._functor (tick._functor.call tock._functor.call : Prop) : Prop -/
#guard_msgs in
#check tock._functor
/-- info: tock._functor.existential (tick._functor.call tock._functor.call : Prop) : Prop -/
#guard_msgs in
#check tock._functor.existential
/--
info: tick.coinduct (pred_1 pred_2 : Prop) (hyp_1 : pred_1 → pred_2 → False) (hyp_2 : (pred_1 → False) → pred_2) :
pred_1 → tick
-/
#guard_msgs in
#check tick.coinduct
/--
info: tock._functor.existential_equiv (tick._functor.call tock._functor.call : Prop) :
tock._functor tick._functor.call tock._functor.call ↔ ¬tick._functor.call
-/
#guard_msgs in
#check tock._functor.existential_equiv
/--
info: tock.induct (pred_1 pred_2 : Prop) (hyp_1 : pred_1 → pred_2 → False) (hyp_2 : (pred_1 → False) → pred_2) : tock → pred_2
-/
#guard_msgs in
#check tock.induct
/--
info: tick.mutual_induct (pred_1 pred_2 : Prop) (hyp_1 : pred_1 → pred_2 → False) (hyp_2 : (pred_1 → False) → pred_2) :
(pred_1 → tick) ∧ (tock → pred_2)
-/
#guard_msgs in
#check tick.mutual_induct
end
/-- error: `coinductive` keyword can only be used to define predicates -/
#guard_msgs in
coinductive my_nat where
| zero : my_nat
| succ : my_nat → my_nat
def Set := Nat → Prop
coinductive Foo : Set where
/--
info: Foo.coinduct (pred : Set) (hyp : ∀ (a : Nat), pred a → False) (a✝ : Nat) : pred a✝ → Foo a✝
-/
#guard_msgs in
#check Foo.coinduct
coinductive Bar : Set where
| make : Bar 42
/--
info: Bar.coinduct (pred : Set) (hyp : ∀ (a : Nat), pred a → a = 42) (a✝ : Nat) : pred a✝ → Bar a✝
-/
#guard_msgs in
#check Bar.coinduct
coinductive dependentTest : (n : Nat) → (Vector α n) → Prop where
| mk (x : α) : dependentTest m v → dependentTest (m+1) (v.push x)
/--
info: dependentTest.coinduct.{u_1} {α : Type u_1} (pred : (n : Nat) → Vector α n → Prop)
(hyp : ∀ (n : Nat) (a : Vector α n), pred n a → ∃ m v x, pred m v ∧ n = m + 1 ∧ a ≍ v.push x) (n : Nat)
(a✝ : Vector α n) : pred n a✝ → dependentTest n a✝
-/
#guard_msgs in
#check dependentTest.coinduct
/-
Duplicated parameters and dependent types
-/
coinductive dependentTest2 : (n : Nat) → (m : Nat) → (Vector α (m + n)) → (Vector α (m + n)) → Prop where
| mk (x : α) : dependentTest2 0 n v v → dependentTest2 0 (n + 1) (v.push x) (v.push x)
coinductive dependentTest3 : (α : Type) → (ls : List α) → (vec : Vector α ls.length) → (Vector α vec.size) → Prop where
| mk : dependentTest3 Nat [a] (Vector.singleton a) (Vector.singleton a)
| mk2 : dependentTest3 String ["hi"] (Vector.singleton b) (Vector.singleton c)
/--
info: dependentTest3.casesOn
{motive :
(α : Type) →
(ls : List α) → (vec : Vector α ls.length) → (a : Vector α vec.size) → dependentTest3 α ls vec a → Prop}
{α : Type} {ls : List α} {vec : Vector α ls.length} {a✝ : Vector α vec.size} (t : dependentTest3 α ls vec a✝)
(mk : ∀ {a : Nat}, motive Nat [a] (Vector.singleton a) (Vector.singleton a) dependentTest3.mk)
(mk2 : ∀ {b c : String}, motive String ["hi"] (Vector.singleton b) (Vector.singleton c) dependentTest3.mk2) :
motive α ls vec a✝ t
-/
#guard_msgs in
#check dependentTest3.casesOn
coinductive test1 (r: αα → Prop) : αα → Prop where
| mk : r a b → test1 r a b → test1 r a a
| mk2 : test1 r a a
coinductive test2 (r: αα → Prop) : αα → Prop where
| mk : r a b → test2 r b b → test2 r a a
/--
error: Cannot define an coinductive predicate and a constructor with the same name `A.mk`
---
error: Cannot define an coinductive predicate and a constructor with the same name `A.mk`
-/
#guard_msgs in
mutual
coinductive A : Prop where
| mk : A.mk → A
coinductive A.mk : Prop where
| mk : A → A.mk
end
macro "test%" : command => `(command|
coinductive MacroTest : Prop where | mk : MacroTest
)
/-- error: Coinductive predicates are not allowed inside of macro scopes -/
#guard_msgs in
test%
namespace unsafe_test
unsafe coinductive infSeq2 (r : αα → Prop) : α → Prop where
| step : r a b → infSeq2 r b → infSeq2 r a
end unsafe_test
/--
@ +4:14...20
error: `coinductive` keyword can only be used to define predicates
-/
#guard_msgs (positions := true) in
mutual
coinductive wrong1 : Prop where
coinductive wrong2 where
| zero : wrong2
| succ : wrong1 → wrong2
end