trait_sel: {Meta,Pointee}Sized on ?Sized types

Expand the automatic implementation of `MetaSized` and `PointeeSized` so
that it is also implemented on non-`Sized` types, just not `ty::Foreign`
(extern type).
This commit is contained in:
David Wood
2025-01-16 14:27:49 +00:00
parent d43da6f4de
commit 3b0e1c17d2
22 changed files with 907 additions and 220 deletions

View File

@@ -1258,6 +1258,11 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
debug!(?item.owner_id);
let def_id = item.owner_id.def_id;
if tcx.is_lang_item(def_id.into(), LangItem::PointeeSized) {
// `PointeeSized` is removed during lowering.
return Ok(());
}
let trait_def = tcx.trait_def(def_id);
if trait_def.is_marker
|| matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)

View File

@@ -328,6 +328,14 @@ impl Key for (DefId, SimplifiedType) {
}
}
impl Key for (DefId, ty::SizedTraitKind) {
type Cache<V> = DefaultCache<Self, V>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
}
impl<'tcx> Key for GenericArgsRef<'tcx> {
type Cache<V> = DefaultCache<Self, V>;

View File

@@ -81,8 +81,8 @@ use crate::ty::layout::ValidityRequirement;
use crate::ty::print::{PrintTraitRefExt, describe_as_module};
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::{
self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt,
TyCtxtFeed,
self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, SizedTraitKind, Ty,
TyCtxt, TyCtxtFeed,
};
use crate::{dep_graph, mir, thir};
@@ -854,9 +854,10 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
query adt_sized_constraint(key: DefId) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
desc { |tcx| "computing the `Sized` constraint for `{}`", tcx.def_path_str(key) }
query adt_sizedness_constraint(
key: (DefId, SizedTraitKind)
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
desc { |tcx| "computing the sizedness constraint for `{}`", tcx.def_path_str(key.0) }
}
query adt_dtorck_constraint(

View File

@@ -229,8 +229,12 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
)
}
fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
self.sized_constraint(tcx)
fn sizedness_constraint(
self,
tcx: TyCtxt<'tcx>,
sizedness: ty::SizedTraitKind,
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
self.sizedness_constraint(tcx, sizedness)
}
fn is_fundamental(self) -> bool {
@@ -634,10 +638,15 @@ impl<'tcx> AdtDef<'tcx> {
tcx.adt_async_destructor(self.did())
}
/// Returns a type such that `Self: Sized` if and only if that type is `Sized`,
/// or `None` if the type is always sized.
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
if self.is_struct() { tcx.adt_sized_constraint(self.did()) } else { None }
/// If this ADT is a struct, returns a type such that `Self: {Meta,Pointee,}Sized` if and only
/// if that type is `{Meta,Pointee,}Sized`, or `None` if this ADT is always
/// `{Meta,Pointee,}Sized`.
pub fn sizedness_constraint(
self,
tcx: TyCtxt<'tcx>,
sizedness: ty::SizedTraitKind,
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
if self.is_struct() { tcx.adt_sizedness_constraint((self.did(), sizedness)) } else { None }
}
}

View File

@@ -60,6 +60,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt;
)]
use rustc_type_ir::inherent;
pub use rustc_type_ir::relate::VarianceDiagInfo;
pub use rustc_type_ir::solve::SizedTraitKind;
pub use rustc_type_ir::*;
#[allow(hidden_glob_reexports, unused_imports)]
use rustc_type_ir::{InferCtxtLike, Interner};

View File

