Comment #0 by bearophile_hugs — 2010-03-11T14:08:26Z
This D2 program compiles and runs with no errors or warnings:
static foo1() {}
final foo2() {}
ref foo3() {}
enum void foo4() {}
nothrow foo5() {}
pure foo6() {}
static int x1 = 10;
static x2 = 10;
void main() {}
Notes:
- foo1, x1, x2: I don't know what a static global void function/variable is in D2, so 'static' can be disallowed for global functions/variables.
- foo2, foo3, foo4: they look like bugs.
- Are most of those attributes supposed to not need the "void"? I think requiring for example "pure void" is a little better than allowing just "pure".
The following lines don't compile, is this correct?
int static x3 = 10;
int enum x4 = 1;
int const x5 = 2;
I like the strictness of the Java compiler, it makes sure your attributes are all correct and meaningful, this helps avoid possible bugs. And I'm sure it helps newbies learn the language in less time too (because when you don't know the rules yet, it's very useful if they don't change).
Comment #1 by bearophile_hugs — 2010-04-14T07:35:46Z
A person in the IRC channel suggests that this too can be bad (this program compiles and runs with dmd 2.043):
extern struct foo;
void main() {}
Comment #2 by smjg — 2010-05-30T14:21:25Z
This seems to be partly a duplicate of issue 3118.
Without a clear spec on the matter, it's hard to decide which of these it's a bug that the compiler accepts, but certainly foo3 and foo4 AISI.
Comment #3 by bearophile_hugs — 2010-06-15T17:10:04Z
This too is wrong (this compiles with dmd v2.047):
struct Foo {
static invariant() {}
}
void main() {}
Comment #4 by bearophile_hugs — 2010-06-30T13:14:48Z
One from Leopold Walkling, this compiles:
auto void main() {}
Comment #5 by smjg — 2010-06-30T16:33:29Z
I certainly call that a bug.
Partly a consequence of auto being an attribute rather than a placeholder for a type, though this seems to be partly for backward compatibility with the old meaning of auto. Either way, it's an inapplicable attribute and one that ought not to be accepted.
Comment #6 by bearophile_hugs — 2010-07-25T07:01:22Z
Two more related cases:
This looks correct:
auto main() {
return 0;
}
But dmd 2.047 prints:
test.d(1): Error: function D main must return int or void
----------------
The error message shows that foo() is not pure:
test.d(5): Error: pure function 'bar' cannot call impure function 'foo'
auto pure foo() {
return 1;
}
pure void bar() {
foo();
}
void main() {}
So it seems 'pure' is ignored if 'auto' is present.
Comment #7 by bearophile_hugs — 2010-08-17T06:07:58Z
From Simen kjaeraas:
__gshared struct foo {
int n;
}
Comment #8 by bearophile_hugs — 2010-08-19T06:14:56Z
From bernardh on IRC, this program compiles:
auto scope shared import std.stdio;
void main() {}
Comment #9 by bearophile_hugs — 2010-08-19T09:11:44Z
This D2 program compiles and runs with DMD 2.048 with no errors, but I think the compiler has to flag this usage of the 'private final' attributes as incorrect:
import std.c.stdio: puts;
class Base {
private final ~this() { puts("Base.~this"); }
}
class Derived : Base {
private final ~this() { puts("Derived.~this"); }
}
void main() {
new Derived();
}
Comment #10 by bearophile_hugs — 2010-09-21T13:28:24Z
Structs can't be subclassed, so protected struct fields seem a bug. This compiles with dmd 2.049:
struct Foo {
protected int x;
}
void main() {}
Comment #11 by bearophile_hugs — 2010-09-26T10:40:03Z
This compiles with no errors with dmd 2.049, but I'd like a compile-time error similar to "manifest constants are always static":
void foo() {
static enum x = 10;
}
void main() {}
Comment #12 by bearophile_hugs — 2010-11-05T11:17:28Z
See the closed bug 5171 for code that may be disallowed statically:
class A {
@disable override equals_t opEquals(Object other) {
return false;
}
}
void main() {
auto a = new A();
auto b = new A();
if(a == b)
assert(0);
}
Comment #13 by bearophile_hugs — 2010-11-08T03:24:30Z
This is C# code:
class Foo {}
public class Test : Foo {
public static void Main() {}
}
The C# compiler gives this error:
prog.cs(2,14): error CS0060: Inconsistent accessibility: base class `Foo' is less accessible than class `Test'
While the D 2.050 compiler gives no errors with this code:
private class Foo {}
public class Bar : Foo {}
void main() {}
Comment #14 by bearophile_hugs — 2010-11-08T04:19:31Z
This bug is now fixed:
auto pure foo() {
return 1;
}
pure void bar() {
foo();
}
void main() {}
DMD 2.050 gives the error:
test.d(5): Error: pure function 'bar' cannot call impure function 'foo'
Comment #15 by bearophile_hugs — 2010-11-08T04:38:03Z
(In reply to comment #14)
> This bug is now fixed:
Ignore comment #14, the bug is not fixed, sorry.
Comment #16 by bearophile_hugs — 2011-01-23T07:18:39Z
Comment #17 by bearophile_hugs — 2011-01-23T09:26:37Z
(In reply to comment #16)
> This shows something strange, dmd 2.051:
According to Mafi that code is correct:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learn&article_id=24058
> I think it's absolutely correct. Look: Foo3 is declared as const
> struct meaning all it's members are const. We are passing a struct
> like that to bar3:
> const Foo3 { const int* p}
> which is implicitely converted to:
> Foo3 { const int* p } //not ref !!
> Because it's not ref you can't manipulate the original struct anyways
> and the pointer is still const. As long as you don't cast you cannot
> change what the pointer points to so this implicit conversion is
> correct IMO.
> It's like const(T[]) => const(T)[] .
Comment #18 by bearophile_hugs — 2011-01-23T16:18:58Z
Another variant of the code, found by Dan Olson, this compiles and runs with no errors with DMD 2.051:
struct Foo { int x; }
void bar(ref Foo f) { f.x = 1; }
void main() {
const f = Foo();
bar(f);
}
Comment #19 by bearophile_hugs — 2011-03-19T06:47:16Z
It seems "emum" implies "static":
enum X = 10;
void main() {
enum int X = 20;
static int foo() {
return X; // No errors
}
assert(foo() == 20); // No errors
}
Yet this compiles:
void main() {
enum static int x = 1;
}
While this:
void main() {
static static int x = 1;
}
Produces the error:
test.d(2): redundant storage class 'static'
Comment #20 by bearophile_hugs — 2011-07-24T05:51:32Z
This is accepted by DMD 2.054, but if it's not meaningful in D then I suggest to statically disallow it, as the other examples:
class Foo {}
class Bar : public Foo {}
void main() {}
Comment #21 by smjg — 2011-07-24T07:38:37Z
(In reply to comment #20)
> This is accepted by DMD 2.054, but if it's not meaningful in D then I suggest
> to statically disallow it, as the other examples:
>
> class Foo {}
> class Bar : public Foo {}
> void main() {}
There are no attributes as such in your example. And I don't see anything that isn't meaningful. So what do you mean?
Comment #22 by code — 2011-07-24T07:42:16Z
(In reply to comment #21)
> (In reply to comment #20)
> > class Foo {}
> > class Bar : public Foo {}
> > void main() {}
>
> There are no attributes as such in your example. And I don't see anything that
> isn't meaningful. So what do you mean?
I think bearophile is referring to the »public« protection attribute in the SuperClass. This is explicitly allowed by the grammar, but I don't know off hand if it actually has any effect in the current implementation, other than giving C++ programmers a wrong sense of coziness maybe. ;)
Comment #23 by smjg — 2011-07-24T07:54:03Z
(In reply to comment #22)
> (In reply to comment #21)
>> (In reply to comment #20)
>>> class Foo {}
>>> class Bar : public Foo {}
>>> void main() {}
>>
>> There are no attributes as such in your example. And I don't see
>> anything that isn't meaningful. So what do you mean?
>
> I think bearophile is referring to the »public« protection attribute in the
> SuperClass. This is explicitly allowed by the grammar, but I don't know off
> hand if it actually has any effect in the current implementation, other than
> giving C++ programmers a wrong sense of coziness maybe. ;)
Therein lies my point - it isn't an attribute as such, and it isn't meaningless. It means the same as in C++, though it doesn't make sense to have the feature in D. But this point is covered by issue 177.
Comment #24 by kennytm — 2011-07-24T09:09:15Z
(In reply to comment #20)
> This is accepted by DMD 2.054, but if it's not meaningful in D then I suggest
> to statically disallow it, as the other examples:
>
>
> class Foo {}
> class Bar : public Foo {}
> void main() {}
Bug 177, Bug 5299.
Comment #25 by bearophile_hugs — 2012-01-08T07:09:32Z
By mleise on IRC #D:
struct Foo {
void bar() const const const {}
}
void main() {}
Comment #26 by bearophile_hugs — 2012-01-08T07:22:14Z
By mleise on IRC #D:
class Base {
abstract void foo();
}
class Ext : Base {
override void foo(); // override should require an implementation
}
void main() {}
If uncaught by the compiler this causes a linker error.
Comment #27 by bearophile_hugs — 2012-09-08T07:51:04Z
Found by Ellery Newcomer:
alias enum int e;
void main() {}
Comment #28 by bearophile_hugs — 2012-10-07T05:48:44Z
Comment #29 by pro.mathias.lang — 2019-07-13T09:06:19Z
There are way too many examples (some of which have been addressed, many still valid) for this to be actionable. A proper proposal would most likely take a lot of time and go through the DIP process, as it is a fundamental change to the grammar (regardless of its validity).
Trivial items such as protection attributes on class inheritance and redundant attributes have been addressed.
Some items are also documented here: https://github.com/Hackerpilot/Idiotmatic-D/blob/master/idiotmatic.d
> I like the strictness of the Java compiler, it makes sure your attributes are all correct and meaningful, this helps avoid possible bugs.
To address this specific point: DMD being lax, while unsettling to some, is also great for generic code. There are quite a lot of cases where DMD being stricter would result in worst code because it would require some special casing in generic code.
Closing as INVALID.