diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 53351f91c46bc..1a52ed02c4042 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -426,7 +426,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this| { this.lower_param_bounds( bounds, - RelaxedBoundPolicy::Allowed, + RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitAlias), ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) }, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4e2243e87873c..0a4d39b175be7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -296,6 +296,7 @@ enum RelaxedBoundPolicy<'a> { enum RelaxedBoundForbiddenReason { TraitObjectTy, SuperTrait, + TraitAlias, AssocTyBounds, LateBoundVarsInScope, } @@ -2085,12 +2086,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, @@ -2103,33 +2106,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 @@ -2142,7 +2153,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(); } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 7accab8df87c7..a3cb49e32d808 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -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 diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 165051744641f..1ce541ffb2797 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -8,7 +8,7 @@ use rustc_errors::{ }; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId, 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( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index eb660804c2b52..f0ab6cd6dbab4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -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, { 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! @@ -1914,10 +1935,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( @@ -1929,11 +1952,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 => @@ -1953,8 +1975,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); @@ -2240,15 +2262,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) => { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3c5c21a7a89c2..2752d94c5bbb7 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1782,9 +1782,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)) } /// Returns a range of the start/end indices specified with the diff --git a/tests/rustdoc-ui/doc-alias-assoc-const.rs b/tests/rustdoc-ui/doc-alias-assoc-const.rs index d95324734be47..cbbc3fe4e21f3 100644 --- a/tests/rustdoc-ui/doc-alias-assoc-const.rs +++ b/tests/rustdoc-ui/doc-alias-assoc-const.rs @@ -1,5 +1,3 @@ -#![feature(trait_alias)] - pub struct Foo; pub trait Bar { diff --git a/tests/rustdoc-ui/doc-alias-assoc-const.stderr b/tests/rustdoc-ui/doc-alias-assoc-const.stderr index cd3ad4ab393a5..cc628c39400b1 100644 --- a/tests/rustdoc-ui/doc-alias-assoc-const.stderr +++ b/tests/rustdoc-ui/doc-alias-assoc-const.stderr @@ -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")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs index 9c727ae3aad4c..191fef3eae457 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs @@ -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) {} //~^ ERROR relaxed bounds are not permitted in trait object types +//~| ERROR bound modifier `?` can only be applied to `Sized` fn bar(_: T) {} //~^ ERROR bound modifier `?` can only be applied to `Sized` //~| ERROR bound modifier `?` can only be applied to `Sized` diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr index da6ad5f16e20c..6503af2b5876d 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr @@ -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 +error: relaxed bounds are not permitted in trait object types + --> $DIR/feature-gate-more-maybe-bounds.rs:12:28 | -LL | trait Trait4 where Self: ?Trait1 {} - | ^^^^^^^ +LL | fn foo(_: Box) {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/feature-gate-more-maybe-bounds.rs:6:15 | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item +LL | trait Trait3: ?Trait1 {} + | ^^^^^^^ -error: relaxed bounds are not permitted in trait object types - --> $DIR/feature-gate-more-maybe-bounds.rs:8:28 +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) {} | ^^^^^^^ 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:15:11 | LL | fn bar(_: 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) {} | ^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/parser/trait-object-trait-parens.stderr b/tests/ui/parser/trait-object-trait-parens.stderr index f498d7d36bba6..c43ca23c4885d 100644 --- a/tests/ui/parser/trait-object-trait-parens.stderr +++ b/tests/ui/parser/trait-object-trait-parens.stderr @@ -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 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 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 diff --git a/tests/ui/sized-hierarchy/default-supertrait.rs b/tests/ui/sized-hierarchy/default-supertrait.rs index ab3b28e84db5a..d5bf152b7963b 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.rs +++ b/tests/ui/sized-hierarchy/default-supertrait.rs @@ -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 {} diff --git a/tests/ui/sized-hierarchy/default-supertrait.stderr b/tests/ui/sized-hierarchy/default-supertrait.stderr index f5589d6e279cc..2a521dce8b6bb 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.stderr +++ b/tests/ui/sized-hierarchy/default-supertrait.stderr @@ -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() { | ^^^^ 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() { | ++++++++++++++++++++++++ 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() { | - this type parameter needs to be `Sized` @@ -43,13 +87,13 @@ LL | requires_sized::(); | ^ 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() {} | ^^^^^ 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() { | - this type parameter needs to be `Sized` @@ -57,19 +101,19 @@ LL | requires_sized::(); | ^ 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() {} | ^^^^^ 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::(); | ^ 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() {} | ^^^^^^^^^ required by this bound in `requires_metasized` @@ -79,7 +123,7 @@ LL | fn with_pointeesized_supertrait $DIR/default-supertrait.rs:54:22 + --> $DIR/default-supertrait.rs:59:22 | LL | fn with_bare_trait() { | - this type parameter needs to be `Sized` @@ -88,19 +132,19 @@ LL | requires_sized::(); | ^ 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() {} | ^^^^^ 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::(); | ^ 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() {} | ^^^^^^^^^ 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() { | ++++++++++++++++++++++++ -error: aborting due to 9 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/sized-hierarchy/trait-aliases.rs b/tests/ui/sized-hierarchy/trait-aliases.rs deleted file mode 100644 index ffec302adaa5c..0000000000000 --- a/tests/ui/sized-hierarchy/trait-aliases.rs +++ /dev/null @@ -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 = ?Sized + IndexMut>::Output>; diff --git a/tests/ui/sized/relaxing-default-bound-error-37534.rs b/tests/ui/sized/relaxing-default-bound-error-37534.rs index d30e9f92ce9fb..5aca030908bfa 100644 --- a/tests/ui/sized/relaxing-default-bound-error-37534.rs +++ b/tests/ui/sized/relaxing-default-bound-error-37534.rs @@ -1,7 +1,5 @@ -struct Foo {} -//~^ ERROR expected trait, found derive macro `Hash` -//~| ERROR bound modifier `?` can only be applied to `Sized` +// issue: -fn main() {} +struct Foo {} //~ ERROR expected trait, found derive macro `Hash` -// https://github.com/rust-lang/rust/issues/37534 +fn main() {} diff --git a/tests/ui/sized/relaxing-default-bound-error-37534.stderr b/tests/ui/sized/relaxing-default-bound-error-37534.stderr index 8b9597f33e307..5de82206d2692 100644 --- a/tests/ui/sized/relaxing-default-bound-error-37534.stderr +++ b/tests/ui/sized/relaxing-default-bound-error-37534.stderr @@ -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 {} | ^^^^ 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 {} - | ^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/trait-bounds/more_maybe_bounds.rs b/tests/ui/trait-bounds/more_maybe_bounds.rs index ddd4313bd5e15..e719327c8858f 100644 --- a/tests/ui/trait-bounds/more_maybe_bounds.rs +++ b/tests/ui/trait-bounds/more_maybe_bounds.rs @@ -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) {} -//~^ 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() where T: Iterator {} //~^ ERROR this relaxed bound is not permitted here +//~| ERROR bound modifier `?` can only be applied to default traits struct S1(T); impl S1 { 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) 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 {} diff --git a/tests/ui/trait-bounds/more_maybe_bounds.stderr b/tests/ui/trait-bounds/more_maybe_bounds.stderr index 0d78cfd582047..ef079213e1179 100644 --- a/tests/ui/trait-bounds/more_maybe_bounds.stderr +++ b/tests/ui/trait-bounds/more_maybe_bounds.stderr @@ -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() where T: Iterator {} | ^^^^^^^ | - = 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) 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) {} | ^^^^^^^ -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) {} | ^^^^^^^ -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) {} | ^^^^^^^ -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() where T: Iterator {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to default traits --> $DIR/more_maybe_bounds.rs:35:34 | LL | struct S2(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 diff --git a/tests/ui/traits/alias/effectively-empty-trait-object-type.rs b/tests/ui/traits/alias/effectively-empty-trait-object-type.rs new file mode 100644 index 0000000000000..f7e8daa88e7c2 --- /dev/null +++ b/tests/ui/traits/alias/effectively-empty-trait-object-type.rs @@ -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() {} diff --git a/tests/ui/traits/alias/effectively-empty-trait-object-type.stderr b/tests/ui/traits/alias/effectively-empty-trait-object-type.stderr new file mode 100644 index 0000000000000..dbef9c3b5b31b --- /dev/null +++ b/tests/ui/traits/alias/effectively-empty-trait-object-type.stderr @@ -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`. diff --git a/tests/ui/traits/alias/empty.rs b/tests/ui/traits/alias/empty.rs new file mode 100644 index 0000000000000..68d642f485395 --- /dev/null +++ b/tests/ui/traits/alias/empty.rs @@ -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() {} + +fn main() { + check::<()>(); // OK. "`(): Empty`" is trivially satisfied + check::(); // OK. `Empty` is truly empty and isn't implicitly bounded by `Sized`. +} diff --git a/tests/ui/traits/alias/maybe-bound.rs b/tests/ui/traits/alias/maybe-bound.rs deleted file mode 100644 index 9fdeb714d5e75..0000000000000 --- a/tests/ui/traits/alias/maybe-bound.rs +++ /dev/null @@ -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() {} diff --git a/tests/ui/traits/alias/only-maybe-bound.rs b/tests/ui/traits/alias/only-maybe-bound.rs deleted file mode 100644 index e4abf314e0a96..0000000000000 --- a/tests/ui/traits/alias/only-maybe-bound.rs +++ /dev/null @@ -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() {} diff --git a/tests/ui/traits/alias/only-maybe-bound.stderr b/tests/ui/traits/alias/only-maybe-bound.stderr deleted file mode 100644 index 175ec8120ecc6..0000000000000 --- a/tests/ui/traits/alias/only-maybe-bound.stderr +++ /dev/null @@ -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`. diff --git a/tests/ui/traits/alias/relaxed-bounds.rs b/tests/ui/traits/alias/relaxed-bounds.rs new file mode 100644 index 0000000000000..88e092c631622 --- /dev/null +++ b/tests/ui/traits/alias/relaxed-bounds.rs @@ -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 =; // OK +trait Alias3 = 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() {} //~ ERROR bound modifier `?` can only be applied to `Sized` + +fn main() {} diff --git a/tests/ui/traits/alias/relaxed-bounds.stderr b/tests/ui/traits/alias/relaxed-bounds.stderr new file mode 100644 index 0000000000000..d7782b723a305 --- /dev/null +++ b/tests/ui/traits/alias/relaxed-bounds.stderr @@ -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() {} + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/traits/wf-object/only-maybe-bound.rs b/tests/ui/traits/wf-object/only-maybe-bound.rs deleted file mode 100644 index 96360e0331cdb..0000000000000 --- a/tests/ui/traits/wf-object/only-maybe-bound.rs +++ /dev/null @@ -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() {} diff --git a/tests/ui/traits/wf-object/only-maybe-bound.stderr b/tests/ui/traits/wf-object/only-maybe-bound.stderr deleted file mode 100644 index 6ae4568c699a7..0000000000000 --- a/tests/ui/traits/wf-object/only-maybe-bound.stderr +++ /dev/null @@ -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`. diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.rs b/tests/ui/unsized/relaxed-bounds-invalid-places.rs index 4c1f242a01cef..5aa1dbb9a094e 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.rs +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.rs @@ -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 diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr index d3f0535e2f0cb..7f54d045a1ce8 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr @@ -4,7 +4,7 @@ error: this relaxed bound is not permitted here LL | struct S1(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) 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) 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) 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) where T: Iterator; | ^^^^^^ | - = 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(*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`.