@@ -1816,7 +1816,7 @@ impl<'tcx> Ty<'tcx> {
ty::Tuple(tys) => tys.last().is_none_or(|ty| ty.is_trivially_sized(tcx)),
ty::Adt(def, args) => def
.sized_constraint(tcx)
.sizedness_constraint(tcx, ty::SizedTraitKind::Sized)
.is_none_or(|ty| ty.instantiate(tcx, args).is_trivially_sized(tcx)),
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false,

View File

@@ -8,6 +8,7 @@ use std::ops::ControlFlow;
use derive_where::derive_where;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::{
self as ty, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _,
TypeVisitor, TypingMode, Upcast as _, elaborate,
@@ -203,31 +204,15 @@ where
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution>;
/// A type is `Sized` if its tail component is `Sized`.
/// A type is `Sized` if its tail component is `Sized` and a type is `MetaSized` if its tail
/// component is `MetaSized`.
///
/// These components are given by built-in rules from
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
fn consider_builtin_sized_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution>;
/// A type is `MetaSized` if its tail component is `MetaSized`.
///
/// These components are given by built-in rules from
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
fn consider_builtin_meta_sized_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution>;
/// A type is `PointeeSized` if its tail component is `PointeeSized`.
///
/// These components are given by built-in rules from
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
fn consider_builtin_pointee_sized_candidate(
/// [`structural_traits::instantiate_constituent_tys_for_sizedness_trait`].
fn consider_builtin_sizedness_candidates(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
sizedness: SizedTraitKind,
) -> Result<Candidate<I>, NoSolution>;
/// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
@@ -484,12 +469,14 @@ where
G::consider_trait_alias_candidate(self, goal)
} else {
match cx.as_lang_item(trait_def_id) {
Some(TraitSolverLangItem::Sized) => G::consider_builtin_sized_candidate(self, goal),
Some(TraitSolverLangItem::Sized) => {
G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::Sized)
}
Some(TraitSolverLangItem::MetaSized) => {
G::consider_builtin_meta_sized_candidate(self, goal)
G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::MetaSized)
}
Some(TraitSolverLangItem::PointeeSized) => {
G::consider_builtin_pointee_sized_candidate(self, goal)
unreachable!("`PointeeSized` is removed during lowering");
}
Some(TraitSolverLangItem::Copy | TraitSolverLangItem::Clone) => {
G::consider_builtin_copy_clone_candidate(self, goal)

View File

@@ -5,6 +5,7 @@ use derive_where::derive_where;
use rustc_type_ir::data_structures::HashMap;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::solve::inspect::ProbeKind;
use rustc_type_ir::{
self as ty, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable,
@@ -104,8 +105,9 @@ where
}
#[instrument(level = "trace", skip(ecx), ret)]
pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<D, I>(
pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
ecx: &EvalCtxt<'_, D>,
sizedness: SizedTraitKind,
ty: I::Ty,
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
where
@@ -113,8 +115,9 @@ where
I: Interner,
{
match ty.kind() {
// impl Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char, &mut? T, [T; N], dyn* Trait, !
// impl Sized for Coroutine, CoroutineWitness, Closure, CoroutineClosure
// impl {Meta,}Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char
// impl {Meta,}Sized for &mut? T, [T; N], dyn* Trait, !, Coroutine, CoroutineWitness
// impl {Meta,}Sized for Closure, CoroutineClosure
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Uint(_)
| ty::Int(_)
@@ -135,13 +138,16 @@ where
| ty::Dynamic(_, _, ty::DynStar)
| ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
ty::Str
| ty::Slice(_)
| ty::Dynamic(..)
| ty::Foreign(..)
| ty::Alias(..)
| ty::Param(_)
| ty::Placeholder(..) => Err(NoSolution),
// impl {Meta,}Sized for str, [T], dyn Trait
ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
SizedTraitKind::Sized => Err(NoSolution),
SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
},
// impl {} for extern type
ty::Foreign(..) => Err(NoSolution),
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
ty::Bound(..)
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
@@ -150,22 +156,27 @@ where
ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
// impl Sized for ()
// impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1
// impl {Meta,}Sized for ()
// impl {Meta,}Sized for (T1, T2, .., Tn) where Tn: {Meta,}Sized if n >= 1
ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
// impl Sized for Adt<Args...> where sized_constraint(Adt)<Args...>: Sized
// `sized_constraint(Adt)` is the deepest struct trail that can be determined
// by the definition of `Adt`, independent of the generic args.
// impl Sized for Adt<Args...> if sized_constraint(Adt) == None
// As a performance optimization, `sized_constraint(Adt)` can return `None`
// if the ADTs definition implies that it is sized by for all possible args.
// impl {Meta,}Sized for Adt<Args...>
// where {meta,pointee,}sized_constraint(Adt)<Args...>: {Meta,}Sized
//
// `{meta,pointee,}sized_constraint(Adt)` is the deepest struct trail that can be
// determined by the definition of `Adt`, independent of the generic args.
//
// impl {Meta,}Sized for Adt<Args...>
// if {meta,pointee,}sized_constraint(Adt) == None
//
// As a performance optimization, `{meta,pointee,}sized_constraint(Adt)` can return `None`
// if the ADTs definition implies that it is {meta,}sized by for all possible args.
// In this case, the builtin impl will have no nested subgoals. This is a
// "best effort" optimization and `sized_constraint` may return `Some`, even
// if the ADT is sized for all possible args.
// "best effort" optimization and `{meta,pointee,}sized_constraint` may return `Some`,
// even if the ADT is {meta,pointee,}sized for all possible args.
ty::Adt(def, args) => {
if let Some(sized_crit) = def.sized_constraint(ecx.cx()) {
Ok(ty::Binder::dummy(vec![sized_crit.instantiate(ecx.cx(), args)]))
if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args)]))
} else {
Ok(ty::Binder::dummy(vec![]))
}

View File

@@ -4,6 +4,7 @@
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::solve::inspect::ProbeKind;
use rustc_type_ir::{self as ty, Interner, elaborate};
use tracing::instrument;
@@ -198,25 +199,12 @@ where
unreachable!("trait aliases are never const")
}
fn consider_builtin_sized_candidate(
fn consider_builtin_sizedness_candidates(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
_sizedness: SizedTraitKind,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("Sized is never const")
}
fn consider_builtin_meta_sized_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("MetaSized is never const")
}
fn consider_builtin_pointee_sized_candidate(
_ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("PointeeSized is never const")
unreachable!("Sized/MetaSized is never const")
}
fn consider_builtin_copy_clone_candidate(

View File

@@ -6,6 +6,7 @@ mod opaque_types;
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::SizedTraitKind;
use rustc_type_ir::{self as ty, Interner, NormalizesTo, PredicateKind, Upcast as _};
use tracing::instrument;
@@ -413,25 +414,12 @@ where
panic!("trait aliases do not have associated types: {:?}", goal);
}
fn consider_builtin_sized_candidate(
fn consider_builtin_sizedness_candidates(
_ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
_sizedness: SizedTraitKind,
) -> Result<Candidate<I>, NoSolution> {
panic!("`Sized` does not have an associated type: {:?}", goal);
}
fn consider_builtin_meta_sized_candidate(
_ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
panic!("`MetaSized` does not have an associated type: {:?}", goal);
}
fn consider_builtin_pointee_sized_candidate(
_ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
panic!("`PointeeSized` does not have an associated type: {:?}", goal);
panic!("`Sized`/`MetaSized` does not have an associated type: {:?}", goal);
}
fn consider_builtin_copy_clone_candidate(

View File

@@ -4,7 +4,7 @@ use rustc_type_ir::data_structures::IndexSet;
use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::solve::CanonicalResponse;
use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind};
use rustc_type_ir::{
self as ty, Interner, Movability, TraitPredicate, TypeVisitableExt as _, TypingMode,
Upcast as _, elaborate,
@@ -245,9 +245,10 @@ where
})
}
fn consider_builtin_sized_candidate(
fn consider_builtin_sizedness_candidates(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
sizedness: SizedTraitKind,
) -> Result<Candidate<I>, NoSolution> {
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
return Err(NoSolution);
@@ -256,37 +257,11 @@ where
ecx.probe_and_evaluate_goal_for_constituent_tys(
CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
goal,
structural_traits::instantiate_constituent_tys_for_sized_trait,
|ecx, ty| {
structural_traits::instantiate_constituent_tys_for_sizedness_trait(
ecx, sizedness, ty,
)
}
fn consider_builtin_meta_sized_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
return Err(NoSolution);
}
ecx.probe_and_evaluate_goal_for_constituent_tys(
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
goal,
structural_traits::instantiate_constituent_tys_for_sized_trait,
)
}
fn consider_builtin_pointee_sized_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
return Err(NoSolution);
}
ecx.probe_and_evaluate_goal_for_constituent_tys(
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
goal,
structural_traits::instantiate_constituent_tys_for_sized_trait,
},
)
}

