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:
Stuart Cook 2025-10-20 22:30:53 +11:00 committed by GitHub
commit f87f9a456c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 475 additions and 318 deletions

View file

@ -426,7 +426,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|this| {
this.lower_param_bounds(
bounds,
RelaxedBoundPolicy::Allowed,
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitAlias),
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
)
},

View file

@ -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();
}

View file

@ -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

View file

@ -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(

View file

@ -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) => {

View file

@ -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 {

View file

@ -1,5 +1,3 @@
#![feature(trait_alias)]
pub struct Foo;
pub trait Bar {

View file

@ -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")]
| ^^^^^^^^^^^^^^^^^^^

View file

@ -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`

View file

@ -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

View file

@ -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

View file

@ -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 {}

View file

@ -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`.

View file

@ -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>;

View file

@ -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

View file

@ -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`.

View file

@ -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 {}

View file

@ -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

View 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() {}

View file

@ -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`.

View 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`.
}

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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`.

View 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() {}

View 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

View file

@ -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() {}

View file

@ -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`.

View file

@ -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

View file

@ -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`.