| Field | Value |
|---|---|
| DIP: | 1028 |
| Review Count: | 2 |
| Author: | Walter Bright walter@digitalmars.com |
| Implementation: | dlang/dmd#10709 |
| Status: | Rejected |
Currently, D functions default to being @system. This DIP proposes changing the default to @safe.
- Rationale
- Prior Work
- Description
- Breaking Changes and Deprecations
- Reference
- Copyright & License
- Reviews
When D was first developed, there was little interest in the extra safety checks
introduced by @safe. But as the costs of unsafe code have become ever more apparent
and expensive, and @safe has grown more capable, the balance has shifted. Users expect
safety to be opt-out, not opt-in.
Most code should be naturally safe, and system code should be relatively rare. It makes sense that the common case - safe code - should be the default and not require an annotation.
- Other languages such as Rust and C# have safety as opt-out, rather than opt-in.
- A previous draft proposal: @safe-by-default First Draft
Functions such as template functions, nested functions, and lambdas that are not annotated
currently have their @safe / @system attribute inferred. This behavior will not change.
Other unannotated functions will now be assumed to be @safe rather than @system.
Because this is expected to break a lot of existing code, it will be enabled with the compiler switch:
-preview=safedefault
There are no grammar changes.
Non-virtual function templates get their attributes inferred if they are not explicitly marked. Hence, this proposal should not affect them.
This will likely break most code that has not already been annotated with @safe,
@trusted, or @system. Annotate functions that aren't safe with @system.
Once the project compiles again successfully, start with the leaves marked @system and
modify as required to make them @safe.
In general, @system should not be applied to blocks of functions. It should be added
specifically to each function that requires it.
An unmarked extern (D) function will now be considered @safe. If its implementation is not recompiled,
it will no longer link because the mangling will be different. But for extern (C) and (C++) functions,
safety is not part of the mangling and it will compile and link without error. This has always
relied on the user getting it correct.
Interfaces to extern C and C++ functions should always be explicitly marked.
It's best practice for 3rd party libraries to use explicit safety annotations and not rely on defaults. It is also best practice to compile those libraries with the same compiler that is being used to compile the project.
An @safe function can override an @system function, but not vice-versa. Hence, with @safe being
the default, the user may see compile errors when overriding a now-default @safe function with
a @system one. The user will have to decide which the inheritance hierarchy should be and annotate
as required.
Copyright (c) 2019 by the D Language Foundation
Licensed under Creative Commons Zero 1.0
In a very long discussion thread, there was a mix of support and opposition. Some critical feedback points were:
- The DIP should specify a deprecation plan.
- The DIP should specify an extended deprecation period.
- Such a major change should be saved for a potential D3.
- The DIP should not be approved until it is possible to make
@saferef-counted types and a tool exists to annotate existing default@systemfunctions as@system. Another commenters suggested the tool should additionally annotate functions@safeif they compile. The DIP author replied that such a tool would be welcome. - Introduce
@legacythat, when added to the top of a module, makes every function@trustedby default. - Weak rationale.
- The rationale should be enhanced to say that the majority of existing, non-template D code is already
@safe, but not annotated as such, preventing projects with dependencies from using the annotation. This change makes dependencies useful in@safecode. - Advising users to fix breakage by annotating unsafe functions with
@trustedor@systemshould be revised to just advise@system, otherwise users may misunderstand and misuse@trusted. The DIP author agreed this is a good idea. - The DIP should also include the introduction of
@trustedexpressions. This was countered by the argument that changes to@trustedshould be a separate DIP. - Make it a compiler option only.
- The DIP does not address bugs in
@safewhich require a DIP to fix. The DIP author replied that this DIP is about making@safethe default, not changing its behavior. - The impact of the change should be assessed. The DIP author replied that compatibility can be achieved by labeling functions that don't compile as
@system. - Too many DIPs resulting in new
-previewswitches. The DIP author replied that all programming languages improve or die. - The DIP does not explore alternatives, as recommended by the DIP guidelines. Examples would be a linting tool that annotates functions as
@safewhen they compile, or the ability to annotate module declarations with@safeor@systemto specify the default behavior in that module. - What about function declarations with no body?
- The DIP should also change
@systemto@unsafe. The DIP author replied that@unsafewas rejected when@systemwas introduced because it has negative connotations. - Perhaps the DIP should discuss DIP1000, since it may have an impact on the amount and nature of breakage this DIP causes. Is this DIP dependent on DIP1000 being the default? Does
-preview=safedefaultimply-preview=dip1000? The DIP should discuss the types breakage that will be avoided with DIP1000 enabled. The DIP author replied that DIP1000 and DIP1028 will remain independent. - The DIP should go into more detail about breaking changes, i.e., migration paths, third-party libraries that are no longer actively maintained, the problem with a catch-all
@system:disabling template inference, the impact of the change onexternAPIs, the impact of the change on@nogccode, and more. - The consideration of prior work should provide more detail.
- How does the DIP affect interfaces and virtual functions? Implementations and subclasses with unmarked
@systemimplementations will fail to compile when their interface/superclass member functions become@safe. The DIP author replied that functions in interfaces and base classes will initially need to be explicitly marked@systemand can later be marked@safein a transition.
The following points were raised in the feedback thread:
- The DIP specifically mentions
extern (D)functions as being marked as@safe? The author replied that allexternfunctions will be@safe. - Saying that interfaces to C and C++ functions "should be explicitly marked" is too vague. How should they be marked?
- Adding
@system:to the top of a file will kill template inference of@safe. The DIP should deal with this somehow. @safeshould not be allowed on function declarations that are notextern (D)or, alternatively, the compiler should require all non-D mangled functions to be explictly marked with one of@safe,@trusted, or@system.
This proposal was initially accepted by the language maintainers. After further discussion in the D forums, the DIP author in his role as language maintainer chose to reverse the decision. The proposal is now rejected.