Skip to content

Commit a6c72be

Browse files
kim-emdigama0
andcommitted
feat: to_additive calls addDeclarationRanges (#461)
Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Mario Carneiro <di.gama@gmail.com>
1 parent 458330e commit a6c72be

File tree

2 files changed

+43
-26
lines changed

2 files changed

+43
-26
lines changed

Mathlib/Tactic/ToAdditive.lean

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Mathlib.Lean.Expr.ReplaceRec
1010
import Mathlib.Lean.Expr
1111
import Lean
1212
import Lean.Data
13+
import Lean.Elab.Term
1314
import Std.Lean.NameMapAttribute
1415

1516
/-!
@@ -166,7 +167,7 @@ def applyReplacementFun : Expr → MetaM Expr :=
166167
Lean.Expr.replaceRecMeta fun r e => do
167168
trace[to_additive_detail] "applyReplacementFun: replace at {e}"
168169
match e with
169-
| .lit (.natVal 1) => pure <| mkNatLit 0
170+
| .lit (.natVal 1) => pure <| mkRawNatLit 0
170171
| .const n₀ ls => do
171172
let n₁ := Name.mapPrefix (findTranslation? <|← getEnv) n₀
172173
trace[to_additive_detail] "applyReplacementFun: {n₀} → {n₁}"
@@ -258,15 +259,14 @@ using the transforms dictionary.
258259
`pre` is the declaration that got the `@[to_additive]` attribute and `tgt_pre` is the target of this
259260
declaration. -/
260261
partial def transformDeclAux
261-
(pre tgt_pre : Name) : Name → CoreM Unit := fun src => do
262+
(ref : Option Syntax) (pre tgt_pre : Name) : Name → CoreM Unit := fun src => do
262263
-- if this declaration is not `pre` or an internal declaration, we do nothing.
263264
if not (src == pre || isInternal' src) then
264265
if (findTranslation? (← getEnv) src).isSome then
265-
return ()
266-
else throwError
267-
("The declaration {pre} depends on the declaration {src} which is in the namespace {pre}," ++
268-
" but does not have the `@[to_additive]` attribute. This is not supported. " ++
269-
"Workaround: move {src} to a different namespace.")
266+
return
267+
throwError "The declaration {pre} depends on the declaration {src} which is in the namespace {
268+
pre}, but does not have the `@[to_additive]` attribute. This is not supported.\n{""
269+
}Workaround: move {src} to a different namespace."
270270
let env ← getEnv
271271
-- we find the additive name of `src`
272272
let tgt := src.mapPrefix (fun n => if n == pre then some tgt_pre else none)
@@ -276,10 +276,10 @@ partial def transformDeclAux
276276
let srcDecl ← getConstInfo src
277277
-- we first transform all the declarations of the form `pre._proof_i`
278278
for n in srcDecl.type.listNamesWithPrefix pre do
279-
transformDeclAux pre tgt_pre n
279+
transformDeclAux none pre tgt_pre n
280280
if let some value := srcDecl.value? then
281281
for n in value.listNamesWithPrefix pre do
282-
transformDeclAux pre tgt_pre n
282+
transformDeclAux none pre tgt_pre n
283283
-- now transform the source declaration
284284
let trgDecl : ConstantInfo ← MetaM.run' $ updateDecl tgt srcDecl
285285
if ¬ trgDecl.hasValue then
@@ -296,6 +296,18 @@ partial def transformDeclAux
296296
Failed to add declaration\n{trgDecl.name}:\n{msg}"
297297
| _ => panic! "unreachable"
298298
addAndCompile trgDecl.toDeclaration!
299+
-- now add declaration ranges so jump-to-definition works
300+
addDeclarationRanges tgt {
301+
range := ← getDeclarationRange (← getRef)
302+
selectionRange := ← getDeclarationRange (ref.getD (← getRef))
303+
}
304+
if let some ref := ref then
305+
-- TODO: make a function for this
306+
pushInfoLeaf <| .ofTermInfo {
307+
elaborator := .anonymous, lctx := {}, expectedType? := none
308+
stx := ref, isBinder := true
309+
expr := ← mkConstWithLevelParams trgDecl.name
310+
}
299311
if isProtected (← getEnv) src then
300312
setEnv $ addProtected (← getEnv) tgt
301313

@@ -308,34 +320,33 @@ allow us to iterate the attributes applied to a given decalaration.
308320
-/
309321
def copyAttributes (src tgt : Name) : CoreM Unit := do
310322
-- [todo] other simp theorems
311-
let some ext ← getSimpExtension? `simp | return ()
323+
let some ext ← getSimpExtension? `simp | return
312324
let thms ← ext.getTheorems
313325
if (¬ thms.isLemma (.decl src)) || thms.isLemma (.decl tgt) then
314-
return ()
326+
return
315327
-- [todo] how to get prio data from SimpTheorems?
316-
MetaM.run' $ Lean.Meta.addSimpTheorem ext tgt
328+
Lean.Meta.addSimpTheorem ext tgt
317329
(post := true)
318330
(inv := false)
319331
(attrKind := AttributeKind.global)
320-
(prio := 1000)
321-
return ()
332+
(prio := 1000) |>.run'
322333

323334
/--
324335
Make a new copy of a declaration, replacing fragments of the names of identifiers in the type and
325336
the body using the `translations` dictionary.
326337
This is used to implement `@[to_additive]`.
327338
-/
328-
def transformDecl (src tgt : Name) : CoreM Unit := do
329-
transformDeclAux src tgt src
339+
def transformDecl (ref : Option Syntax) (src tgt : Name) : CoreM Unit := do
340+
transformDeclAux ref src tgt src
330341
let eqns? ← MetaM.run' (getEqnsFor? src true)
331342
-- now transform all of the equational lemmas
332343
if let some eqns := eqns? then
333344
for src_eqn in eqns do
334-
transformDeclAux src tgt src_eqn
345+
transformDeclAux none src tgt src_eqn
335346
-- [todo] copy attributes for equations
336347
-- [todo] add equation lemmas to tgt_eqn
337348
copyAttributes src tgt
338-
return ()
349+
339350
/--
340351
Find the first argument of `nm` that has a multiplicative type-class on it.
341352
Returns 1 if there are no types with a multiplicative class as arguments.
@@ -360,7 +371,6 @@ def firstMultiplicativeArg (nm : Name) : MetaM (Option Nat) := do
360371
| [] => return none
361372
| (head :: tail) => return some <| tail.foldr Nat.min head
362373

363-
364374
/-- `ValueType` is the type of the arguments that can be provided to `to_additive`. -/
365375
structure ValueType : Type where
366376
/-- Replace all multiplicative declarations, do not use the heuristic. -/
@@ -375,6 +385,10 @@ structure ValueType : Type where
375385
/-- If `allow_auto_name` is `false` (default) then
376386
`@[to_additive]` will check whether the given name can be auto-generated. -/
377387
allowAutoName : Bool := false
388+
/-- The `Syntax` element corresponding to the original multiplicative declaration
389+
(or the `to_additive` attribute if it is added later),
390+
which we need for adding definition ranges. -/
391+
ref : Syntax
378392
deriving Repr
379393

380394
/-- `add_comm_prefix x s` returns `"comm_" ++ s` if `x = tt` and `s` otherwise. -/
@@ -464,18 +478,19 @@ def proceedFields (src tgt : Name) : CoreM Unit := do
464478
-- [todo] run to_additive on the constructors of n:
465479
-- aux (fun n => (env.constructorsOf n).mmap $ ...
466480

467-
private def elabToAdditiveAux
468-
(replaceAll trace : Bool) (tgt : Option Syntax) (doc : Option Syntax) : ValueType :=
481+
private def elabToAdditiveAux (ref : Syntax) (replaceAll trace : Bool) (tgt : Option Syntax)
482+
(doc : Option Syntax) : ValueType :=
469483
{ replaceAll := replaceAll
470484
trace := trace
471485
tgt := match tgt with | some tgt => tgt.getId | none => Name.anonymous
472486
doc := doc.bind (·.isStrLit?)
473487
allowAutoName := false
488+
ref
474489
}
475490

476491
private def elabToAdditive : Syntax → CoreM ValueType
477-
| `(attr| to_additive $[!%$replaceAll]? $[?%$trace]? $[$tgt]? $[$doc]?) =>
478-
return elabToAdditiveAux replaceAll.isSome trace.isSome tgt doc
492+
| `(attr| to_additive%$tk $[!%$replaceAll]? $[?%$trace]? $[$tgt]? $[$doc]?) =>
493+
return elabToAdditiveAux ((tgt.map (·.raw)).getD tk) replaceAll.isSome trace.isSome tgt doc
479494
| _ => throwUnsupportedSyntax
480495

481496
/-!
@@ -701,10 +716,12 @@ initialize registerBuiltinAttribute {
701716
withOptions
702717
(fun o => o |>.setBool `to_additive.replaceAll val.replaceAll
703718
|>.setBool `trace.to_additive shouldTrace)
704-
(transformDecl src tgt)
719+
(transformDecl val.ref src tgt)
705720
if let some doc := val.doc then
706721
addDocString tgt doc
707-
return ()
722+
-- Because `@[simp]` runs after compilation,
723+
-- we have to as well to be able to copy attributes correctly.
724+
applicationTime := .afterCompilation
708725
}
709726

710727

test/toAdditive.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ if some_def.in_namespace then x * x else x
9595

9696
-- cannot apply `@[to_additive]` to `some_def` if `some_def.in_namespace` doesn't have the attribute
9797
run_cmd do
98-
Elab.Command.liftCoreM <| successIfFail (ToAdditive.transformDecl `Test.some_def `Test.add_some_def)
98+
Elab.Command.liftCoreM <| successIfFail (ToAdditive.transformDecl (← getRef) `Test.some_def `Test.add_some_def)
9999

100100

101101
attribute [to_additive some_other_name] some_def.in_namespace

0 commit comments

Comments
 (0)