Rollup merge of #147734 - fmease:tighten-relaxed, r=lcnr
Further tighten up relaxed bounds Follow-up to rust-lang/rust#142693, rust-lang/rust#135331 and rust-lang/rust#135841. Fixes rust-lang/rust#143122. * Reject relaxed bounds `?Trait` in the bounds of trait aliases. Just like `trait Trait {}` doesn't mean `trait Trait: Sized {}` and we therefore reject `trait Trait: ?Sized {}`, `trait Trait =;` (sic!) doesn't mean `trait Trait = Sized;` (never did!) and as a logical consequence `trait Trait = ?Sized;` is meaningless and should be forbidden. * Don't permit `?Sized` in more places (e.g., supertrait bounds, trait object types) if feature `more_maybe_bounds` is enabled. That internal feature is only meant to allow the user to define & use *new* default traits (that have fewer rules to follow for now to ease experimentation). * Unconditionally check that the `Trait` in `?Trait` is a default trait. Previously, we would only perform this check in selected places which was very brittle and led to bugs slipping through. * Slightly improve diagnostics.
This commit is contained in:
commit
f87f9a456c
30 changed files with 475 additions and 318 deletions
|
|
@ -426,7 +426,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|this| {
|
||||
this.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitAlias),
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -297,6 +297,7 @@ enum RelaxedBoundPolicy<'a> {
|
|||
enum RelaxedBoundForbiddenReason {
|
||||
TraitObjectTy,
|
||||
SuperTrait,
|
||||
TraitAlias,
|
||||
AssocTyBounds,
|
||||
LateBoundVarsInScope,
|
||||
}
|
||||
|
|
@ -2086,12 +2087,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
span: Span,
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
) {
|
||||
// Even though feature `more_maybe_bounds` bypasses the given policy and (currently) enables
|
||||
// relaxed bounds in every conceivable position[^1], we don't want to advertise it to the user
|
||||
// (via a feature gate) since it's super internal. Besides this, it'd be quite distracting.
|
||||
// Even though feature `more_maybe_bounds` enables the user to relax all default bounds
|
||||
// other than `Sized` in a lot more positions (thereby bypassing the given policy), we don't
|
||||
// want to advertise it to the user (via a feature gate error) since it's super internal.
|
||||
//
|
||||
// [^1]: Strictly speaking, this is incorrect (at the very least for `Sized`) because it's
|
||||
// no longer fully consistent with default trait elaboration in HIR ty lowering.
|
||||
// FIXME(more_maybe_bounds): Moreover, if we actually were to add proper default traits
|
||||
// (like a hypothetical `Move` or `Leak`) we would want to validate the location according
|
||||
// to default trait elaboration in HIR ty lowering (which depends on the specific trait in
|
||||
// question: E.g., `?Sized` & `?Move` most likely won't be allowed in all the same places).
|
||||
|
||||
match rbp {
|
||||
RelaxedBoundPolicy::Allowed => return,
|
||||
|
|
@ -2104,33 +2107,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
RelaxedBoundPolicy::Forbidden(reason) => {
|
||||
let gate = |context, subject| {
|
||||
let extended = self.tcx.features().more_maybe_bounds();
|
||||
let is_sized = trait_ref
|
||||
.trait_def_id()
|
||||
.is_some_and(|def_id| self.tcx.is_lang_item(def_id, hir::LangItem::Sized));
|
||||
|
||||
if extended && !is_sized {
|
||||
return;
|
||||
}
|
||||
|
||||
let prefix = if extended { "`Sized` " } else { "" };
|
||||
let mut diag = self.dcx().struct_span_err(
|
||||
span,
|
||||
format!("relaxed {prefix}bounds are not permitted in {context}"),
|
||||
);
|
||||
if is_sized {
|
||||
diag.note(format!(
|
||||
"{subject} are not implicitly bounded by `Sized`, \
|
||||
so there is nothing to relax"
|
||||
));
|
||||
}
|
||||
diag.emit();
|
||||
};
|
||||
|
||||
match reason {
|
||||
RelaxedBoundForbiddenReason::TraitObjectTy => {
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.dcx().span_err(
|
||||
span,
|
||||
"relaxed bounds are not permitted in trait object types",
|
||||
);
|
||||
gate("trait object types", "trait object types");
|
||||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::SuperTrait => {
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut diag = self.dcx().struct_span_err(
|
||||
span,
|
||||
"relaxed bounds are not permitted in supertrait bounds",
|
||||
);
|
||||
if let Some(def_id) = trait_ref.trait_def_id()
|
||||
&& self.tcx.is_lang_item(def_id, hir::LangItem::Sized)
|
||||
{
|
||||
diag.note("traits are `?Sized` by default");
|
||||
}
|
||||
diag.emit();
|
||||
gate("supertrait bounds", "traits");
|
||||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::TraitAlias => {
|
||||
gate("trait alias bounds", "trait aliases");
|
||||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::AssocTyBounds
|
||||
|
|
@ -2143,7 +2154,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
.struct_span_err(span, "this relaxed bound is not permitted here")
|
||||
.with_note(
|
||||
"in this context, relaxed bounds are only allowed on \
|
||||
type parameters defined by the closest item",
|
||||
type parameters defined on the closest item",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,11 +202,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// where we are guaranteed to catch *all* bounds like in
|
||||
// `Self::lower_poly_trait_ref`. List of concrete issues:
|
||||
// FIXME(more_maybe_bounds): We don't call this for trait object tys, supertrait
|
||||
// bounds or associated type bounds (ATB)!
|
||||
// FIXME(trait_alias, #143122): We don't call it for the RHS. Arguably however,
|
||||
// AST lowering should reject them outright.
|
||||
// bounds, trait alias bounds, assoc type bounds (ATB)!
|
||||
let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
|
||||
self.check_and_report_invalid_relaxed_bounds(bounds);
|
||||
self.reject_duplicate_relaxed_bounds(bounds);
|
||||
}
|
||||
|
||||
let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);
|
||||
|
|
@ -310,6 +308,53 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
!self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any()
|
||||
}
|
||||
|
||||
fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default();
|
||||
|
||||
for bound in &relaxed_bounds {
|
||||
if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res {
|
||||
grouped_bounds.entry(trait_def_id).or_default().push(bound.span);
|
||||
}
|
||||
}
|
||||
|
||||
for (trait_def_id, spans) in grouped_bounds {
|
||||
if spans.len() > 1 {
|
||||
let name = tcx.item_name(trait_def_id);
|
||||
self.dcx()
|
||||
.struct_span_err(spans, format!("duplicate relaxed `{name}` bounds"))
|
||||
.with_code(E0203)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn require_bound_to_relax_default_trait(
|
||||
&self,
|
||||
trait_ref: hir::TraitRef<'_>,
|
||||
span: Span,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
|
||||
if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res
|
||||
&& (tcx.is_lang_item(def_id, hir::LangItem::Sized) || tcx.is_default_trait(def_id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.dcx().span_err(
|
||||
span,
|
||||
if tcx.sess.opts.unstable_opts.experimental_default_bounds
|
||||
|| tcx.features().more_maybe_bounds()
|
||||
{
|
||||
"bound modifier `?` can only be applied to default traits"
|
||||
} else {
|
||||
"bound modifier `?` can only be applied to `Sized`"
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.
|
||||
///
|
||||
/// ### Examples
|
||||
|
|
|
|||
|
|
@ -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, PolyTraitRef};
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
|
||||
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
|
||||
|
|
@ -35,52 +35,6 @@ use crate::fluent_generated as fluent;
|
|||
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
|
||||
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// Check for duplicate relaxed bounds and relaxed bounds of non-default traits.
|
||||
pub(crate) fn check_and_report_invalid_relaxed_bounds(
|
||||
&self,
|
||||
relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default();
|
||||
|
||||
for bound in &relaxed_bounds {
|
||||
if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res {
|
||||
grouped_bounds.entry(trait_def_id).or_default().push(bound.span);
|
||||
}
|
||||
}
|
||||
|
||||
for (trait_def_id, spans) in grouped_bounds {
|
||||
if spans.len() > 1 {
|
||||
let name = tcx.item_name(trait_def_id);
|
||||
self.dcx()
|
||||
.struct_span_err(spans, format!("duplicate relaxed `{name}` bounds"))
|
||||
.with_code(E0203)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, DUMMY_SP);
|
||||
|
||||
for bound in relaxed_bounds {
|
||||
if let Res::Def(DefKind::Trait, def_id) = bound.trait_ref.path.res
|
||||
&& (def_id == sized_def_id || tcx.is_default_trait(def_id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
self.dcx().span_err(
|
||||
bound.span,
|
||||
if tcx.sess.opts.unstable_opts.experimental_default_bounds
|
||||
|| tcx.features().more_maybe_bounds()
|
||||
{
|
||||
"bound modifier `?` can only be applied to default traits like `Sized`"
|
||||
} else {
|
||||
"bound modifier `?` can only be applied to `Sized`"
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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(
|
||||
|
|
|
|||
|
|
@ -717,16 +717,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
trait_ref: &hir::TraitRef<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
) -> ty::TraitRef<'tcx> {
|
||||
let _ = self.prohibit_generic_args(
|
||||
trait_ref.path.segments.split_last().unwrap().1.iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
let [leading_segments @ .., segment] = trait_ref.path.segments else { bug!() };
|
||||
|
||||
let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
|
||||
|
||||
self.lower_mono_trait_ref(
|
||||
trait_ref.path.span,
|
||||
trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
|
||||
self_ty,
|
||||
trait_ref.path.segments.last().unwrap(),
|
||||
segment,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
|
@ -757,7 +756,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
#[instrument(level = "debug", skip(self, bounds))]
|
||||
pub(crate) fn lower_poly_trait_ref(
|
||||
&self,
|
||||
poly_trait_ref: &hir::PolyTraitRef<'tcx>,
|
||||
&hir::PolyTraitRef {
|
||||
bound_generic_params,
|
||||
modifiers: hir::TraitBoundModifiers { constness, polarity },
|
||||
trait_ref,
|
||||
span,
|
||||
}: &hir::PolyTraitRef<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
predicate_filter: PredicateFilter,
|
||||
|
|
@ -767,50 +771,67 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
|
||||
// We use the *resolved* bound vars later instead of the HIR ones since the former
|
||||
// also include the bound vars of the overarching predicate if applicable.
|
||||
let hir::PolyTraitRef { bound_generic_params: _, modifiers, ref trait_ref, span } =
|
||||
*poly_trait_ref;
|
||||
let hir::TraitBoundModifiers { constness, polarity } = modifiers;
|
||||
let _ = bound_generic_params;
|
||||
|
||||
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
|
||||
|
||||
// Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the `middle::ty` IR
|
||||
// Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the middle::ty IR
|
||||
// as they denote the *absence* of a default bound. However, we can't bail out early here since
|
||||
// we still need to perform several validation steps (see below). Instead, simply "pour" all
|
||||
// resulting bounds "down the drain", i.e., into a new `Vec` that just gets dropped at the end.
|
||||
let (polarity, bounds) = match polarity {
|
||||
rustc_ast::BoundPolarity::Positive
|
||||
if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) =>
|
||||
{
|
||||
let transient = match polarity {
|
||||
hir::BoundPolarity::Positive => {
|
||||
// To elaborate on the comment directly above, regarding `PointeeSized` specifically,
|
||||
// we don't "reify" such bounds to avoid trait system limitations -- namely,
|
||||
// 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.
|
||||
(ty::PredicatePolarity::Positive, &mut Vec::new())
|
||||
tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized)
|
||||
}
|
||||
rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds),
|
||||
rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds),
|
||||
rustc_ast::BoundPolarity::Maybe(_) => {
|
||||
(ty::PredicatePolarity::Positive, &mut Vec::new())
|
||||
hir::BoundPolarity::Negative(_) => false,
|
||||
hir::BoundPolarity::Maybe(_) => {
|
||||
self.require_bound_to_relax_default_trait(trait_ref, span);
|
||||
true
|
||||
}
|
||||
};
|
||||
let bounds = if transient { &mut Vec::new() } else { bounds };
|
||||
|
||||
let trait_segment = trait_ref.path.segments.last().unwrap();
|
||||
let polarity = match polarity {
|
||||
hir::BoundPolarity::Positive | hir::BoundPolarity::Maybe(_) => {
|
||||
ty::PredicatePolarity::Positive
|
||||
}
|
||||
hir::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
|
||||
};
|
||||
|
||||
let _ = self.prohibit_generic_args(
|
||||
trait_ref.path.segments.split_last().unwrap().1.iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
self.report_internal_fn_trait(span, trait_def_id, trait_segment, false);
|
||||
let [leading_segments @ .., segment] = trait_ref.path.segments else { bug!() };
|
||||
|
||||
let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
|
||||
self.report_internal_fn_trait(span, trait_def_id, segment, false);
|
||||
|
||||
let (generic_args, arg_count) = self.lower_generic_args_of_path(
|
||||
trait_ref.path.span,
|
||||
trait_def_id,
|
||||
&[],
|
||||
trait_segment,
|
||||
segment,
|
||||
Some(self_ty),
|
||||
);
|
||||
|
||||
let constraints = segment.args().constraints;
|
||||
|
||||
if transient && (!generic_args[1..].is_empty() || !constraints.is_empty()) {
|
||||
// Since the bound won't be present in the middle::ty IR as established above, any
|
||||
// arguments or constraints won't be checked for well-formedness in later passes.
|
||||
//
|
||||
// This is only an issue if the trait ref is otherwise valid which can only happen if
|
||||
// the corresponding default trait has generic parameters or associated items. Such a
|
||||
// trait would be degenerate. We delay a bug to detect and guard us against these.
|
||||
//
|
||||
// E.g: Given `/*default*/ trait Bound<'a: 'static, T, const N: usize> {}`,
|
||||
// `?Bound<Vec<str>, { panic!() }>` won't be wfchecked.
|
||||
self.dcx()
|
||||
.span_delayed_bug(span, "transient bound should not have args or constraints");
|
||||
}
|
||||
|
||||
let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
|
||||
debug!(?bound_vars);
|
||||
|
||||
|
|
@ -922,7 +943,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
== OverlappingAsssocItemConstraints::Forbidden)
|
||||
.then_some(FxIndexMap::default());
|
||||
|
||||
for constraint in trait_segment.args().constraints {
|
||||
for constraint in constraints {
|
||||
// Don't register any associated item constraints for negative bounds,
|
||||
// since we should have emitted an error for them earlier, and they
|
||||
// would not be well-formed!
|
||||
|
|
@ -1911,10 +1932,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
Res::Def(DefKind::OpaqueTy, did) => {
|
||||
// Check for desugared `impl Trait`.
|
||||
assert_matches!(tcx.opaque_ty_origin(did), hir::OpaqueTyOrigin::TyAlias { .. });
|
||||
let item_segment = path.segments.split_last().unwrap();
|
||||
let _ = self
|
||||
.prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy);
|
||||
let args = self.lower_generic_args_of_path_segment(span, did, item_segment.0);
|
||||
let [leading_segments @ .., segment] = path.segments else { bug!() };
|
||||
let _ = self.prohibit_generic_args(
|
||||
leading_segments.iter(),
|
||||
GenericsArgsErrExtend::OpaqueTy,
|
||||
);
|
||||
let args = self.lower_generic_args_of_path_segment(span, did, segment);
|
||||
Ty::new_opaque(tcx, did, args)
|
||||
}
|
||||
Res::Def(
|
||||
|
|
@ -1926,11 +1949,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
did,
|
||||
) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
let _ = self.prohibit_generic_args(
|
||||
path.segments.split_last().unwrap().1.iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
self.lower_path_segment(span, did, path.segments.last().unwrap())
|
||||
let [leading_segments @ .., segment] = path.segments else { bug!() };
|
||||
let _ = self
|
||||
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
|
||||
self.lower_path_segment(span, did, segment)
|
||||
}
|
||||
Res::Def(kind @ DefKind::Variant, def_id)
|
||||
if let PermitVariants::Yes = permit_variants =>
|
||||
|
|
@ -1950,8 +1972,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
GenericsArgsErrExtend::DefVariant(&path.segments),
|
||||
);
|
||||
|
||||
let GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
|
||||
self.lower_path_segment(span, *def_id, &path.segments[*index])
|
||||
let &GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
|
||||
self.lower_path_segment(span, def_id, &path.segments[index])
|
||||
}
|
||||
Res::Def(DefKind::TyParam, def_id) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
|
|
@ -2237,15 +2259,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
let _ = self.prohibit_generic_args(
|
||||
path.segments.split_last().unwrap().1.iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
let args = self.lower_generic_args_of_path_segment(
|
||||
span,
|
||||
did,
|
||||
path.segments.last().unwrap(),
|
||||
);
|
||||
let [leading_segments @ .., segment] = path.segments else { bug!() };
|
||||
let _ = self
|
||||
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
|
||||
let args = self.lower_generic_args_of_path_segment(span, did, segment);
|
||||
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
|
||||
}
|
||||
Res::Def(DefKind::AssocConst, did) => {
|
||||
|
|
|
|||
|
|
@ -1785,9 +1785,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
pub fn is_default_trait(self, def_id: DefId) -> bool {
|
||||
self.default_traits()
|
||||
.iter()
|
||||
.any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id))
|
||||
self.default_traits().iter().any(|&default_trait| self.is_lang_item(def_id, default_trait))
|
||||
}
|
||||
|
||||
pub fn is_sizedness_trait(self, def_id: DefId) -> bool {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![feature(trait_alias)]
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
pub trait Bar {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: `#[doc(alias = "...")]` isn't allowed on associated constant in trait implementation block
|
||||
--> $DIR/doc-alias-assoc-const.rs:10:11
|
||||
--> $DIR/doc-alias-assoc-const.rs:8:11
|
||||
|
|
||||
LL | #[doc(alias = "CONST_BAZ")]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
#![feature(auto_traits)]
|
||||
#![feature(auto_traits, lang_items)]
|
||||
|
||||
trait Trait1 {}
|
||||
auto trait Trait2 {}
|
||||
trait Trait3: ?Trait1 {} //~ ERROR relaxed bounds are not permitted in supertrait bounds
|
||||
trait Trait4 where Self: ?Trait1 {} //~ ERROR this relaxed bound is not permitted here
|
||||
#[lang = "default_trait1"] trait Trait1 {}
|
||||
#[lang = "default_trait2"] auto trait Trait2 {}
|
||||
|
||||
trait Trait3: ?Trait1 {}
|
||||
//~^ ERROR relaxed bounds are not permitted in supertrait bounds
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
|
||||
fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
|
||||
//~^ ERROR relaxed bounds are not permitted in trait object types
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
|
||||
//~^ ERROR bound modifier `?` can only be applied to `Sized`
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
|
|
|
|||
|
|
@ -1,34 +1,54 @@
|
|||
error: relaxed bounds are not permitted in supertrait bounds
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:5:15
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:6:15
|
||||
|
|
||||
LL | trait Trait3: ?Trait1 {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:6:26
|
||||
|
|
||||
LL | trait Trait4 where Self: ?Trait1 {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:8:28
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:12:28
|
||||
|
|
||||
LL | fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:10:11
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:6:15
|
||||
|
|
||||
LL | trait Trait3: ?Trait1 {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:6:15
|
||||
|
|
||||
LL | trait Trait3: ?Trait1 {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:6:15
|
||||
|
|
||||
LL | trait Trait3: ?Trait1 {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:12:28
|
||||
|
|
||||
LL | fn foo(_: Box<dyn Trait1 + ?Trait2>) {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:15:11
|
||||
|
|
||||
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:10:21
|
||||
--> $DIR/feature-gate-more-maybe-bounds.rs:15:21
|
||||
|
|
||||
LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -3,18 +3,24 @@ error: relaxed bounds are not permitted in trait object types
|
|||
|
|
||||
LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/trait-object-trait-parens.rs:13:16
|
||||
|
|
||||
LL | let _: Box<?Sized + (for<'a> Trait<'a>) + (Obj)>;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/trait-object-trait-parens.rs:18:44
|
||||
|
|
||||
LL | let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
warning: trait objects without an explicit `dyn` are deprecated
|
||||
--> $DIR/trait-object-trait-parens.rs:8:16
|
||||
|
|
|
|||
|
|
@ -12,12 +12,17 @@ trait MetaSized_: MetaSized { }
|
|||
|
||||
trait NegMetaSized: ?MetaSized { }
|
||||
//~^ ERROR relaxed bounds are not permitted in supertrait bounds
|
||||
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
|
||||
trait PointeeSized_: PointeeSized { }
|
||||
|
||||
trait NegPointeeSized: ?PointeeSized { }
|
||||
//~^ ERROR relaxed bounds are not permitted in supertrait bounds
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
|
||||
trait Bare {}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ error: relaxed bounds are not permitted in supertrait bounds
|
|||
LL | trait NegSized: ?Sized { }
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: traits are `?Sized` by default
|
||||
= note: traits are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in supertrait bounds
|
||||
--> $DIR/default-supertrait.rs:13:21
|
||||
|
|
@ -13,19 +13,63 @@ LL | trait NegMetaSized: ?MetaSized { }
|
|||
| ^^^^^^^^^^
|
||||
|
||||
error: relaxed bounds are not permitted in supertrait bounds
|
||||
--> $DIR/default-supertrait.rs:19:24
|
||||
--> $DIR/default-supertrait.rs:21:24
|
||||
|
|
||||
LL | trait NegPointeeSized: ?PointeeSized { }
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/default-supertrait.rs:13:21
|
||||
|
|
||||
LL | trait NegMetaSized: ?MetaSized { }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/default-supertrait.rs:13:21
|
||||
|
|
||||
LL | trait NegMetaSized: ?MetaSized { }
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/default-supertrait.rs:13:21
|
||||
|
|
||||
LL | trait NegMetaSized: ?MetaSized { }
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/default-supertrait.rs:21:24
|
||||
|
|
||||
LL | trait NegPointeeSized: ?PointeeSized { }
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/default-supertrait.rs:21:24
|
||||
|
|
||||
LL | trait NegPointeeSized: ?PointeeSized { }
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/default-supertrait.rs:21:24
|
||||
|
|
||||
LL | trait NegPointeeSized: ?PointeeSized { }
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known
|
||||
--> $DIR/default-supertrait.rs:52:38
|
||||
--> $DIR/default-supertrait.rs:57: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
|
||||
--> $DIR/default-supertrait.rs:27:1
|
||||
|
|
||||
LL | trait Bare {}
|
||||
| ^^^^^^^^^^^^^ required by this bound in `Bare`
|
||||
|
|
@ -35,7 +79,7 @@ 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
|
||||
--> $DIR/default-supertrait.rs:40:22
|
||||
|
|
||||
LL | fn with_metasized_supertrait<T: PointeeSized + MetaSized_>() {
|
||||
| - this type parameter needs to be `Sized`
|
||||
|
|
@ -43,13 +87,13 @@ 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
|
||||
--> $DIR/default-supertrait.rs:29: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
|
||||
--> $DIR/default-supertrait.rs:48:22
|
||||
|
|
||||
LL | fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_>() {
|
||||
| - this type parameter needs to be `Sized`
|
||||
|
|
@ -57,19 +101,19 @@ 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
|
||||
--> $DIR/default-supertrait.rs:29: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
|
||||
--> $DIR/default-supertrait.rs:50: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
|
||||
--> $DIR/default-supertrait.rs:30:26
|
||||
|
|
||||
LL | fn requires_metasized<T: MetaSized>() {}
|
||||
| ^^^^^^^^^ required by this bound in `requires_metasized`
|
||||
|
|
@ -79,7 +123,7 @@ LL | fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_ + std::mark
|
|||
| ++++++++++++++++++++++++
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/default-supertrait.rs:54:22
|
||||
--> $DIR/default-supertrait.rs:59:22
|
||||
|
|
||||
LL | fn with_bare_trait<T: PointeeSized + Bare>() {
|
||||
| - this type parameter needs to be `Sized`
|
||||
|
|
@ -88,19 +132,19 @@ 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
|
||||
--> $DIR/default-supertrait.rs:29: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
|
||||
--> $DIR/default-supertrait.rs:61: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
|
||||
--> $DIR/default-supertrait.rs:30:26
|
||||
|
|
||||
LL | fn requires_metasized<T: MetaSized>() {}
|
||||
| ^^^^^^^^^ required by this bound in `requires_metasized`
|
||||
|
|
@ -109,6 +153,6 @@ help: consider further restricting type parameter `T` with unstable trait `MetaS
|
|||
LL | fn with_bare_trait<T: PointeeSized + Bare + std::marker::MetaSized>() {
|
||||
| ++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
//@ 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>;
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
struct Foo<T: ?Hash> {}
|
||||
//~^ ERROR expected trait, found derive macro `Hash`
|
||||
//~| ERROR bound modifier `?` can only be applied to `Sized`
|
||||
// issue: <https://github.com/rust-lang/rust/issues/37534>
|
||||
|
||||
struct Foo<T: ?Hash> {} //~ ERROR expected trait, found derive macro `Hash`
|
||||
|
||||
fn main() {}
|
||||
|
||||
// https://github.com/rust-lang/rust/issues/37534
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0404]: expected trait, found derive macro `Hash`
|
||||
--> $DIR/relaxing-default-bound-error-37534.rs:1:16
|
||||
--> $DIR/relaxing-default-bound-error-37534.rs:3:16
|
||||
|
|
||||
LL | struct Foo<T: ?Hash> {}
|
||||
| ^^^^ not a trait
|
||||
|
|
@ -9,12 +9,6 @@ help: consider importing this trait instead
|
|||
LL + use std::hash::Hash;
|
||||
|
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/relaxing-default-bound-error-37534.rs:1:15
|
||||
|
|
||||
LL | struct Foo<T: ?Hash> {}
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0404`.
|
||||
|
|
|
|||
|
|
@ -1,40 +1,40 @@
|
|||
// FIXME(more_maybe_bounds): Even under `more_maybe_bounds` / `-Zexperimental-default-bounds`,
|
||||
// trying to relax non-default bounds should still be an error in all contexts! As you can see
|
||||
// there are places like supertrait bounds, trait object types or associated type bounds (ATB)
|
||||
// where we currently don't perform this check.
|
||||
#![feature(auto_traits, more_maybe_bounds, negative_impls)]
|
||||
|
||||
trait Trait1 {}
|
||||
auto trait Trait2 {}
|
||||
|
||||
// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`.
|
||||
trait Trait3: ?Trait1 {}
|
||||
//~^ ERROR bound modifier `?` can only be applied to default traits
|
||||
//~| ERROR bound modifier `?` can only be applied to default traits
|
||||
//~| ERROR bound modifier `?` can only be applied to default traits
|
||||
trait Trait4 where Self: Trait1 {}
|
||||
|
||||
// FIXME: `?Trait2` should be rejected, `Trait2` isn't marked `#[lang = "default_traitN"]`.
|
||||
|
||||
fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {}
|
||||
//~^ ERROR bound modifier `?` can only be applied to default traits
|
||||
|
||||
fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
||||
//~^ ERROR bound modifier `?` can only be applied to default traits like `Sized`
|
||||
//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
|
||||
//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
|
||||
//~^ ERROR bound modifier `?` can only be applied to default traits
|
||||
//~| ERROR bound modifier `?` can only be applied to default traits
|
||||
//~| ERROR bound modifier `?` can only be applied to default traits
|
||||
|
||||
// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`.
|
||||
fn baz<T>() where T: Iterator<Item: ?Trait1> {}
|
||||
//~^ ERROR this relaxed bound is not permitted here
|
||||
//~| ERROR bound modifier `?` can only be applied to default traits
|
||||
|
||||
struct S1<T>(T);
|
||||
|
||||
impl<T> S1<T> {
|
||||
fn f() where T: ?Trait1 {}
|
||||
//~^ ERROR this relaxed bound is not permitted here
|
||||
//~| ERROR bound modifier `?` can only be applied to default traits
|
||||
}
|
||||
|
||||
trait Trait5<'a> {}
|
||||
|
||||
struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
|
||||
//~^ ERROR this relaxed bound is not permitted here
|
||||
//~| ERROR bound modifier `?` can only be applied to default traits like `Sized`
|
||||
//~| ERROR bound modifier `?` can only be applied to default traits
|
||||
|
||||
struct S;
|
||||
impl !Trait2 for S {}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/more_maybe_bounds.rs:23:37
|
||||
--> $DIR/more_maybe_bounds.rs:21:37
|
||||
|
|
||||
LL | fn baz<T>() where T: Iterator<Item: ?Trait1> {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/more_maybe_bounds.rs:29:21
|
||||
--> $DIR/more_maybe_bounds.rs:28:21
|
||||
|
|
||||
LL | fn f() where T: ?Trait1 {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/more_maybe_bounds.rs:35:34
|
||||
|
|
@ -20,31 +20,71 @@ error: this relaxed bound is not permitted here
|
|||
LL | struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: bound modifier `?` can only be applied to default traits like `Sized`
|
||||
--> $DIR/more_maybe_bounds.rs:17:20
|
||||
error: bound modifier `?` can only be applied to default traits
|
||||
--> $DIR/more_maybe_bounds.rs:6:15
|
||||
|
|
||||
LL | trait Trait3: ?Trait1 {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to default traits
|
||||
--> $DIR/more_maybe_bounds.rs:6:15
|
||||
|
|
||||
LL | trait Trait3: ?Trait1 {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: bound modifier `?` can only be applied to default traits
|
||||
--> $DIR/more_maybe_bounds.rs:6:15
|
||||
|
|
||||
LL | trait Trait3: ?Trait1 {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: bound modifier `?` can only be applied to default traits
|
||||
--> $DIR/more_maybe_bounds.rs:13:29
|
||||
|
|
||||
LL | fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to default traits
|
||||
--> $DIR/more_maybe_bounds.rs:16:20
|
||||
|
|
||||
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to default traits like `Sized`
|
||||
--> $DIR/more_maybe_bounds.rs:17:30
|
||||
error: bound modifier `?` can only be applied to default traits
|
||||
--> $DIR/more_maybe_bounds.rs:16:30
|
||||
|
|
||||
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to default traits like `Sized`
|
||||
--> $DIR/more_maybe_bounds.rs:17:40
|
||||
error: bound modifier `?` can only be applied to default traits
|
||||
--> $DIR/more_maybe_bounds.rs:16:40
|
||||
|
|
||||
LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to default traits like `Sized`
|
||||
error: bound modifier `?` can only be applied to default traits
|
||||
--> $DIR/more_maybe_bounds.rs:21:37
|
||||
|
|
||||
LL | fn baz<T>() where T: Iterator<Item: ?Trait1> {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: bound modifier `?` can only be applied to default traits
|
||||
--> $DIR/more_maybe_bounds.rs:35:34
|
||||
|
|
||||
LL | struct S2<T>(T) where for<'a> T: ?Trait5<'a>;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: bound modifier `?` can only be applied to default traits
|
||||
--> $DIR/more_maybe_bounds.rs:28:21
|
||||
|
|
||||
LL | fn f() where T: ?Trait1 {}
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
|
||||
|
|
|
|||
20
tests/ui/traits/alias/effectively-empty-trait-object-type.rs
Normal file
20
tests/ui/traits/alias/effectively-empty-trait-object-type.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Test that we reject trait object types that effectively (i.e., after trait alias expansion)
|
||||
// don't contain any bounds.
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait Empty0 =;
|
||||
|
||||
// Nest a couple of levels deep:
|
||||
trait Empty1 = Empty0;
|
||||
trait Empty2 = Empty1;
|
||||
|
||||
// Straight list expansion:
|
||||
type Type0 = dyn Empty2; //~ ERROR at least one trait is required for an object type [E0224]
|
||||
|
||||
// Twice:
|
||||
trait Empty3 = Empty2 + Empty2;
|
||||
|
||||
type Type1 = dyn Empty3; //~ ERROR at least one trait is required for an object type [E0224]
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/effectively-empty-trait-object-type.rs:13:14
|
||||
|
|
||||
LL | trait Empty2 = Empty1;
|
||||
| ------------ this alias does not contain a trait
|
||||
...
|
||||
LL | type Type0 = dyn Empty2;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/effectively-empty-trait-object-type.rs:18:14
|
||||
|
|
||||
LL | trait Empty3 = Empty2 + Empty2;
|
||||
| ------------ this alias does not contain a trait
|
||||
LL |
|
||||
LL | type Type1 = dyn Empty3;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0224`.
|
||||
17
tests/ui/traits/alias/empty.rs
Normal file
17
tests/ui/traits/alias/empty.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Ensure that there are straightforward ways to define "empty" / "trivial" / "unit" trait aliases
|
||||
// which don't impose any constraints when used as a bound (since they expand to nothing).
|
||||
//@ check-pass
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait Empty =;
|
||||
|
||||
trait Trivial = where;
|
||||
|
||||
trait Unit = where Self:;
|
||||
|
||||
fn check<T: ?Sized + Empty>() {}
|
||||
|
||||
fn main() {
|
||||
check::<()>(); // OK. "`(): Empty`" is trivially satisfied
|
||||
check::<str>(); // OK. `Empty` is truly empty and isn't implicitly bounded by `Sized`.
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
//@ build-pass (FIXME(62277): could be check-pass?)
|
||||
|
||||
// Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay.
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait Foo {}
|
||||
|
||||
trait S = ?Sized;
|
||||
|
||||
// Nest a couple of levels deep:
|
||||
trait _0 = S;
|
||||
trait _1 = _0;
|
||||
|
||||
// Straight list expansion:
|
||||
type _T0 = dyn _1 + Foo;
|
||||
|
||||
// In second position:
|
||||
type _T1 = dyn Foo + _1;
|
||||
|
||||
// ... and with an auto trait:
|
||||
type _T2 = dyn Foo + Send + _1;
|
||||
|
||||
// Twice:
|
||||
trait _2 = _1 + _1;
|
||||
|
||||
type _T3 = dyn _2 + Foo;
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed, when just
|
||||
// `?Sized` results from trait alias expansion.
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait S = ?Sized;
|
||||
|
||||
// Nest a couple of levels deep:
|
||||
trait _0 = S;
|
||||
trait _1 = _0;
|
||||
|
||||
// Straight list expansion:
|
||||
type _T0 = dyn _1;
|
||||
//~^ ERROR at least one trait is required for an object type [E0224]
|
||||
|
||||
// Twice:
|
||||
trait _2 = _1 + _1;
|
||||
|
||||
type _T1 = dyn _2;
|
||||
//~^ ERROR at least one trait is required for an object type [E0224]
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/only-maybe-bound.rs:13:12
|
||||
|
|
||||
LL | trait _1 = _0;
|
||||
| -------- this alias does not contain a trait
|
||||
...
|
||||
LL | type _T0 = dyn _1;
|
||||
| ^^^^^^
|
||||
|
||||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/only-maybe-bound.rs:19:12
|
||||
|
|
||||
LL | trait _2 = _1 + _1;
|
||||
| -------- this alias does not contain a trait
|
||||
LL |
|
||||
LL | type _T1 = dyn _2;
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0224`.
|
||||
19
tests/ui/traits/alias/relaxed-bounds.rs
Normal file
19
tests/ui/traits/alias/relaxed-bounds.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#![feature(trait_alias)]
|
||||
|
||||
// Ensure that relaxed bounds are not permitted in the `Self` bounds of trait aliases because trait
|
||||
// aliases (like traits) aren't implicitly bounded by `Sized` so there's nothing to relax.
|
||||
|
||||
trait Alias0 = ?Sized; //~ ERROR relaxed bounds are not permitted in trait alias bounds
|
||||
trait Alias1 = where Self: ?Sized; //~ ERROR this relaxed bound is not permitted here
|
||||
|
||||
trait Alias2<T: ?Sized> =; // OK
|
||||
trait Alias3<T> = where T: ?Sized; // OK
|
||||
|
||||
// Make sure that we don't permit "relaxing" trait aliases since we don't want to expand trait
|
||||
// aliases during sized elaboration for simplicity as we'd need to handle relaxing arbitrary bounds
|
||||
// (e.g., ones with modifiers, outlives-bounds, …) and where-clauses.
|
||||
|
||||
trait SizedAlias = Sized;
|
||||
fn take<T: ?SizedAlias>() {} //~ ERROR bound modifier `?` can only be applied to `Sized`
|
||||
|
||||
fn main() {}
|
||||
24
tests/ui/traits/alias/relaxed-bounds.stderr
Normal file
24
tests/ui/traits/alias/relaxed-bounds.stderr
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
error: relaxed bounds are not permitted in trait alias bounds
|
||||
--> $DIR/relaxed-bounds.rs:6:16
|
||||
|
|
||||
LL | trait Alias0 = ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: trait aliases are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/relaxed-bounds.rs:7:28
|
||||
|
|
||||
LL | trait Alias1 = where Self: ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/relaxed-bounds.rs:17:12
|
||||
|
|
||||
LL | fn take<T: ?SizedAlias>() {}
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed.
|
||||
|
||||
type _0 = dyn ?Sized;
|
||||
//~^ ERROR at least one trait is required for an object type [E0224]
|
||||
//~| ERROR relaxed bounds are not permitted in trait object types
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/only-maybe-bound.rs:3:15
|
||||
|
|
||||
LL | type _0 = dyn ?Sized;
|
||||
| ^^^^^^
|
||||
|
||||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/only-maybe-bound.rs:3:11
|
||||
|
|
||||
LL | type _0 = dyn ?Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0224`.
|
||||
|
|
@ -30,6 +30,9 @@ trait Tr: ?Sized {} //~ ERROR relaxed bounds are not permitted in supertrait bou
|
|||
|
||||
// Test that relaxed `Sized` bounds are rejected in trait object types:
|
||||
|
||||
type O0 = dyn ?Sized;
|
||||
//~^ ERROR relaxed bounds are not permitted in trait object types
|
||||
//~| ERROR at least one trait is required for an object type [E0224]
|
||||
type O1 = dyn Tr + ?Sized; //~ ERROR relaxed bounds are not permitted in trait object types
|
||||
type O2 = dyn ?Sized + ?Sized + Tr;
|
||||
//~^ ERROR relaxed bounds are not permitted in trait object types
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ error: this relaxed bound is not permitted here
|
|||
LL | struct S1<T>(T) where (T): ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:8:27
|
||||
|
|
@ -12,7 +12,7 @@ error: this relaxed bound is not permitted here
|
|||
LL | struct S2<T>(T) where u8: ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:10:35
|
||||
|
|
@ -20,7 +20,7 @@ error: this relaxed bound is not permitted here
|
|||
LL | struct S3<T>(T) where &'static T: ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:14:34
|
||||
|
|
@ -28,7 +28,7 @@ error: this relaxed bound is not permitted here
|
|||
LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:22:21
|
||||
|
|
@ -36,7 +36,7 @@ error: this relaxed bound is not permitted here
|
|||
LL | fn f() where T: ?Sized {}
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:27:41
|
||||
|
|
@ -44,7 +44,7 @@ error: this relaxed bound is not permitted here
|
|||
LL | struct S6<T>(T) where T: Iterator<Item: ?Sized>;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: relaxed bounds are not permitted in supertrait bounds
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:29:11
|
||||
|
|
@ -52,25 +52,39 @@ error: relaxed bounds are not permitted in supertrait bounds
|
|||
LL | trait Tr: ?Sized {}
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: traits are `?Sized` by default
|
||||
= note: traits are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:33:20
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:33:15
|
||||
|
|
||||
LL | type O0 = dyn ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:36:20
|
||||
|
|
||||
LL | type O1 = dyn Tr + ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:34:15
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:37:15
|
||||
|
|
||||
LL | type O2 = dyn ?Sized + ?Sized + Tr;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:34:24
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:37:24
|
||||
|
|
||||
LL | type O2 = dyn ?Sized + ?Sized + Tr;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:14:34
|
||||
|
|
@ -84,5 +98,12 @@ error: bound modifier `?` can only be applied to `Sized`
|
|||
LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:33:11
|
||||
|
|
||||
LL | type O0 = dyn ?Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0224`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue