mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 05:00:16 +03:00
purge changelog
This commit is contained in:
parent
c403accecf
commit
c6863be720
31 changed files with 0 additions and 673 deletions
|
@ -1,19 +0,0 @@
|
||||||
Storage classes `ref` and `auto ref` can now be applied to local, static, extern, and global variables
|
|
||||||
|
|
||||||
For example, one can now write:
|
|
||||||
```
|
|
||||||
struct S { int a; }
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
S s;
|
|
||||||
ref int r = s.a;
|
|
||||||
r = 3;
|
|
||||||
assert(s.a == 3);
|
|
||||||
|
|
||||||
auto ref x = 0;
|
|
||||||
auto ref y = x;
|
|
||||||
static assert(!__traits(isRef, x));
|
|
||||||
static assert( __traits(isRef, y));
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1,18 +0,0 @@
|
||||||
Keywords `auto` and `ref` must be adjacent
|
|
||||||
|
|
||||||
It's now deprecated to declare `auto ref` parameters without putting those two keywords next to each other.
|
|
||||||
This way it's clear that `auto ref` semantics are intended, rather than `ref` and `auto` semantics separately.
|
|
||||||
For the newly introduced $(RELATIVE_LINK2 dmd.reflocal, `ref` local / global variables), it's an error immediately.
|
|
||||||
|
|
||||||
---
|
|
||||||
void t()(ref const auto int x) // Deprecation
|
|
||||||
{
|
|
||||||
ref auto y = x; // Error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Correction:
|
|
||||||
void t()(auto ref const int x)
|
|
||||||
{
|
|
||||||
auto ref y = x;
|
|
||||||
}
|
|
||||||
---
|
|
|
@ -1,23 +0,0 @@
|
||||||
The `align` attribute now allows specifying `default` explicitly
|
|
||||||
|
|
||||||
A lone `align` sets the alignment to the type’s default.
|
|
||||||
To be more explicit, `align(default)` does the same.
|
|
||||||
|
|
||||||
```
|
|
||||||
struct S
|
|
||||||
{
|
|
||||||
align(4)
|
|
||||||
{
|
|
||||||
byte x;
|
|
||||||
align(default) long y;
|
|
||||||
long z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
pragma(msg, S.x.alignof); // 4
|
|
||||||
pragma(msg, S.y.alignof); // 8
|
|
||||||
pragma(msg, S.z.alignof); // 4
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1,15 +0,0 @@
|
||||||
Remove `delete` as a keyword
|
|
||||||
|
|
||||||
After being superseded by `destroy()`, deprecated, and turned into an error, `delete` can now be used as an identifier:
|
|
||||||
|
|
||||||
---
|
|
||||||
enum Action
|
|
||||||
{
|
|
||||||
add, delete
|
|
||||||
}
|
|
||||||
|
|
||||||
void delete(T)(T obj)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
---
|
|
|
@ -1,18 +0,0 @@
|
||||||
Case fallthough for multivalued cases is an error now
|
|
||||||
|
|
||||||
This used to give a deprecation and now gives an error:
|
|
||||||
```
|
|
||||||
int i;
|
|
||||||
switch (0)
|
|
||||||
{
|
|
||||||
case 0, 1: i = 20;
|
|
||||||
default: assert(0); // Error: switch case fallthrough - use 'goto default;' if intended
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (0)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case 0, 1: i = 20;
|
|
||||||
case 2, 3: i = 30; // Error: switch case fallthrough - use 'goto case;' if intended
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1,32 +0,0 @@
|
||||||
An error is now given for constructors when a field's destructor has stricter attributes
|
|
||||||
|
|
||||||
```
|
|
||||||
struct HasDtor
|
|
||||||
{
|
|
||||||
~this() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Pure
|
|
||||||
{
|
|
||||||
HasDtor member;
|
|
||||||
this(int) pure {} // Error: `this` has stricter attributes than its destructor (`pure`)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Nothrow
|
|
||||||
{
|
|
||||||
HasDtor member;
|
|
||||||
this(int) nothrow {} // Error: `this` has stricter attributes than its destructor (`nothrow`)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NoGC
|
|
||||||
{
|
|
||||||
HasDtor member;
|
|
||||||
this(int) @nogc {} // Error: `this` has stricter attributes than its destructor (`@nogc`)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Safe
|
|
||||||
{
|
|
||||||
HasDtor member;
|
|
||||||
this(int) @safe {} // Error: `this` has stricter attributes than its destructor (`@safe`)
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1,16 +0,0 @@
|
||||||
Initializing a field with itself has been deprecated
|
|
||||||
|
|
||||||
This is to prevent a common mistake when a field and a parameter ought to have the same name,
|
|
||||||
but one is misspelled where it's declared:
|
|
||||||
|
|
||||||
---
|
|
||||||
struct S
|
|
||||||
{
|
|
||||||
int field;
|
|
||||||
|
|
||||||
this(int feild) // supposed to be: this(int field)
|
|
||||||
{
|
|
||||||
this.field = field; // equal to this.field = this.field
|
|
||||||
}
|
|
||||||
}
|
|
||||||
---
|
|
|
@ -1,11 +0,0 @@
|
||||||
An error is now given for subtracting pointers of different types
|
|
||||||
|
|
||||||
The following code now gives errors:
|
|
||||||
```
|
|
||||||
static assert(cast(void*)8 - cast(int*) 0 == 2L);
|
|
||||||
static assert(cast(int*) 8 - cast(void*)0 == 8L);
|
|
||||||
void test()
|
|
||||||
{
|
|
||||||
auto foo = (ushort*).init - (ubyte*).init;
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1,17 +0,0 @@
|
||||||
An error is now issued for `in`/`out` contracts of `nothrow` functions that may throw
|
|
||||||
|
|
||||||
This used to issue a deprecation, it is now an error:
|
|
||||||
```
|
|
||||||
void test() nothrow
|
|
||||||
in
|
|
||||||
{
|
|
||||||
throw new Exception(null); // Error: `in` contract may throw but function is marked as `nothrow`
|
|
||||||
}
|
|
||||||
out
|
|
||||||
{
|
|
||||||
throw new Exception(null); // Error: `out` contract may throw but function is marked as `nothrow`
|
|
||||||
}
|
|
||||||
do
|
|
||||||
{
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1,40 +0,0 @@
|
||||||
Typesafe variadic class parameters have been deprecated
|
|
||||||
|
|
||||||
This obscure feature allowed a limited form of implicit construction:
|
|
||||||
|
|
||||||
---
|
|
||||||
void check(bool x, Exception e...)
|
|
||||||
{
|
|
||||||
if (!x)
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main(string[] args)
|
|
||||||
{
|
|
||||||
check(args.length > 1, "missing argument");
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
However, few uses of this feature have been found, and one project was actually mistakenly using it instead of the more common Typesafe variadic array parameter.
|
|
||||||
Considering D doesn't support implicit construction and already has a confusing amount of different variadic parameter forms, it was decided to remove this feature.
|
|
||||||
|
|
||||||
As a corrective action, either call the constructor in the callee:
|
|
||||||
|
|
||||||
---
|
|
||||||
void check(string msg)
|
|
||||||
{
|
|
||||||
if (!x)
|
|
||||||
throw new Exception(msg);
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
Or let the caller construct the class instance:
|
|
||||||
|
|
||||||
---
|
|
||||||
void check(bool x, Exception e);
|
|
||||||
|
|
||||||
void main(string[] args)
|
|
||||||
{
|
|
||||||
check(args.length > 1, new Exception("missing argument"));
|
|
||||||
}
|
|
||||||
---
|
|
|
@ -1,5 +0,0 @@
|
||||||
Integers in `debug` or `version` statements have been removed from the language
|
|
||||||
|
|
||||||
These were deprecated in 2.101.
|
|
||||||
Use `-debug=identifier` and `-version=identifier` instead for versions set on the command line,
|
|
||||||
and likewise `version = identifier;` and `debug = identifier;` for versions set in code at global scope.
|
|
|
@ -1,123 +0,0 @@
|
||||||
Many error messages have changed
|
|
||||||
|
|
||||||
Some changes have been made without being associated to a reported issue:
|
|
||||||
|
|
||||||
Error messages for `@safe` violations now consistently mention they are related to `@safe` functions (or default functions with `-preview=safer`).
|
|
||||||
In general, function attributes that failed to infer have a more compact error message:
|
|
||||||
|
|
||||||
Before:
|
|
||||||
$(CONSOLE
|
|
||||||
app.d(8): Error: function `attributediagnostic_nothrow.gc1` is not `nothrow`
|
|
||||||
app.d(2): which wasn't inferred `nothrow` because of:
|
|
||||||
app.d(2): `object.Exception` is thrown but not caught
|
|
||||||
)
|
|
||||||
|
|
||||||
After:
|
|
||||||
$(CONSOLE
|
|
||||||
app.d(8): Error: function `attributediagnostic_nothrow.gc1` is not `nothrow`
|
|
||||||
app.d(2): and `object.Exception` being thrown but not caught makes it fail to infer `nothrow`
|
|
||||||
)
|
|
||||||
|
|
||||||
Function literals are now referred to by their (truncated) function body, instead of the internal `__lambda` name.
|
|
||||||
|
|
||||||
---
|
|
||||||
/*
|
|
||||||
BEFORE:
|
|
||||||
|
|
||||||
../test/test_.d(3): Error: function literal `__lambda1()` is not callable using argument types `(int)`
|
|
||||||
(() => 42)(1);
|
|
||||||
^
|
|
||||||
AFTER:
|
|
||||||
|
|
||||||
../test/test_.d(3): Error: function literal `() => 42` is not callable using argument types `(int)`
|
|
||||||
(() => 42)(1);
|
|
||||||
^
|
|
||||||
*/
|
|
||||||
---
|
|
||||||
|
|
||||||
Match levels are now mentioned on ambiguous overloads: [#20637](https://github.com/dlang/dmd/pull/20637)
|
|
||||||
|
|
||||||
Before:
|
|
||||||
$(CONSOLE
|
|
||||||
Error: `app.bar` called with argument types `(string)` matches both:
|
|
||||||
)
|
|
||||||
|
|
||||||
After:
|
|
||||||
$(CONSOLE
|
|
||||||
Error: `app.bar` called with argument types `(string)` matches multiple overloads after implicit conversions:
|
|
||||||
)
|
|
||||||
|
|
||||||
Error messages related to operator overloading have been improved.
|
|
||||||
When the related template functions (`opUnary`, `opBinary`, `opBinaryRight`, `opOpAssign`, `opIndex`, `opSlice`)
|
|
||||||
are missing, a suggestion to implement them is given.
|
|
||||||
|
|
||||||
When they do exist but fail to instantiate, the error from instantiation is shown.
|
|
||||||
There's no longer a need to manually e.g. rewrite `s + 1` to `s.opBinary!"+"(1)` to diagnose the error.
|
|
||||||
|
|
||||||
---
|
|
||||||
struct S {}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
S s;
|
|
||||||
const x = s[3 .. "4"];
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
Before:
|
|
||||||
$(CONSOLE
|
|
||||||
app.d(6): Error: no `[]` operator overload for type `S`
|
|
||||||
)
|
|
||||||
|
|
||||||
After:
|
|
||||||
$(CONSOLE
|
|
||||||
app.d(6): Error: no `[3.."4"]` operator overload for type `S`
|
|
||||||
app.d(1): perhaps define `auto opSlice(int lower, string upper) {}` for `app.S`
|
|
||||||
)
|
|
||||||
|
|
||||||
---
|
|
||||||
struct Str {}
|
|
||||||
|
|
||||||
struct Number
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
int opBinary(string op : "+")(int rhs) => this.x + x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void f(Str str, Number number)
|
|
||||||
{
|
|
||||||
const s = str ~ "hey";
|
|
||||||
const n = number + "oops";
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
Before:
|
|
||||||
$(CONSOLE
|
|
||||||
app.d(12): Error: incompatible types for `(str) ~ ("hey")`: `Str` and `string`
|
|
||||||
const s = str ~ "hey";
|
|
||||||
^
|
|
||||||
app.d(13): Error: incompatible types for `(number) + ("oops")`: `Number` and `string`
|
|
||||||
const n = number + "oops";
|
|
||||||
)
|
|
||||||
|
|
||||||
After:
|
|
||||||
$(CONSOLE
|
|
||||||
app.d(12): Error: operator `~` is not defined for type `Str`
|
|
||||||
const s = str ~ "hey";
|
|
||||||
^
|
|
||||||
app.d(2): perhaps overload the operator with `auto opBinary(string op : "~")(string rhs) {}`
|
|
||||||
struct Str {}
|
|
||||||
^
|
|
||||||
app.d(13): Error: function `test_.Number.opBinary!"+".opBinary(int rhs)` is not callable using argument types `(string)`
|
|
||||||
const n = number + "oops";
|
|
||||||
^
|
|
||||||
app.d(13): cannot pass argument `"oops"` of type `string` to parameter `int rhs`
|
|
||||||
app.d(7): `opBinary` defined here
|
|
||||||
int opBinary(string op : "+")(int rhs) => this.x + x;
|
|
||||||
^
|
|
||||||
)
|
|
||||||
|
|
||||||
Furthermore:
|
|
||||||
|
|
||||||
- D1 operator overloading functions (`opAdd`, `opDot`) are completely removed and no longer mentioned in error messages specifically.
|
|
||||||
- Class allocators (`auto new() {}`) are not only a semantic error, but no longer parse.
|
|
|
@ -1,4 +0,0 @@
|
||||||
The compiler now accepts `-extern-std=c++23`
|
|
||||||
|
|
||||||
The compiler now accepts c++23 as a supported standard for `-extern-std=`.
|
|
||||||
Currently this only changes the value of `__traits(getTargetInfo, "cppStd")`.
|
|
|
@ -1,16 +0,0 @@
|
||||||
Build time profiling has been added to DMD
|
|
||||||
|
|
||||||
The `-ftime-trace` switch that the LDC compiler already has, is now also available in dmd.
|
|
||||||
It can be used to figure out which parts of your code take the longest to compile, so you can optimize your build times.
|
|
||||||
|
|
||||||
$(CONSOLE
|
|
||||||
dmd -ftime-trace app.d
|
|
||||||
)
|
|
||||||
|
|
||||||
This will output `app.o.time-trace`.
|
|
||||||
|
|
||||||
A different output file can be selected with `-ftime-trace-file=trace.json`.
|
|
||||||
|
|
||||||
The output is in Google Chrome's profiler format, which can be viewed in an interactive viewer like [ui.perfetto.dev](https://ui.perfetto.dev).
|
|
||||||
|
|
||||||
See also the YouTube tutorial [*Easily Reduce Build Times by Profiling the D Compiler*](https://www.youtube.com/watch?v=b8wZqU5t9vs).
|
|
|
@ -1,16 +0,0 @@
|
||||||
New traits `getBitfieldOffset` and `getBitfieldWidth` for built-in bitfields
|
|
||||||
|
|
||||||
This completes the introspection capabilities of built-in bitfields. For example:
|
|
||||||
|
|
||||||
---
|
|
||||||
struct S
|
|
||||||
{
|
|
||||||
int a,b;
|
|
||||||
int :2, c:3;
|
|
||||||
}
|
|
||||||
|
|
||||||
static assert(__traits(getBitfieldOffset, S.b) == 0);
|
|
||||||
static assert(__traits(getBitfieldOffset, S.c) == 2);
|
|
||||||
static assert(__traits(getBitfieldWidth, S.b) == 32);
|
|
||||||
static assert(__traits(getBitfieldWidth, S.c) == 3);
|
|
||||||
---
|
|
|
@ -1,3 +0,0 @@
|
||||||
Using the compiler flag `-i` will now properly pick up C source files
|
|
||||||
|
|
||||||
Previously, you needed to manually include `*.c` source files, it now works just like with D files.
|
|
|
@ -1,25 +0,0 @@
|
||||||
A pragma for ImportC allows to set `nothrow`, `@nogc` or `pure`
|
|
||||||
|
|
||||||
The following new pragma for ImportC allows to set default storage
|
|
||||||
classes for function declarations:
|
|
||||||
```c
|
|
||||||
#pragma attribute(push, [storage classes...])
|
|
||||||
```
|
|
||||||
The storage classes `nothrow`, `nogc` and `pure` are supported.
|
|
||||||
Unrecognized attributes are ignored.
|
|
||||||
Enabling a default storage class affects all function declarations
|
|
||||||
after the pragma until it is disabled with another pragma.
|
|
||||||
Declarations in includes are also affected.
|
|
||||||
The changed storage classes are pushed on a stack. The last change can
|
|
||||||
be undone with the following pragma.
|
|
||||||
The following example
|
|
||||||
enables `@nogc` and `nothrow` for a library:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#pragma attribute(push, nogc, nothrow)
|
|
||||||
#include <somelibrary.h>
|
|
||||||
#pragma attribute(pop)
|
|
||||||
```
|
|
||||||
|
|
||||||
This can also disable multiple default storage classes at the same time,
|
|
||||||
if they were enabled with a single `#pragma attribute(push, ...)` directive.
|
|
|
@ -1,8 +0,0 @@
|
||||||
Mixin templates can now use assignment syntax
|
|
||||||
|
|
||||||
Previously, giving a name to a mixed-in mixin template instance required putting the name at the end.
|
|
||||||
Now, it can also go in front of the instantiation using assignment syntax.
|
|
||||||
---
|
|
||||||
mixin MyMixinTemplate!(Args) myName; // old style
|
|
||||||
mixin myName = MyMixinTemplate!(Args); // new style
|
|
||||||
---
|
|
|
@ -1,6 +0,0 @@
|
||||||
Object file extensions `.o` and `.obj` are now accepted on all platforms
|
|
||||||
|
|
||||||
Accepting `.o` and `.obj` file extensions on all platforms makes DMD behave
|
|
||||||
like Clang and other modern compilers. There is no point in
|
|
||||||
discarding `*.o` or `*.obj` depending on the current operating system, as both extensions
|
|
||||||
unambiguously denote object file.
|
|
|
@ -1,38 +0,0 @@
|
||||||
Objective-C selectors are now automatically generated when not specified with `@selector`.
|
|
||||||
|
|
||||||
Additionally, the Objective-C selector generation rules have changed, following these steps:
|
|
||||||
1. Functions marked with `@property` will generate `setXYZ:` for the setters.
|
|
||||||
2. For property functions with names starting with `is`, that prefix will be stripped off in the setter.
|
|
||||||
3. Selector generation now uses the names of the function parameters instead of their D-mangled types.
|
|
||||||
|
|
||||||
Selectors may still be specified with the `@selector` UDA, in which case it takes precedence over the
|
|
||||||
automatically generated selectors.
|
|
||||||
|
|
||||||
These new rules apply both for `extern` and non-`extern` Objective-C classes and protocols.
|
|
||||||
|
|
||||||
---
|
|
||||||
extern(Objective-C)
|
|
||||||
extern class NSObject {
|
|
||||||
static NSObject alloc(); // Generates as `alloc`
|
|
||||||
NSObject init(); // Generates as `init`
|
|
||||||
}
|
|
||||||
|
|
||||||
extern(Objective-C)
|
|
||||||
class Fox : NSObject {
|
|
||||||
bool fluffy;
|
|
||||||
|
|
||||||
@property bool isFluffy() => fluffy; // `isFluffy`
|
|
||||||
@property void isFluffy(bool value) { fluffy = value; } // `setFluffy:`
|
|
||||||
|
|
||||||
void yip(int a) @selector("bark:") { // `bark:`
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
void doSomething(int a, int b, int c) { // `doSomething:b:c:`
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
These changes should not break any existing code because the automatic selector generation
|
|
||||||
was not present before. And automatic selector generation only applies to `extern(Objective-C)` methods.
|
|
|
@ -1,15 +0,0 @@
|
||||||
New compiler switch `-oq` for DMD
|
|
||||||
|
|
||||||
The switch gives fully qualified names to object files, preventing name conflicts when using the switch `-od`
|
|
||||||
while compiling multiple modules with the same name, but inside different packages.
|
|
||||||
The switch already existed in LDC, but is now in dmd as well.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
$(CONSOLE
|
|
||||||
dmd -c -oq -od=. app.d util/app.d misc/app.d
|
|
||||||
)
|
|
||||||
|
|
||||||
This will output `app.obj`, `util.app.obj`, and `misc.app.obj`, instead of just `app.obj`.
|
|
||||||
|
|
||||||
The switch `-oq` also applies to other outputs, such as Ddoc (`-D -Dd=.`) and `.di` header generation (`-H -Hd=.`).
|
|
|
@ -1,20 +0,0 @@
|
||||||
Added Placement New Expression
|
|
||||||
|
|
||||||
Placement `new` explicitly provides the storage for `new` expression to initialize
|
|
||||||
with the newly created value, rather than using the GC.
|
|
||||||
|
|
||||||
---
|
|
||||||
struct S
|
|
||||||
{
|
|
||||||
float d;
|
|
||||||
int i;
|
|
||||||
char c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() @system @nogc
|
|
||||||
{
|
|
||||||
S s;
|
|
||||||
S* p = new (s) S(3.14, 42, 'X'); // place new object into s
|
|
||||||
assert(p.i == 42 && p.c == 'X');
|
|
||||||
}
|
|
||||||
---
|
|
|
@ -1,13 +0,0 @@
|
||||||
Postfix type qualifier method attributes for `-H` and `-D`
|
|
||||||
|
|
||||||
The `.di` interface file generation and Ddoc output will now have type qualifier
|
|
||||||
attributes placed after the parameter list for methods (and constructors).
|
|
||||||
This avoids confusion with the return type.
|
|
||||||
|
|
||||||
---
|
|
||||||
struct S
|
|
||||||
{
|
|
||||||
const int f(); // before
|
|
||||||
int f() const; // now
|
|
||||||
}
|
|
||||||
---
|
|
|
@ -1,8 +0,0 @@
|
||||||
The folder *samples* has been removed from DMD installations
|
|
||||||
|
|
||||||
Every DMD release has included a folder with small D code examples.
|
|
||||||
These examples are quite old, and not a good representation of modern D.
|
|
||||||
They're also hard to discover, since D compilers are often installed through an installer or package manager.
|
|
||||||
|
|
||||||
Since there are better resources available online nowadays, these samples have
|
|
||||||
been moved to the [undeaD](https://github.com/dlang/undeaD) repository.
|
|
|
@ -1,40 +0,0 @@
|
||||||
New keyword `__rvalue`
|
|
||||||
|
|
||||||
The newly added primary expression of the form `__rvalue(expression)`
|
|
||||||
evaluates to `expression`, except that it is treated as an rvalue,
|
|
||||||
even if would be an lvalue otherwise.
|
|
||||||
|
|
||||||
Overloads on `ref`:
|
|
||||||
```
|
|
||||||
foo( S s); // selected if the argument is an rvalue
|
|
||||||
foo(ref S s); // selected if the argument is an lvalue
|
|
||||||
|
|
||||||
S s;
|
|
||||||
S bar();
|
|
||||||
...
|
|
||||||
foo(s); // selects foo(ref S)
|
|
||||||
foo(bar()); // selects foo(S)
|
|
||||||
```
|
|
||||||
With this change:
|
|
||||||
```
|
|
||||||
foo(__rvalue(s)); // selects foo(S)
|
|
||||||
```
|
|
||||||
This also applies to constructors and assignments, meaning move constructors and
|
|
||||||
move assignments are enabled. Moving instead of copying can be much more resource
|
|
||||||
efficient, as, say, a string can be moved rather than copied/deleted.
|
|
||||||
|
|
||||||
A moved object will still be destructed, so take that into account when moving
|
|
||||||
a field - set it to a benign value that can be destructed.
|
|
||||||
|
|
||||||
`__rvalue` may also be used as an attribute on a function which returns by ref
|
|
||||||
to declare that the result should be treated as an rvalue at the callsite:
|
|
||||||
```
|
|
||||||
ref T move(T)(return ref T source) __rvalue
|
|
||||||
{
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
S s;
|
|
||||||
S t = move(s); // call expression rewritten as: S t = __rvalue(move(s))
|
|
||||||
```
|
|
||||||
This is used as an internal tool to implement library primitives such as `move` and `forward`.
|
|
|
@ -1,22 +0,0 @@
|
||||||
Add `-preview=safer` switch for safety checking on unattributed functions
|
|
||||||
|
|
||||||
All the checks currently enabled in `@safe` code, that are easily fixed (as in
|
|
||||||
the fix is constrained to the function), will be enabled in `-preview=safer` code.
|
|
||||||
|
|
||||||
Code not easily fixed, such as calls to `@system` or unattributed functions, will
|
|
||||||
be allowed as before.
|
|
||||||
|
|
||||||
---
|
|
||||||
void f();
|
|
||||||
@system void g();
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
int* p;
|
|
||||||
p++; // Error, pointer arithmetic
|
|
||||||
f(); // allowed
|
|
||||||
g(); // allowed
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
For more information, see [this document](https://github.com/WalterBright/documents/blob/38f0a846726b571f8108f6e63e5e217b91421c86/safer.md).
|
|
|
@ -1,18 +0,0 @@
|
||||||
Shortened method syntax can now be used in constructors
|
|
||||||
|
|
||||||
This used to raise an error (cannot return expression from constructor), but is now supported:
|
|
||||||
|
|
||||||
---
|
|
||||||
struct Number
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
|
|
||||||
void vf(int);
|
|
||||||
this(int x) => vf(x);
|
|
||||||
this(float x) => this(cast(int) x);
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
The expression body must be a `this`/`super` call or have type `void`.
|
|
||||||
|
|
||||||
Postblits and destructors already supported shortened method syntax because they return `void`.
|
|
|
@ -1,7 +0,0 @@
|
||||||
Add Windows BCrypt bindings under `core.sys.windows.bcrypt`
|
|
||||||
|
|
||||||
Adds full [BCrypt API](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/) bindings
|
|
||||||
to the Windows-specific system bindings.
|
|
||||||
|
|
||||||
The Windows-specific bindings under `core.sys.windows.sdkddkver` and `core.sys.windows.w32api`
|
|
||||||
have also been updated in order to facilitate the creation of the BCrypt bindings.
|
|
|
@ -1,5 +0,0 @@
|
||||||
Remove `criticalRegionLock`
|
|
||||||
|
|
||||||
The `criticalRegionLock` feature suffer from a serious design flaw: $(LINK https://issues.dlang.org/show_bug.cgi?id=24741)
|
|
||||||
|
|
||||||
It turns out it is not used, so rather than fixing the flaw, the feature was removed.
|
|
|
@ -1,7 +0,0 @@
|
||||||
Adds `expect`, `likely`, `unlikely`, and `trap` to `core.builtins`
|
|
||||||
|
|
||||||
Adds the functions `expect` and `likely`/`unlikely` for branch and value hints for the LDC/GDC compilers.
|
|
||||||
DMD ignores these hints.
|
|
||||||
|
|
||||||
Adds the function `trap` to be lowered to the target-dependent trap instruction.
|
|
||||||
If the target does not have a trap instruction, this intrinsic will be lowered to a call of the `abort` function.
|
|
|
@ -1,65 +0,0 @@
|
||||||
New segfault handler showing backtraces for null access / call stack overflow on linux
|
|
||||||
|
|
||||||
While buffer overflows are usually caught by array bounds checks, there are still other situations where a segmentation fault occurs in D programs:
|
|
||||||
|
|
||||||
- `null` pointer dereference
|
|
||||||
- Corrupted or dangling pointer dereference in `@system` code
|
|
||||||
- Call stack overflow (infinite recursion)
|
|
||||||
|
|
||||||
These result in an uninformative runtime error such as:
|
|
||||||
|
|
||||||
$(CONSOLE
|
|
||||||
[1] 37856 segmentation fault (core dumped) ./app
|
|
||||||
)
|
|
||||||
|
|
||||||
In order to find the cause of the error, the program needs to be run again in a debugger like GDB.
|
|
||||||
|
|
||||||
There is the `registerMemoryErrorHandler` function in `etc.linux.memoryerror`, which catches `SIGSEGV` signals and transforms them into a thrown `InvalidPointerError`, providing a better message.
|
|
||||||
However, it doesn't work on call stack overflow, because it uses stack memory itself, so the segfault handler segfaults.
|
|
||||||
It also relies on inline assembly, limiting it to the x86 architecture.
|
|
||||||
|
|
||||||
A new function `registerMemoryAssertHandler` has been introduced, which does handle stack overflow by setting up an [altstack](https://man7.org/linux/man-pages/man2/sigaltstack.2.html).
|
|
||||||
It uses `assert(0)` instead of throwing an `Error` object, so the result corresponds to the chosen `-checkaction` setting.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
---
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
version (linux)
|
|
||||||
{
|
|
||||||
import etc.linux.memoryerror;
|
|
||||||
registerMemoryAssertHandler();
|
|
||||||
}
|
|
||||||
int* p = null;
|
|
||||||
int* q = cast(int*) 0xDEADBEEF;
|
|
||||||
|
|
||||||
// int a = *p; // segmentation fault: null pointer read/write operation
|
|
||||||
// int b = *q; // segmentation fault: invalid pointer read/write operation
|
|
||||||
recurse(); // segmentation fault: call stack overflow
|
|
||||||
}
|
|
||||||
|
|
||||||
void recurse()
|
|
||||||
{
|
|
||||||
recurse();
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
Output with `dmd -g -run app.d`:
|
|
||||||
|
|
||||||
$(CONSOLE
|
|
||||||
core.exception.AssertError@src/etc/linux/memoryerror.d(82): segmentation fault: call stack overflow
|
|
||||||
$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)$(NDASH)
|
|
||||||
src/core/exception.d:587 onAssertErrorMsg [0x58e270d2802d]
|
|
||||||
src/core/exception.d:803 _d_assert_msg [0x58e270d1fb64]
|
|
||||||
src/etc/linux/memoryerror.d:82 _d_handleSignalAssert [0x58e270d1f48d]
|
|
||||||
??:? [0x7004139e876f]
|
|
||||||
./app.d:16 void scratch.recurse() [0x58e270d1d757]
|
|
||||||
./app.d:18 void scratch.recurse() [0x58e270d1d75c]
|
|
||||||
./app.d:18 void scratch.recurse() [0x58e270d1d75c]
|
|
||||||
./app.d:18 void scratch.recurse() [0x58e270d1d75c]
|
|
||||||
./app.d:18 void scratch.recurse() [0x58e270d1d75c]
|
|
||||||
...
|
|
||||||
...
|
|
||||||
...
|
|
||||||
)
|
|
Loading…
Add table
Add a link
Reference in a new issue