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.
This commit is contained in:
parent
f0b84b8dcf
commit
86ab2b60cd
20 changed files with 798 additions and 207 deletions
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
28
tests/ui/sized-hierarchy/alias-bounds.rs
Normal file
28
tests/ui/sized-hierarchy/alias-bounds.rs
Normal file
|
|
@ -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>();
|
||||
}
|
||||
49
tests/ui/sized-hierarchy/default-bound.rs
Normal file
49
tests/ui/sized-hierarchy/default-bound.rs
Normal file
|
|
@ -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>();
|
||||
}
|
||||
88
tests/ui/sized-hierarchy/default-bound.stderr
Normal file
88
tests/ui/sized-hierarchy/default-bound.stderr
Normal file
|
|
@ -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`.
|
||||
61
tests/ui/sized-hierarchy/default-supertrait.rs
Normal file
61
tests/ui/sized-hierarchy/default-supertrait.rs
Normal file
|
|
@ -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() { }
|
||||
125
tests/ui/sized-hierarchy/default-supertrait.stderr
Normal file
125
tests/ui/sized-hierarchy/default-supertrait.stderr
Normal file
|
|
@ -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`.
|
||||
20
tests/ui/sized-hierarchy/extern-type-behind-ptr.rs
Normal file
20
tests/ui/sized-hierarchy/extern-type-behind-ptr.rs
Normal file
|
|
@ -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());
|
||||
}
|
||||
|
|
@ -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>();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
28
tests/ui/sized-hierarchy/pointee-supertrait.rs
Normal file
28
tests/ui/sized-hierarchy/pointee-supertrait.rs
Normal file
|
|
@ -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() { }
|
||||
9
tests/ui/sized-hierarchy/trait-aliases.rs
Normal file
9
tests/ui/sized-hierarchy/trait-aliases.rs
Normal file
|
|
@ -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>;
|
||||
Loading…
Add table
Add a link
Reference in a new issue