diff options
| author | David Wood <david.wood2@arm.com> | 2025-02-27 21:19:51 +0000 |
|---|---|---|
| committer | David Wood <david.wood2@arm.com> | 2025-06-16 23:04:33 +0000 |
| commit | 86ab2b60cd22f6190eb586c889f8a2504f0d926b (patch) | |
| tree | c379a930de63e5cb21b83110dccd82c1c3874a25 | |
| parent | f0b84b8dcfc15c3936256ccb438b1d050620ff3c (diff) | |
| download | rust-86ab2b60cd22f6190eb586c889f8a2504f0d926b.tar.gz rust-86ab2b60cd22f6190eb586c889f8a2504f0d926b.zip | |
hir_analysis: add `{Meta,Pointee}Sized` bounds
Opting-out of `Sized` with `?Sized` is now equivalent to adding a `MetaSized` bound, and adding a `MetaSized` or `PointeeSized` bound is equivalent to removing the default `Sized` bound - this commit implements this change in `rustc_hir_analysis::hir_ty_lowering`. `MetaSized` is also added as a supertrait of all traits, as this is necessary to preserve backwards compatibility. Unfortunately, non-global where clauses being preferred over item bounds (where `PointeeSized` bounds would be proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is added to some items. Rather than `PointeeSized` being a bound on everything, it can be the absence of a bound on everything, as `?Sized` was.
20 files changed, 798 insertions, 207 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index c5c7e6b2aa7..5b8aa28102c 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -76,6 +76,7 @@ pub use check::{check_abi, check_abi_fn_ptr, check_custom_abi}; use rustc_abi::{ExternAbi, VariantIdx}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err}; +use rustc_hir::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_index::bit_set::DenseBitSet; @@ -331,7 +332,7 @@ fn bounds_from_generic_predicates<'tcx>( ty::ClauseKind::Trait(trait_predicate) => { let entry = types.entry(trait_predicate.self_ty()).or_default(); let def_id = trait_predicate.def_id(); - if !tcx.is_default_trait(def_id) { + if !tcx.is_default_trait(def_id) && !tcx.is_lang_item(def_id, LangItem::Sized) { // Do not add that restriction to the list if it is a positive requirement. entry.push(trait_predicate.def_id()); } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 5f1cdeddc19..53c44cdc411 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -44,6 +44,14 @@ fn associated_type_bounds<'tcx>( | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { + icx.lowerer().add_sizedness_bounds( + &mut bounds, + item_ty, + hir_bounds, + None, + None, + span, + ); icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span); } // `ConstIfConst` is only interested in `~const` bounds. @@ -333,6 +341,14 @@ fn opaque_type_bounds<'tcx>( | PredicateFilter::SelfOnly | PredicateFilter::SelfTraitThatDefines(_) | PredicateFilter::SelfAndAssociatedTypeBounds => { + icx.lowerer().add_sizedness_bounds( + &mut bounds, + item_ty, + hir_bounds, + None, + None, + span, + ); icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span); } //`ConstIfConst` is only interested in `~const` bounds. diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index ce0f83d0ec2..c337765c5fe 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -162,7 +162,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen .map(|t| ty::Binder::dummy(t.instantiate_identity())); } } - ItemKind::Trait(_, _, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, _, self_bounds) => { is_trait = Some((self_bounds, item.span)); @@ -183,21 +182,29 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // and the explicit where-clauses, but to get the full set of predicates // on a trait we must also consider the bounds that follow the trait's name, // like `trait Foo: A + B + C`. - if let Some(self_bounds) = is_trait { + if let Some((self_bounds, span)) = is_trait { let mut bounds = Vec::new(); icx.lowerer().lower_bounds( tcx.types.self_param, - self_bounds.0, + self_bounds, &mut bounds, ty::List::empty(), PredicateFilter::All, ); + icx.lowerer().add_sizedness_bounds( + &mut bounds, + tcx.types.self_param, + self_bounds, + None, + Some(def_id), + span, + ); icx.lowerer().add_default_super_traits( def_id, &mut bounds, - self_bounds.0, + self_bounds, hir_generics, - self_bounds.1, + span, ); predicates.extend(bounds); } @@ -224,6 +231,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen let param_ty = icx.lowerer().lower_ty_param(param.hir_id); let mut bounds = Vec::new(); // Implicit bounds are added to type params unless a `?Trait` bound is found + icx.lowerer().add_sizedness_bounds( + &mut bounds, + param_ty, + &[], + Some((param.def_id, hir_generics.predicates)), + None, + param.span, + ); icx.lowerer().add_default_traits( &mut bounds, param_ty, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 106420faa4c..ea1dfdfd806 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -4,15 +4,15 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::AmbigArg; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::{AmbigArg, LangItem, PolyTraitRef}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, }; -use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; +use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw}; use rustc_trait_selection::traits; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -23,23 +23,213 @@ use crate::hir_ty_lowering::{ AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason, }; +#[derive(Debug, Default)] +struct CollectedBound { + /// `Trait` + positive: bool, + /// `?Trait` + maybe: bool, + /// `!Trait` + negative: bool, +} + +impl CollectedBound { + /// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered. + fn any(&self) -> bool { + self.positive || self.maybe || self.negative + } +} + +#[derive(Debug)] +struct CollectedSizednessBounds { + // Collected `Sized` bounds + sized: CollectedBound, + // Collected `MetaSized` bounds + meta_sized: CollectedBound, + // Collected `PointeeSized` bounds + pointee_sized: CollectedBound, +} + +impl CollectedSizednessBounds { + /// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered for `Sized`, + /// `MetaSized` or `PointeeSized`. + fn any(&self) -> bool { + self.sized.any() || self.meta_sized.any() || self.pointee_sized.any() + } +} + +fn search_bounds_for<'tcx>( + hir_bounds: &'tcx [hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>), +) { + let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| { + for hir_bound in hir_bounds { + let hir::GenericBound::Trait(ptr) = hir_bound else { + continue; + }; + + f(ptr) + } + }; + + search_bounds(hir_bounds); + if let Some((self_ty, where_clause)) = self_ty_where_predicates { + for clause in where_clause { + if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind + && pred.is_param_bound(self_ty.to_def_id()) + { + search_bounds(pred.bounds); + } + } + } +} + +fn collect_unbounds<'tcx>( + hir_bounds: &'tcx [hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, +) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> { + let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); + search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| { + if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) { + unbounds.push(ptr); + } + }); + unbounds +} + +fn collect_bounds<'a, 'tcx>( + hir_bounds: &'a [hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + target_did: DefId, +) -> CollectedBound { + let mut collect_into = CollectedBound::default(); + search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| { + if !matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) { + return; + } + + match ptr.modifiers.polarity { + hir::BoundPolarity::Maybe(_) => collect_into.maybe = true, + hir::BoundPolarity::Negative(_) => collect_into.negative = true, + hir::BoundPolarity::Positive => collect_into.positive = true, + } + }); + collect_into +} + +fn collect_sizedness_bounds<'tcx>( + tcx: TyCtxt<'tcx>, + hir_bounds: &'tcx [hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + span: Span, +) -> CollectedSizednessBounds { + let sized_did = tcx.require_lang_item(LangItem::Sized, span); + let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did); + + let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span); + let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did); + + let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); + let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did); + + CollectedSizednessBounds { sized, meta_sized, pointee_sized } +} + +/// Add a trait bound for `did`. +fn add_trait_bound<'tcx>( + tcx: TyCtxt<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + self_ty: Ty<'tcx>, + did: DefId, + span: Span, +) { + let trait_ref = ty::TraitRef::new(tcx, did, [self_ty]); + // Preferable to put sizedness obligations first, since we report better errors for `Sized` + // ambiguity. + bounds.insert(0, (trait_ref.upcast(tcx), span)); +} + impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - pub(crate) fn add_default_traits( + /// Skip `PointeeSized` bounds. + /// + /// `PointeeSized` is a "fake bound" insofar as anywhere a `PointeeSized` bound exists, there + /// is actually the absence of any bounds. This avoids limitations around non-global where + /// clauses being preferred over item bounds (where `PointeeSized` bounds would be + /// proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is + /// added to some items. + pub(crate) fn should_skip_sizedness_bound<'hir>( + &self, + bound: &'hir hir::GenericBound<'tcx>, + ) -> bool { + bound + .trait_ref() + .and_then(|tr| tr.trait_def_id()) + .map(|did| self.tcx().is_lang_item(did, LangItem::PointeeSized)) + .unwrap_or(false) + } + + /// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type. + /// + /// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit + /// sizedness bounds are present. + /// - On traits and trait aliases, add default `MetaSized` supertrait if no explicit sizedness + /// bounds are present. + /// - On parameters, opaque type, associated types and trait aliases, add a `MetaSized` bound if + /// a `?Sized` bound is present. + pub(crate) fn add_sizedness_bounds( &self, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, - hir_bounds: &[hir::GenericBound<'tcx>], + hir_bounds: &'tcx [hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + trait_did: Option<LocalDefId>, span: Span, ) { - self.add_default_traits_with_filter( - bounds, - self_ty, - hir_bounds, - self_ty_where_predicates, - span, - |_| true, - ); + let tcx = self.tcx(); + + let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span); + let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); + + // If adding sizedness bounds to a trait, then there are some relevant early exits + if let Some(trait_did) = trait_did { + let trait_did = trait_did.to_def_id(); + // Never add a default supertrait to `PointeeSized`. + if trait_did == pointee_sized_did { + return; + } + // Don't add default sizedness supertraits to auto traits because it isn't possible to + // relax an automatically added supertrait on the defn itself. + if tcx.trait_is_auto(trait_did) { + return; + } + } else { + // Report invalid unbounds on sizedness-bounded generic parameters. + let unbounds = collect_unbounds(hir_bounds, self_ty_where_predicates); + self.check_and_report_invalid_unbounds_on_param(unbounds); + } + + let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span); + if (collected.sized.maybe || collected.sized.negative) + && !collected.sized.positive + && !collected.meta_sized.any() + && !collected.pointee_sized.any() + { + // `?Sized` is equivalent to `MetaSized` (but only add the bound if there aren't any + // other explicit ones) - this can happen for trait aliases as well as bounds. + add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span); + } else if !collected.any() { + if trait_did.is_some() { + // If there are no explicit sizedness bounds on a trait then add a default + // `MetaSized` supertrait. + add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span); + } else { + // If there are no explicit sizedness bounds on a parameter then add a default + // `Sized` bound. + let sized_did = tcx.require_lang_item(LangItem::Sized, span); + add_trait_bound(tcx, bounds, self_ty, sized_did, span); + } + } } /// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds @@ -146,13 +336,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if !self.requires_default_supertraits(trait_bounds, trait_generics) { let self_ty_where_predicates = (parent, trait_item.generics.predicates); - self.add_default_traits_with_filter( + self.add_default_traits( bounds, tcx.types.self_param, &[], Some(self_ty_where_predicates), trait_item.span, - |tr| tr != hir::LangItem::Sized, ); } } @@ -174,41 +363,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias)); if self.requires_default_supertraits(hir_bounds, hir_generics) { let self_ty_where_predicates = (trait_def_id, hir_generics.predicates); - self.add_default_traits_with_filter( + self.add_default_traits( bounds, self.tcx().types.self_param, hir_bounds, Some(self_ty_where_predicates), span, - |default_trait| default_trait != hir::LangItem::Sized, ); } } - pub(crate) fn add_default_traits_with_filter( + pub(crate) fn add_default_traits( &self, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, hir_bounds: &[hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, span: Span, - f: impl Fn(hir::LangItem) -> bool, ) { - self.tcx().default_traits().iter().filter(|&&default_trait| f(default_trait)).for_each( - |default_trait| { - self.add_default_trait( - *default_trait, - bounds, - self_ty, - hir_bounds, - self_ty_where_predicates, - span, - ); - }, - ); + self.tcx().default_traits().iter().for_each(|default_trait| { + self.add_default_trait( + *default_trait, + bounds, + self_ty, + hir_bounds, + self_ty_where_predicates, + span, + ); + }); } - /// Add a `Sized` or `experimental_default_bounds` bounds to the `bounds` if appropriate. + /// Add a `experimental_default_bounds` bound to the `bounds` if appropriate. /// /// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`. pub(crate) fn add_default_trait( @@ -220,7 +405,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, span: Span, ) { - let trait_id = self.tcx().lang_items().get(trait_); + let tcx = self.tcx(); + let trait_id = tcx.lang_items().get(trait_); if let Some(trait_id) = trait_id && self.do_not_provide_default_trait_bound( trait_id, @@ -228,11 +414,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self_ty_where_predicates, ) { - // There was no `?Trait` or `!Trait` bound; - // add `Trait` if it's available. - let trait_ref = ty::TraitRef::new(self.tcx(), trait_id, [self_ty]); - // Preferable to put this obligation first, since we report better errors for sized ambiguity. - bounds.insert(0, (trait_ref.upcast(self.tcx()), span)); + add_trait_bound(tcx, bounds, self_ty, trait_id, span); } } @@ -242,90 +424,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_bounds: &'a [hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, ) -> bool { - let tcx = self.tcx(); - let mut seen_negative_bound = false; - let mut seen_positive_bound = false; - - // Try to find an unbound in bounds. - let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); - let mut search_bounds = |hir_bounds: &'a [hir::GenericBound<'tcx>]| { - for hir_bound in hir_bounds { - let hir::GenericBound::Trait(ptr) = hir_bound else { - continue; - }; - match ptr.modifiers.polarity { - hir::BoundPolarity::Maybe(_) => unbounds.push(ptr), - hir::BoundPolarity::Negative(_) => { - if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) { - seen_negative_bound = true; - } - } - hir::BoundPolarity::Positive => { - if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) { - seen_positive_bound = true; - } - } - } - } - }; - search_bounds(hir_bounds); - if let Some((self_ty, where_clause)) = self_ty_where_predicates { - for clause in where_clause { - if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind - && pred.is_param_bound(self_ty.to_def_id()) - { - search_bounds(pred.bounds); - } - } - } - - let mut unique_bounds = FxIndexSet::default(); - let mut seen_repeat = false; - for unbound in &unbounds { - if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res { - seen_repeat |= !unique_bounds.insert(unbound_def_id); - } - } - if unbounds.len() > 1 { - let err = errors::MultipleRelaxedDefaultBounds { - spans: unbounds.iter().map(|ptr| ptr.span).collect(), - }; - if seen_repeat { - self.dcx().emit_err(err); - } else if !tcx.features().more_maybe_bounds() { - self.tcx().sess.create_feature_err(err, sym::more_maybe_bounds).emit(); - }; - } - - let mut seen_unbound = false; - for unbound in unbounds { - let unbound_def_id = unbound.trait_ref.trait_def_id(); - if unbound_def_id == Some(trait_def_id) { - seen_unbound = true; - } - let emit_relax_err = || { - let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds { - true => "`?Sized` and `experimental_default_bounds`", - false => "`?Sized`", - }; - // There was a `?Trait` bound, but it was neither `?Sized` nor `experimental_default_bounds`. - self.dcx().span_err( - unbound.span, - format!( - "relaxing a default bound only does something for {}; \ - all other traits are not bound by default", - unbound_traits - ), - ); - }; - match unbound_def_id { - Some(def_id) if !tcx.is_default_trait(def_id) => emit_relax_err(), - None => emit_relax_err(), - _ => {} - } - } - - !(seen_unbound || seen_negative_bound || seen_positive_bound) + let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id); + !collected.any() } /// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any. @@ -361,6 +461,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { 'tcx: 'hir, { for hir_bound in hir_bounds { + if self.should_skip_sizedness_bound(hir_bound) { + continue; + } + // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`, // we skip over any traits that don't define the given associated type. if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index c7cdf1d5bd2..05465b47a26 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -61,14 +61,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let ast_bounds: Vec<_> = hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect(); - self.add_default_traits_with_filter( - &mut user_written_bounds, - dummy_self, - &ast_bounds, - None, - span, - |tr| tr != hir::LangItem::Sized, - ); + self.add_default_traits(&mut user_written_bounds, dummy_self, &ast_bounds, None, span); let (elaborated_trait_bounds, elaborated_projection_bounds) = traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied()); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 45fee0fa402..1cda6dff21e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -8,7 +8,7 @@ use rustc_errors::{ }; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId}; +use rustc_hir::{self as hir, HirId, LangItem, PolyTraitRef}; use rustc_middle::bug; use rustc_middle::ty::fast_reject::{TreatParams, simplify_type}; use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; @@ -34,6 +34,57 @@ use crate::fluent_generated as fluent; use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { + /// Check for multiple relaxed default bounds and relaxed bounds of non-sizedness traits. + pub(crate) fn check_and_report_invalid_unbounds_on_param( + &self, + unbounds: SmallVec<[&PolyTraitRef<'_>; 1]>, + ) { + let tcx = self.tcx(); + + let sized_did = tcx.require_lang_item(LangItem::Sized, DUMMY_SP); + + let mut unique_bounds = FxIndexSet::default(); + let mut seen_repeat = false; + for unbound in &unbounds { + if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res { + seen_repeat |= !unique_bounds.insert(unbound_def_id); + } + } + + if unbounds.len() > 1 { + let err = errors::MultipleRelaxedDefaultBounds { + spans: unbounds.iter().map(|ptr| ptr.span).collect(), + }; + + if seen_repeat { + tcx.dcx().emit_err(err); + } else if !tcx.features().more_maybe_bounds() { + tcx.sess.create_feature_err(err, sym::more_maybe_bounds).emit(); + }; + } + + for unbound in unbounds { + if let Res::Def(DefKind::Trait, did) = unbound.trait_ref.path.res + && ((did == sized_did) || tcx.is_default_trait(did)) + { + continue; + } + + let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds { + true => "`?Sized` and `experimental_default_bounds`", + false => "`?Sized`", + }; + self.dcx().span_err( + unbound.span, + format!( + "relaxing a default bound only does something for {}; all other traits are \ + not bound by default", + unbound_traits + ), + ); + } + } + /// On missing type parameters, emit an E0393 error and provide a structured suggestion using /// the type parameter's name as a placeholder. pub(crate) fn report_missing_type_params( diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 850c9207877..f1395c242f2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1619,16 +1619,17 @@ impl<'tcx> TyCtxt<'tcx> { self.reserve_and_set_memory_dedup(alloc, salt) } + /// Traits added on all bounds by default, excluding `Sized` which is treated separately. pub fn default_traits(self) -> &'static [rustc_hir::LangItem] { - match self.sess.opts.unstable_opts.experimental_default_bounds { - true => &[ - LangItem::Sized, + if self.sess.opts.unstable_opts.experimental_default_bounds { + &[ LangItem::DefaultTrait1, LangItem::DefaultTrait2, LangItem::DefaultTrait3, LangItem::DefaultTrait4, - ], - false => &[LangItem::Sized], + ] + } else { + &[] } } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 923c9242ff8..d996ee2b60a 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -95,7 +95,7 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness { /// `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 meta-sized type (str, slices, trait objects, etc) /// - an pointee-sized type (extern types) /// - a type parameter or projection whose sizedness can't be known /// diff --git a/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs b/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs index 5e2a76ba254..33688c2e2ce 100644 --- a/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs +++ b/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs @@ -3,8 +3,8 @@ use std::marker::{MetaSized, PointeeSized}; -fn needs_pointeesized<T: ?Sized + PointeeSized>() {} -fn needs_metasized<T: ?Sized + MetaSized>() {} +fn needs_pointeesized<T: PointeeSized>() {} +fn needs_metasized<T: MetaSized>() {} fn needs_sized<T: Sized>() {} fn main() { diff --git a/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr b/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr index 8cbea3b6ba4..6a35fcfb0e8 100644 --- a/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr +++ b/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr @@ -19,10 +19,10 @@ LL | needs_metasized::<Foo>(); | = help: the trait `MetaSized` is not implemented for `main::Foo` note: required by a bound in `needs_metasized` - --> $DIR/feature-gate-sized-hierarchy.rs:7:32 + --> $DIR/feature-gate-sized-hierarchy.rs:7:23 | -LL | fn needs_metasized<T: ?Sized + MetaSized>() {} - | ^^^^^^^^^ required by this bound in `needs_metasized` +LL | fn needs_metasized<T: MetaSized>() {} + | ^^^^^^^^^ required by this bound in `needs_metasized` error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time --> $DIR/feature-gate-sized-hierarchy.rs:27:19 diff --git a/tests/ui/sized-hierarchy/alias-bounds.rs b/tests/ui/sized-hierarchy/alias-bounds.rs new file mode 100644 index 00000000000..87b4bab11b7 --- /dev/null +++ b/tests/ui/sized-hierarchy/alias-bounds.rs @@ -0,0 +1,28 @@ +//@ check-pass +//@ compile-flags: --crate-type=lib +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +#![feature(sized_hierarchy)] + +use std::marker::{PointeeSized, MetaSized}; + +trait Id: PointeeSized { + type This: PointeeSized; +} + +impl<T: PointeeSized> Id for T { + type This = T; +} + +fn requires_metasized<T: MetaSized>() {} + +fn foo<T>() +where + T: PointeeSized, + <T as Id>::This: Sized +{ + // `T: Sized` from where bounds (`T: PointeeSized` removes any default bounds and + // `<T as Id>::This: Sized` normalizes to `T: Sized`). This should trivially satisfy + // `T: MetaSized`. + requires_metasized::<T>(); +} diff --git a/tests/ui/sized-hierarchy/default-bound.rs b/tests/ui/sized-hierarchy/default-bound.rs new file mode 100644 index 00000000000..12b2eb2b5c1 --- /dev/null +++ b/tests/ui/sized-hierarchy/default-bound.rs @@ -0,0 +1,49 @@ +//@ check-fail +#![feature(extern_types, sized_hierarchy)] + +use std::marker::{MetaSized, PointeeSized}; + +fn bare<T>() {} + + +fn sized<T: Sized>() {} + +fn neg_sized<T: ?Sized>() {} + + +fn metasized<T: MetaSized>() {} + +fn neg_metasized<T: ?MetaSized>() {} +//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + + +fn pointeesized<T: PointeeSized>() { } + +fn neg_pointeesized<T: ?PointeeSized>() { } +//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + + +fn main() { + // Functions which should have a `T: Sized` bound - check for an error given a non-Sized type: + + bare::<[u8]>(); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + sized::<[u8]>(); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + metasized::<[u8]>(); + pointeesized::<[u8]>(); + + // Functions which should have a `T: MetaSized` bound - check for an error given a + // non-MetaSized type: + unsafe extern "C" { + type Foo; + } + + bare::<Foo>(); + //~^ ERROR the size for values of type `main::Foo` cannot be known + sized::<Foo>(); + //~^ ERROR the size for values of type `main::Foo` cannot be known + metasized::<Foo>(); + //~^ ERROR the size for values of type `main::Foo` cannot be known + pointeesized::<Foo>(); +} diff --git a/tests/ui/sized-hierarchy/default-bound.stderr b/tests/ui/sized-hierarchy/default-bound.stderr new file mode 100644 index 00000000000..22f0fa29d3e --- /dev/null +++ b/tests/ui/sized-hierarchy/default-bound.stderr @@ -0,0 +1,88 @@ +error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/default-bound.rs:16:21 + | +LL | fn neg_metasized<T: ?MetaSized>() {} + | ^^^^^^^^^^ + +error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default + --> $DIR/default-bound.rs:22:24 + | +LL | fn neg_pointeesized<T: ?PointeeSized>() { } + | ^^^^^^^^^^^^^ + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/default-bound.rs:29:12 + | +LL | bare::<[u8]>(); + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by an implicit `Sized` bound in `bare` + --> $DIR/default-bound.rs:6:9 + | +LL | fn bare<T>() {} + | ^ required by the implicit `Sized` requirement on this type parameter in `bare` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn bare<T: ?Sized>() {} + | ++++++++ + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/default-bound.rs:31:13 + | +LL | 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 `sized` + --> $DIR/default-bound.rs:9:13 + | +LL | fn sized<T: Sized>() {} + | ^^^^^ required by this bound in `sized` + +error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time + --> $DIR/default-bound.rs:42:12 + | +LL | bare::<Foo>(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `main::Foo` +note: required by an implicit `Sized` bound in `bare` + --> $DIR/default-bound.rs:6:9 + | +LL | fn bare<T>() {} + | ^ required by the implicit `Sized` requirement on this type parameter in `bare` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn bare<T: ?Sized>() {} + | ++++++++ + +error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time + --> $DIR/default-bound.rs:44:13 + | +LL | 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 `sized` + --> $DIR/default-bound.rs:9:13 + | +LL | fn sized<T: Sized>() {} + | ^^^^^ required by this bound in `sized` + +error[E0277]: the size for values of type `main::Foo` cannot be known + --> $DIR/default-bound.rs:46:17 + | +LL | metasized::<Foo>(); + | ^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `main::Foo` +note: required by a bound in `metasized` + --> $DIR/default-bound.rs:14:17 + | +LL | fn metasized<T: MetaSized>() {} + | ^^^^^^^^^ required by this bound in `metasized` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/sized-hierarchy/default-supertrait.rs b/tests/ui/sized-hierarchy/default-supertrait.rs new file mode 100644 index 00000000000..b25acf9e6ea --- /dev/null +++ b/tests/ui/sized-hierarchy/default-supertrait.rs @@ -0,0 +1,61 @@ +//@ check-fail +#![feature(sized_hierarchy)] + +use std::marker::{MetaSized, PointeeSized}; + +trait Sized_: Sized { } + +trait NegSized: ?Sized { } +//~^ ERROR `?Trait` is not permitted in supertraits + +trait MetaSized_: MetaSized { } + +trait NegMetaSized: ?MetaSized { } +//~^ ERROR `?Trait` is not permitted in supertraits + + +trait PointeeSized_: PointeeSized { } + +trait NegPointeeSized: ?PointeeSized { } +//~^ ERROR `?Trait` is not permitted in supertraits + +trait Bare {} + +fn requires_sized<T: Sized>() {} +fn requires_metasized<T: MetaSized>() {} +fn requires_pointeesized<T: PointeeSized>() {} + +fn with_sized_supertrait<T: PointeeSized + Sized_>() { + requires_sized::<T>(); + requires_metasized::<T>(); + requires_pointeesized::<T>(); +} + +fn with_metasized_supertrait<T: PointeeSized + MetaSized_>() { + requires_sized::<T>(); + //~^ ERROR the size for values of type `T` cannot be known at compilation time + requires_metasized::<T>(); + requires_pointeesized::<T>(); +} + +// It isn't really possible to write this one.. +fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_>() { + requires_sized::<T>(); + //~^ ERROR the size for values of type `T` cannot be known + requires_metasized::<T>(); + //~^ ERROR the size for values of type `T` cannot be known + requires_pointeesized::<T>(); +} + +// `T` won't inherit the `const MetaSized` implicit supertrait of `Bare`, so there is an error on +// the bound, which is expected. +fn with_bare_trait<T: PointeeSized + Bare>() { +//~^ ERROR the size for values of type `T` cannot be known + requires_sized::<T>(); + //~^ ERROR the size for values of type `T` cannot be known + requires_metasized::<T>(); + //~^ ERROR the size for values of type `T` cannot be known + requires_pointeesized::<T>(); +} + +fn main() { } diff --git a/tests/ui/sized-hierarchy/default-supertrait.stderr b/tests/ui/sized-hierarchy/default-supertrait.stderr new file mode 100644 index 00000000000..de23936b900 --- /dev/null +++ b/tests/ui/sized-hierarchy/default-supertrait.stderr @@ -0,0 +1,125 @@ +error[E0658]: `?Trait` is not permitted in supertraits + --> $DIR/default-supertrait.rs:8:17 + | +LL | trait NegSized: ?Sized { } + | ^^^^^^ + | + = note: traits are `?Sized` by default + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `?Trait` is not permitted in supertraits + --> $DIR/default-supertrait.rs:13:21 + | +LL | trait NegMetaSized: ?MetaSized { } + | ^^^^^^^^^^ + | + = note: traits are `?MetaSized` by default + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `?Trait` is not permitted in supertraits + --> $DIR/default-supertrait.rs:19:24 + | +LL | trait NegPointeeSized: ?PointeeSized { } + | ^^^^^^^^^^^^^ + | + = note: traits are `?PointeeSized` by default + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0277]: the size for values of type `T` cannot be known + --> $DIR/default-supertrait.rs:52:38 + | +LL | fn with_bare_trait<T: PointeeSized + Bare>() { + | ^^^^ doesn't have a known size + | +note: required by a bound in `Bare` + --> $DIR/default-supertrait.rs:22:1 + | +LL | trait Bare {} + | ^^^^^^^^^^^^^ required by this bound in `Bare` +help: consider further restricting type parameter `T` with unstable trait `MetaSized` + | +LL | fn with_bare_trait<T: PointeeSized + Bare + std::marker::MetaSized>() { + | ++++++++++++++++++++++++ + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/default-supertrait.rs:35:22 + | +LL | fn with_metasized_supertrait<T: PointeeSized + MetaSized_>() { + | - this type parameter needs to be `Sized` +LL | requires_sized::<T>(); + | ^ doesn't have a size known at compile-time + | +note: required by a bound in `requires_sized` + --> $DIR/default-supertrait.rs:24:22 + | +LL | fn requires_sized<T: Sized>() {} + | ^^^^^ required by this bound in `requires_sized` + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/default-supertrait.rs:43:22 + | +LL | fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_>() { + | - this type parameter needs to be `Sized` +LL | requires_sized::<T>(); + | ^ doesn't have a size known at compile-time + | +note: required by a bound in `requires_sized` + --> $DIR/default-supertrait.rs:24:22 + | +LL | fn requires_sized<T: Sized>() {} + | ^^^^^ required by this bound in `requires_sized` + +error[E0277]: the size for values of type `T` cannot be known + --> $DIR/default-supertrait.rs:45:26 + | +LL | requires_metasized::<T>(); + | ^ doesn't have a known size + | +note: required by a bound in `requires_metasized` + --> $DIR/default-supertrait.rs:25:26 + | +LL | fn requires_metasized<T: MetaSized>() {} + | ^^^^^^^^^ required by this bound in `requires_metasized` +help: consider further restricting type parameter `T` with unstable trait `MetaSized` + | +LL | fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_ + std::marker::MetaSized>() { + | ++++++++++++++++++++++++ + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/default-supertrait.rs:54:22 + | +LL | fn with_bare_trait<T: PointeeSized + Bare>() { + | - this type parameter needs to be `Sized` +LL | +LL | requires_sized::<T>(); + | ^ doesn't have a size known at compile-time + | +note: required by a bound in `requires_sized` + --> $DIR/default-supertrait.rs:24:22 + | +LL | fn requires_sized<T: Sized>() {} + | ^^^^^ required by this bound in `requires_sized` + +error[E0277]: the size for values of type `T` cannot be known + --> $DIR/default-supertrait.rs:56:26 + | +LL | requires_metasized::<T>(); + | ^ doesn't have a known size + | +note: required by a bound in `requires_metasized` + --> $DIR/default-supertrait.rs:25:26 + | +LL | fn requires_metasized<T: MetaSized>() {} + | ^^^^^^^^^ required by this bound in `requires_metasized` +help: consider further restricting type parameter `T` with unstable trait `MetaSized` + | +LL | fn with_bare_trait<T: PointeeSized + Bare + std::marker::MetaSized>() { + | ++++++++++++++++++++++++ + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/sized-hierarchy/extern-type-behind-ptr.rs b/tests/ui/sized-hierarchy/extern-type-behind-ptr.rs new file mode 100644 index 00000000000..70a84aabf2c --- /dev/null +++ b/tests/ui/sized-hierarchy/extern-type-behind-ptr.rs @@ -0,0 +1,20 @@ +//@ check-pass +#![feature(extern_types, sized_hierarchy)] + +use std::marker::{MetaSized, PointeeSized}; + +pub fn hash<T: PointeeSized>(_: *const T) { + unimplemented!(); +} + +unsafe extern "C" { + type Foo; +} + +fn get() -> *const Foo { + unimplemented!() +} + +fn main() { + hash::<Foo>(get()); +} diff --git a/tests/ui/sized-hierarchy/impls.rs b/tests/ui/sized-hierarchy/impls.rs index b05313dccae..601d837043e 100644 --- a/tests/ui/sized-hierarchy/impls.rs +++ b/tests/ui/sized-hierarchy/impls.rs @@ -1,8 +1,10 @@ //@ check-fail -//@ edition:2021 +//@ edition: 2024 + #![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}; @@ -11,11 +13,11 @@ use std::marker::{MetaSized, PointeeSized}; 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_metasized<T: MetaSized>() { } +fn takes_metasized<T: MetaSized>(_t: T) { } -fn needs_pointeesized<T: ?Sized + PointeeSized>() { } -fn takes_pointeesized<T: ?Sized + PointeeSized>(_t: T) { } +fn needs_pointeesized<T: PointeeSized>() { } +fn takes_pointeesized<T: PointeeSized>(_t: T) { } fn main() { // `bool` @@ -173,7 +175,7 @@ fn main() { needs_pointeesized::<dyn Debug>(); // `extern type` - extern "C" { + unsafe extern "C" { type Foo; } needs_sized::<Foo>(); diff --git a/tests/ui/sized-hierarchy/impls.stderr b/tests/ui/sized-hierarchy/impls.stderr index 5fffe478663..02ccfebdc44 100644 --- a/tests/ui/sized-hierarchy/impls.stderr +++ b/tests/ui/sized-hierarchy/impls.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/impls.rs:237:42 + --> $DIR/impls.rs:239:42 | LL | struct StructAllFieldsMetaSized { x: [u8], y: [u8] } | ^^^^ doesn't have a size known at compile-time @@ -17,7 +17,7 @@ LL | struct StructAllFieldsMetaSized { x: Box<[u8]>, y: [u8] } | ++++ + error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time - --> $DIR/impls.rs:245:40 + --> $DIR/impls.rs:247:40 | LL | struct StructAllFieldsUnsized { x: Foo, y: Foo } | ^^^ doesn't have a size known at compile-time @@ -35,7 +35,7 @@ LL | struct StructAllFieldsUnsized { x: Box<Foo>, y: Foo } | ++++ + error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/impls.rs:281:44 + --> $DIR/impls.rs:283:44 | LL | enum EnumAllFieldsMetaSized { Qux { x: [u8], y: [u8] } } | ^^^^ doesn't have a size known at compile-time @@ -53,7 +53,7 @@ LL | enum EnumAllFieldsMetaSized { Qux { x: Box<[u8]>, y: [u8] } } | ++++ + error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time - --> $DIR/impls.rs:288:42 + --> $DIR/impls.rs:290:42 | LL | enum EnumAllFieldsUnsized { Qux { x: Foo, y: Foo } } | ^^^ doesn't have a size known at compile-time @@ -71,7 +71,7 @@ LL | enum EnumAllFieldsUnsized { Qux { x: Box<Foo>, y: Foo } } | ++++ + error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/impls.rs:295:52 + --> $DIR/impls.rs:297:52 | LL | enum EnumLastFieldMetaSized { Qux { x: u32, y: [u8] } } | ^^^^ doesn't have a size known at compile-time @@ -89,7 +89,7 @@ LL | enum EnumLastFieldMetaSized { Qux { x: u32, y: Box<[u8]> } } | ++++ + error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time - --> $DIR/impls.rs:302:50 + --> $DIR/impls.rs:304:50 | LL | enum EnumLastFieldUnsized { Qux { x: u32, y: Foo } } | ^^^ doesn't have a size known at compile-time @@ -107,72 +107,72 @@ 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 + --> $DIR/impls.rs:160: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 + --> $DIR/impls.rs:13: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 + --> $DIR/impls.rs:166: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 + --> $DIR/impls.rs:13: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 + --> $DIR/impls.rs:172: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 + --> $DIR/impls.rs:13: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 + --> $DIR/impls.rs:181: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 + --> $DIR/impls.rs:13: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 + --> $DIR/impls.rs:183: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 + --> $DIR/impls.rs:16:23 | -LL | fn needs_metasized<T: ?Sized + MetaSized>() { } - | ^^^^^^^^^ required by this bound in `needs_metasized` +LL | fn needs_metasized<T: MetaSized>() { } + | ^^^^^^^^^ required by this bound in `needs_metasized` error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/impls.rs:196:19 + --> $DIR/impls.rs:198:19 | LL | needs_sized::<([u8], [u8])>(); | ^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -181,7 +181,7 @@ LL | needs_sized::<([u8], [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 + --> $DIR/impls.rs:200:23 | LL | needs_metasized::<([u8], [u8])>(); | ^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -190,7 +190,7 @@ LL | needs_metasized::<([u8], [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 + --> $DIR/impls.rs:202:26 | LL | needs_pointeesized::<([u8], [u8])>(); | ^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -199,7 +199,7 @@ LL | needs_pointeesized::<([u8], [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 + --> $DIR/impls.rs:206:19 | LL | needs_sized::<(Foo, Foo)>(); | ^^^^^^^^^^ doesn't have a size known at compile-time @@ -208,7 +208,7 @@ LL | needs_sized::<(Foo, 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 + --> $DIR/impls.rs:208:23 | LL | needs_metasized::<(Foo, Foo)>(); | ^^^^^^^^^^ doesn't have a size known at compile-time @@ -217,7 +217,7 @@ LL | needs_metasized::<(Foo, 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 + --> $DIR/impls.rs:210:26 | LL | needs_pointeesized::<(Foo, Foo)>(); | ^^^^^^^^^^ doesn't have a size known at compile-time @@ -226,7 +226,7 @@ LL | needs_pointeesized::<(Foo, Foo)>(); = note: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/impls.rs:212:19 + --> $DIR/impls.rs:214:19 | LL | needs_sized::<(u32, [u8])>(); | ^^^^^^^^^^^ doesn't have a size known at compile-time @@ -234,13 +234,13 @@ LL | needs_sized::<(u32, [u8])>(); = 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 + --> $DIR/impls.rs:13: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 + --> $DIR/impls.rs:220:19 | LL | needs_sized::<(u32, Foo)>(); | ^^^^^^^^^^ doesn't have a size known at compile-time @@ -248,13 +248,13 @@ LL | needs_sized::<(u32, Foo)>(); = 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 + --> $DIR/impls.rs:13: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 + --> $DIR/impls.rs:222:23 | LL | needs_metasized::<(u32, Foo)>(); | ^^^^^^^^^^ doesn't have a known size @@ -262,118 +262,118 @@ LL | needs_metasized::<(u32, Foo)>(); = 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 + --> $DIR/impls.rs:16:23 | -LL | fn needs_metasized<T: ?Sized + MetaSized>() { } - | ^^^^^^^^^ required by this bound in `needs_metasized` +LL | fn needs_metasized<T: MetaSized>() { } + | ^^^^^^^^^ required by this bound in `needs_metasized` error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/impls.rs:239:19 + --> $DIR/impls.rs:241: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 + --> $DIR/impls.rs:239:12 | LL | struct StructAllFieldsMetaSized { x: [u8], y: [u8] } | ^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `needs_sized` - --> $DIR/impls.rs:11:19 + --> $DIR/impls.rs:13: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 + --> $DIR/impls.rs:249: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 + --> $DIR/impls.rs:247:12 | LL | struct StructAllFieldsUnsized { x: Foo, y: Foo } | ^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `needs_sized` - --> $DIR/impls.rs:11:19 + --> $DIR/impls.rs:13: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 + --> $DIR/impls.rs:251: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 + --> $DIR/impls.rs:247:12 | LL | struct StructAllFieldsUnsized { x: Foo, y: Foo } | ^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `needs_metasized` - --> $DIR/impls.rs:14:32 + --> $DIR/impls.rs:16:23 | -LL | fn needs_metasized<T: ?Sized + MetaSized>() { } - | ^^^^^^^^^ required by this bound in `needs_metasized` +LL | fn needs_metasized<T: MetaSized>() { } + | ^^^^^^^^^ required by this bound in `needs_metasized` error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/impls.rs:255:19 + --> $DIR/impls.rs:257: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 + --> $DIR/impls.rs:256:12 | LL | struct StructLastFieldMetaSized { x: u32, y: [u8] } | ^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `needs_sized` - --> $DIR/impls.rs:11:19 + --> $DIR/impls.rs:13: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 + --> $DIR/impls.rs:264: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 + --> $DIR/impls.rs:263:12 | LL | struct StructLastFieldUnsized { x: u32, y: Foo } | ^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `needs_sized` - --> $DIR/impls.rs:11:19 + --> $DIR/impls.rs:13: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 + --> $DIR/impls.rs:266: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 + --> $DIR/impls.rs:263:12 | LL | struct StructLastFieldUnsized { x: u32, y: Foo } | ^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `needs_metasized` - --> $DIR/impls.rs:14:32 + --> $DIR/impls.rs:16:23 | -LL | fn needs_metasized<T: ?Sized + MetaSized>() { } - | ^^^^^^^^^ required by this bound in `needs_metasized` +LL | fn needs_metasized<T: MetaSized>() { } + | ^^^^^^^^^ required by this bound in `needs_metasized` error: aborting due to 26 previous errors diff --git a/tests/ui/sized-hierarchy/pointee-supertrait.rs b/tests/ui/sized-hierarchy/pointee-supertrait.rs new file mode 100644 index 00000000000..4bf486890bf --- /dev/null +++ b/tests/ui/sized-hierarchy/pointee-supertrait.rs @@ -0,0 +1,28 @@ +//@ check-pass +#![feature(sized_hierarchy)] + +// This is a reduction of some code in `library/core/src/cmp.rs` that would ICE if a default +// `Pointee` bound is added - motivating the current status quo of `PointeeSized` being syntactic +// sugar for an absense of any bounds whatsoever. + +use std::marker::PhantomData; + +pub trait Bar<'a> { + type Foo; +} + +pub struct Foo<'a, T: Bar<'a>> { + phantom: PhantomData<&'a T>, +} + +impl<'a, 'b, T> PartialEq<Foo<'b, T>> for Foo<'a, T> + where + T: for<'c> Bar<'c>, + <T as Bar<'a>>::Foo: PartialEq<<T as Bar<'b>>::Foo>, +{ + fn eq(&self, _: &Foo<'b, T>) -> bool { + loop {} + } +} + +fn main() { } diff --git a/tests/ui/sized-hierarchy/trait-aliases.rs b/tests/ui/sized-hierarchy/trait-aliases.rs new file mode 100644 index 00000000000..ffec302adaa --- /dev/null +++ b/tests/ui/sized-hierarchy/trait-aliases.rs @@ -0,0 +1,9 @@ +//@ check-pass +//@ compile-flags: --crate-type=lib +#![feature(trait_alias)] + +// Checks that `?Sized` in a trait alias doesn't trigger an ICE. + +use std::ops::{Index, IndexMut}; + +pub trait SlicePrereq<T> = ?Sized + IndexMut<usize, Output = <[T] as Index<usize>>::Output>; |
