Skip to content

Trait aliases make it possible to sidestep various syntactic trait bound checks #135342

Closed as not planned
@fmease

Description

@fmease

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

  1. I.e., checks on the AST or HIR without any sort of prior substitution/expansion/normalization/...

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.F-trait_alias`#![feature(trait_alias)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions