Deprecation
When an API is on its way out, mark it [Deprecated("message")]. Code that
uses it still compiles, but every use gets a warning that shows your message,
the same way clang reports [[deprecated]]. That gives the code that depends
on the API time to move before you remove it.
struct Temperature {
int celsius;
# A method on its way out: it still works, but every call warns.
[Deprecated("use 'fahrenheit' instead", "fahrenheit")]
to_f(): int { return fahrenheit(); }
fahrenheit(): int { return celsius * 9 / 5 + 32; }
}
# The second argument names the replacement: the warning carries a fix that
# renames the call.
[Deprecated("use 'boiling' instead", "boiling")]
boiling_point(): Temperature { return boiling(); }
boiling(): Temperature {
var t = Temperature();
t.celsius = 100;
return t;
}
main(): int {
# Both calls warn, and both still work.
var old = boiling_point();
assert(old.to_f() == 212, "the old API still works");
var t = boiling();
assert(t.fahrenheit() == 212, "100 C is 212 F");
return 0;
}
Compiling this prints a warning at each use of a deprecated name, with a note at its declaration. The second of the two is:
main.pep:25:16: warning: 'to_f' is deprecated: use 'fahrenheit' instead [deprecated]
25 | assert(old.to_f() == 212, "the old API still works");
| ^~~~
| fahrenheit
main.pep:6:5: note: 'to_f' declared here
6 | to_f(): int { return fahrenheit(); }
| ^~~~
Warnings never stop the build. The program above compiles and runs.
The replacement
The attribute takes an optional second argument: the name that replaces the deprecated one.
[Deprecated("use 'copy' instead", "copy")]
clone(): Counter { ... }
With a replacement, the warning comes with a fix that renames the use. The compiler shows the new name under the old one, as in the warning above, and the language server offers the rename as a quick fix. The fix only renames, so give a replacement only when the new declaration can be used the same way. Otherwise leave it out and explain the change in the message.
An empty message is allowed. The warning then says only 'name' is deprecated.
What it applies to
Put [Deprecated(...)] before any declaration other code refers to by name:
- a function or an
extern - a struct, a trait, or a type alias
- a module-scope variable
- a field, a method, or a constructor of a struct, or a method of an enum
- a method in a trait or in an extension (put it on each method, not on the
extendblock)
A doc comment goes above the attribute, as it does for any attribute.
To rename a parameter while calls still name the old
one, put [Rename("old", "new")] on the
function instead (see Other names for a parameter).
Which uses warn
Every use of the declaration warns, at the name you wrote:
- a call, a reference to a function or variable, or a construction
S()(a deprecated constructor is reported at the struct’s name) - a type name, anywhere a type is written
- a member access
x.name, a method callx.name(), a static callS.name(), and a bare field or method name inside the struct’s own methods - an entry in an import list,
import [name] from m, and a qualified usem.name, where the warning points atname - a call the compiler writes for you, at the token that stands for it: a
forloop’snext()andcurrent()atfor, awithblock’senter()atwith, and an operator overload at its operator (a + bat+; a deprecated==also warns at a!=that uses it). These warnings offer no rename fix.
These do not warn:
- the declaration itself
- a use inside a declaration that is deprecated too, including the methods of a deprecated struct and closures written inside a deprecated function, so old code can keep calling old code without noise
- a re-export,
export name as otherorexport [name] from source, which passes the name on without using it
Mistakes in the attribute
A malformed attribute is an error at the attribute:
main.pep:1:1: error: 'Deprecated' expects a message string: [Deprecated("message")]
1 | [Deprecated]
| ^~~~~~~~~~~~
The other errors are 'Deprecated' expects the replacement as a string, the replacement 'a b' is not a name, too many arguments to 'Deprecated': expected at most 2, have 3, duplicate 'Deprecated' attribute, and
'Deprecated' cannot be applied to an extension or a destructor.