Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

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.

Legacy Features
FeatureSummaryEdition check
body keywordbody after a contract statement - use do instead2024
Aliasing an instance member Use typeof(instance).member instead2024
Escaping scope data scope is enforced in @safe code2024
Assigning to struct rvalue Disallow for structs which overload e.g. opAssign2024
alias target first syntaxuse alias name = target instead.
Struct/union postblituse 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! */ }
Rationale: The body keyword was only used for this single purpose. Since D grammar aims to be context free, this common word was reserved, which led to frequent trouble for people interfacing with other languages (e.g. javascript) or auto-generating code.

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.

Note: Aliasing this.member and super.member are valid inside methods.
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);
    }
}

Assigning to struct rvalue

It has always been an error for POD structs to assign from an rvalue.

From the 2024 edition, it is an error to discard the result of an assignment from a struct rvalue when it would call opAssign, opOpAssign, opUnary!"++", or opUnary!"--" and the struct has no pointer fields:

struct S
{
    int i;

    void opAssign(S s);
}

S foo();

void main()
{
    foo() = S(2); // Error, possible no-op
}

Above, unless opAssign mutates global data, the assignment in main will have no effect and indicates a bug.

Corrective Action

If a struct rvalue assignment is needed to mutate global state, either call the operator overload method directly or use an lvalue. Note: Calling a non-const method on a struct rvalue is allowed.

Glossary
Editions