View File

@@ -14,7 +14,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind};
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode, elaborate};
use rustc_middle::ty::{self, SizedTraitKind, Ty, TypeVisitableExt, TypingMode, elaborate};
use rustc_middle::{bug, span_bug};
use tracing::{debug, instrument, trace};
@@ -87,13 +87,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
candidates.vec.push(BuiltinCandidate { has_nested: false });
}
Some(LangItem::Sized) => {
self.assemble_builtin_sized_candidate(obligation, &mut candidates);
self.assemble_builtin_sized_candidate(
obligation,
&mut candidates,
SizedTraitKind::Sized,
);
}
Some(LangItem::MetaSized) => {
self.assemble_builtin_sized_candidate(obligation, &mut candidates);
self.assemble_builtin_sized_candidate(
obligation,
&mut candidates,
SizedTraitKind::MetaSized,
);
}
Some(LangItem::PointeeSized) => {
self.assemble_builtin_sized_candidate(obligation, &mut candidates);
bug!("`PointeeSized` is removed during lowering");
}
Some(LangItem::Unsize) => {
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
@@ -1092,15 +1100,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
/// Assembles the trait which are built-in to the language itself:
/// `Copy`, `Clone` and `Sized`.
/// Assembles the `Sized` and `MetaSized` traits which are built-in to the language itself.
#[instrument(level = "debug", skip(self, candidates))]
fn assemble_builtin_sized_candidate(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
sizedness: SizedTraitKind,
) {
match self.sized_conditions(obligation) {
match self.sizedness_conditions(obligation, sizedness) {
BuiltinImplConditions::Where(nested) => {
candidates
.vec

View File

@@ -14,7 +14,9 @@ use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk};
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, Upcast, elaborate};
use rustc_middle::ty::{
self, GenericArgsRef, Region, SizedTraitKind, Ty, TyCtxt, Upcast, elaborate,
};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use thin_vec::thin_vec;
@@ -251,9 +253,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let obligations = if has_nested {
let trait_def = obligation.predicate.def_id();
let conditions = match tcx.as_lang_item(trait_def) {
Some(LangItem::Sized) => self.sized_conditions(obligation),
Some(LangItem::MetaSized) => self.sized_conditions(obligation),
Some(LangItem::PointeeSized) => self.sized_conditions(obligation),
Some(LangItem::Sized) => {
self.sizedness_conditions(obligation, SizedTraitKind::Sized)
}
Some(LangItem::MetaSized) => {
self.sizedness_conditions(obligation, SizedTraitKind::MetaSized)
}
Some(LangItem::PointeeSized) => {
bug!("`PointeeSized` is removing during lowering");
}
Some(LangItem::Copy | LangItem::Clone) => self.copy_clone_conditions(obligation),
Some(LangItem::FusedIterator) => self.fused_iterator_conditions(obligation),
other => bug!("unexpected builtin trait {trait_def:?} ({other:?})"),

View File

@@ -27,8 +27,8 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::TypeErrorToStringExt;
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
use rustc_middle::ty::{
self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable,
TypeVisitableExt, TypingMode, Upcast, elaborate,
self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt,
TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate,
};
use rustc_span::{Symbol, sym};
use tracing::{debug, instrument, trace};
@@ -2094,9 +2094,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
impl<'tcx> SelectionContext<'_, 'tcx> {
fn sized_conditions(
fn sizedness_conditions(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
sizedness: SizedTraitKind,
) -> BuiltinImplConditions<'tcx> {
use self::BuiltinImplConditions::{Ambiguous, None, Where};
@@ -2126,7 +2127,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
Where(ty::Binder::dummy(Vec::new()))
}
ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None,
ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
SizedTraitKind::Sized => None,
SizedTraitKind::MetaSized => Where(ty::Binder::dummy(Vec::new())),
},
ty::Foreign(..) => None,
ty::Tuple(tys) => Where(
obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])),
@@ -2135,11 +2141,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
ty::Pat(ty, _) => Where(obligation.predicate.rebind(vec![*ty])),
ty::Adt(def, args) => {
if let Some(sized_crit) = def.sized_constraint(self.tcx()) {
if let Some(crit) = def.sizedness_constraint(self.tcx(), sizedness) {
// (*) binder moved here
Where(
obligation.predicate.rebind(vec![sized_crit.instantiate(self.tcx(), args)]),
)
Where(obligation.predicate.rebind(vec![crit.instantiate(self.tcx(), args)]))
} else {
Where(ty::Binder::dummy(Vec::new()))
}

View File

@@ -1,23 +1,29 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::LangItem;
use rustc_hir::def::DefKind;
use rustc_index::bit_set::DenseBitSet;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::{
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, fold_regions,
self, SizedTraitKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast,
fold_regions,
};
use rustc_span::DUMMY_SP;
use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
use rustc_trait_selection::traits;
use tracing::instrument;
/// If `ty` implements the given `sizedness` trait, returns `None`. Otherwise, returns the type
/// that must implement the given `sizedness` for `ty` to implement it.
#[instrument(level = "debug", skip(tcx), ret)]
fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
fn sizedness_constraint_for_ty<'tcx>(
tcx: TyCtxt<'tcx>,
sizedness: SizedTraitKind,
ty: Ty<'tcx>,
) -> Option<Ty<'tcx>> {
match ty.kind() {
// these are always sized
// Always `Sized` or `MetaSized`
ty::Bool
| ty::Char
| ty::Int(..)
@@ -35,31 +41,40 @@ fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'
| ty::Never
| ty::Dynamic(_, _, ty::DynStar) => None,
// these are never sized
ty::Str | ty::Slice(..) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => Some(ty),
ty::Str | ty::Slice(..) | ty::Dynamic(_, _, ty::Dyn) => match sizedness {
// Never `Sized`
SizedTraitKind::Sized => Some(ty),
// Always `MetaSized`
SizedTraitKind::MetaSized => None,
},
ty::Pat(ty, _) => sized_constraint_for_ty(tcx, *ty),
ty::Tuple(tys) => tys.last().and_then(|&ty| sized_constraint_for_ty(tcx, ty)),
// recursive case
ty::Adt(adt, args) => adt.sized_constraint(tcx).and_then(|intermediate| {
let ty = intermediate.instantiate(tcx, args);
sized_constraint_for_ty(tcx, ty)
}),
// these can be sized or unsized.
// Maybe `Sized` or `MetaSized`
ty::Param(..) | ty::Alias(..) | ty::Error(_) => Some(ty),
// We cannot instantiate the binder, so just return the *original* type back,
// but only if the inner type has a sized constraint. Thus we skip the binder,
// but don't actually use the result from `sized_constraint_for_ty`.
ty::UnsafeBinder(inner_ty) => {
sized_constraint_for_ty(tcx, inner_ty.skip_binder()).map(|_| ty)
sizedness_constraint_for_ty(tcx, sizedness, inner_ty.skip_binder()).map(|_| ty)
}
// Never `MetaSized` or `Sized`
ty::Foreign(..) => Some(ty),
// Recursive cases
ty::Pat(ty, _) => sizedness_constraint_for_ty(tcx, sizedness, *ty),
ty::Tuple(tys) => {
tys.last().and_then(|&ty| sizedness_constraint_for_ty(tcx, sizedness, ty))
}
ty::Adt(adt, args) => adt.sizedness_constraint(tcx, sizedness).and_then(|intermediate| {
let ty = intermediate.instantiate(tcx, args);
sizedness_constraint_for_ty(tcx, sizedness, ty)
}),
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => {
bug!("unexpected type `{ty:?}` in sized_constraint_for_ty")
bug!("unexpected type `{ty:?}` in `sizedness_constraint_for_ty`")
}
}
}
@@ -75,15 +90,22 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
}
}
/// Calculates the `Sized` constraint.
/// Returns the type of the last field of a struct ("the constraint") which must implement the
/// `sizedness` trait for the whole ADT to be considered to implement that `sizedness` trait.
/// `def_id` is assumed to be the `AdtDef` of a struct and will panic otherwise.
///
/// In fact, there are only a few options for the types in the constraint:
/// - an obviously-unsized type
/// For `Sized`, there are only a few options for the types in the constraint:
/// - an metasized type (str, slices, trait objects, etc)
/// - an pointee-sized type (extern types)
/// - a type parameter or projection whose sizedness can't be known
///
/// For `MetaSized`, there are only a few options for the types in the constraint:
/// - an pointee-sized type (extern types)
/// - a type parameter or projection whose sizedness can't be known
#[instrument(level = "debug", skip(tcx), ret)]
fn adt_sized_constraint<'tcx>(
fn adt_sizedness_constraint<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
(def_id, sizedness): (DefId, SizedTraitKind),
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
if let Some(def_id) = def_id.as_local() {
if let ty::Representability::Infinite(_) = tcx.representability(def_id) {
@@ -93,21 +115,21 @@ fn adt_sized_constraint<'tcx>(
let def = tcx.adt_def(def_id);
if !def.is_struct() {
bug!("`adt_sized_constraint` called on non-struct type: {def:?}");
bug!("`adt_sizedness_constraint` called on non-struct type: {def:?}");
}
let tail_def = def.non_enum_variant().tail_opt()?;
let tail_ty = tcx.type_of(tail_def.did).instantiate_identity();
let constraint_ty = sized_constraint_for_ty(tcx, tail_ty)?;
let constraint_ty = sizedness_constraint_for_ty(tcx, sizedness, tail_ty)?;
// perf hack: if there is a `constraint_ty: Sized` bound, then we know
// perf hack: if there is a `constraint_ty: {Meta,}Sized` bound, then we know
// that the type is sized and do not need to check it on the impl.
let sized_trait_def_id = tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
let sizedness_trait_def_id = sizedness.require_lang_item(tcx);
let predicates = tcx.predicates_of(def.did()).predicates;
if predicates.iter().any(|(p, _)| {
p.as_trait_clause().is_some_and(|trait_pred| {
trait_pred.def_id() == sized_trait_def_id
trait_pred.def_id() == sizedness_trait_def_id
&& trait_pred.self_ty().skip_binder() == constraint_ty
})
}) {
@@ -369,7 +391,7 @@ fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId)
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
asyncness,
adt_sized_constraint,
adt_sizedness_constraint,
param_env,
typing_env_normalized_for_post_analysis,
defaultness,

View File

@@ -11,7 +11,7 @@ use rustc_ast_ir::Mutability;
use crate::elaborate::Elaboratable;
use crate::fold::{TypeFoldable, TypeSuperFoldable};
use crate::relate::Relate;
use crate::solve::AdtDestructorKind;
use crate::solve::{AdtDestructorKind, SizedTraitKind};
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
use crate::{self as ty, CollectAndApply, Interner, UpcastFrom};
@@ -571,7 +571,11 @@ pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
// FIXME: perhaps use `all_fields` and expose `FieldDef`.
fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl IntoIterator<Item = I::Ty>>;
fn sized_constraint(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
fn sizedness_constraint(
self,
interner: I,
sizedness: SizedTraitKind,
) -> Option<ty::EarlyBinder<I, I::Ty>>;
fn is_fundamental(self) -> bool;

View File

@@ -8,6 +8,7 @@ use derive_where::derive_where;
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use crate::lang_items::TraitSolverLangItem;
use crate::search_graph::PathKind;
use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast};
@@ -366,3 +367,24 @@ pub enum AdtDestructorKind {
NotConst,
Const,
}
/// Which sizedness trait - `Sized`, `MetaSized`? `PointeeSized` is omitted as it is removed during
/// lowering.
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub enum SizedTraitKind {
/// `Sized` trait
Sized,
/// `MetaSized` trait
MetaSized,
}
impl SizedTraitKind {
/// Returns `DefId` of corresponding language item.
pub fn require_lang_item<I: Interner>(self, cx: I) -> I::DefId {
cx.require_lang_item(match self {
SizedTraitKind::Sized => TraitSolverLangItem::Sized,
SizedTraitKind::MetaSized => TraitSolverLangItem::MetaSized,
})
}
}

View File

@@ -35,6 +35,7 @@ LL | type Assoc<P: Eq>: std::ops::Deref<Target = ()>
= 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: [] }
= note: Binder { value: TraitPredicate(<<Self as Trait<T>>::Assoc<P> as std::marker::PointeeSized>, polarity:Positive), bound_vars: [] }
error: aborting due to 3 previous errors

View File

@@ -13,9 +13,7 @@ fn main() {
needs_sized::<u8>();
needs_pointeesized::<str>();
//~^ ERROR values of type `str` may or may not have a size
needs_metasized::<str>();
//~^ ERROR the size for values of type `str` cannot be known
needs_sized::<str>();
//~^ ERROR the size for values of type `str` cannot be known at compilation time
@@ -24,7 +22,6 @@ fn main() {
}
needs_pointeesized::<Foo>();
//~^ ERROR values of type `main::Foo` may or may not have a size
needs_metasized::<Foo>();
//~^ ERROR the size for values of type `main::Foo` cannot be known
needs_sized::<Foo>();

View File

@@ -1,31 +1,5 @@
error[E0277]: values of type `str` may or may not have a size
--> $DIR/feature-gate-sized-hierarchy.rs:15:26
|
LL | needs_pointeesized::<str>();
| ^^^ may or may not have a known size
|
= help: the trait `PointeeSized` is not implemented for `str`
note: required by a bound in `needs_pointeesized`
--> $DIR/feature-gate-sized-hierarchy.rs:6:35
|
LL | fn needs_pointeesized<T: ?Sized + PointeeSized>() {}
| ^^^^^^^^^^^^ required by this bound in `needs_pointeesized`
error[E0277]: the size for values of type `str` cannot be known
--> $DIR/feature-gate-sized-hierarchy.rs:17:23
|
LL | needs_metasized::<str>();
| ^^^ doesn't have a known size
|
= help: the trait `MetaSized` is not implemented for `str`
note: required by a bound in `needs_metasized`
--> $DIR/feature-gate-sized-hierarchy.rs:7:32
|
LL | fn needs_metasized<T: ?Sized + MetaSized>() {}
| ^^^^^^^^^ required by this bound in `needs_metasized`
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/feature-gate-sized-hierarchy.rs:19:19
--> $DIR/feature-gate-sized-hierarchy.rs:17:19
|
LL | needs_sized::<str>();
| ^^^ doesn't have a size known at compile-time
@@ -37,21 +11,8 @@ note: required by a bound in `needs_sized`
LL | fn needs_sized<T: Sized>() {}
| ^^^^^ required by this bound in `needs_sized`
error[E0277]: values of type `main::Foo` may or may not have a size
--> $DIR/feature-gate-sized-hierarchy.rs:26:26
|
LL | needs_pointeesized::<Foo>();
| ^^^ may or may not have a known size
|
= help: the trait `PointeeSized` is not implemented for `main::Foo`
note: required by a bound in `needs_pointeesized`
--> $DIR/feature-gate-sized-hierarchy.rs:6:35
|
LL | fn needs_pointeesized<T: ?Sized + PointeeSized>() {}
| ^^^^^^^^^^^^ required by this bound in `needs_pointeesized`
error[E0277]: the size for values of type `main::Foo` cannot be known
--> $DIR/feature-gate-sized-hierarchy.rs:28:23
--> $DIR/feature-gate-sized-hierarchy.rs:25:23
|
LL | needs_metasized::<Foo>();
| ^^^ doesn't have a known size
@@ -64,7 +25,7 @@ LL | fn needs_metasized<T: ?Sized + 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/feature-gate-sized-hierarchy.rs:30:19
--> $DIR/feature-gate-sized-hierarchy.rs:27:19
|
LL | needs_sized::<Foo>();
| ^^^ doesn't have a size known at compile-time
@@ -76,6 +37,6 @@ note: required by a bound in `needs_sized`
LL | fn needs_sized<T: Sized>() {}
| ^^^^^ required by this bound in `needs_sized`
error: aborting due to 6 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@@ -0,0 +1,307 @@
//@ check-fail
//@ edition:2021
#![allow(incomplete_features, internal_features)]
#![feature(sized_hierarchy)]
#![feature(coroutines, dyn_star, extern_types, f16, never_type, unsized_fn_params)]
use std::fmt::Debug;
use std::marker::{MetaSized, PointeeSized};
// This test checks that `Sized` and `MetaSized` are automatically implemented appropriately.
fn needs_sized<T: Sized>() { }
fn takes_sized<T: Sized>(_t: T) { }
fn needs_metasized<T: ?Sized + MetaSized>() { }
fn takes_metasized<T: ?Sized + MetaSized>(_t: T) { }
fn needs_pointeesized<T: ?Sized + PointeeSized>() { }
fn takes_pointeesized<T: ?Sized + PointeeSized>(_t: T) { }
fn main() {
// `bool`
needs_sized::<bool>();
needs_metasized::<bool>();
needs_pointeesized::<bool>();
// `char`
needs_sized::<char>();
needs_metasized::<char>();
needs_pointeesized::<char>();
// `i8`
needs_sized::<i8>();
needs_metasized::<i8>();
needs_pointeesized::<i8>();
// `i16`
needs_sized::<i16>();
needs_metasized::<i16>();
needs_pointeesized::<i16>();
// `i32`
needs_sized::<i32>();
needs_metasized::<i32>();
needs_pointeesized::<i32>();
// `i64`
needs_sized::<i64>();
needs_metasized::<i64>();
needs_pointeesized::<i64>();
// `i128`
needs_sized::<i128>();
needs_metasized::<i128>();
needs_pointeesized::<i128>();
// `u8`
needs_sized::<u8>();
needs_metasized::<u8>();
needs_pointeesized::<u8>();
// `u16`
needs_sized::<u16>();
needs_metasized::<u16>();
needs_pointeesized::<u16>();
// `u32`
needs_sized::<u32>();
needs_metasized::<u32>();
needs_pointeesized::<u32>();
// `u64`
needs_sized::<u64>();
needs_metasized::<u64>();
needs_pointeesized::<u64>();
// `u128`
needs_sized::<u128>();
needs_metasized::<u128>();
needs_pointeesized::<u128>();
// `f16`
needs_sized::<f16>();
needs_metasized::<f16>();
needs_pointeesized::<f16>();
// `f32`
needs_sized::<f32>();
needs_metasized::<f32>();
needs_pointeesized::<f32>();
// `f64`
needs_sized::<f64>();
needs_metasized::<f64>();
needs_pointeesized::<f64>();
// `*const`
needs_sized::<*const u8>();
needs_metasized::<*const u8>();
needs_pointeesized::<*const u8>();
// `*mut`
needs_sized::<*mut u8>();
needs_metasized::<*mut u8>();
needs_pointeesized::<*mut u8>();
// `&`
needs_sized::<&u8>();
needs_metasized::<&u8>();
needs_pointeesized::<&u8>();
// `&mut`
needs_sized::<&mut u8>();
needs_metasized::<&mut u8>();
needs_pointeesized::<&mut u8>();
// fn-def
fn foo(x: u8) -> u8 { x }
takes_sized(foo);
takes_metasized(foo);
takes_pointeesized(foo);
// fn-ptr
takes_sized::<fn(u8) -> u8>(foo);
takes_metasized::<fn(u8) -> u8>(foo);
takes_pointeesized::<fn(u8) -> u8>(foo);
// `[T; x]`
needs_sized::<[u8; 1]>();
needs_metasized::<[u8; 1]>();
needs_pointeesized::<[u8; 1]>();
// `|a| { a }`
takes_sized(|a| { a });
takes_metasized(|a| { a });
takes_pointeesized(|a| { a });
// `async |a| { a }`
takes_sized(async |a| { a });
takes_metasized(async |a| { a });
takes_pointeesized(async |a| { a });
// `|a| { yield a }`
takes_sized(#[coroutine] |a| { yield a });
takes_metasized(#[coroutine] |a| { yield a });
takes_pointeesized(#[coroutine] |a| { yield a });
// `!`
needs_sized::<!>();
needs_metasized::<!>();
needs_pointeesized::<!>();
// `dyn*`
needs_sized::<dyn* Debug>();
needs_metasized::<dyn* Debug>();
needs_pointeesized::<dyn* Debug>();
// `str`
needs_sized::<str>();
//~^ ERROR the size for values of type `str` cannot be known at compilation time
needs_metasized::<str>();
needs_pointeesized::<str>();
// `[T]`
needs_sized::<[u8]>();
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
needs_metasized::<[u8]>();
needs_pointeesized::<[u8]>();
// `dyn Debug`
needs_sized::<dyn Debug>();
//~^ ERROR the size for values of type `dyn Debug` cannot be known at compilation time
needs_metasized::<dyn Debug>();
needs_pointeesized::<dyn Debug>();
// `extern type`
extern "C" {
type Foo;
}
needs_sized::<Foo>();
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time
needs_metasized::<Foo>();
//~^ ERROR the size for values of type `main::Foo` cannot be known
needs_pointeesized::<Foo>();
// empty tuple
needs_sized::<()>();
needs_metasized::<()>();
needs_pointeesized::<()>();
// tuple w/ all elements sized
needs_sized::<(u32, u32)>();
needs_metasized::<(u32, u32)>();
needs_pointeesized::<(u32, u32)>();
// tuple w/ all elements metasized
needs_sized::<([u8], [u8])>();
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
needs_metasized::<([u8], [u8])>();
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
needs_pointeesized::<([u8], [u8])>();
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
// tuple w/ all elements pointeesized
needs_sized::<(Foo, Foo)>();
//~^ 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
needs_pointeesized::<(Foo, Foo)>();
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time
// tuple w/ last element metasized
needs_sized::<(u32, [u8])>();
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
needs_metasized::<(u32, [u8])>();
needs_pointeesized::<(u32, [u8])>();
// tuple w/ last element pointeesized
needs_sized::<(u32, Foo)>();
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time
needs_metasized::<(u32, Foo)>();
//~^ ERROR the size for values of type `main::Foo` cannot be known
needs_pointeesized::<(u32, Foo)>();
// struct w/ no fields
struct StructEmpty {}
needs_sized::<StructEmpty>();
needs_metasized::<StructEmpty>();
needs_pointeesized::<StructEmpty>();
// struct w/ all fields sized
struct StructAllFieldsSized { x: u32, y: u32 }
needs_sized::<StructAllFieldsSized>();
needs_metasized::<StructAllFieldsSized>();
needs_pointeesized::<StructAllFieldsSized>();
// struct w/ all fields metasized
struct StructAllFieldsMetaSized { x: [u8], y: [u8] }
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
needs_sized::<StructAllFieldsMetaSized>();
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
needs_metasized::<StructAllFieldsMetaSized>();
needs_pointeesized::<StructAllFieldsMetaSized>();
// struct w/ all fields unsized
struct StructAllFieldsUnsized { x: Foo, y: Foo }
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time
needs_sized::<StructAllFieldsUnsized>();
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time
needs_metasized::<StructAllFieldsUnsized>();
//~^ ERROR the size for values of type `main::Foo` cannot be known
needs_pointeesized::<StructAllFieldsUnsized>();
// struct w/ last fields metasized
struct StructLastFieldMetaSized { x: u32, y: [u8] }
needs_sized::<StructLastFieldMetaSized>();
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
needs_metasized::<StructLastFieldMetaSized>();
needs_pointeesized::<StructLastFieldMetaSized>();
// struct w/ last fields unsized
struct StructLastFieldUnsized { x: u32, y: Foo }
needs_sized::<StructLastFieldUnsized>();
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time
needs_metasized::<StructLastFieldUnsized>();
//~^ ERROR the size for values of type `main::Foo` cannot be known
needs_pointeesized::<StructLastFieldUnsized>();
// enum w/ no fields
enum EnumEmpty {}
needs_sized::<EnumEmpty>();
needs_metasized::<EnumEmpty>();
needs_pointeesized::<EnumEmpty>();
// enum w/ all variant fields sized
enum EnumAllFieldsSized { Qux { x: u32, y: u32 } }
needs_sized::<StructAllFieldsSized>();
needs_metasized::<StructAllFieldsSized>();
needs_pointeesized::<StructAllFieldsSized>();
// enum w/ all variant fields metasized
enum EnumAllFieldsMetaSized { Qux { x: [u8], y: [u8] } }
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
needs_sized::<EnumAllFieldsMetaSized>();
needs_metasized::<EnumAllFieldsMetaSized>();
needs_pointeesized::<EnumAllFieldsMetaSized>();
// enum w/ all variant fields unsized
enum EnumAllFieldsUnsized { Qux { x: Foo, y: Foo } }
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time
needs_sized::<EnumAllFieldsUnsized>();
needs_metasized::<EnumAllFieldsUnsized>();
needs_pointeesized::<EnumAllFieldsUnsized>();
// enum w/ last variant fields metasized
enum EnumLastFieldMetaSized { Qux { x: u32, y: [u8] } }
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
needs_sized::<EnumLastFieldMetaSized>();
needs_metasized::<EnumLastFieldMetaSized>();
needs_pointeesized::<EnumLastFieldMetaSized>();
// enum w/ last variant fields unsized
enum EnumLastFieldUnsized { Qux { x: u32, y: Foo } }
//~^ ERROR the size for values of type `main::Foo` cannot be known at compilation time
needs_sized::<EnumLastFieldUnsized>();
needs_metasized::<EnumLastFieldUnsized>();
needs_pointeesized::<EnumLastFieldUnsized>();
}

View File

@@ -0,0 +1,380 @@
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/impls.rs:237:42
|
LL | struct StructAllFieldsMetaSized { x: [u8], y: [u8] }
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
= note: only the last field of a struct may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
LL | struct StructAllFieldsMetaSized { x: &[u8], y: [u8] }
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
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:245:40
|
LL | struct StructAllFieldsUnsized { x: Foo, y: Foo }
| ^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `main::Foo`
= note: only the last field of a struct may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
LL | struct StructAllFieldsUnsized { x: &Foo, y: Foo }
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
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:281:44
|
LL | enum EnumAllFieldsMetaSized { Qux { x: [u8], y: [u8] } }
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
= note: no field of an enum variant may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
LL | enum EnumAllFieldsMetaSized { Qux { x: &[u8], y: [u8] } }
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
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:288:42
|
LL | enum EnumAllFieldsUnsized { Qux { x: Foo, y: Foo } }
| ^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `main::Foo`
= note: no field of an enum variant may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
LL | enum EnumAllFieldsUnsized { Qux { x: &Foo, y: Foo } }
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
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:295:52
|
LL | enum EnumLastFieldMetaSized { Qux { x: u32, y: [u8] } }
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
= note: no field of an enum variant may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
LL | enum EnumLastFieldMetaSized { Qux { x: u32, y: &[u8] } }
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
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:302:50
|
LL | enum EnumLastFieldUnsized { Qux { x: u32, y: Foo } }
| ^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `main::Foo`
= note: no field of an enum variant may have a dynamically sized type
= help: change the field's type to have a statically known size
help: borrowed types always have a statically known size
|
LL | enum EnumLastFieldUnsized { Qux { x: u32, y: &Foo } }
| +
help: the `Box` type always has a statically known size and allocates its contents in the heap
|
LL | enum EnumLastFieldUnsized { Qux { x: u32, y: Box<Foo> } }
| ++++ +
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/impls.rs:158:19
|
LL | needs_sized::<str>();
| ^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
note: required by a bound in `needs_sized`
--> $DIR/impls.rs:11:19
|
LL | fn needs_sized<T: Sized>() { }
| ^^^^^ required by this bound in `needs_sized`
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/impls.rs:164:19
|
LL | needs_sized::<[u8]>();
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `needs_sized`
--> $DIR/impls.rs:11:19
|
LL | fn needs_sized<T: Sized>() { }
| ^^^^^ required by this bound in `needs_sized`
error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
--> $DIR/impls.rs:170:19
|
LL | needs_sized::<dyn Debug>();
| ^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn Debug`
note: required by a bound in `needs_sized`
--> $DIR/impls.rs:11:19
|
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:179:19
|
LL | needs_sized::<Foo>();
| ^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `main::Foo`
note: required by a bound in `needs_sized`
--> $DIR/impls.rs:11:19
|
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:181:23
|
LL | needs_metasized::<Foo>();
| ^^^ doesn't have a known size
|
= help: the trait `MetaSized` is not implemented for `main::Foo`
note: required by a bound in `needs_metasized`
--> $DIR/impls.rs:14:32
|
LL | fn needs_metasized<T: ?Sized + 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:196:19
|
LL | needs_sized::<([u8], [u8])>();
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
= 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:198:23
|
LL | needs_metasized::<([u8], [u8])>();
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
= 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:200:26
|
LL | needs_pointeesized::<([u8], [u8])>();
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
= 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 at compilation time
--> $DIR/impls.rs:204:19
|
LL | needs_sized::<(Foo, Foo)>();
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= 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 at compilation time
--> $DIR/impls.rs:206:23
|
LL | needs_metasized::<(Foo, Foo)>();
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= 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 at compilation time
--> $DIR/impls.rs:208:26
|
LL | needs_pointeesized::<(Foo, Foo)>();
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= 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 `[u8]` cannot be known at compilation time
--> $DIR/impls.rs:212:19
|
LL | needs_sized::<(u32, [u8])>();
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `(u32, [u8])`, the trait `Sized` is not implemented for `[u8]`
= note: required because it appears within the type `(u32, [u8])`
note: required by a bound in `needs_sized`
--> $DIR/impls.rs:11:19
|
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:218:19
|
LL | needs_sized::<(u32, Foo)>();
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `(u32, main::Foo)`, the trait `Sized` is not implemented for `main::Foo`
= note: required because it appears within the type `(u32, main::Foo)`
note: required by a bound in `needs_sized`
--> $DIR/impls.rs:11:19
|
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:220:23
|
LL | needs_metasized::<(u32, Foo)>();
| ^^^^^^^^^^ doesn't have a known size
|
= help: within `(u32, main::Foo)`, the trait `MetaSized` is not implemented for `main::Foo`
= note: required because it appears within the type `(u32, main::Foo)`
note: required by a bound in `needs_metasized`
--> $DIR/impls.rs:14:32
|
LL | fn needs_metasized<T: ?Sized + 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:239: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:237:12
|
LL | struct StructAllFieldsMetaSized { x: [u8], y: [u8] }
| ^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `needs_sized`
--> $DIR/impls.rs:11:19
|
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:247: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:245:12
|
LL | struct StructAllFieldsUnsized { x: Foo, y: Foo }
| ^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `needs_sized`
--> $DIR/impls.rs:11:19
|
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:249: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:245:12
|
LL | struct StructAllFieldsUnsized { x: Foo, y: Foo }
| ^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `needs_metasized`
--> $DIR/impls.rs:14:32
|
LL | fn needs_metasized<T: ?Sized + 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:255: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:254:12
|
LL | struct StructLastFieldMetaSized { x: u32, y: [u8] }
| ^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `needs_sized`
--> $DIR/impls.rs:11:19
|
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:262: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:261:12
|
LL | struct StructLastFieldUnsized { x: u32, y: Foo }
| ^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `needs_sized`
--> $DIR/impls.rs:11:19
|
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:264: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:261:12
|
LL | struct StructLastFieldUnsized { x: u32, y: Foo }
| ^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `needs_metasized`
--> $DIR/impls.rs:14:32
|
LL | fn needs_metasized<T: ?Sized + MetaSized>() { }
| ^^^^^^^^^ required by this bound in `needs_metasized`
error: aborting due to 26 previous errors
For more information about this error, try `rustc --explain E0277`.