Skip to content

Commit ddf53ab

Browse files
committed
chore: move T% notation to the Topology folder
1 parent 24bf43f commit ddf53ab

File tree

2 files changed

+173
-0
lines changed

2 files changed

+173
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7879,6 +7879,7 @@ public import Mathlib.Topology.VectorBundle.Basic
78797879
public import Mathlib.Topology.VectorBundle.Constructions
78807880
public import Mathlib.Topology.VectorBundle.FiniteDimensional
78817881
public import Mathlib.Topology.VectorBundle.Hom
7882+
public import Mathlib.Topology.VectorBundle.Notation
78827883
public import Mathlib.Topology.VectorBundle.Riemannian
78837884
public import Mathlib.Util.AddRelatedDecl
78847885
public import Mathlib.Util.AliasIn
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/-
2+
Copyright (c) 2025 Patrick Massot. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Patrick Massot, Michael Rothgang, Thomas Murrills
5+
-/
6+
module
7+
8+
-- TODO: minimise!
9+
public import Mathlib.Geometry.Manifold.ContMDiff.Defs
10+
--public import Mathlib.Topology.VectorBundle.Basic -- new
11+
public import Mathlib.Geometry.Manifold.MFDeriv.Defs
12+
13+
/-!
14+
# Notation for Elaborators for differential geometry
15+
16+
This file defines custom notation for vector bundles: we introduce an elaborator `T%` to ease
17+
working with sections in a fibre bundle, scoped to the `Bundle` namespace.
18+
19+
It converts a section `s : Π x : B, V x` to a non-dependent function into the total space of the
20+
bundle. (Mathematically, this is the same as post-composing with the inclusion map from each fiber
21+
into the total space.)
22+
```lean
23+
-- omitted: let `V` be a fibre bundle over `B`
24+
25+
variable {σ : Π x : B, V x} in
26+
#check T% σ -- `(fun x ↦ TotalSpace.mk' F x (σ x)) : M → TotalSpace F V`
27+
28+
-- Note how the name of the bound variable `x` is preserved.
29+
variable {σ : (x : E) → Trivial E E' x} in
30+
#check T% σ -- `(fun x ↦ TotalSpace.mk' E' x (σ x)) : E → TotalSpace E' (Trivial E E')`
31+
32+
variable {s : E → E'} in
33+
#check T% s -- `(fun a ↦ TotalSpace.mk' E' a (s a)) : E → TotalSpace E' (Trivial E E')`
34+
```
35+
36+
-/
37+
38+
public meta section
39+
40+
open scoped Bundle
41+
42+
open Lean Meta Elab Tactic
43+
open Mathlib.Tactic
44+
open Qq
45+
46+
namespace Bundle.Elab
47+
48+
/- Note: these functions are convenient in this file, and may be convenient elsewhere, but their
49+
precise behavior should be considered before adding them to the meta API. -/
50+
51+
/-- Finds the first local instance of class `c` for which `p inst type` produces `some a`.
52+
Instantiates mvars in and runs `whnfR` on `type` before passing it to `p`. (Does not validate that
53+
`c` resolves to a class.) -/
54+
private def findSomeLocalInstanceOf? (c : Name) {α} (p : Expr → Expr → MetaM (Option α)) :
55+
MetaM (Option α) := do
56+
(← getLocalInstances).findSomeM? fun inst ↦ do
57+
if inst.className == c then
58+
let type ← whnfR <| ← instantiateMVars <| ← inferType inst.fvar
59+
p inst.fvar type
60+
else return none
61+
62+
/-- Finds the most recent local declaration for which `p fvar type` produces `some a`.
63+
Skips implementation details; instantiates mvars in and runs `whnfR` on `type` before providing it
64+
to `p`. -/
65+
private def findSomeLocalHyp? {α} (p : Expr → Expr → MetaM (Option α)) : MetaM (Option α) := do
66+
(← getLCtx).findDeclRevM? fun decl ↦ do
67+
if decl.isImplementationDetail then return none
68+
let type ← whnfR <| ← instantiateMVars decl.type
69+
p decl.toExpr type
70+
71+
/--
72+
Utility for sections in a fibre bundle: if an expression `e` is a section
73+
`s : Π x : M, V x` as a dependent function, convert it to a non-dependent function into the total
74+
space. This handles the cases of
75+
- sections of a trivial bundle
76+
- vector fields on a manifold (i.e., sections of the tangent bundle)
77+
- sections of an explicit fibre bundle
78+
- turning a bare function `E → E'` into a section of the trivial bundle `Bundle.Trivial E E'`
79+
80+
This searches the local context for suitable hypotheses for the above cases by matching
81+
on the expression structure, avoiding `isDefEq`. Therefore, it should be fast enough to always run.
82+
This process can be traced with `set_option Elab.Bundle.TotalSpaceMk true`.
83+
84+
All applications of `e` in the resulting expression are beta-reduced.
85+
If none of the handled cases apply, we simply return `e` (after beta-reducing).
86+
87+
This function is used for implementing the `T%` elaborator.
88+
-/
89+
-- TODO: document how this elaborator works, any gotchas, etc.
90+
def totalSpaceMk (e : Expr) : MetaM Expr := do
91+
let etype ← whnf <| ← instantiateMVars <| ← inferType e
92+
match etype with
93+
| .forallE x base tgt _ => withLocalDeclD x base fun x ↦ do
94+
let tgtHasLooseBVars := tgt.hasLooseBVars
95+
let tgt := tgt.instantiate1 x
96+
-- Note: we do not run `whnfR` on `tgt` because `Bundle.Trivial` is reducible.
97+
match_expr tgt with
98+
| Bundle.Trivial E E' _ =>
99+
trace[Elab.Bundle.TotalSpaceMk] "`{e}` is a section of `Bundle.Trivial {E} {E'}`"
100+
-- Note: we allow `isDefEq` here because any mvar assignments should persist.
101+
if ← withReducible (isDefEq E base) then
102+
let body ← mkAppM ``Bundle.TotalSpace.mk' #[E', x, (e.app x).headBeta]
103+
mkLambdaFVars #[x] body
104+
else return e
105+
| TangentSpace _k _ E _ _ _H _ _I M _ _ _x =>
106+
trace[Elab.Bundle.TotalSpaceMk] "`{e}` is a vector field on `{M}`"
107+
let body ← mkAppM ``Bundle.TotalSpace.mk' #[E, x, (e.app x).headBeta]
108+
mkLambdaFVars #[x] body
109+
| _ => match (← instantiateMVars tgt).cleanupAnnotations with
110+
| .app V _ =>
111+
trace[Elab.Bundle.TotalSpaceMk] "Section of a bundle as a dependent function"
112+
let f? ← findSomeLocalInstanceOf? `FiberBundle fun _ declType ↦
113+
/- Note: we do not use `match_expr` here since that would require importing
114+
`Mathlib.Topology.FiberBundle.Basic` to resolve `FiberBundle`. -/
115+
match declType with
116+
| mkApp7 (.const `FiberBundle _) _ F _ _ E _ _ => do
117+
if ← withReducible (pureIsDefEq E V) then
118+
let body ← mkAppM ``Bundle.TotalSpace.mk' #[F, x, (e.app x).headBeta]
119+
some <$> mkLambdaFVars #[x] body
120+
else return none
121+
| _ => return none
122+
return f?.getD e.headBeta
123+
| tgt =>
124+
trace[Elab.Bundle.TotalSpaceMk] "Section of a trivial bundle as a non-dependent function"
125+
-- TODO: can `tgt` depend on `x` in a way that is not a function application?
126+
-- Check that `x` is not a bound variable in `tgt`!
127+
if tgtHasLooseBVars then
128+
throwError "Attempted to fall back to creating a section of the trivial bundle out of \
129+
(`{e}` : `{etype}`) as a non-dependent function, but return type `{tgt}` depends on the
130+
bound variable (`{x}` : `{base}`).\n\
131+
Hint: applying the `T%` elaborator twice makes no sense."
132+
let trivBundle ← mkAppOptM ``Bundle.Trivial #[base, tgt]
133+
let body ← mkAppOptM ``Bundle.TotalSpace.mk' #[base, trivBundle, tgt, x, (e.app x).headBeta]
134+
mkLambdaFVars #[x] body
135+
| _ => return e.headBeta
136+
137+
end Elab
138+
139+
open Elab in
140+
/--
141+
Elaborator for sections in a fibre bundle: converts a section `s : Π x : M, V x` as a dependent
142+
function to a non-dependent function into the total space. This handles the cases of
143+
- sections of a trivial bundle
144+
- vector fields on a manifold (i.e., sections of the tangent bundle)
145+
- sections of an explicit fibre bundle
146+
- turning a bare function `E → E'` into a section of the trivial bundle `Bundle.Trivial E E'`
147+
148+
This elaborator searches the local context for suitable hypotheses for the above cases by matching
149+
on the expression structure, avoiding `isDefEq`. Therefore, it should be fast enough to always run.
150+
The search can be traced with `set_option Elab.Bundle.TotalSpaceMk true`.
151+
-/
152+
scoped elab:max "T% " t:term:arg : term => do
153+
totalSpaceMk (← Term.elabTerm t none)
154+
155+
end Bundle
156+
157+
section trace
158+
159+
/-!
160+
### Trace classes
161+
162+
Note that the overall `Elab` trace class does not inherit the trace classes defined in this
163+
section, since they provide verbose information.
164+
-/
165+
166+
/--
167+
Trace class for the `T%` elaborator, which converts a section of a vector bundle as a dependent
168+
function to a non-dependent function into the total space.
169+
-/
170+
initialize registerTraceClass `Elab.Bundle.TotalSpaceMk
171+
172+
end trace

0 commit comments

Comments
 (0)