trait_sel: skip elaboration of sizedness supertrait

As a performance optimization, skip elaborating the supertraits of
`Sized`, and if a `MetaSized` obligation is being checked, then look for
a `Sized` predicate in the parameter environment. This makes the
`ParamEnv` smaller which should improve compiler performance as it avoids
all the iteration over the larger `ParamEnv`.
This commit is contained in:
David Wood 2025-03-17 10:24:56 +00:00
parent 47abf2e144
commit 607eb322a8
No known key found for this signature in database
16 changed files with 268 additions and 40 deletions

View file

@ -6,7 +6,7 @@ use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
use rustc_type_ir::{
self as ty, Interner, Movability, TraitPredicate, TypeVisitableExt as _, TypingMode,
self as ty, Interner, Movability, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode,
Upcast as _, elaborate,
};
use tracing::{debug, instrument, trace};
@ -131,9 +131,11 @@ where
assumption: I::Clause,
) -> Result<(), NoSolution> {
if let Some(trait_clause) = assumption.as_trait_clause() {
if trait_clause.def_id() == goal.predicate.def_id()
&& trait_clause.polarity() == goal.predicate.polarity
{
if trait_clause.polarity() != goal.predicate.polarity {
return Err(NoSolution);
}
if trait_clause.def_id() == goal.predicate.def_id() {
if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
goal.predicate.trait_ref.args,
trait_clause.skip_binder().trait_ref.args,
@ -141,6 +143,17 @@ where
return Ok(());
}
}
// PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
// check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds
// are syntactic sugar for a lack of bounds so don't need this.
if ecx.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::MetaSized)
&& ecx.cx().is_lang_item(trait_clause.def_id(), TraitSolverLangItem::Sized)
{
let meta_sized_clause =
trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
return Self::fast_reject_assumption(ecx, goal, meta_sized_clause);
}
}
Err(NoSolution)
@ -154,6 +167,17 @@ where
) -> QueryResult<I> {
let trait_clause = assumption.as_trait_clause().unwrap();
// PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
// check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds
// are syntactic sugar for a lack of bounds so don't need this.
if ecx.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::MetaSized)
&& ecx.cx().is_lang_item(trait_clause.def_id(), TraitSolverLangItem::Sized)
{
let meta_sized_clause =
trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
return Self::match_assumption(ecx, goal, meta_sized_clause, then);
}
let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;
@ -817,6 +841,25 @@ where
}
}
/// Small helper function to change the `def_id` of a trait predicate - this is not normally
/// something that you want to do, as different traits will require different args and so making
/// it easy to change the trait is something of a footgun, but it is useful in the narrow
/// circumstance of changing from `MetaSized` to `Sized`, which happens as part of the lazy
/// elaboration of sizedness candidates.
#[inline(always)]
fn trait_predicate_with_def_id<I: Interner>(
cx: I,
clause: ty::Binder<I, ty::TraitPredicate<I>>,
did: I::DefId,
) -> I::Clause {
clause
.map_bound(|c| TraitPredicate {
trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
polarity: c.polarity,
})
.upcast(cx)
}
impl<D, I> EvalCtxt<'_, D>
where
D: SolverDelegate<Interner = I>,

View file

@ -462,6 +462,7 @@ fn impl_intersection_has_negative_obligation(
let param_env = infcx.resolve_vars_if_possible(param_env);
util::elaborate(tcx, tcx.predicates_of(impl2_def_id).instantiate(tcx, impl2_header.impl_args))
.elaborate_sized()
.any(|(clause, _)| try_prove_negated_where_clause(infcx, clause, param_env))
}

View file

@ -215,6 +215,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
selcx.infcx.probe(|_| {
let bound = util::lazily_elaborate_sizedness_candidate(
selcx.infcx,
obligation,
bound,
);
// We checked the polarity already
match selcx.match_normalize_trait_ref(
obligation,
@ -259,14 +265,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.caller_bounds()
.iter()
.filter_map(|p| p.as_trait_clause())
// Micro-optimization: filter out predicates relating to different traits.
.filter(|p| p.def_id() == stack.obligation.predicate.def_id())
// Micro-optimization: filter out predicates with different polarities.
.filter(|p| p.polarity() == stack.obligation.predicate.polarity());
let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
// Keep only those bounds which may apply, and propagate overflow if it occurs.
for bound in bounds {
let bound =
util::lazily_elaborate_sizedness_candidate(self.infcx, stack.obligation, bound);
// Micro-optimization: filter out predicates relating to different traits.
if bound.def_id() != stack.obligation.predicate.def_id() {
continue;
}
let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
continue;

View file

@ -166,10 +166,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
.break_value()
.expect("expected to index into clause that exists");
let candidate = candidate_predicate
let candidate_predicate = candidate_predicate
.as_trait_clause()
.expect("projection candidate is not a trait predicate")
.map_bound(|t| t.trait_ref);
.expect("projection candidate is not a trait predicate");
let candidate_predicate =
util::lazily_elaborate_sizedness_candidate(self.infcx, obligation, candidate_predicate);
let candidate = candidate_predicate.map_bound(|t| t.trait_ref);
let candidate = self.infcx.instantiate_binder_with_fresh_vars(
obligation.cause.span,
@ -226,6 +229,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> PredicateObligations<'tcx> {
debug!(?obligation, ?param, "confirm_param_candidate");
let param = util::lazily_elaborate_sizedness_candidate(
self.infcx,
obligation,
param.upcast(self.infcx.tcx),
)
.map_bound(|p| p.trait_ref);
// During evaluation, we already checked that this
// where-clause trait-ref could be unified with the obligation
// trait-ref. Repeat that unification now without any

View file

@ -4,10 +4,13 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir::LangItem;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::PolyTraitObligation;
pub use rustc_infer::traits::util::*;
use rustc_middle::bug;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{
self, SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
self, PolyTraitPredicate, SizedTraitKind, TraitPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
pub use rustc_next_trait_solver::placeholder::BoundVarReplacer;
use rustc_span::Span;
@ -382,3 +385,39 @@ pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
false
}
/// To improve performance, sizedness traits are not elaborated and so special-casing is required
/// in the trait solver to find a `Sized` candidate for a `MetaSized` obligation. Returns the
/// predicate to used in the candidate for such a `obligation`, given a `candidate`.
pub(crate) fn lazily_elaborate_sizedness_candidate<'tcx>(
infcx: &InferCtxt<'tcx>,
obligation: &PolyTraitObligation<'tcx>,
candidate: PolyTraitPredicate<'tcx>,
) -> PolyTraitPredicate<'tcx> {
if !infcx.tcx.is_lang_item(obligation.predicate.def_id(), LangItem::MetaSized)
|| !infcx.tcx.is_lang_item(candidate.def_id(), LangItem::Sized)
{
return candidate;
}
if obligation.predicate.polarity() != candidate.polarity() {
return candidate;
}
let drcx = DeepRejectCtxt::relate_rigid_rigid(infcx.tcx);
if !drcx.args_may_unify(
obligation.predicate.skip_binder().trait_ref.args,
candidate.skip_binder().trait_ref.args,
) {
return candidate;
}
candidate.map_bound(|c| TraitPredicate {
trait_ref: TraitRef::new_from_args(
infcx.tcx,
obligation.predicate.def_id(),
c.trait_ref.args,
),
polarity: c.polarity,
})
}

View file

@ -4,6 +4,7 @@ use smallvec::smallvec;
use crate::data_structures::HashSet;
use crate::inherent::*;
use crate::lang_items::TraitSolverLangItem;
use crate::outlives::{Component, push_outlives_components};
use crate::{self as ty, Interner, Upcast as _};
@ -18,6 +19,7 @@ pub struct Elaborator<I: Interner, O> {
stack: Vec<O>,
visited: HashSet<ty::Binder<I, ty::PredicateKind<I>>>,
mode: Filter,
elaborate_sized: ElaborateSized,
}
enum Filter {
@ -25,6 +27,12 @@ enum Filter {
OnlySelf,
}
#[derive(Eq, PartialEq)]
enum ElaborateSized {
Yes,
No,
}
/// Describes how to elaborate an obligation into a sub-obligation.
pub trait Elaboratable<I: Interner> {
fn predicate(&self) -> I::Predicate;
@ -77,13 +85,19 @@ pub fn elaborate<I: Interner, O: Elaboratable<I>>(
cx: I,
obligations: impl IntoIterator<Item = O>,
) -> Elaborator<I, O> {
let mut elaborator =
Elaborator { cx, stack: Vec::new(), visited: HashSet::default(), mode: Filter::All };
let mut elaborator = Elaborator {
cx,
stack: Vec::new(),
visited: HashSet::default(),
mode: Filter::All,
elaborate_sized: ElaborateSized::No,
};
elaborator.extend_deduped(obligations);
elaborator
}
impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
/// Adds `obligations` to the stack.
fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = O>) {
// Only keep those bounds that we haven't already seen.
// This is necessary to prevent infinite recursion in some
@ -103,6 +117,13 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
self
}
/// Start elaborating `Sized` - reqd during coherence checking, normally skipped to improve
/// compiler performance.
pub fn elaborate_sized(mut self) -> Self {
self.elaborate_sized = ElaborateSized::Yes;
self
}
fn elaborate(&mut self, elaboratable: &O) {
let cx = self.cx;
@ -111,6 +132,19 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
return;
};
// PERF(sized-hierarchy): To avoid iterating over sizedness supertraits in
// parameter environments, as an optimisation, sizedness supertraits aren't
// elaborated, so check if a `Sized` obligation is being elaborated to a
// `MetaSized` obligation and emit it. Candidate assembly and confirmation
// are modified to check for the `Sized` subtrait when a `MetaSized` obligation
// is present.
if self.elaborate_sized == ElaborateSized::No
&& let Some(did) = clause.as_trait_clause().map(|c| c.def_id())
&& self.cx.is_lang_item(did, TraitSolverLangItem::Sized)
{
return;
}
let bound_clause = clause.kind();
match bound_clause.skip_binder() {
ty::ClauseKind::Trait(data) => {

View file

@ -36,7 +36,6 @@ LL | type Assoc<P: Eq>: std::ops::Deref<Target = ()>
= note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(Projection, AliasTy { args: [Self/#0, T/#1, P/#2], def_id: DefId(..), .. })], def_id: DefId(..), .. }, Term::Ty(())), bound_vars: [] }
= note: Binder { value: TraitPredicate(<<Self as Trait<T>>::Assoc<P> as std::ops::Deref>, polarity:Positive), bound_vars: [] }
= note: Binder { value: TraitPredicate(<<Self as Trait<T>>::Assoc<P> as std::marker::Sized>, polarity:Positive), bound_vars: [] }
= note: Binder { value: TraitPredicate(<<Self as Trait<T>>::Assoc<P> as std::marker::MetaSized>, polarity:Positive), bound_vars: [] }
error: aborting due to 3 previous errors

View file

@ -27,7 +27,9 @@ fn main() {
assert_sized::<Bar<A>>();
//~^ ERROR the size for values of type
//~| ERROR the size for values of type
assert_sized::<Bar<Bar<A>>>();
//~^ ERROR the size for values of type
//~| ERROR the size for values of type
}

View file

@ -59,8 +59,21 @@ help: consider relaxing the implicit `Sized` restriction
LL | fn assert_sized<T: ?Sized>() {}
| ++++++++
error[E0277]: the size for values of type `A` cannot be known
--> $DIR/extern-types-unsized.rs:28:20
|
LL | assert_sized::<Bar<A>>();
| ^^^^^^ doesn't have a known size
|
= help: the trait `MetaSized` is not implemented for `A`
note: required by a bound in `Bar`
--> $DIR/extern-types-unsized.rs:14:12
|
LL | struct Bar<T: ?Sized> {
| ^ required by this bound in `Bar`
error[E0277]: the size for values of type `A` cannot be known at compilation time
--> $DIR/extern-types-unsized.rs:31:20
--> $DIR/extern-types-unsized.rs:32:20
|
LL | assert_sized::<Bar<Bar<A>>>();
| ^^^^^^^^^^^ doesn't have a size known at compile-time
@ -81,6 +94,19 @@ help: consider relaxing the implicit `Sized` restriction
LL | fn assert_sized<T: ?Sized>() {}
| ++++++++
error: aborting due to 4 previous errors
error[E0277]: the size for values of type `A` cannot be known
--> $DIR/extern-types-unsized.rs:32:20
|
LL | assert_sized::<Bar<Bar<A>>>();
| ^^^^^^^^^^^ doesn't have a known size
|
= help: the trait `MetaSized` is not implemented for `A`
note: required by a bound in `Bar`
--> $DIR/extern-types-unsized.rs:14:12
|
LL | struct Bar<T: ?Sized> {
| ^ required by this bound in `Bar`
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -5,7 +5,7 @@ trait A {
type X: ?Sized;
}
fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) //~ ERROR mismatched types
fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) //~ ERROR
where
for<'b> &'b T: A,
<&'static T as A>::X: Sized

View file

@ -0,0 +1,18 @@
//@ check-pass
//@ compile-flags: --crate-type=lib
//@ revisions: old next
//@[next] compile-flags: -Znext-solver
#![feature(sized_hierarchy)]
use std::marker::{PhantomData, MetaSized, PointeeSized};
struct Foo<'a, T: PointeeSized>(*mut &'a (), T);
fn requires_metasized<'a, T: MetaSized>(f: &'a T) {}
fn foo<'a, T: PointeeSized>(f: &Foo<'a, T>)
where
Foo<'a, T>: Sized
{
requires_metasized(f);
}

View file

@ -0,0 +1,18 @@
//@ check-pass
//@ compile-flags: --crate-type=lib
//@ revisions: old next
//@[next] compile-flags: -Znext-solver
#![feature(sized_hierarchy)]
use std::marker::{PhantomData, MetaSized, PointeeSized};
struct Foo<'a, T: PointeeSized>(PhantomData<&'a T>, T);
fn requires_metasized<T: MetaSized>() {}
fn foo<'a, T: 'a + PointeeSized>()
where
Foo<'a, T>: Sized
{
requires_metasized::<Foo<'_, T>>();
}

View file

@ -207,6 +207,7 @@ fn main() {
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time
needs_metasized::<(Foo, Foo)>();
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time
//~| ERROR the size for values of type `main::Foo` cannot be known
needs_pointeesized::<(Foo, Foo)>();
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time

View file

@ -1,5 +1,5 @@
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/impls.rs:239:42
--> $DIR/impls.rs:240:42
|
LL | struct StructAllFieldsMetaSized { x: [u8], y: [u8] }
| ^^^^ doesn't have a size known at compile-time
@ -17,7 +17,7 @@ LL | struct StructAllFieldsMetaSized { x: Box<[u8]>, y: [u8] }
| ++++ +
error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
--> $DIR/impls.rs:247:40
--> $DIR/impls.rs:248:40
|
LL | struct StructAllFieldsUnsized { x: Foo, y: Foo }
| ^^^ doesn't have a size known at compile-time
@ -35,7 +35,7 @@ LL | struct StructAllFieldsUnsized { x: Box<Foo>, y: Foo }
| ++++ +
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/impls.rs:283:44
--> $DIR/impls.rs:284:44
|
LL | enum EnumAllFieldsMetaSized { Qux { x: [u8], y: [u8] } }
| ^^^^ doesn't have a size known at compile-time
@ -53,7 +53,7 @@ LL | enum EnumAllFieldsMetaSized { Qux { x: Box<[u8]>, y: [u8] } }
| ++++ +
error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
--> $DIR/impls.rs:290:42
--> $DIR/impls.rs:291:42
|
LL | enum EnumAllFieldsUnsized { Qux { x: Foo, y: Foo } }
| ^^^ doesn't have a size known at compile-time
@ -71,7 +71,7 @@ LL | enum EnumAllFieldsUnsized { Qux { x: Box<Foo>, y: Foo } }
| ++++ +
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/impls.rs:297:52
--> $DIR/impls.rs:298:52
|
LL | enum EnumLastFieldMetaSized { Qux { x: u32, y: [u8] } }
| ^^^^ doesn't have a size known at compile-time
@ -89,7 +89,7 @@ LL | enum EnumLastFieldMetaSized { Qux { x: u32, y: Box<[u8]> } }
| ++++ +
error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
--> $DIR/impls.rs:304:50
--> $DIR/impls.rs:305:50
|
LL | enum EnumLastFieldUnsized { Qux { x: u32, y: Foo } }
| ^^^ doesn't have a size known at compile-time
@ -216,8 +216,22 @@ LL | needs_metasized::<(Foo, Foo)>();
= help: the trait `Sized` is not implemented for `main::Foo`
= note: only the last element of a tuple may have a dynamically sized type
error[E0277]: the size for values of type `main::Foo` cannot be known
--> $DIR/impls.rs:208:23
|
LL | needs_metasized::<(Foo, Foo)>();
| ^^^^^^^^^^ doesn't have a known size
|
= help: within `(main::Foo, main::Foo)`, the trait `MetaSized` is not implemented for `main::Foo`
= note: required because it appears within the type `(main::Foo, main::Foo)`
note: required by a bound in `needs_metasized`
--> $DIR/impls.rs:16:23
|
LL | fn needs_metasized<T: MetaSized>() { }
| ^^^^^^^^^ required by this bound in `needs_metasized`
error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
--> $DIR/impls.rs:210:26
--> $DIR/impls.rs:211:26
|
LL | needs_pointeesized::<(Foo, Foo)>();
| ^^^^^^^^^^ doesn't have a size known at compile-time
@ -226,7 +240,7 @@ LL | needs_pointeesized::<(Foo, Foo)>();
= note: only the last element of a tuple may have a dynamically sized type
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/impls.rs:214:19
--> $DIR/impls.rs:215:19
|
LL | needs_sized::<(u32, [u8])>();
| ^^^^^^^^^^^ doesn't have a size known at compile-time
@ -240,7 +254,7 @@ LL | fn needs_sized<T: Sized>() { }
| ^^^^^ required by this bound in `needs_sized`
error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
--> $DIR/impls.rs:220:19
--> $DIR/impls.rs:221:19
|
LL | needs_sized::<(u32, Foo)>();
| ^^^^^^^^^^ doesn't have a size known at compile-time
@ -254,7 +268,7 @@ LL | fn needs_sized<T: Sized>() { }
| ^^^^^ required by this bound in `needs_sized`
error[E0277]: the size for values of type `main::Foo` cannot be known
--> $DIR/impls.rs:222:23
--> $DIR/impls.rs:223:23
|
LL | needs_metasized::<(u32, Foo)>();
| ^^^^^^^^^^ doesn't have a known size
@ -268,14 +282,14 @@ LL | fn needs_metasized<T: MetaSized>() { }
| ^^^^^^^^^ required by this bound in `needs_metasized`
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/impls.rs:241:19
--> $DIR/impls.rs:242:19
|
LL | needs_sized::<StructAllFieldsMetaSized>();
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `StructAllFieldsMetaSized`, the trait `Sized` is not implemented for `[u8]`
note: required because it appears within the type `StructAllFieldsMetaSized`
--> $DIR/impls.rs:239:12
--> $DIR/impls.rs:240:12
|
LL | struct StructAllFieldsMetaSized { x: [u8], y: [u8] }
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -286,14 +300,14 @@ LL | fn needs_sized<T: Sized>() { }
| ^^^^^ required by this bound in `needs_sized`
error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
--> $DIR/impls.rs:249:19
--> $DIR/impls.rs:250:19
|
LL | needs_sized::<StructAllFieldsUnsized>();
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `StructAllFieldsUnsized`, the trait `Sized` is not implemented for `main::Foo`
note: required because it appears within the type `StructAllFieldsUnsized`
--> $DIR/impls.rs:247:12
--> $DIR/impls.rs:248:12
|
LL | struct StructAllFieldsUnsized { x: Foo, y: Foo }
| ^^^^^^^^^^^^^^^^^^^^^^
@ -304,14 +318,14 @@ LL | fn needs_sized<T: Sized>() { }
| ^^^^^ required by this bound in `needs_sized`
error[E0277]: the size for values of type `main::Foo` cannot be known
--> $DIR/impls.rs:251:23
--> $DIR/impls.rs:252:23
|
LL | needs_metasized::<StructAllFieldsUnsized>();
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size
|
= help: within `StructAllFieldsUnsized`, the trait `MetaSized` is not implemented for `main::Foo`
note: required because it appears within the type `StructAllFieldsUnsized`
--> $DIR/impls.rs:247:12
--> $DIR/impls.rs:248:12
|
LL | struct StructAllFieldsUnsized { x: Foo, y: Foo }
| ^^^^^^^^^^^^^^^^^^^^^^
@ -322,14 +336,14 @@ LL | fn needs_metasized<T: MetaSized>() { }
| ^^^^^^^^^ required by this bound in `needs_metasized`
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/impls.rs:257:19
--> $DIR/impls.rs:258:19
|
LL | needs_sized::<StructLastFieldMetaSized>();
| ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `StructLastFieldMetaSized`, the trait `Sized` is not implemented for `[u8]`
note: required because it appears within the type `StructLastFieldMetaSized`
--> $DIR/impls.rs:256:12
--> $DIR/impls.rs:257:12
|
LL | struct StructLastFieldMetaSized { x: u32, y: [u8] }
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -340,14 +354,14 @@ LL | fn needs_sized<T: Sized>() { }
| ^^^^^ required by this bound in `needs_sized`
error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
--> $DIR/impls.rs:264:19
--> $DIR/impls.rs:265:19
|
LL | needs_sized::<StructLastFieldUnsized>();
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `StructLastFieldUnsized`, the trait `Sized` is not implemented for `main::Foo`
note: required because it appears within the type `StructLastFieldUnsized`
--> $DIR/impls.rs:263:12
--> $DIR/impls.rs:264:12
|
LL | struct StructLastFieldUnsized { x: u32, y: Foo }
| ^^^^^^^^^^^^^^^^^^^^^^
@ -358,14 +372,14 @@ LL | fn needs_sized<T: Sized>() { }
| ^^^^^ required by this bound in `needs_sized`
error[E0277]: the size for values of type `main::Foo` cannot be known
--> $DIR/impls.rs:266:23
--> $DIR/impls.rs:267:23
|
LL | needs_metasized::<StructLastFieldUnsized>();
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size
|
= help: within `StructLastFieldUnsized`, the trait `MetaSized` is not implemented for `main::Foo`
note: required because it appears within the type `StructLastFieldUnsized`
--> $DIR/impls.rs:263:12
--> $DIR/impls.rs:264:12
|
LL | struct StructLastFieldUnsized { x: u32, y: Foo }
| ^^^^^^^^^^^^^^^^^^^^^^
@ -375,6 +389,6 @@ note: required by a bound in `needs_metasized`
LL | fn needs_metasized<T: MetaSized>() { }
| ^^^^^^^^^ required by this bound in `needs_metasized`
error: aborting due to 26 previous errors
error: aborting due to 27 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -39,6 +39,7 @@ pub fn pointeesized() -> Box<impl Tr + PointeeSized> {
//~^ ERROR: the size for values of type `impl Tr + PointeeSized` cannot be known
let y: Box<dyn Tr> = x;
//~^ ERROR: the size for values of type `impl Tr + PointeeSized` cannot be known
//~| ERROR: the size for values of type `impl Tr + PointeeSized` cannot be known
}
Box::new(1u32)
}

View file

@ -45,6 +45,15 @@ LL | let y: Box<dyn Tr> = x;
= help: the trait `Sized` is not implemented for `impl Tr + PointeeSized`
= note: required for the cast from `Box<impl Tr + PointeeSized>` to `Box<dyn Tr>`
error: aborting due to 5 previous errors
error[E0277]: the size for values of type `impl Tr + PointeeSized` cannot be known
--> $DIR/pretty-print-opaque.rs:40:30
|
LL | let y: Box<dyn Tr> = x;
| ^ doesn't have a known size
|
= help: the trait `MetaSized` is not implemented for `impl Tr + PointeeSized`
= note: required for the cast from `Box<impl Tr + PointeeSized>` to `Box<dyn Tr>`
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0277`.