This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$(P Replace all uses of invariant as a storage class or type modifier with immutable. The invariant() syntax for struct and class invariants is still supported.
)
<h4>Rationale</h4>
$(P The alias is unnecessary.
)
<h3>$(DEPNAME Using * to dereference arrays)</h3>
D array variables can be dereferenced to get the first element, much like pointers.
---
int[] arr = [1, 2, 3];
assert(*arr == 1);
---
<h4>Corrective Action</h4>
$(P Use indexing syntax to access first member.
---
int[] arr = [1, 2, 3];
assert(arr[0] == 1);
---
)
<h4>Rationale</h4>
$(P D arrays are not pointers.
)
<h3>$(DEPNAME Removing an item from an associative array with delete)</h3>
delete can be used to remove an item from an associative array.
---
int[int] aa = [1 : 2];
delete aa[1];
assert(1 !in aa);
---
<h4>Corrective Action</h4>
$(P Use .remove instead.
---
int[int] aa = [1 : 2];
aa.remove(1);
assert(1 !in aa);
---
)
<h4>Rationale</h4>
$(P The delete syntax is confusing and conflicts with the normal delete syntax.
)
<h3>$(DEPNAME .offset property)</h3>
The .offset property can be used to get member offset information.
---
struct S { int a, b; }
static assert(S.b.offset == 4);
---
<h4>Corrective Action</h4>
$(P Use .offsetof instead
---
struct S { int a, b; }
static assert(S.b.offsetof == 4);
---
)
<h4>Rationale</h4>
$(P The .offset syntax has been superseded by .offsetof
)
<h3>$(DEPNAME Escape string literals)</h3>
Escape string literals can be used to describe characters using escape sequences.
---
string x = "hello" ~ \n;
---
<h4>Corrective Action</h4>
$(P Put escape sequences inside a regular string literal.
---
string x = "hello\n";
---
)
<h4>Rationale</h4>
$(P Escape string literals are unintuitive and unnecessary.
)
<h3>$(DEPNAME Lower case 'l' suffix for integer literals)</h3>
Lower case 'l' is an alternative suffix to denote 64 bit integer literals.
---
auto x = 123l;
---
<h4>Corrective Action</h4>
$(P Use the upper case 'L' suffix.
---
auto x = 123L;
---
)
<h4>Rationale</h4>
$(P The lower case suffix is easily confused with the digit '1'.
)
<h3>$(DEPNAME Octal literals)</h3>
Octal literals can be used to enter literals in base 8.
---
auto x = 0123;
---
<h4>Corrective Action</h4>
$(P Use the octal!num template.
---
auto x = octal!123;
---
)
<h4>Rationale</h4>
$(P The use of a leading zero is confusing, as 0123 != 123.
)
<h3>$(DEPNAME Upper case 'I' suffix for imaginary literals)</h3>
The 'I' suffix can be used to denote imaginary floating point values.
---
auto x = 1.234I;
---
<h4>Corrective Action</h4>
$(P Use the lower case 'i' suffix.
---
auto x = 1.234i;
---
)
<h4>Rationale</h4>
$(P The 'I' suffix is easily confused with the digit '1'.
)
<h3>$(DEPNAME HTML source files)</h3>
The D compiler can parse html files by ignoring everything not contained in <code></code> tags.
---
<html>
<code>
... source ...
</code>
</html>
---
<h4>Corrective Action</h4>
$(P Extract code to regular source files.
)
<h4>Rationale</h4>
$(P This has been replaced for documentation by the introduction of ddoc
)
<h3>$(DEPNAME HTML source files)</h3>
The D compiler can parse html files by ignoring everything not contained in <code></code> tags.
---
<html>
<code>
... source ...
</code>
</html>
---
<h4>Corrective Action</h4>
$(P Extract code to regular source files.
)
<h4>Rationale</h4>
$(P This has been replaced for documentation by the introduction of ddoc
)
<h3>$(DEPNAME .typeinfo property)</h3>
The .typeinfo property can be used to get the associated TypeInfo class.
---
T.typeinfo
---
<h4>Corrective Action</h4>
$(P Use .typeid instead
---
T.typeid
---
)
<h4>Rationale</h4>
$(P The .typeinfo syntax has been superseded by .typeid
)
<h3>$(DEPNAME C-style function pointers)</h3>
C-style function pointers can be used in D.
---
alias void(*fptr)(int, long);
---
<h4>Corrective Action</h4>
$(P Replace with D-style function pointers.
---
alias void function(int, long) fptr;
---
)
<h4>Rationale</h4>
$(P The D syntax is much cleaner and easier to use.
)
<h3>$(DEPNAME C-style array pointers)</h3>
C-style array pointers can be used in D.
---
alias float *arrayptr[10][15];
---
<h4>Corrective Action</h4>
$(P Replace with D-style array pointers.
---
alias float[15][10]* arrayptr;
---
)
<h4>Rationale</h4>
$(P The D syntax is much cleaner and easier to use.
)
<h3>$(DEPNAME if (v; e))</h3>
This syntax can be used to declare a variable in an if statement condition.
---
if (v; calculateAndReturnPointer()) { ... }
---
<h4>Corrective Action</h4>
$(P Replace with an auto declaration.
---
if (auto v = calculateAndReturnPointer()) { ... }
---
)
<h4>Rationale</h4>
$(P The syntax is clearer with auto.
)
<h3>$(DEPNAME volatile)</h3>
volatile can be used to mark statement, in order to prevent some compiler optimizations.
---
volatile
{
... do something involving ghared variables ...
}
---
<h4>Corrective Action</h4>
$(P Convert the code to use synchronized statements instead.
)
<h4>Rationale</h4>
$(P volatile statements are a misfeature.
)
<h3>$(DEPNAME Non-final switch statements without a default case)</h3>
Switch statements can be declared without a default case, and the compiler automatically adds one.
---
switch(a)
{
case 1:
break;
case 2:
break;
// the compiler adds
// default:
// throw new SwitchError();
}
---
<h4>Corrective Action</h4>
$(P Add the default case manually.
---
switch(a)
{
case 1:
break;
case 2:
break;
default:
assert(0);
}
---
)
<h4>Rationale</h4>
$(P Missing default cases can hide bugs, and making the default case explicit should be mandatory.
)
<h3>$(DEPNAME Hiding base class functions)</h3>
Declaration functions in a derived class that can be called with the same arguments as a function in a base class, but do not override that function causes the base class function to be hidden.
---
class A
{
void fun(int x) {}
}
class B : A
{
void fun(long x) {}
}
---
<h4>Corrective Action</h4>
$(P Add the function to the base class, or use an alias to bring the base class overload into the derived class.
---
class A
{
void fun(int x) {}
void fun(long x) {} // this fixes it
}
class B : A
{
void fun(long x) {}
alias A.fun fun; // so does this
}
---
)
<h4>Rationale</h4>
$(P This is an error that is already detected at runtime, and is being extended to compile time.
)
<h3>$(DEPNAME .min property for floating point types)</h3>
Floating point types have the .min property to access the smallest value.
---
enum m = real.min;
---
<h4>Corrective Action</h4>
$(P Replace with .min_normal
---
enum m = real.min_normal;
---
)
<h4>Rationale</h4>
$(P The name min_normal is more accurate, as .min does not include denormalized floating point values.
)
<h3>$(DEPNAME imaginary and complex types)</h3>
D currently supports imaginary and complex versions of all floating point types.
---
float a = 2;
ifloat b = 4i;
cfloat c = a + b;
assert(c == 2 + 4i);
---
<h4>Corrective Action</h4>
$(P Use the library types in std.complex
)
<h4>Rationale</h4>
$(P These types are too specialized to be a part of the core lanugage.
)
<h3>$(DEPNAME floating point NCEG operators)</h3>
D currently the NCEG floating point operators (!<>=, <>, <>=, !>, !>=, !<, !<=, !<>) for comparisons involving NaNs.
<h4>Corrective Action</h4>
$(P Use the normal operators and std.math.isNaN.
)
<h4>Rationale</h4>
$(P These operators are too specialized to be a part of the core lanugage.
)
<h3>$(DEPNAME .sort and .reverse properties for arrays)</h3>
D arrays can be manipulated using these built-in properties.
---
int[] x = [2, 3, 1];
assert(x.sort == [1, 2, 3]);
---
<h4>Corrective Action</h4>
$(P Use the generic functions in std.algorithm
)
<h4>Rationale</h4>
$(P These operations are better implemented in the standard library
)
<h3>$(DEPNAME delete)</h3>
Memory allocated on the GC heap can be freed with delete.
---
auto a = new Class();
delete a;
---
<h4>Corrective Action</h4>
$(P Use object.clear() instead.
---
auto a = new Class();
clear(a);
---
)
<h4>Rationale</h4>
$(P delete makes assumptions about the type of garbage collector available that limits which implementations can be used, and can be replaced by a library solution.
)
<h3>$(DEPNAME overriding without override)</h3>
Virtual functions can currently override a function in a base class without the 'override' attribute.
---
class A
{
void fun() {}
}
class B : A
{
// overrides but is not marked with override
void fun() {}
}
---
<h4>Corrective Action</h4>
$(P Mark overriding functions with 'override'
---
class A
{
void fun() {}
}
class B : A
{
override void fun() {}
}
---
)
<h4>Rationale</h4>
$(P Making the 'override' attribute mandatory makes it explicit, and can catch errors when a base class function is accidentally overridden.
)
$(P With D's module system, it doesn't seem to serve any useful purpose.)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters