Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it an error to have on F when F is final in another library. #2956

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 59 additions & 25 deletions accepted/future-releases/class-modifiers/feature-specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Author: Bob Nystrom, Lasse Nielsen

Status: Accepted

Version 1.7
Version 1.8

Experiment flag: class-modifiers

Expand Down Expand Up @@ -662,10 +662,10 @@ It's a compile-time error if:
* A declaration depends directly on a `sealed` declaration from another
library. _No exceptions, not even for platform libraries._

More formally:
A declaration *D* from library *L* has a direct superdeclaration *S*
marked `sealed` (so necessarily a `class` declaration) in a library
different from *L*.
More formally, it's a compile-time error if:
A `class`, `mixin class`, `mixin` or `enum` declaration from library *L*
has a direct superdeclaration marked `sealed` _(so necessarily a `class`
declaration)_ from a library other than *L*.

```dart
// a.dart
Expand All @@ -680,18 +680,48 @@ It's a compile-time error if:
class M with S {} // Error, for several reasons.
```

* A class extends or mixes in a declaration marked `interface` or `final`
* A declaration depends directly on a `final` declaration from another
library _(with some exceptions for platform libraries)_.

_(You cannot subtype a `final` declaration, except inside the same library.
Unless you are in a pre-feature library and the super-declaration is from
a platform library.)_

More formally, it's a compile-time error if:
A `class`, `mixin class`, `mixin` or `enum` declaration from library *L*
has a direct superdeclaration *S* marked `final` _(so necessarily a `class`
declaration)_ in a library *K*, neither:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would do "neither" -> "and neither of the following is true".

And then remove the "nor," from the first bullet.

Likewise further below.

* *L* and *K* is the same library, nor
* *L* is a pre-feature library and *K* is a platform library.

```dart
// a.dart
final class S {}

// b.dart
import 'a.dart';

class E extends S {} // Error.
class I implements S {} // Error.
mixin O on S {} // Error.
class M with S {} // Error.
```
Except that if `b.dart` is a pre-feature library
and `a.dart` is a platform library, then all the errors go away.

* A class _extends or mixes in_ a declaration marked `interface`
from another library _(with some exceptions for platform libraries)_.

_(You cannot inherit implementation from a class marked `interface`
or `final` except inside the same library. Unless you are in a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe remove the final-related example on lines 599 and 705 if we aren't talking about it in this section anymore.

pre-feature library and you are inheriting from a platform library.)_
except inside the same library. Unless you are in a pre-feature library
and you are inheriting from a platform library.)_

More formally:
A declaration *C* from library *L* has a declared superclass or mixin
declaration *S* marked `interface` or `final` from library *K*, and neither
More formally, it's a compile-time error if:
A `class` or `enum` declaration in library *L* has a declared
superclass or mixin declaration marked `interface` from
library *K*, and neither
* *L* and *K* is the same library, nor
* *K* is a platform library and *L* is a pre-feature library.
* *L* is a pre-feature library and *K* is a platform library.

```dart
// a.dart
Expand All @@ -715,13 +745,13 @@ It's a compile-time error if:
a pre-feature library and all `base` or `final` superdeclarations
are in platform libraries.)_

More formally:
A declaration *C* in library *L* has a declared interface *P*,
and *P* has any superdeclaration *S*, from a library *K*,
which is marked `base` or `final` _(including *S* being *P* itself)_,
and neither:
* *K* and *L* is the same library, mor
* *K* is a platform library and *L* is a pre-feature library.
More formally, it's a compile-time error if:
A `class`, `mixin-class`, `mixin` or `enum` declaration in library *L* has
a declared interface *P*, and *P* has any superdeclaration *S*,
from a library *K*, which is marked `base` or `final`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, since you specify behaviour for final declaration subtyping on line 683, maybe move these final examples (that aren't already in the final section) over to there and remove talking about both base and final in this section?

It's nice to read about each modifier one at a time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rule might just be about base, because it's impossible to have a super-declaration marked final in another library without also having a super-declaration marked base in that other library, because that's the only possible way to have a direct super-declaration from that library with the final declaration as super-declaration.

(I think. It's always worrisome to define rules that depend on other rules to be complete. If we remove or tweak the other rule, then this rule might start allowing something we didn't intend.
So, be complete in every rule, as if it was stand-alone, or be minimal and non-redundant? I'm aiming for the former.)

_(including *S* being *P* itself)_, and neither:
* *L* and *K* is the same library, nor
* *L* is a pre-feature library and *K* is a platform library.

```dart
// a.dart
Expand All @@ -742,7 +772,7 @@ It's a compile-time error if:
base class C implements P {} // Error.
```

* A declaration has a `base` or `final` superdeclaration,
* A declaration has any `base` or `final` superdeclaration,
and is not itself marked `base`, `final` or `sealed`.
_This also applies to declarations inside the same library._

Expand All @@ -751,7 +781,7 @@ It's a compile-time error if:
The entire subclass tree below such a declaration must prevent
implementation too.)_

More formally:
More formally, it's a compile-time error if:
A `class`, `mixin class` or `mixin` declaration *D* in a post-feature
library has any proper superdeclaration marked `base` or `final`,
and *D* is not itself marked `base`, `final` or `sealed`.
Expand Down Expand Up @@ -1102,13 +1132,17 @@ errors and fixups would help keep them on the rails.

## Changelog

1.8

- Disallow mixin on a `final` type from another library.

1.7

* Update the modifiers applied to anonymous mixin applications to closer
- Update the modifiers applied to anonymous mixin applications to closer
match the superclass/mixin modifiers.
* State that `enum` declarations count as `final`.
* Rephrase semantics completely, based only on relations between declarations.
* Say that pre-feature libraries can mix in non-`mixin` platform library classes
- State that `enum` declarations count as `final`.
- Rephrase semantics completely, based only on relations between declarations.
- Say that pre-feature libraries can mix in non-`mixin` platform library classes
which satisfy the old requirements for being used as a mixin.

1.6
Expand Down