Skip to content

Commit 4d74669

Browse files
committed
Expanded and corrected "Forbidden implementation combinations"
1 parent 360a594 commit 4d74669

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

text/3634-scoped-impl-trait-for-type.md

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,30 +1492,40 @@ The same limitations as for trait object types apply to `Alias` of `type Alias =
14921492
## Forbidden implementation combinations
14931493
[forbidden-implementation-combinations]: #forbidden-implementation-combinations
14941494

1495-
Due to uniqueness of global implementations for trait/type pairs, it has been possible for `unsafe` implementations to generically make safety-relevant assertions also about only loosely-related implementations.
1495+
Due to uniqueness of global implementations for trait/type pairs, it has been possible for `unsafe` implementations and blocks to generically make safety-relevant assertions and assumptions also about only loosely-related implementations.
14961496

14971497
In order for existing code to remain sound in all cases, at least the following implementation combinations must be forbidden by default when fulfilling bounds:
14981498

14991499
- `<T: UnsafeGlobal + Scoped>`
15001500
- `<T: UnsafeGlobal<U>, U: Scoped>`
15011501
- `<T: UnsafeGlobal<Type = U>, U: Scoped>`
1502+
- `<T: Sealed + ExternalScoped>`
1503+
- `<T: Sealed<U>, U: ExternalScoped>`
1504+
- `<T: Sealed<Type = U>, U: ExternalScoped>`
1505+
- for patterns with `U`: also cases where `T` is replaced with a concrete type
15021506
- combinations of these patterns, regardless of how the connecting bounds are fulfilled
15031507

15041508
where
15051509

15061510
- `UnsafeGlobal` is fulfilled by a global implementation of an `unsafe` trait (including through imports (direct or indirect)),
1507-
- `Scoped` is fulfilled by a scoped implementation and
1511+
- `Scoped` is fulfilled by a scoped implementation,
1512+
- `Sealed` is fulfilled by an implementation of a sealed trait,
1513+
- `ExternalScoped` is fulfilled by a scoped implementation defined in a different crate from where the bounded item is defined and
15081514
- the type parameter definitions and bounds may be split between an `impl` and e.g. `fn` or `type` (as what matters is only that the relation is visible generically in some way).
15091515

15101516
Running afoul of this restriction produces the error [potentially-unsound-combination-of-implementations].
15111517

1512-
Unsafe traits are opted-out of imposing these limits if their definition has the new attribute `#[asserts_non_supertrait_impls(false)]`. In particular, all auto-traits like `Send`, `Sync` and `Unpin` and to my knowledge all other `unsafe` traits defined in the standard library can do this without issue.
1518+
Unsafe and sealed traits are opted-out of imposing these limits in place of `UnsafeGlobal` if their definition has the new attribute `#[asserts_non_supertrait_impls(false)]`. In particular, all auto-traits like `Send`, `Sync` and `Unpin` and to my knowledge all other `unsafe` traits defined in the standard library can do this without issue.
15131519

1514-
> Depending on how much friction this rule causes, changing the default may eventually be a candidate for inclusion in an edition change, but personally I wouldn't do this before scoped implementations have become a well-established part of the language.
1520+
Bounded items are opted out of imposing the limits containing `Sealed` on their uses if their definition has the new attribute `#[assumes_unique_impls(false)]`. Applying this attribute in turn triggers [potentially-unsound-combination-of-implementations] on nested uses of bounds combinations where the nested `ExternalScoped` bound is fulfilled through any outer bound (including indirectly through blanket implementations enabled by any outer bound).
1521+
1522+
> Depending on how much friction these rules cause, changing the default(s) may eventually be a candidate for inclusion in an edition change, but personally I wouldn't do this before scoped implementations have become a well-established part of the language.
15151523
>
1516-
> The migration for that would add `#[asserts_non_supertrait_impls(true)]` to all `unsafe` trait definitions without the attribute.
1524+
> The migrations for that would add `#[asserts_non_supertrait_impls(true)]` to all `unsafe`-or-sealed traits' definitions without the attribute, and `#[assumes_unique_impls(true)]` to all public items where a sealed-trait-bound is combined with another as above.
1525+
1526+
These limits don't apply to `unsafe` implementations in place of `UnsafeGlobal` that are originally implemented as scoped. Instead, it is unsound to expose (to external safe code) an originally-scoped `unsafe` implementation that asserts non-supertrait implementations.
15171527

1518-
These limits don't apply to `unsafe` implementations that are originally implemented as scoped. Instead, it is unsound to expose (to external safe code) an originally-scoped `unsafe` implementation that asserts non-supertrait implementations.
1528+
By the same principle, scoped implementations defined by the same crate as the bounded item don't necessarily have to be forbidden when used in place of `ExternalScoped` for those bounds.
15191529

15201530
## Warnings
15211531

0 commit comments

Comments
 (0)