-
Notifications
You must be signed in to change notification settings - Fork 227
Description
Working on augmentations raises some questions around which compile errors are defined on a single syntactic declaration or the resulting semantic declaration after all augmentations are merged. For most errors, the distinction doesn't matter. But digging into this has revealed some corners of the language that feel inconsistent and somewhat arbitrary. So this issue to see if we want to make some changes to the language to be more consistent.
abstract class I {}
class C implements I, I {}Today, this is an error:
Error: 'I' can only be implemented once.
However, this is fine:
abstract class I {}
class B implements I
class C extends B implements I {}So you can implement the same interface twice if you go through a level of indirection. That makes sense because it's harmless to do so and would otherwise mean that adding an implements clause to a class could be a breaking change if a subclass already implemented the same interface.
Also, this is fine:
mixin M {}
class C with M, M {}I suppose there is maybe an argument that allowing applying the same mixin multiple times is potentially useful for a mixin with certain carefully crafted methods and uses of super().
This is also allowed:
mixin class M {}
class C extends M with M {}But this is an error:
class B {}
class C extends B implements B {}Yields:
Error: 'B' can't be used in both 'extends' and 'implements' clauses.
But again a layer of indirection permits it:
class B {}
class C extends B {}
class D extends C implements B {}No error here.
Most curiously, this is allowed:
mixin M {}
class C with M implements M {}I can think of absolutely no reason to allow this while disallowing extends M implements C. I assume it was just an oversight.
With augmentations
Adding in augmentations complicates this. Consider:
abstract class I {}
class C implements I {}
augment class C implements I {}Is that an error?
-
If not, then we'll have to explicitly specify that redundant interfaces in implements are restricted to a single syntactic declaration before augmentations are applied. But that may be hard because augmentations are generally applied early in the compilation process before resolution and type checking has happened.
-
If it is an error, then a code generator has to be careful to omit a redundant
implementsclause if the hand-authored class happens to already specify implementing the same interface.
No redundant implements errors
I think a better approach is to eliminate these errors completely. So these classes would all be valid:
mixin class M {}
class C implements M, M {}
class D extends M implements M {}
class E with M implements M {}The third one is already valid. This would make the first two consistent.
Yes, it means you can write something that's a little redundant and pointless. But... we have empty statements in the language. You can often write code that doesn't do anything. Making this specific flavor of redundancy an error seems to carry little positive value and makes augmentations more complicated.