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
Context: Default trait bounds like
Sizedare 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?Traitsyntax). Only default traits qualify. Currently those areSized,MetaSized(featsized_hierarchy) and four dummy ones (featmore_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:
SizedThe following rightfully compiles because the user-written bound
T: Sizedgets implied over atf.In contrast, the version with a default
Sizedbound fails to compile: Wrongfully the defaultT: Sizeddoesn't get implied but since it's of course still required for trait alias refA<T>to be well-formed we ultimately fail due toT: Sizednot holding inf's environment.Reproducer 1:
MetaSized(sized_hierarchy)Rightfully accepted:
Wrongfully rejected:
Reproducer 2: Dummy trait (
more_maybe_bounds)Rightfully accepted:
Wrongfully rejected: