This PR adds a `@[deprecated_arg]` attribute that marks individual function parameters as deprecated. When a caller uses the old parameter name, the elaborator emits a deprecation warning with a code action hint to rename or delete the argument, and silently forwards the value to the correct binder. Supported forms: - `@[deprecated_arg old new (since := "...")]` — renamed parameter, warns and forwards - `@[deprecated_arg old new "reason" (since := "...")]` — with custom message - `@[deprecated_arg removed (since := "...")]` — removed parameter, errors with delete hint - `@[deprecated_arg removed "reason" (since := "...")]` — removed with custom message A warning is emitted if `(since := "...")` is omitted. When a parameter is deprecated without a replacement, the elaborator treats it as no longer present: using it as a named argument produces an error. Note that positional uses of deprecated arguments are not checked — if a function's arity changed, the caller will simply get a "function expected" error. The `linter.deprecated.arg` option (default `true`) controls behavior: when enabled, renamed args produce warnings and removed args produce specific deprecation errors with code action hints; when disabled, both fall through to the standard "invalid argument name" error. This lets library authors phase out old parameter names without breaking downstream code immediately. Example (renamed parameter): ```lean @[deprecated_arg old new (since := "2026-03-18")] def f (new : Nat) : Nat := new /-- warning: parameter `old` of `f` has been deprecated, use `new` instead Hint: Rename this argument: o̵l̵d̵n̲e̲w̲ --- info: f 42 : Nat -/ #guard_msgs in #check f (old := 42) ``` Example (removed parameter): ```lean @[deprecated_arg removed (since := "2026-03-18")] def g (x : Nat) : Nat := x /-- error: parameter `removed` of `g` has been deprecated Hint: Delete this argument: (̵r̵e̵m̵o̵v̵e̵d̵ ̵:̵=̵ ̵4̵2̵)̵ -/ #guard_msgs in #check g (removed := 42) ```
55 lines
1.1 KiB
Text
55 lines
1.1 KiB
Text
import DeprecatedArg.Def
|
|
|
|
-- Cross-file: old name produces warning
|
|
/--
|
|
warning: parameter `arg` of `f` has been deprecated, use `foo` instead
|
|
|
|
Hint: Rename this argument:
|
|
a̵r̵g̵f̲o̲o̲
|
|
---
|
|
info: f 42 : Nat
|
|
-/
|
|
#guard_msgs in
|
|
#check f (arg := 42)
|
|
|
|
-- Cross-file: new name produces no warning
|
|
/--
|
|
info: f 42 : Nat
|
|
-/
|
|
#guard_msgs in
|
|
#check f (foo := 42)
|
|
|
|
-- Cross-file: positional arg produces no warning
|
|
/--
|
|
info: f 42 : Nat
|
|
-/
|
|
#guard_msgs in
|
|
#check f 42
|
|
|
|
-- Cross-file: multiple renames
|
|
/--
|
|
warning: parameter `old1` of `g` has been deprecated, use `new1` instead
|
|
|
|
Hint: Rename this argument:
|
|
o̵l̵d̵n̲e̲w̲1
|
|
---
|
|
warning: parameter `old2` of `g` has been deprecated, use `new2` instead
|
|
|
|
Hint: Rename this argument:
|
|
o̵l̵d̵n̲e̲w̲2
|
|
---
|
|
info: g 1 2 : Nat
|
|
-/
|
|
#guard_msgs in
|
|
#check g (old1 := 1) (old2 := 2)
|
|
|
|
-- Cross-file: disabling the linter rejects old names with a clean error
|
|
/--
|
|
error: Invalid argument name `arg` for function `f`
|
|
|
|
Hint: Perhaps you meant one of the following parameter names:
|
|
• `foo`: a̵r̵g̵f̲o̲o̲
|
|
-/
|
|
#guard_msgs in
|
|
set_option linter.deprecated.arg false in
|
|
#check f (arg := 42)
|