Bug 12821 – Missed redundant storage class / protection errors.
Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-05-30T05:31:00Z
Last change time
2014-06-24T02:11:12Z
Keywords
accepts-invalid, spec
Assigned to
nobody
Creator
ibuclaw
Comments
Comment #0 by ibuclaw — 2014-05-30T05:31:05Z
There are cases where redundant storage classes are caught, and others where it just slides through undetected.
Example:
final final void foo() { } // Error, redundant 'final'
final shared final void foo() { } // Error, redundant 'final'
final static final void foo() { } // OK
We can find the exact culprits by iterating through each storage class to find missed cases.
static static void foo() { } // OK
extern extern void foo() { } // OK
align align void foo() { } // OK
debug debug void foo() { } // OK
And we can test this:
shared shared void foo() { } // Error, redundant 'shared'
shared static shared void foo() { } // OK
shared extern shared void foo() { } // OK
shared extern(D) shared void foo() { } // OK
shared align shared void foo() { } // OK
shared debug shared void foo() { } // OK
Other cases include mixing and matching any protection/storage class together.
const const void foo() { } // Error, redundant 'const'
protected protected void foo() { } // Error, redundant 'protection'
const protected const void foo() { } // OK
protected const protected void foo() { } // OK
Resulting in allowing you to even mix conflicting storage classes together.
const immutable void foo() { } // Error, conflicting
const package immutable void foo() { } // OK
const static immutable void foo() { } // OK
Penultimately, the following throw an error unless you specify void. All of which seems redundant as there's no return type.
immutable foo() { } // Without 'this' cannot be immutable
immutable void foo() { } // OK
const foo() { } // Without 'this' cannot be const
const void foo() { } // OK
inout foo() { } // Without 'this' cannot be inout
inout void foo() { } // OK
shared foo() { } // Without 'this' cannot be shared
shared void foo() { } // OK
Lastly, these are considered perfectly valid, if somewhat odd.
ref foo() { } // OK, inferred as 'ref void'
ref void foo() { } // OK
auto void foo() { } // OK
auto int foo() { return 0; } // OK, redundant 'auto'
auto double foo() { return 0; } // OK, redundant 'auto'
All these tests are using functions declared at module scope.
Comment #1 by k.hara.pg — 2014-06-20T03:52:34Z
By recent git-head change, many cases are properly fixed.
final final void foo() { } // Error, redundant 'final'
final shared final void foo() { } // Error, redundant 'final'
final static final void foo() { } // Error, redundant 'final' <- OK
static static void foo() { } // Error, redundant 'static' <- OK
extern extern void foo() { } // Error, redundant 'extern' <- OK
align align void foo() { } // Error, redundant 'align' <- OK
shared shared void foo() { } // Error, redundant 'shared'
shared static shared void foo() { } // Error, redundant 'shared' <- OK
shared extern shared void foo() { } // Error, redundant 'shared' <- OK
shared extern(D) shared void foo() { } // Error, redundant 'shared' <- OK
shared align shared void foo() { } // Error, redundant 'shared' <- OK
const const void foo() { } // Error, redundant 'const'
protected protected void foo() { } // Error, redundant 'protection'
const protected const void foo() { } // Error, redundant 'const' <- OK
protected const protected void foo() { } // Error, redundant 'protection' <- OK
const immutable void foo() { } // Error, conflicting
const package immutable void foo() { } // Error, conflicting <- OK
const static immutable void foo() { } // Error, conflicting <- OK
These are still OK cases:
debug debug void foo() { } // OK
shared debug shared void foo() { } // OK
Currently it's intended. Because `debug ...` is parsed as ConditionalDeclaration, so they are equivalent with:
debug { debug { void foo() { } } }
shared { debug { shared { void foo() { } } } }
Comment #2 by k.hara.pg — 2014-06-24T01:13:43Z
(In reply to Iain Buclaw from comment #0)
> Penultimately, the following throw an error unless you specify void. All of
> which seems redundant as there's no return type.
>
> immutable foo() { } // Without 'this' cannot be immutable
> immutable void foo() { } // OK
'immutable' does not modify return type. But in module scope, 'this' qualifier for non-member function is meaningless and "Without 'this' cannot be immutable" error occurs in first case. But second case does not raise same error, and it's inconsistent behavior.
> const foo() { } // Without 'this' cannot be const
> const void foo() { } // OK
> inout foo() { } // Without 'this' cannot be inout
> inout void foo() { } // OK
> shared foo() { } // Without 'this' cannot be shared
> shared void foo() { } // OK
As well, same "Without 'this' cannot be xxx" error should occur in all cases.
To improve compiler behavior, I opened issue 12967.
Comment #3 by k.hara.pg — 2014-06-24T02:11:12Z
Most cases are properly improved, and remained issue is separated to 12967. Therefore, I'd like to close this issue right now.