@@ -312,6 +312,13 @@ where
312312 let iTerm : Term ← ``(𝓘($eT, $eT))
313313 Term.elabTerm iTerm none
314314
315+ /-- Ensures that `e` is a function. Attempts to coerce `e` to a function if necessary. -/
316+ def ensureIsFunction (e : Expr) : MetaM Expr := do
317+ let ty ← whnf <|← instantiateMVars <|← inferType e
318+ if ty.isForall then return e else (← coerceToFunction? e).getDM <|
319+ throwError "Expected{indentD e}\n of type{indentD ty}\n to be a function, or to be coercible to \
320+ a function"
321+
315322/-- If the type of `e` is a non-dependent function between spaces `src` and `tgt`, try to find a
316323model with corners on both `src` and `tgt`. If successful, return both models.
317324
@@ -337,43 +344,7 @@ def findModels (e : Expr) (es : Option Expr) : TermElabM (Expr × Expr) := do
337344 the set {es} : {estype}"
338345 let tgtI ← findModel tgt (src, srcI)
339346 return (srcI, tgtI)
340- | _ =>
341- match_expr etype with
342- | OpenPartialHomeomorph src tgt _ _ =>
343- trace[Elab.DiffGeo.MDiff] m! "found a partial homeomorphism from { src} to { tgt} "
344- if tgt.hasLooseBVars then
345- -- TODO: try `T%` here, and if it works, add an interactive suggestion to use it
346- throwError "Term {e} is a dependent function, of type {etype}\n Hint: you can use the `T%` \
347- elaborator to convert a dependent function to a non-dependent one"
348- let srcI ← findModel src
349- if let some es := es then
350- let estype ← inferType es
351- /- Note: we use `isDefEq` here since persistent metavariable assignments in `src` and
352- `estype` are acceptable.
353- TODO: consider attempting to coerce `es` to a `Set`. -/
354- if !(← isDefEq estype <|← mkAppM ``Set #[src]) then
355- throwError "The domain {src} of {e} is not definitionally equal to the carrier type of \
356- the set {es} : {estype}"
357- let tgtI ← findModel tgt (src, srcI)
358- return (srcI, tgtI)
359- | PartialEquiv src tgt =>
360- trace[Elab.DiffGeo.MDiff] m! "found a partial equivalence from { src} to { tgt} "
361- if tgt.hasLooseBVars then
362- -- TODO: try `T%` here, and if it works, add an interactive suggestion to use it
363- throwError "Term {e} is a dependent function, of type {etype}\n Hint: you can use the `T%` \
364- elaborator to convert a dependent function to a non-dependent one"
365- let srcI ← findModel src
366- if let some es := es then
367- let estype ← inferType es
368- /- Note: we use `isDefEq` here since persistent metavariable assignments in `src` and
369- `estype` are acceptable.
370- TODO: consider attempting to coerce `es` to a `Set`. -/
371- if !(← isDefEq estype <|← mkAppM ``Set #[src]) then
372- throwError "The domain {src} of {e} is not definitionally equal to the carrier type of \
373- the set {es} : {estype}"
374- let tgtI ← findModel tgt (src, srcI)
375- return (srcI, tgtI)
376- | _ => throwError "Expected{indentD e}\n of type{indentD etype}\n to be a function"
347+ | _ => throwError "Expected{indentD e}\n of type{indentD etype}\n to be a function"
377348
378349end Elab
379350
@@ -384,7 +355,7 @@ trying to determine `I` and `J` from the local context.
384355The argument `x` can be omitted. -/
385356scoped elab :max "MDiffAt[" s:term "]" ppSpace f:term:arg : term => do
386357 let es ← Term.elabTerm s none
387- let ef ← Term.elabTerm f none
358+ let ef ← ensureIsFunction <|← Term.elabTerm f none
388359 let (srcI, tgtI) ← findModels ef es
389360 mkAppM ``MDifferentiableWithinAt #[srcI, tgtI, ef, es]
390361
0 commit comments