@@ -151,17 +151,24 @@ private partial def elabChoiceAux (cmds : Array Syntax) (i : Nat) : CommandElabM
151
151
open Lean.Parser.Term
152
152
153
153
private def typelessBinder? : Syntax → Option (Array (TSyntax [`ident, `Lean.Parser.Term.hole]) × BinderInfo)
154
- | `(bracketedBinderF|($ids*)) => some (ids, .default)
155
- | `(bracketedBinderF|{$ids*}) => some (ids, .implicit)
156
- | `(bracketedBinderF|⦃$ids*⦄) => some (ids, .strictImplicit)
157
- | _ => none
154
+ | `(bracketedBinderF|($ids*)) => some (ids, .default)
155
+ | `(bracketedBinderF|{$ids*}) => some (ids, .implicit)
156
+ | `(bracketedBinderF|⦃$ids*⦄) => some (ids, .strictImplicit)
157
+ | `(bracketedBinderF|[$id:ident]) => some (#[id], .instImplicit)
158
+ | _ => none
158
159
159
160
/-- If `id` is an identifier, return true if `ids` contains `id`. -/
160
161
private def containsId (ids : Array (TSyntax [`ident, ``Parser.Term.hole])) (id : TSyntax [`ident, ``Parser.Term.hole]) : Bool :=
161
162
id.raw.isIdent && ids.any fun id' => id'.raw.getId == id.raw.getId
162
163
164
+ /-- Elaborates `binders` using `withSynthesize` and `withAutoBoundImplicit`. -/
165
+ private def elabBindersSynthesizingAutoBound (binders : TSyntaxArray ``bracketedBinder) :=
166
+ runTermElabM fun _ => Term.withSynthesize <| Term.withAutoBoundImplicit <|
167
+ Term.elabBinders binders fun _ => pure ()
168
+
163
169
/--
164
- Auxiliary method for processing binder annotation update commands: `variable (α)` and `variable {α}`.
170
+ Auxiliary method for processing binder annotation update commands:
171
+ `variable (α)`, `variable {α}`, `variable ⦃α⦄`, and `variable [α]`.
165
172
The argument `binder` is the binder of the `variable` command.
166
173
The method returns an array containing the "residue", that is, variables that do not correspond to updates.
167
174
Recall that a `bracketedBinder` can be of the form `(x y)`.
@@ -211,12 +218,22 @@ private def replaceBinderAnnotation (binder : TSyntax ``Parser.Term.bracketedBin
211
218
| .implicit => `(bracketedBinderF| {$id $[: $ty?]?})
212
219
| .strictImplicit => `(bracketedBinderF| {{$id $[: $ty?]?}})
213
220
| .instImplicit => do
214
- let some ty := ty? | throwErrorAt id "instance-implicit binders must provide an explicit type"
221
+ let some ty := ty?
222
+ | throwErrorAt binder "cannot update binder annotation of variable `{id}` to instance-implicit:\n \
223
+ variable was originally declared without an explicit type"
215
224
`(bracketedBinderF| [$(⟨id⟩) : $ty])
216
225
for id in ids.reverse do
217
226
if let some idx := binderIds.findFinIdx? fun binderId => binderId.raw.isIdent && binderId.raw.getId == id.raw.getId then
218
227
binderIds := binderIds.eraseIdx idx
219
228
modifiedVarDecls := true
229
+ let newBinder ← mkBinder id binderInfo
230
+ if binderInfo.isInstImplicit then
231
+ -- We elaborate the new binder to make sure it's valid as instance-implicit
232
+ try
233
+ elabBindersSynthesizingAutoBound #[newBinder]
234
+ catch e =>
235
+ throwErrorAt binder m!"cannot update binder annotation of variable `{id}` to instance-implicit:\n \
236
+ {e.toMessageData}"
220
237
varDeclsNew := varDeclsNew.push (← mkBinder id binderInfo)
221
238
else
222
239
varDeclsNew := varDeclsNew.push (← mkBinder id binderInfo')
@@ -228,16 +245,15 @@ private def replaceBinderAnnotation (binder : TSyntax ``Parser.Term.bracketedBin
228
245
| .default => `(bracketedBinderF| ($binderId))
229
246
| .implicit => `(bracketedBinderF| {$binderId})
230
247
| .strictImplicit => `(bracketedBinderF| {{$binderId}})
231
- | .instImplicit => throwErrorAt binderId "instance-implicit binders must provide an explicit type"
248
+ | .instImplicit => throwUnsupportedSyntax
232
249
else
233
250
return #[binder]
234
251
235
252
@[builtin_command_elab «variable»] def elabVariable : CommandElab
236
253
| `(variable $binders*) => do
237
254
let binders ← binders.flatMapM replaceBinderAnnotation
238
255
-- Try to elaborate `binders` for sanity checking
239
- runTermElabM fun _ => Term.withSynthesize <| Term.withAutoBoundImplicit <|
240
- Term.elabBinders binders fun _ => pure ()
256
+ elabBindersSynthesizingAutoBound binders
241
257
-- Remark: if we want to produce error messages when variables shadow existing ones, here is the place to do it.
242
258
for binder in binders do
243
259
let varUIds ← (← getBracketedBinderIds binder) |>.mapM (withFreshMacroScope ∘ MonadQuotation.addMacroScope)
0 commit comments