Skip to content

Trait aliases don't imply default trait bounds on type params other than Self #152687

@fmease

Description

@fmease

Context: Default trait bounds like Sized are bounds that are implicitly added to certain definition sites (like type params, traits, assoc types) unless relaxed via another bound (in most cases via the ?Trait syntax). Only default traits qualify. Currently those are Sized, MetaSized (feat sized_hierarchy) and four dummy ones (feat more_maybe_bounds).

First of all, I would expect default trait bounds to behave identically to user-written trait bounds when it comes to trait solving and type checking.

However, this doesn't hold for type params on trait aliases as default trait bounds aren't implied at usage sites of the trait alias unlike user-written trait bounds.

Reproducer 0: Sized

The following rightfully compiles because the user-written bound T: Sized gets implied over at f.

#![feature(trait_alias)]

trait A<T: Sized> =;
fn f<T: ?Sized>() where (): A<T> {}

In contrast, the version with a default Sized bound fails to compile: Wrongfully the default T: Sized doesn't get implied but since it's of course still required for trait alias ref A<T> to be well-formed we ultimately fail due to T: Sized not holding in f's environment.

#![feature(trait_alias)]

trait A<T> =; // has a default `T: Sized` bound
fn f<T: ?Sized>() where (): A<T> {} // wrongfully rejected!
//~^ ERROR the size for values of type `T` cannot be known at compilation time

Reproducer 1: MetaSized (sized_hierarchy)

Rightfully accepted:

#![feature(trait_alias, sized_hierarchy)]

trait A<T: std::marker::MetaSized> =;
fn f<T: std::marker::PointeeSized>() where (): A<T> {}

Wrongfully rejected:

#![feature(trait_alias, sized_hierarchy)]

trait A<T: ?Sized> =; // has a default `T: MetaSized` bound
fn f<T: std::marker::PointeeSized>() where (): A<T> {}
//~^ ERROR the size for values of type `T` cannot be known

Reproducer 2: Dummy trait (more_maybe_bounds)

Rightfully accepted:

//@ compile-flags: -Zexperimental-default-bounds
#![feature(trait_alias, more_maybe_bounds, lang_items, auto_traits)]

#[lang = "default_trait1"]
auto trait Mark {}

trait A<T: Mark> = ?Mark;
fn f<T: ?Mark>() where (): A<T> {}

Wrongfully rejected:

//@ compile-flags: -Zexperimental-default-bounds
#![feature(trait_alias, more_maybe_bounds, lang_items, auto_traits)]

#[lang = "default_trait1"]
auto trait Mark {}

trait A<T> = ?Mark; // has a default `T: Mark` bound
fn f<T: ?Mark>() where (): A<T> {}
//~^ ERROR the trait bound `T: Mark` is not satisfied

Metadata

Metadata

Assignees

Labels

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

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions