Closed as not planned
Closed as not planned
Description
Similar to how type aliases allow you to circumvent some syntactic/syntax-driven1 checks made by AST lowering (#132212), you can utilize trait aliases to bypass certain restrictions applying to trait bounds.
#![feature(trait_alias)]
trait SuperMaybeNeg: ?Sized {} // 🔴 REJECTED: `?Trait` is not permitted in supertraits
trait SuperMaybePos: MaybeSized {} // 🟢 Workaround: ACCEPTED
type DynMaybeNeg = dyn std::io::Write + ?Sized; // 🔴 REJECTED: `?Trait` is not permitted in trait object types
type DynMaybePos = dyn std::io::Write + MaybeSized; // 🟢 Workaround: ACCEPTED
fn noop_maybe_neg() where i32: ?Sized {} // 🔴 REJECTED: `?Trait` bounds are only permitted at the point where a type parameter is declared
fn noop_maybe_pos() where i32: MaybeSized {} // 🟢 Workaround: ACCEPTED
trait MaybeSized = ?Sized;
#![feature(trait_alias, const_trait_impl)]
const fn incompat_modifs_neg<T: const ?Trait>() {} // 🔴 REJECTED: const` trait not allowed with `?` trait polarity modifier
const fn incompat_modifs_pos<T: ?ConstTrait>() {} // 🟢 Workaround: ACCEPTED
trait ConstTrait = const Trait; // alternatively, `async Fn()` under feat `async_trait_bounds`
#[const_trait] trait Trait {}
#![feature(trait_alias)]
type DupeAssocNeg = dyn std::ops::Deref<Target = String, Target = i32>; // 🔴 REJECTED: the value of the associated type `Target` in trait `Deref` is already specified
type DupeAssocPos = dyn AssocFixed<Target = i32>; // 🟢 Workaround: ACCEPTED
//^ This bypasses a HIR ty lowering check, not an AST validation one.
type DynAtbNeg = dyn std::ops::Deref<Target: Copy>; // 🔴 REJECTED: associated type bounds are not allowed in `dyn` types
type DynAtbPosIsh<T> = dyn AssocBounded<Target = T>; // 🟢 Workaround-ish: ACCEPTED
trait AssocFixed = std::ops::Deref<Target = String>;
trait AssocBounded = std::ops::Deref<Target: Copy>;
#![feature(trait_alias, return_type_notation)]
struct DynRtnNeg(dyn Trait<method(..): Copy>); // 🔴 REJECTED: associated type bounds are not allowed in `dyn` types
// return type notation is not allowed to use type equality
struct DynRtnPos(dyn Rtn); // 🟢 Workaround: ACCEPTED
trait Trait { fn method(&self) -> impl Sized where Self: Sized; }
trait Rtn = Trait<method(..): Copy>;
This either calls into question the very existence of these restrictions or it demonstrates that all of these checks ought to run "later" (i.e., after trait alias expansion).
Footnotes
-
I.e., checks on the AST or HIR without any sort of prior substitution/expansion/normalization/... ↩