This commit is contained in:
Leonardo de Moura 2022-11-19 07:01:02 -08:00
parent 5e9767a283
commit a5ab59a413
3 changed files with 40 additions and 2 deletions

View file

@ -527,6 +527,33 @@ mutual
private partial def processExplictArg (argName : Name) : M Expr := do
match (← get).args with
| arg::args =>
unless (← get).namedArgs.isEmpty do
if (← anyNamedArgDependsOnCurrent) then
/-
We treat the explicit argument `argName` as implicit if we have named arguments that depend on it.
The idea is that this explicit argument can be inferred using the type of the named argument one.
Note that we also use this approach in the branch where there are no explicit arguments left.
This is important to make sure the system behaves in a uniform way.
Moreover, users rely on this behavior. For example, consider the example on issue #1851
```
class Approx {α : Type} (a : α) (X : Type) : Type where
val : X
variable {α β X Y : Type} {f' : α → β} {x' : α} [f : Approx f' (X → Y)] [x : Approx x' X]
#check f.val
#check f.val x.val
```
The type of `Approx.val` is `{α : Type} → (a : α) → {X : Type} → [self : Approx a X] → X`
Note that the argument `a` is explicit since there is no way to infer it from the expected
type or the type of other explicit arguments.
Recall that `f.val` is sugar for `Approx.val (self := f)`. In both `#check` commands above
the user assumed that `a` does not need to be provided since it can be inferred from the type
of `self`.
We used to that only in the branch where `(← get).args` was empty, but it created an asymmetry
because `#check f.val` worked as expected, but one would have to write `#check f.val _ x.val`
-/
return (← addImplicitArg argName)
propagateExpectedType arg
modify fun s => { s with args }
elabAndAddNewArg argName arg

View file

@ -26,7 +26,7 @@ def f7 (xs : Vec α n) : Nat :=
xs.casesOn (a := 10) 0 -- Error unused named args
def f8 (xs : List Nat) : xs ≠ [] → xs.length > 0 :=
@List.casesOn _ (motive := fun xs => xs ≠ [] → xs.length > 0) xs (by dsimp; intros; contradiction) (by dsimp; intros; simp_arith)
@List.casesOn _ (fun xs => xs ≠ [] → xs.length > 0) xs (by dsimp; intros; contradiction) (by dsimp; intros; simp_arith)
def f5' (xs : List Nat) (h : xs ≠ []) : xs.length > 0 :=
xs.casesOn (fun h => absurd rfl h) (fun _ _ _ => Nat.zero_lt_succ ..) h
@ -87,4 +87,3 @@ noncomputable def f : Nat → Nat :=
example : ∀ x, x ≥ 0 :=
Nat.rec (Nat.le_refl 0) (fun _ ih => Nat.le_succ_of_le ih)

12
tests/lean/run/1851.lean Normal file
View file

@ -0,0 +1,12 @@
class Approx {α : Type} (a : α) (X : Type) : Type where
val : X
variable {α β X Y : Type} {f' : α → β} {x' : α} [f : Approx f' (X → Y)] [x : Approx x' X]
-- fails
#check f.val x.val
-- works
#check let f'' := f.val
let x'' := x.val
f'' x''