Legacy Code
To maintain compatibility with older D code, many legacy features remain supported. This page describes each legacy feature that is supported, with a suggestion of how to modernize the code.
| Feature | Summary | Edition check |
|---|---|---|
| body keyword | body after a contract statement - use do instead | 2024 |
| alias target name; syntax | use alias name = target; instead | 2024 |
| Aliasing an instance member | Use typeof(instance).member instead | 2024 |
| Escaping scope data | scope is enforced in @safe code | 2024 |
| Struct/union postblit | use a copy constructor instead. |
body keyword
body was a keyword used to specify a function/method's body after a contract statement:
class Foo { void bar(int i) in { assert(i >= 42); } body { /* Do something interesting */ } string method(string s) out(v) { assert(v.length == s.length); } body { /* Do something even more interesting */ } void noBody() { /* No contracts, no body */ } }
Corrective Action
Use the do keyword instead (introduced in v2.075.0):
void bar(int i) in { assert(i >= 42); } do { /* Look ma, no body! */ }
alias target name; syntax
From the 2024 edition, AliasDeclaration only supports alias name = target; syntax. This is easier to find the symbol identifier, particularly when target is a complex symbol. The target first order came from C's typedef syntax.
Aliasing an instance member
E.g. alias a = instance.field;. Such an alias actually aliases a member of the instance's type, not the instance member itself. That could be confusing. Instead, alias a member of the type.
struct Bar { Foo f; alias v = f.v; // Error, use `typeof(f).v` } struct Foo { int v; void test(Foo that) const { alias a = this.v; // OK alias b = that.v; // Error, use `typeof(that).v` instead assert(&a is &b); // passes assert(&b !is &that.v); } }