diff options
| author | David Wood <david.wood2@arm.com> | 2025-01-16 14:27:49 +0000 |
|---|---|---|
| committer | David Wood <david.wood2@arm.com> | 2025-06-16 15:00:22 +0000 |
| commit | 3b0e1c17d285f5e8f93c07b5fc8f9c6aa277c0dd (patch) | |
| tree | e27b0db7c88b60332b6790cf4aaeadca99ab8911 | |
| parent | d43da6f4de19ccfc6ac5a8e6b16ab8cf2893692a (diff) | |
| download | rust-3b0e1c17d285f5e8f93c07b5fc8f9c6aa277c0dd.tar.gz rust-3b0e1c17d285f5e8f93c07b5fc8f9c6aa277c0dd.zip | |
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).
22 files changed, 907 insertions, 220 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b8dc01cbc03..20d0e87b7a7 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -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) diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 9ed1f10455a..4d914c42cfc 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -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>; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 15e8c1ef3cc..e4fcd7e56f1 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -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( diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index d92b4f9c06b..6d5a3abf665 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -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 } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0402d098822..97408e31854 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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}; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index cbf545c01c5..2adda8263a1 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -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, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 434e2a818bd..a300558c0c9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -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) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 4a2a7761f7f..f39d3226009 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -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![])) } diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index dda00a0a2c5..1690c908d12 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -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( diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 42aeb170d6b..d51c87fe68e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -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( diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 50a7647be62..a8bbc2d60f1 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -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, - ) - } - - 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, + |ecx, ty| { + structural_traits::instantiate_constituent_tys_for_sizedness_trait( + ecx, sizedness, ty, + ) + }, ) } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 93ffea3b031..b7be73a3c2b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -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 diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 93d3e3ba2a8..b2d2f1188c3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -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:?})"), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1b9b68fa980..9c0ccb26e53 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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())) } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 11becea998c..923c9242ff8 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -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::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) - }), + ty::Str | ty::Slice(..) | ty::Dynamic(_, _, ty::Dyn) => match sizedness { + // Never `Sized` + SizedTraitKind::Sized => Some(ty), + // Always `MetaSized` + SizedTraitKind::MetaSized => None, + }, - // 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. +/// +/// 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 /// -/// In fact, there are only a few options for the types in the constraint: -/// - an obviously-unsized type +/// 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, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 436ab9f80b6..608efc7515c 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -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; diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index ba777c7c59a..bbbeaa29f84 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -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, + }) + } +} diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr index fe662dd48f4..7db2abc5ffe 100644 --- a/tests/ui/attributes/dump-preds.stderr +++ b/tests/ui/attributes/dump-preds.stderr @@ -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 diff --git a/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs b/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs index bc81a7e6c38..5e2a76ba254 100644 --- a/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs +++ b/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs @@ -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>(); diff --git a/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr b/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr index 64f544c5d8f..8cbea3b6ba4 100644 --- a/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr +++ b/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr @@ -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`. diff --git a/tests/ui/sized-hierarchy/impls.rs b/tests/ui/sized-hierarchy/impls.rs new file mode 100644 index 00000000000..b05313dccae --- /dev/null +++ b/tests/ui/sized-hierarchy/impls.rs @@ -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>(); +} diff --git a/tests/ui/sized-hierarchy/impls.stderr b/tests/ui/sized-hierarchy/impls.stderr new file mode 100644 index 00000000000..5fffe478663 --- /dev/null +++ b/tests/ui/sized-hierarchy/impls.stderr @@ -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`. |
