diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index c6472fd45fa98..370b15d2871a9 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -127,9 +127,6 @@ ast_lowering_misplaced_impl_trait = `impl Trait` is not allowed in {$position} .note = `impl Trait` is only allowed in arguments and return types of functions and methods -ast_lowering_misplaced_relax_trait_bound = - `?Trait` bounds are only permitted at the point where a type parameter is declared - ast_lowering_never_pattern_with_body = a never pattern is always unreachable .label = this will never be executed diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index b444324ef9143..83f3a976e83f7 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -324,13 +324,6 @@ pub(crate) struct MisplacedDoubleDot { pub span: Span, } -#[derive(Diagnostic)] -#[diag(ast_lowering_misplaced_relax_trait_bound)] -pub(crate) struct MisplacedRelaxTraitBound { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(ast_lowering_match_arm_with_no_body)] pub(crate) struct MatchArmWithNoBody { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ef27d0ef69b14..35bf9ac371261 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -15,14 +15,11 @@ use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; use tracing::instrument; -use super::errors::{ - InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound, TupleStructWithDefault, - UnionWithDefault, -}; +use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault}; use super::stability::{enabled_names, gate_unstable_abi}; use super::{ AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, - ResolverAstLoweringExt, + RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt, }; pub(super) struct ItemLowerer<'a, 'hir> { @@ -427,6 +424,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this| { let bounds = this.lower_param_bounds( bounds, + RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait), ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ); let items = this.arena.alloc_from_iter( @@ -447,6 +445,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this| { this.lower_param_bounds( bounds, + RelaxedBoundPolicy::Allowed, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) }, @@ -938,6 +937,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::TraitItemKind::Type( this.lower_param_bounds( bounds, + RelaxedBoundPolicy::Allowed, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), ), ty, @@ -1703,61 +1703,6 @@ impl<'hir> LoweringContext<'_, 'hir> { assert!(self.impl_trait_defs.is_empty()); assert!(self.impl_trait_bounds.is_empty()); - // Error if `?Trait` bounds in where clauses don't refer directly to type parameters. - // Note: we used to clone these bounds directly onto the type parameter (and avoid lowering - // these into hir when we lower thee where clauses), but this makes it quite difficult to - // keep track of the Span info. Now, `::add_implicit_sized_bound` - // checks both param bounds and where clauses for `?Sized`. - for pred in &generics.where_clause.predicates { - let WherePredicateKind::BoundPredicate(bound_pred) = &pred.kind else { - continue; - }; - let compute_is_param = || { - // Check if the where clause type is a plain type parameter. - match self - .resolver - .get_partial_res(bound_pred.bounded_ty.id) - .and_then(|r| r.full_res()) - { - Some(Res::Def(DefKind::TyParam, def_id)) - if bound_pred.bound_generic_params.is_empty() => - { - generics - .params - .iter() - .any(|p| def_id == self.local_def_id(p.id).to_def_id()) - } - // Either the `bounded_ty` is not a plain type parameter, or - // it's not found in the generic type parameters list. - _ => false, - } - }; - // We only need to compute this once per `WherePredicate`, but don't - // need to compute this at all unless there is a Maybe bound. - let mut is_param: Option = None; - for bound in &bound_pred.bounds { - if !matches!( - *bound, - GenericBound::Trait(PolyTraitRef { - modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. }, - .. - }) - ) { - continue; - } - let is_param = *is_param.get_or_insert_with(compute_is_param); - if !is_param && !self.tcx.features().more_maybe_bounds() { - self.tcx - .sess - .create_feature_err( - MisplacedRelaxTraitBound { span: bound.span() }, - sym::more_maybe_bounds, - ) - .emit(); - } - } - } - let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new(); predicates.extend(generics.params.iter().filter_map(|param| { self.lower_generic_bound_predicate( @@ -1767,6 +1712,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ¶m.bounds, param.colon_span, generics.span, + RelaxedBoundPolicy::Allowed, itctx, PredicateOrigin::GenericParam, ) @@ -1776,7 +1722,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .where_clause .predicates .iter() - .map(|predicate| self.lower_where_predicate(predicate)), + .map(|predicate| self.lower_where_predicate(predicate, &generics.params)), ); let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self @@ -1853,6 +1799,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounds: &[GenericBound], colon_span: Option, parent_span: Span, + rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, origin: PredicateOrigin, ) -> Option> { @@ -1861,7 +1808,7 @@ impl<'hir> LoweringContext<'_, 'hir> { return None; } - let bounds = self.lower_param_bounds(bounds, itctx); + let bounds = self.lower_param_bounds(bounds, rbp, itctx); let param_span = ident.span; @@ -1913,7 +1860,11 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::WherePredicate { hir_id, span, kind }) } - fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> { + fn lower_where_predicate( + &mut self, + pred: &WherePredicate, + params: &[ast::GenericParam], + ) -> hir::WherePredicate<'hir> { let hir_id = self.lower_node_id(pred.id); let span = self.lower_span(pred.span); self.lower_attrs(hir_id, &pred.attrs, span); @@ -1922,17 +1873,29 @@ impl<'hir> LoweringContext<'_, 'hir> { bound_generic_params, bounded_ty, bounds, - }) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { - bound_generic_params: self - .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder), - bounded_ty: self - .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), - bounds: self.lower_param_bounds( - bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - ), - origin: PredicateOrigin::WhereClause, - }), + }) => { + let rbp = if bound_generic_params.is_empty() { + RelaxedBoundPolicy::AllowedIfOnTyParam(bounded_ty.id, params) + } else { + RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::LateBoundVarsInScope) + }; + hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { + bound_generic_params: self.lower_generic_params( + bound_generic_params, + hir::GenericParamSource::Binder, + ), + bounded_ty: self.lower_ty( + bounded_ty, + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ), + bounds: self.lower_param_bounds( + bounds, + rbp, + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ), + origin: PredicateOrigin::WhereClause, + }) + } WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => { hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { lifetime: self.lower_lifetime( @@ -1942,6 +1905,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ), bounds: self.lower_param_bounds( bounds, + RelaxedBoundPolicy::Allowed, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), in_where_clause: true, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 26d7c0cd6d38f..8faf96a6df2d1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -53,14 +53,14 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; use rustc_hir::lints::DelayedLint; use rustc_hir::{ - self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, - LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate, + self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource, + LifetimeSyntax, ParamName, TraitCandidate, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; -use rustc_session::parse::add_feature_diagnostics; +use rustc_session::parse::{add_feature_diagnostics, feature_err}; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; use smallvec::SmallVec; @@ -276,6 +276,20 @@ impl ResolverAstLowering { } } +#[derive(Clone, Copy, Debug)] +enum RelaxedBoundPolicy<'a> { + Allowed, + AllowedIfOnTyParam(NodeId, &'a [ast::GenericParam]), + Forbidden(RelaxedBoundForbiddenReason), +} + +#[derive(Clone, Copy, Debug)] +enum RelaxedBoundForbiddenReason { + TraitObjectTy, + SuperTrait, + LateBoundVarsInScope, +} + /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, /// and if so, what meaning it has. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -1079,10 +1093,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); hir::AssocItemConstraintKind::Equality { term: err_ty.into() } } else { - // Desugar `AssocTy: Bounds` into an assoc type binding where the - // later desugars into a trait predicate. - let bounds = self.lower_param_bounds(bounds, itctx); - + // FIXME(#135229): These should be forbidden! + let bounds = + self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx); hir::AssocItemConstraintKind::Bound { bounds } } } @@ -1210,6 +1223,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, span: t.span, }, + RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitObjectTy), itctx, ); let bounds = this.arena.alloc_from_iter([bound]); @@ -1265,7 +1279,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { parenthesized: hir::GenericArgsParentheses::No, span_ext: span, }); - let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args)); + let path = self.make_lang_item_qpath(hir::LangItem::Pin, span, Some(args)); hir::TyKind::Path(path) } TyKind::BareFn(f) => { @@ -1326,7 +1340,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // takes care of rejecting invalid modifier combinations and // const trait bounds in trait object types. GenericBound::Trait(ty) => { - let trait_ref = this.lower_poly_trait_ref(ty, itctx); + let trait_ref = this.lower_poly_trait_ref( + ty, + RelaxedBoundPolicy::Forbidden( + RelaxedBoundForbiddenReason::TraitObjectTy, + ), + itctx, + ); Some(trait_ref) } GenericBound::Outlives(lifetime) => { @@ -1381,9 +1401,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } - ImplTraitContext::InBinding => { - hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx)) - } + ImplTraitContext::InBinding => hir::TyKind::TraitAscription( + self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx), + ), ImplTraitContext::FeatureGated(position, feature) => { let guar = self .tcx @@ -1499,7 +1519,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| { - this.lower_param_bounds(bounds, itctx) + this.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx) }) } @@ -1793,10 +1813,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bound( &mut self, tpb: &GenericBound, + rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { - GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)), + GenericBound::Trait(p) => { + hir::GenericBound::Trait(self.lower_poly_trait_ref(p, rbp, itctx)) + } GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime( lifetime, LifetimeSource::OutlivesBound, @@ -2011,19 +2034,81 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { #[instrument(level = "debug", skip(self))] fn lower_poly_trait_ref( &mut self, - p: &PolyTraitRef, + tr: &PolyTraitRef, + rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, ) -> hir::PolyTraitRef<'hir> { + let PolyTraitRef { ref bound_generic_params, modifiers, ref trait_ref, span } = *tr; + let bound_generic_params = - self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); - let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx); - let modifiers = self.lower_trait_bound_modifiers(p.modifiers); + self.lower_lifetime_binder(trait_ref.ref_id, bound_generic_params); + let trait_ref = self.lower_trait_ref(modifiers, trait_ref, itctx); + let modifiers = self.lower_trait_bound_modifiers(modifiers); + + if let ast::BoundPolarity::Maybe(_) = modifiers.polarity { + self.validate_relaxed_bound(trait_ref, span, rbp); + } + hir::PolyTraitRef { bound_generic_params, modifiers, trait_ref, - span: self.lower_span(p.span), + span: self.lower_span(span), + } + } + + fn validate_relaxed_bound( + &self, + trait_ref: hir::TraitRef<'_>, + span: Span, + rbp: RelaxedBoundPolicy<'_>, + ) { + let err = |message| feature_err(&self.tcx.sess, sym::more_maybe_bounds, span, message); + + match rbp { + RelaxedBoundPolicy::Allowed => return, + RelaxedBoundPolicy::AllowedIfOnTyParam(id, params) => { + if let Some(res) = self.resolver.get_partial_res(id).and_then(|r| r.full_res()) + && let Res::Def(DefKind::TyParam, def_id) = res + && params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id()) + { + return; + } + if self.tcx.features().more_maybe_bounds() { + return; + } + } + RelaxedBoundPolicy::Forbidden(reason) => { + if self.tcx.features().more_maybe_bounds() { + return; + } + + match reason { + RelaxedBoundForbiddenReason::TraitObjectTy => { + err("relaxed bounds are not permitted in trait object types").emit(); + return; + } + RelaxedBoundForbiddenReason::SuperTrait => { + let mut diag = err("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(); + return; + } + RelaxedBoundForbiddenReason::LateBoundVarsInScope => {} + }; + } } + + err("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", + ) + .emit(); } fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { @@ -2034,17 +2119,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds( &mut self, bounds: &[GenericBound], + rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, ) -> hir::GenericBounds<'hir> { - self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) + self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, rbp, itctx)) } fn lower_param_bounds_mut( &mut self, bounds: &[GenericBound], + rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, ) -> impl Iterator> { - bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) + bounds.iter().map(move |bound| self.lower_param_bound(bound, rbp, itctx)) } #[instrument(level = "debug", skip(self), ret)] @@ -2078,6 +2165,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds, /* colon_span */ None, span, + RelaxedBoundPolicy::Allowed, ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 9a267501230fe..d9e95490c0b44 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -207,11 +207,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax .help = use `auto trait Trait {"{}"}` instead -ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types - -ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits - .note = traits are `?{$path_str}` by default - ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters .suggestion = reorder the parameters: lifetimes, then consts and types diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b69a91e2f5f86..472dc12b7bfd9 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1320,29 +1320,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match bound { GenericBound::Trait(trait_ref) => { match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) { - (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) - if !self.features.more_maybe_bounds() => - { - self.sess - .create_feature_err( - errors::OptionalTraitSupertrait { - span: trait_ref.span, - path_str: pprust::path_to_string(&trait_ref.trait_ref.path), - }, - sym::more_maybe_bounds, - ) - .emit(); - } - (BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) - if !self.features.more_maybe_bounds() => - { - self.sess - .create_feature_err( - errors::OptionalTraitObject { span: trait_ref.span }, - sym::more_maybe_bounds, - ) - .emit(); - } ( BoundKind::TraitObject, BoundConstness::Always(_), diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index c437e62f4d373..e0c7953c8adfe 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -565,22 +565,6 @@ pub(crate) struct NestedLifetimes { pub span: Span, } -#[derive(Diagnostic)] -#[diag(ast_passes_optional_trait_supertrait)] -#[note] -pub(crate) struct OptionalTraitSupertrait { - #[primary_span] - pub span: Span, - pub path_str: String, -} - -#[derive(Diagnostic)] -#[diag(ast_passes_optional_trait_object)] -pub(crate) struct OptionalTraitObject { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(ast_passes_const_bound_trait_object)] pub(crate) struct ConstBoundTraitObject { diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index bd2252c1bf8fd..a41903d26d6a5 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -371,9 +371,6 @@ hir_analysis_missing_type_params = *[other] parameters } must be specified on the object type -hir_analysis_multiple_relaxed_default_bounds = - type parameter has more than one relaxed default bound, only one is supported - hir_analysis_must_be_name_of_associated_function = must be a name of an associated function hir_analysis_must_implement_not_function = not a function diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index c337765c5fec3..e033eec5a8fbe 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -266,20 +266,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen match predicate.kind { hir::WherePredicateKind::BoundPredicate(bound_pred) => { let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty); - let bound_vars = tcx.late_bound_vars(predicate.hir_id); - // Keep the type around in a dummy predicate, in case of no bounds. - // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` - // is still checked for WF. + + // This is a `where Ty:` (sic!). if bound_pred.bounds.is_empty() { if let ty::Param(_) = ty.kind() { - // This is a `where T:`, which can be in the HIR from the - // transformation that moves `?Sized` to `T`'s declaration. - // We can skip the predicate because type parameters are - // trivially WF, but also we *should*, to avoid exposing - // users who never wrote `where Type:,` themselves, to - // compiler/tooling bugs from not handling WF predicates. + // We can skip the predicate because type parameters are trivially WF. } else { + // Keep the type around in a dummy predicate. That way, it's not a complete + // noop (see #53696) and `Ty` is still checked for WF. + let span = bound_pred.bounded_ty.span; let predicate = ty::Binder::bind_with_vars( ty::ClauseKind::WellFormed(ty.into()), diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 318aaab50f4d4..915f5a375e24c 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -277,13 +277,6 @@ pub(crate) struct CopyImplOnTypeWithDtor { pub span: Span, } -#[derive(Diagnostic)] -#[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)] -pub(crate) struct MultipleRelaxedDefaultBounds { - #[primary_span] - pub spans: Vec, -} - #[derive(Diagnostic)] #[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)] pub(crate) struct CopyImplOnNonAdt { 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 ea1dfdfd80619..de18e3e87b69c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -6,7 +6,7 @@ use rustc_errors::struct_span_code_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{AmbigArg, LangItem, PolyTraitRef}; +use rustc_hir::{AmbigArg, PolyTraitRef}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -85,17 +85,17 @@ fn search_bounds_for<'tcx>( } } -fn collect_unbounds<'tcx>( +fn collect_relaxed_bounds<'tcx>( hir_bounds: &'tcx [hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, ) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> { - let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); + let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new(); search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| { if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) { - unbounds.push(ptr); + relaxed_bounds.push(ptr); } }); - unbounds + relaxed_bounds } fn collect_bounds<'a, 'tcx>( @@ -124,13 +124,13 @@ fn collect_sizedness_bounds<'tcx>( self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, span: Span, ) -> CollectedSizednessBounds { - let sized_did = tcx.require_lang_item(LangItem::Sized, span); + let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span); let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did); - let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span); + let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span); let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did); - let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); + let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span); let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did); CollectedSizednessBounds { sized, meta_sized, pointee_sized } @@ -151,24 +151,6 @@ fn add_trait_bound<'tcx>( } impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Skip `PointeeSized` bounds. - /// - /// `PointeeSized` is a "fake bound" insofar as anywhere a `PointeeSized` bound exists, there - /// is actually the absence of any bounds. This avoids limitations around non-global where - /// clauses being preferred over item bounds (where `PointeeSized` bounds would be - /// proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is - /// added to some items. - pub(crate) fn should_skip_sizedness_bound<'hir>( - &self, - bound: &'hir hir::GenericBound<'tcx>, - ) -> bool { - bound - .trait_ref() - .and_then(|tr| tr.trait_def_id()) - .map(|did| self.tcx().is_lang_item(did, LangItem::PointeeSized)) - .unwrap_or(false) - } - /// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type. /// /// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit @@ -188,8 +170,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) { let tcx = self.tcx(); - let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span); - let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); + let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span); + let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span); // If adding sizedness bounds to a trait, then there are some relevant early exits if let Some(trait_did) = trait_did { @@ -204,9 +186,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return; } } else { - // Report invalid unbounds on sizedness-bounded generic parameters. - let unbounds = collect_unbounds(hir_bounds, self_ty_where_predicates); - self.check_and_report_invalid_unbounds_on_param(unbounds); + // Report invalid relaxed bounds. + // FIXME(more_maybe_bounds): This validation function is only called in contexts where + // we perform "sized elaboration". This means, it doesn't get called for e.g., + // trait object types or supertrait bounds! + // Ideally, we would do these checks in `Self::lower_poly_trait_ref`! + let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates); + self.check_and_report_invalid_relaxed_bounds(bounds); } let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span); @@ -226,7 +212,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else { // If there are no explicit sizedness bounds on a parameter then add a default // `Sized` bound. - let sized_did = tcx.require_lang_item(LangItem::Sized, span); + let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span); add_trait_bound(tcx, bounds, self_ty, sized_did, span); } } @@ -461,10 +447,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { 'tcx: 'hir, { for hir_bound in hir_bounds { - if self.should_skip_sizedness_bound(hir_bound) { - continue; - } - // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`, // we skip over any traits that don't define the given associated type. if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter { @@ -480,12 +462,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match hir_bound { hir::GenericBound::Trait(poly_trait_ref) => { - let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers; let _ = self.lower_poly_trait_ref( - &poly_trait_ref.trait_ref, - poly_trait_ref.span, - constness, - polarity, + poly_trait_ref, param_ty, bounds, predicate_filter, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 05465b47a26a8..821e0ea780def 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -17,9 +17,7 @@ use tracing::{debug, instrument}; use super::HirTyLowerer; use crate::errors::SelfInTypeAlias; -use crate::hir_ty_lowering::{ - GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason, -}; +use crate::hir_ty_lowering::{GenericArgCountMismatch, PredicateFilter, RegionInferReason}; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Lower a trait object type from the HIR to our internal notion of a type. @@ -37,24 +35,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut user_written_bounds = Vec::new(); let mut potential_assoc_types = Vec::new(); - for trait_bound in hir_bounds.iter() { - if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity { - continue; - } - if let GenericArgCountResult { - correct: - Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), - .. - } = self.lower_poly_trait_ref( - &trait_bound.trait_ref, - trait_bound.span, - hir::BoundConstness::Never, - hir::BoundPolarity::Positive, + for poly_trait_ref in hir_bounds.iter() { + let result = self.lower_poly_trait_ref( + poly_trait_ref, dummy_self, &mut user_written_bounds, PredicateFilter::SelfOnly, - ) { - potential_assoc_types.extend(cur_potential_assoc_types); + ); + if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct { + potential_assoc_types.extend(invalid_args); } } 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 0e79a8918b050..cc484e2915857 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, LangItem, PolyTraitRef}; +use rustc_hir::{self as hir, HirId, PolyTraitRef}; use rustc_middle::bug; use rustc_middle::ty::fast_reject::{TreatParams, simplify_type}; use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; @@ -35,53 +35,48 @@ use crate::fluent_generated as fluent; use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Check for multiple relaxed default bounds and relaxed bounds of non-sizedness traits. - pub(crate) fn check_and_report_invalid_unbounds_on_param( + /// Check for duplicate relaxed bounds and relaxed bounds of non-default traits. + pub(crate) fn check_and_report_invalid_relaxed_bounds( &self, - unbounds: SmallVec<[&PolyTraitRef<'_>; 1]>, + relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>, ) { let tcx = self.tcx(); - let sized_did = tcx.require_lang_item(LangItem::Sized, DUMMY_SP); + let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default(); - let mut unique_bounds = FxIndexSet::default(); - let mut seen_repeat = false; - for unbound in &unbounds { - if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res { - seen_repeat |= !unique_bounds.insert(unbound_def_id); + 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); } } - if unbounds.len() > 1 { - let err = errors::MultipleRelaxedDefaultBounds { - spans: unbounds.iter().map(|ptr| ptr.span).collect(), - }; - - if seen_repeat { - tcx.dcx().emit_err(err); - } else if !tcx.features().more_maybe_bounds() { - tcx.sess.create_feature_err(err, sym::more_maybe_bounds).emit(); - }; + for (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(); + } } - for unbound in unbounds { - if let Res::Def(DefKind::Trait, did) = unbound.trait_ref.path.res - && ((did == sized_did) || tcx.is_default_trait(did)) + 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; } - - let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds { - true => "`?Sized` and `experimental_default_bounds`", - false => "`?Sized`", - }; self.dcx().span_err( - unbound.span, - format!( - "relaxing a default bound only does something for {}; all other traits are \ - not bound by default", - unbound_traits - ), + 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`" + }, ); } } 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 b99f7b44661ec..1fc65aded3d06 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -750,18 +750,45 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` /// where `'a` is a bound region at depth 0. Similarly, the `trait_ref` would be `Bar<'a>`. /// The lowered poly-trait-ref will track this binder explicitly, however. - #[instrument(level = "debug", skip(self, span, constness, bounds))] + #[instrument(level = "debug", skip(self, bounds))] pub(crate) fn lower_poly_trait_ref( &self, - trait_ref: &hir::TraitRef<'tcx>, - span: Span, - constness: hir::BoundConstness, - polarity: hir::BoundPolarity, + poly_trait_ref: &hir::PolyTraitRef<'tcx>, self_ty: Ty<'tcx>, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, predicate_filter: PredicateFilter, ) -> GenericArgCountResult { + let tcx = self.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 trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); + + let (polarity, bounds) = match polarity { + rustc_ast::BoundPolarity::Positive + if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) => + { + // Skip `PointeeSized` bounds. + // + // `PointeeSized` is a "fake bound" insofar as anywhere a `PointeeSized` bound exists, there + // is actually the absence of any bounds. This avoids limitations around non-global where + // clauses being preferred over item bounds (where `PointeeSized` bounds would be + // proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is + // added to some items. + (ty::PredicatePolarity::Positive, &mut Vec::new()) + } + rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds), + rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds), + // FIXME(fmease): This is super hacky! `Option` is also sad. + rustc_ast::BoundPolarity::Maybe(_) => { + (ty::PredicatePolarity::Positive, &mut Vec::new()) + } + }; + let trait_segment = trait_ref.path.segments.last().unwrap(); let _ = self.prohibit_generic_args( @@ -778,7 +805,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(self_ty), ); - let tcx = self.tcx(); let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); debug!(?bound_vars); @@ -789,27 +815,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?poly_trait_ref); - let polarity = match polarity { - rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive, - rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative, - rustc_ast::BoundPolarity::Maybe(_) => { - // Validate associated type at least. We may want to reject these - // outright in the future... - for constraint in trait_segment.args().constraints { - let _ = self.lower_assoc_item_constraint( - trait_ref.hir_ref_id, - poly_trait_ref, - constraint, - &mut Default::default(), - &mut Default::default(), - constraint.span, - predicate_filter, - ); - } - return arg_count; - } - }; - // We deal with const conditions later. match predicate_filter { PredicateFilter::All @@ -912,7 +917,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // 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! - if polarity != ty::PredicatePolarity::Positive { + if polarity == ty::PredicatePolarity::Negative { self.dcx().span_delayed_bug( constraint.span, "negative trait bounds should not have assoc item constraints", diff --git a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs index b90bb9ea4ddf6..029ce7d0e7e49 100644 --- a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs +++ b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs @@ -1,8 +1,7 @@ // Regression test for . fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { - //~^ ERROR `?Trait` is not permitted in trait object types - //~| ERROR expected trait, found associated function `Iterator::advance_by` - //~| ERROR the value of the associated type `Item` in `Iterator` must be specified + //~^ ERROR expected trait, found associated function `Iterator::advance_by` + //~| ERROR relaxed bounds are not permitted in trait object types todo!() } diff --git a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr index 7f0fbc800ed1c..3dc7fd78e41e8 100644 --- a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr +++ b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr @@ -1,25 +1,19 @@ -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/missing-associated_item_or_field_def_ids.rs:3:29 - | -LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0404]: expected trait, found associated function `Iterator::advance_by` --> $DIR/missing-associated_item_or_field_def_ids.rs:3:30 | LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait -error[E0191]: the value of the associated type `Item` in `Iterator` must be specified - --> $DIR/missing-associated_item_or_field_def_ids.rs:3:18 +error[E0658]: relaxed bounds are not permitted in trait object types + --> $DIR/missing-associated_item_or_field_def_ids.rs:3:29 | LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { - | ^^^^^^^^ help: specify the associated type: `Iterator` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0191, E0404, E0658. -For more information about an error, try `rustc --explain E0191`. +Some errors have detailed explanations: E0404, E0658. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs index f6b749a5100b9..bac4e60886772 100644 --- a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs +++ b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs @@ -6,7 +6,6 @@ trait Tr { fn main() { let _: dyn Tr + ?Foo; - //~^ ERROR: `?Trait` is not permitted in trait object types - //~| ERROR: cannot find trait `Foo` in this scope - //~| ERROR: the value of the associated type `Item` in `Tr` must be specified + //~^ ERROR: cannot find trait `Foo` in this scope + //~| ERROR: relaxed bounds are not permitted in trait object types } diff --git a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr index f31a1de76a790..3b35c164d37d4 100644 --- a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr +++ b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr @@ -1,28 +1,19 @@ -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:21 - | -LL | let _: dyn Tr + ?Foo; - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0405]: cannot find trait `Foo` in this scope --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:22 | LL | let _: dyn Tr + ?Foo; | ^^^ not found in this scope -error[E0191]: the value of the associated type `Item` in `Tr` must be specified - --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:16 +error[E0658]: relaxed bounds are not permitted in trait object types + --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:21 | -LL | type Item; - | --------- `Item` defined here -... LL | let _: dyn Tr + ?Foo; - | ^^ help: specify the associated type: `Tr` + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0191, E0405, E0658. -For more information about an error, try `rustc --explain E0191`. +Some errors have detailed explanations: E0405, E0658. +For more information about an error, try `rustc --explain E0405`. 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 6a832744e3ee9..9c727ae3aad4c 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs @@ -2,23 +2,13 @@ trait Trait1 {} auto trait Trait2 {} -trait Trait3: ?Trait1 {} -//~^ ERROR `?Trait` is not permitted in supertraits -trait Trait4 where Self: ?Trait1 {} -//~^ ERROR ?Trait` bounds are only permitted at the point where a type parameter is declared +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 fn foo(_: Box) {} -//~^ ERROR `?Trait` is not permitted in trait object types +//~^ ERROR relaxed bounds are not permitted in trait object types fn bar(_: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - -trait Trait {} -// Do not suggest `#![feature(more_maybe_bounds)]` for repetitions -fn baz(_ : T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +//~^ ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` fn main() {} 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 729df4eb37cac..d01d9cbef3adc 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr @@ -1,71 +1,43 @@ -error[E0658]: `?Trait` is not permitted in supertraits +error[E0658]: relaxed bounds are not permitted in supertrait bounds --> $DIR/feature-gate-more-maybe-bounds.rs:5:15 | LL | trait Trait3: ?Trait1 {} | ^^^^^^^ | - = note: traits are `?Trait1` by default = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/feature-gate-more-maybe-bounds.rs:10:28 - | -LL | fn foo(_: Box) {} - | ^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/feature-gate-more-maybe-bounds.rs:7:26 +error[E0658]: this relaxed bound is not permitted here + --> $DIR/feature-gate-more-maybe-bounds.rs:6:26 | LL | trait Trait4 where Self: ?Trait1 {} | ^^^^^^^ | = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/feature-gate-more-maybe-bounds.rs:12:11 +error[E0658]: relaxed bounds are not permitted in trait object types + --> $DIR/feature-gate-more-maybe-bounds.rs:8:28 | -LL | fn bar(_: T) {} - | ^^^^^^^ ^^^^^^^ +LL | fn foo(_: Box) {} + | ^^^^^^^ | = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/feature-gate-more-maybe-bounds.rs:12:11 +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/feature-gate-more-maybe-bounds.rs:10:11 | LL | fn bar(_: T) {} | ^^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/feature-gate-more-maybe-bounds.rs:12:21 +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/feature-gate-more-maybe-bounds.rs:10:21 | LL | fn bar(_: T) {} | ^^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/feature-gate-more-maybe-bounds.rs:19:11 - | -LL | fn baz(_ : T) {} - | ^^^^^^ ^^^^^^ - -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/feature-gate-more-maybe-bounds.rs:19:11 - | -LL | fn baz(_ : T) {} - | ^^^^^^ - -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/feature-gate-more-maybe-bounds.rs:19:20 - | -LL | fn baz(_ : T) {} - | ^^^^^^ - -error: aborting due to 9 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0203, E0658. -For more information about an error, try `rustc --explain E0203`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs b/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs index 27c493a13bf91..7e0e1eadf9c75 100644 --- a/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs +++ b/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs @@ -3,8 +3,8 @@ use std::future::Future; fn foo() -> impl ?Future { - //~^ ERROR: relaxing a default bound only does something for `?Sized` - //~| ERROR: relaxing a default bound only does something for `?Sized` + //~^ ERROR: bound modifier `?` can only be applied to `Sized` + //~| ERROR: bound modifier `?` can only be applied to `Sized` () } diff --git a/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr b/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr index dc4314c58ad2f..f99d6a7e5f6d0 100644 --- a/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr +++ b/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr @@ -1,10 +1,10 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/opt-out-bound-not-satisfied.rs:5:18 | LL | fn foo() -> impl ?Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/opt-out-bound-not-satisfied.rs:5:18 | LL | fn foo() -> impl ?Future { diff --git a/tests/ui/issues/issue-37534.rs b/tests/ui/issues/issue-37534.rs index 09d60b7786b99..63f6479ae2e24 100644 --- a/tests/ui/issues/issue-37534.rs +++ b/tests/ui/issues/issue-37534.rs @@ -1,5 +1,5 @@ struct Foo {} //~^ ERROR expected trait, found derive macro `Hash` -//~| ERROR relaxing a default bound only does something for `?Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` fn main() {} diff --git a/tests/ui/issues/issue-37534.stderr b/tests/ui/issues/issue-37534.stderr index 3219854bc70ce..0860735420301 100644 --- a/tests/ui/issues/issue-37534.stderr +++ b/tests/ui/issues/issue-37534.stderr @@ -9,7 +9,7 @@ help: consider importing this trait instead LL + use std::hash::Hash; | -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/issue-37534.rs:1:15 | LL | struct Foo {} diff --git a/tests/ui/issues/issue-87199.rs b/tests/ui/issues/issue-87199.rs index 4e4e35c6a71e8..dd9dfc74ca352 100644 --- a/tests/ui/issues/issue-87199.rs +++ b/tests/ui/issues/issue-87199.rs @@ -6,12 +6,12 @@ // Check that these function definitions only emit warnings, not errors fn arg(_: T) {} -//~^ ERROR: relaxing a default bound only does something for `?Sized` +//~^ ERROR: bound modifier `?` can only be applied to `Sized` fn ref_arg(_: &T) {} -//~^ ERROR: relaxing a default bound only does something for `?Sized` +//~^ ERROR: bound modifier `?` can only be applied to `Sized` fn ret() -> impl Iterator + ?Send { std::iter::empty() } -//~^ ERROR: relaxing a default bound only does something for `?Sized` -//~| ERROR: relaxing a default bound only does something for `?Sized` +//~^ ERROR: bound modifier `?` can only be applied to `Sized` +//~| ERROR: bound modifier `?` can only be applied to `Sized` // Check that there's no `?Sized` relaxation! fn main() { diff --git a/tests/ui/issues/issue-87199.stderr b/tests/ui/issues/issue-87199.stderr index acc4e84779c9c..8a930a3d704c1 100644 --- a/tests/ui/issues/issue-87199.stderr +++ b/tests/ui/issues/issue-87199.stderr @@ -1,22 +1,22 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/issue-87199.rs:8:11 | LL | fn arg(_: T) {} | ^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/issue-87199.rs:10:15 | LL | fn ref_arg(_: &T) {} | ^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/issue-87199.rs:12:40 | LL | fn ret() -> impl Iterator + ?Send { std::iter::empty() } | ^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/issue-87199.rs:12:40 | LL | fn ret() -> impl Iterator + ?Send { std::iter::empty() } diff --git a/tests/ui/maybe-bounds.rs b/tests/ui/maybe-bounds.rs index 02ed45c656f1c..194292a70f275 100644 --- a/tests/ui/maybe-bounds.rs +++ b/tests/ui/maybe-bounds.rs @@ -1,9 +1,9 @@ trait Tr: ?Sized {} -//~^ ERROR `?Trait` is not permitted in supertraits +//~^ ERROR relaxed bounds are not permitted in supertrait bounds type A1 = dyn Tr + (?Sized); -//~^ ERROR `?Trait` is not permitted in trait object types +//~^ ERROR relaxed bounds are not permitted in trait object types type A2 = dyn for<'a> Tr + (?Sized); -//~^ ERROR `?Trait` is not permitted in trait object types +//~^ ERROR relaxed bounds are not permitted in trait object types fn main() {} diff --git a/tests/ui/maybe-bounds.stderr b/tests/ui/maybe-bounds.stderr index 230d11fd0ae66..5cb377d79824c 100644 --- a/tests/ui/maybe-bounds.stderr +++ b/tests/ui/maybe-bounds.stderr @@ -1,14 +1,14 @@ -error[E0658]: `?Trait` is not permitted in supertraits +error[E0658]: relaxed bounds are not permitted in supertrait bounds --> $DIR/maybe-bounds.rs:1:11 | LL | trait Tr: ?Sized {} | ^^^^^^ | - = note: traits are `?Sized` by default = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: traits are `?Sized` by default -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/maybe-bounds.rs:4:20 | LL | type A1 = dyn Tr + (?Sized); @@ -17,7 +17,7 @@ LL | type A1 = dyn Tr + (?Sized); = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/maybe-bounds.rs:6:28 | LL | type A2 = dyn for<'a> Tr + (?Sized); diff --git a/tests/ui/parser/trait-object-trait-parens.rs b/tests/ui/parser/trait-object-trait-parens.rs index 438034bc38aa4..51f0e2de6116f 100644 --- a/tests/ui/parser/trait-object-trait-parens.rs +++ b/tests/ui/parser/trait-object-trait-parens.rs @@ -6,17 +6,17 @@ fn f Trait<'a>)>() {} fn main() { let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; - //~^ ERROR `?Trait` is not permitted in trait object types + //~^ ERROR relaxed bounds are not permitted in trait object types //~| ERROR only auto traits can be used as additional traits //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition let _: Box Trait<'a>) + (Obj)>; - //~^ ERROR `?Trait` is not permitted in trait object types + //~^ ERROR relaxed bounds are not permitted in trait object types //~| ERROR only auto traits can be used as additional traits //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition let _: Box Trait<'a> + (Obj) + (?Sized)>; - //~^ ERROR `?Trait` is not permitted in trait object types + //~^ ERROR relaxed bounds are not permitted in trait object types //~| ERROR only auto traits can be used as additional traits //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition diff --git a/tests/ui/parser/trait-object-trait-parens.stderr b/tests/ui/parser/trait-object-trait-parens.stderr index d75352b6811ea..8f8ddeac1c5aa 100644 --- a/tests/ui/parser/trait-object-trait-parens.stderr +++ b/tests/ui/parser/trait-object-trait-parens.stderr @@ -1,4 +1,4 @@ -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/trait-object-trait-parens.rs:8:24 | LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; @@ -7,7 +7,7 @@ LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/trait-object-trait-parens.rs:13:16 | LL | let _: Box Trait<'a>) + (Obj)>; @@ -16,7 +16,7 @@ LL | let _: Box Trait<'a>) + (Obj)>; = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/trait-object-trait-parens.rs:18:44 | LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; diff --git a/tests/ui/sized-hierarchy/default-bound.rs b/tests/ui/sized-hierarchy/default-bound.rs index 12b2eb2b5c1b4..bbb2c6d96baa8 100644 --- a/tests/ui/sized-hierarchy/default-bound.rs +++ b/tests/ui/sized-hierarchy/default-bound.rs @@ -14,13 +14,13 @@ fn neg_sized() {} fn metasized() {} fn neg_metasized() {} -//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +//~^ ERROR bound modifier `?` can only be applied to `Sized` fn pointeesized() { } fn neg_pointeesized() { } -//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +//~^ ERROR bound modifier `?` can only be applied to `Sized` fn main() { diff --git a/tests/ui/sized-hierarchy/default-bound.stderr b/tests/ui/sized-hierarchy/default-bound.stderr index 22f0fa29d3e23..0a4ea6f44d8ed 100644 --- a/tests/ui/sized-hierarchy/default-bound.stderr +++ b/tests/ui/sized-hierarchy/default-bound.stderr @@ -1,10 +1,10 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/default-bound.rs:16:21 | LL | fn neg_metasized() {} | ^^^^^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/default-bound.rs:22:24 | LL | fn neg_pointeesized() { } diff --git a/tests/ui/sized-hierarchy/default-supertrait.rs b/tests/ui/sized-hierarchy/default-supertrait.rs index b25acf9e6ea4f..ab3b28e84db5a 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.rs +++ b/tests/ui/sized-hierarchy/default-supertrait.rs @@ -6,18 +6,18 @@ use std::marker::{MetaSized, PointeeSized}; trait Sized_: Sized { } trait NegSized: ?Sized { } -//~^ ERROR `?Trait` is not permitted in supertraits +//~^ ERROR relaxed bounds are not permitted in supertrait bounds trait MetaSized_: MetaSized { } trait NegMetaSized: ?MetaSized { } -//~^ ERROR `?Trait` is not permitted in supertraits +//~^ ERROR relaxed bounds are not permitted in supertrait bounds trait PointeeSized_: PointeeSized { } trait NegPointeeSized: ?PointeeSized { } -//~^ ERROR `?Trait` is not permitted in supertraits +//~^ ERROR relaxed bounds are not permitted in supertrait bounds trait Bare {} diff --git a/tests/ui/sized-hierarchy/default-supertrait.stderr b/tests/ui/sized-hierarchy/default-supertrait.stderr index de23936b900bc..77cb9755d4a1c 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.stderr +++ b/tests/ui/sized-hierarchy/default-supertrait.stderr @@ -1,30 +1,28 @@ -error[E0658]: `?Trait` is not permitted in supertraits +error[E0658]: relaxed bounds are not permitted in supertrait bounds --> $DIR/default-supertrait.rs:8:17 | LL | trait NegSized: ?Sized { } | ^^^^^^ | - = note: traits are `?Sized` by default = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: traits are `?Sized` by default -error[E0658]: `?Trait` is not permitted in supertraits +error[E0658]: relaxed bounds are not permitted in supertrait bounds --> $DIR/default-supertrait.rs:13:21 | LL | trait NegMetaSized: ?MetaSized { } | ^^^^^^^^^^ | - = note: traits are `?MetaSized` by default = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in supertraits +error[E0658]: relaxed bounds are not permitted in supertrait bounds --> $DIR/default-supertrait.rs:19:24 | LL | trait NegPointeeSized: ?PointeeSized { } | ^^^^^^^^^^^^^ | - = note: traits are `?PointeeSized` by default = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/sized-hierarchy/pointee-validation.rs b/tests/ui/sized-hierarchy/pointee-validation.rs new file mode 100644 index 0000000000000..35ece5047bec2 --- /dev/null +++ b/tests/ui/sized-hierarchy/pointee-validation.rs @@ -0,0 +1,14 @@ +// Test that despite us dropping `PointeeSized` bounds during HIR ty lowering +// we still validate it first. +// issue: +#![feature(sized_hierarchy)] + +use std::marker::PointeeSized; + +struct Test where (): const PointeeSized<(), Undefined = ()>; +//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied +//~| ERROR associated type `Undefined` not found for `PointeeSized` +//~| ERROR `const` can only be applied to `#[const_trait]` traits +//~| ERROR const trait impls are experimental + +fn main() {} diff --git a/tests/ui/sized-hierarchy/pointee-validation.stderr b/tests/ui/sized-hierarchy/pointee-validation.stderr new file mode 100644 index 0000000000000..ee748a6d3e031 --- /dev/null +++ b/tests/ui/sized-hierarchy/pointee-validation.stderr @@ -0,0 +1,37 @@ +error[E0658]: const trait impls are experimental + --> $DIR/pointee-validation.rs:8:23 + | +LL | struct Test where (): const PointeeSized<(), Undefined = ()>; + | ^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/pointee-validation.rs:8:29 + | +LL | struct Test where (): const PointeeSized<(), Undefined = ()>; + | ^^^^^^^^^^^^-------------------- help: remove the unnecessary generics + | | + | expected 0 generic arguments + +error: `const` can only be applied to `#[const_trait]` traits + --> $DIR/pointee-validation.rs:8:23 + | +LL | struct Test where (): const PointeeSized<(), Undefined = ()>; + | ^^^^^ can't be applied to `PointeeSized` + | +note: `PointeeSized` can't be used with `const` because it isn't annotated with `#[const_trait]` + --> $SRC_DIR/core/src/marker.rs:LL:COL + +error[E0220]: associated type `Undefined` not found for `PointeeSized` + --> $DIR/pointee-validation.rs:8:46 + | +LL | struct Test where (): const PointeeSized<(), Undefined = ()>; + | ^^^^^^^^^ associated type `Undefined` not found + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0220, E0658. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/trait-bounds/duplicate-relaxed-bounds.rs b/tests/ui/trait-bounds/duplicate-relaxed-bounds.rs new file mode 100644 index 0000000000000..a1681ddec77b0 --- /dev/null +++ b/tests/ui/trait-bounds/duplicate-relaxed-bounds.rs @@ -0,0 +1,22 @@ +fn dupes() {} +//~^ ERROR duplicate relaxed `Sized` bounds +//~| ERROR duplicate relaxed `Iterator` bounds +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` + +trait Trait { + // We used to say "type parameter has more than one relaxed default bound" + // even on *associated types* like here. Test that we no longer do that. + type Type: ?Sized + ?Sized; + //~^ ERROR duplicate relaxed `Sized` bounds + //~| ERROR duplicate relaxed `Sized` bounds +} + +// We used to emit an additional error about "multiple relaxed default bounds". +// However, multiple relaxed bounds are actually *fine* if they're distinct. +// Ultimately, we still reject this because `Sized` is +// the only (stable) default trait, so we're fine. +fn not_dupes() {} +//~^ ERROR bound modifier `?` can only be applied to `Sized` + +fn main() {} diff --git a/tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr b/tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr new file mode 100644 index 0000000000000..ea236789e3227 --- /dev/null +++ b/tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr @@ -0,0 +1,47 @@ +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/duplicate-relaxed-bounds.rs:1:13 + | +LL | fn dupes() {} + | ^^^^^^ ^^^^^^ + +error[E0203]: duplicate relaxed `Iterator` bounds + --> $DIR/duplicate-relaxed-bounds.rs:1:31 + | +LL | fn dupes() {} + | ^^^^^^^^^ ^^^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/duplicate-relaxed-bounds.rs:1:31 + | +LL | fn dupes() {} + | ^^^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/duplicate-relaxed-bounds.rs:1:43 + | +LL | fn dupes() {} + | ^^^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/duplicate-relaxed-bounds.rs:18:26 + | +LL | fn not_dupes() {} + | ^^^^^^^^^ + +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/duplicate-relaxed-bounds.rs:10:16 + | +LL | type Type: ?Sized + ?Sized; + | ^^^^^^ ^^^^^^ + +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/duplicate-relaxed-bounds.rs:10:16 + | +LL | type Type: ?Sized + ?Sized; + | ^^^^^^ ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0203`. diff --git a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs similarity index 51% rename from tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs rename to tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs index e6d7f74880fb2..1aa36207bc3ea 100644 --- a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs +++ b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs @@ -1,39 +1,38 @@ -// Regression test for #127441 - -// Tests that we make the correct suggestion -// in case there are more than one `?Sized` -// bounds on a function parameter +// Test that we emit a correct structured suggestions for dynamically sized ("maybe unsized") +// function parameters. +// We used to emit a butchered suggestion if duplicate relaxed `Sized` bounds were present. +// issue: . use std::fmt::Debug; fn foo1(a: T) {} -//~^ ERROR he size for values of type `T` cannot be known at compilation time +//~^ ERROR the size for values of type `T` cannot be known at compilation time fn foo2(a: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported +//~^ ERROR duplicate relaxed `Sized` bounds //~| ERROR the size for values of type `T` cannot be known at compilation time fn foo3(a: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR he size for values of type `T` cannot be known at compilation time +//~^ ERROR duplicate relaxed `Sized` bounds +//~| ERROR the size for values of type `T` cannot be known at compilation time fn foo4(a: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported +//~^ ERROR duplicate relaxed `Sized` bounds //~| ERROR the size for values of type `T` cannot be known at compilation time fn foo5(_: impl ?Sized) {} //~^ ERROR the size for values of type `impl ?Sized` cannot be known at compilation time fn foo6(_: impl ?Sized + ?Sized) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported +//~^ ERROR duplicate relaxed `Sized` bounds //~| ERROR the size for values of type `impl ?Sized + ?Sized` cannot be known at compilation tim fn foo7(_: impl ?Sized + ?Sized + Debug) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported +//~^ ERROR duplicate relaxed `Sized` bounds //~| ERROR the size for values of type `impl ?Sized + ?Sized + Debug` cannot be known at compilation time fn foo8(_: impl ?Sized + Debug + ?Sized ) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported +//~^ ERROR duplicate relaxed `Sized` bounds //~| ERROR the size for values of type `impl ?Sized + Debug + ?Sized` cannot be known at compilation time fn main() {} diff --git a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr similarity index 80% rename from tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr rename to tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr index 363f52d6df8d5..7a9c2f043ac41 100644 --- a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr +++ b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr @@ -1,41 +1,41 @@ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:12:12 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:11:12 | LL | fn foo2(a: T) {} | ^^^^^^ ^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:16:12 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:15:12 | LL | fn foo3(a: T) {} | ^^^^^^ ^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:20:12 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:19:12 | LL | fn foo4(a: T) {} | ^^^^^^ ^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:27:17 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:26:17 | LL | fn foo6(_: impl ?Sized + ?Sized) {} | ^^^^^^ ^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:31:17 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:30:17 | LL | fn foo7(_: impl ?Sized + ?Sized + Debug) {} | ^^^^^^ ^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:35:17 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:34:17 | LL | fn foo8(_: impl ?Sized + Debug + ?Sized ) {} | ^^^^^^ ^^^^^^ error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:9:23 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:8:23 | LL | fn foo1(a: T) {} | - ^ doesn't have a size known at compile-time @@ -54,7 +54,7 @@ LL | fn foo1(a: &T) {} | + error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:12:32 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:11:32 | LL | fn foo2(a: T) {} | - ^ doesn't have a size known at compile-time @@ -73,7 +73,7 @@ LL | fn foo2(a: &T) {} | + error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:16:40 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:15:40 | LL | fn foo3(a: T) {} | - ^ doesn't have a size known at compile-time @@ -92,7 +92,7 @@ LL | fn foo3(a: &T) {} | + error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:20:41 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:19:41 | LL | fn foo4(a: T) {} | - ^ doesn't have a size known at compile-time @@ -111,7 +111,7 @@ LL | fn foo4(a: &T) {} | + error[E0277]: the size for values of type `impl ?Sized` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:24:12 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:23:12 | LL | fn foo5(_: impl ?Sized) {} | ^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | fn foo5(_: &impl ?Sized) {} | + error[E0277]: the size for values of type `impl ?Sized + ?Sized` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:27:12 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:26:12 | LL | fn foo6(_: impl ?Sized + ?Sized) {} | ^^^^^^^^^^^^^^^^^^^^ @@ -151,7 +151,7 @@ LL | fn foo6(_: &impl ?Sized + ?Sized) {} | + error[E0277]: the size for values of type `impl ?Sized + ?Sized + Debug` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:31:12 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:30:12 | LL | fn foo7(_: impl ?Sized + ?Sized + Debug) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -171,7 +171,7 @@ LL | fn foo7(_: &impl ?Sized + ?Sized + Debug) {} | + error[E0277]: the size for values of type `impl ?Sized + Debug + ?Sized` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:35:12 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:34:12 | LL | fn foo8(_: impl ?Sized + Debug + ?Sized ) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.rs b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs index e5abcae5d219b..14a2667049775 100644 --- a/tests/ui/trait-bounds/maybe-bound-has-path-args.rs +++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs @@ -2,6 +2,6 @@ trait Trait {} fn test::Trait>() {} //~^ ERROR type arguments are not allowed on module `maybe_bound_has_path_args` -//~| ERROR relaxing a default bound only does something for `?Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` fn main() {} diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr index dc55b26c9183c..bf968b05af085 100644 --- a/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr +++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr @@ -1,4 +1,4 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/maybe-bound-has-path-args.rs:3:12 | LL | fn test::Trait>() {} diff --git a/tests/ui/trait-bounds/maybe-bound-with-assoc.rs b/tests/ui/trait-bounds/maybe-bound-with-assoc.rs index 9127c2de16d5e..e123f18474d1c 100644 --- a/tests/ui/trait-bounds/maybe-bound-with-assoc.rs +++ b/tests/ui/trait-bounds/maybe-bound-with-assoc.rs @@ -2,11 +2,11 @@ trait HasAssoc { type Assoc; } fn hasassoc>() {} -//~^ ERROR relaxing a default bound +//~^ ERROR bound modifier `?` can only be applied to `Sized` trait NoAssoc {} fn noassoc>() {} -//~^ ERROR relaxing a default bound +//~^ ERROR bound modifier `?` can only be applied to `Sized` //~| ERROR associated type `Missing` not found for `NoAssoc` fn main() {} diff --git a/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr b/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr index 36a1e0ade2063..b2ae0584aff91 100644 --- a/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr +++ b/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr @@ -1,10 +1,10 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/maybe-bound-with-assoc.rs:4:16 | LL | fn hasassoc>() {} | ^^^^^^^^^^^^^^^^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/maybe-bound-with-assoc.rs:8:15 | LL | fn noassoc>() {} diff --git a/tests/ui/trait-bounds/more_maybe_bounds.rs b/tests/ui/trait-bounds/more_maybe_bounds.rs new file mode 100644 index 0000000000000..d70c9bb158cc4 --- /dev/null +++ b/tests/ui/trait-bounds/more_maybe_bounds.rs @@ -0,0 +1,25 @@ +// FIXME(more_maybe_bounds): This used to be a check-pass test before rustc started to reject +// relaxed bounds of *non-default* traits. Therefore, the original test intention has been lost. +#![feature(auto_traits, more_maybe_bounds, negative_impls)] + +trait Trait1 {} +auto trait Trait2 {} + +trait Trait3 : ?Trait1 {} +trait Trait4 where Self: Trait1 {} + +fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {} +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` + +struct S; +impl !Trait2 for S {} +impl Trait1 for S {} +impl Trait3 for S {} + +fn main() { + foo(Box::new(S)); + bar(&S); +} diff --git a/tests/ui/trait-bounds/more_maybe_bounds.stderr b/tests/ui/trait-bounds/more_maybe_bounds.stderr new file mode 100644 index 0000000000000..6041ca65823ee --- /dev/null +++ b/tests/ui/trait-bounds/more_maybe_bounds.stderr @@ -0,0 +1,20 @@ +error: bound modifier `?` can only be applied to default traits like `Sized` + --> $DIR/more_maybe_bounds.rs:12:20 + | +LL | fn bar(_: &T) {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to default traits like `Sized` + --> $DIR/more_maybe_bounds.rs:12:30 + | +LL | fn bar(_: &T) {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to default traits like `Sized` + --> $DIR/more_maybe_bounds.rs:12:40 + | +LL | fn bar(_: &T) {} + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs index 2dac1970835d2..f695b8df45642 100644 --- a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs +++ b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs @@ -14,5 +14,7 @@ fn main() { trait NonConst {} const fn handle(_: &dyn const NonConst) {} //~^ ERROR const trait bounds are not allowed in trait object types +//~| ERROR `const` can only be applied to `#[const_trait]` traits const fn take(_: &dyn ~const NonConst) {} //~^ ERROR `~const` is not allowed here +//~| ERROR `~const` can only be applied to `#[const_trait]` traits diff --git a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr index bd29b4b860b62..fb26e1c238e79 100644 --- a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr +++ b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr @@ -19,12 +19,34 @@ LL | const fn handle(_: &dyn const NonConst) {} | ^^^^^^^^^^^^^^ error: `~const` is not allowed here - --> $DIR/const-trait-bounds-trait-objects.rs:17:23 + --> $DIR/const-trait-bounds-trait-objects.rs:18:23 | LL | const fn take(_: &dyn ~const NonConst) {} | ^^^^^^ | = note: trait objects cannot have `~const` trait bounds -error: aborting due to 4 previous errors +error: `const` can only be applied to `#[const_trait]` traits + --> $DIR/const-trait-bounds-trait-objects.rs:15:25 + | +LL | const fn handle(_: &dyn const NonConst) {} + | ^^^^^ can't be applied to `NonConst` + | +help: mark `NonConst` as `#[const_trait]` to allow it to have `const` implementations + | +LL | #[const_trait] trait NonConst {} + | ++++++++++++++ + +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-trait-bounds-trait-objects.rs:18:23 + | +LL | const fn take(_: &dyn ~const NonConst) {} + | ^^^^^^ can't be applied to `NonConst` + | +help: mark `NonConst` as `#[const_trait]` to allow it to have `const` implementations + | +LL | #[const_trait] trait NonConst {} + | ++++++++++++++ + +error: aborting due to 6 previous errors diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs index 5069cd256b277..e7cca41a47eab 100644 --- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs @@ -64,4 +64,8 @@ fn main() { x.leak_foo(); //~^ ERROR the trait bound `dyn Trait: Leak` is not satisfied x.maybe_leak_foo(); + // Ensure that we validate the generic args of relaxed bounds in trait object types. + let _: dyn Trait + ?Leak<(), Undefined = ()>; + //~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR associated type `Undefined` not found for `Leak` } diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr index 48745e40268d4..350233b7cbe9d 100644 --- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr @@ -18,6 +18,27 @@ note: required by a bound in `Trait::leak_foo` LL | fn leak_foo(&self) {} | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo` -error: aborting due to 2 previous errors +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/maybe-bounds-in-dyn-traits.rs:68:25 + | +LL | let _: dyn Trait + ?Leak<(), Undefined = ()>; + | ^^^^-------------------- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/maybe-bounds-in-dyn-traits.rs:44:12 + | +LL | auto trait Leak {} + | ^^^^ + +error[E0220]: associated type `Undefined` not found for `Leak` + --> $DIR/maybe-bounds-in-dyn-traits.rs:68:34 + | +LL | let _: dyn Trait + ?Leak<(), Undefined = ()>; + | ^^^^^^^^^ associated type `Undefined` not found + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0107, E0220, E0277. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/maybe-polarity-pass.rs b/tests/ui/traits/maybe-polarity-pass.rs deleted file mode 100644 index 1ccd52bc1694a..0000000000000 --- a/tests/ui/traits/maybe-polarity-pass.rs +++ /dev/null @@ -1,25 +0,0 @@ -#![feature(auto_traits)] -#![feature(more_maybe_bounds)] -#![feature(negative_impls)] - -trait Trait1 {} -auto trait Trait2 {} - -trait Trait3 : ?Trait1 {} -trait Trait4 where Self: Trait1 {} - -fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {} -fn bar(_: &T) {} -//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - -struct S; -impl !Trait2 for S {} -impl Trait1 for S {} -impl Trait3 for S {} - -fn main() { - foo(Box::new(S)); - bar(&S); -} diff --git a/tests/ui/traits/maybe-polarity-pass.stderr b/tests/ui/traits/maybe-polarity-pass.stderr deleted file mode 100644 index 1f378dd665ae6..0000000000000 --- a/tests/ui/traits/maybe-polarity-pass.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-polarity-pass.rs:12:20 - | -LL | fn bar(_: &T) {} - | ^^^^^^^ - -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-polarity-pass.rs:12:30 - | -LL | fn bar(_: &T) {} - | ^^^^^^^ - -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-polarity-pass.rs:12:40 - | -LL | fn bar(_: &T) {} - | ^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/tests/ui/traits/maybe-polarity-repeated.rs b/tests/ui/traits/maybe-polarity-repeated.rs deleted file mode 100644 index fd1ef567b3eab..0000000000000 --- a/tests/ui/traits/maybe-polarity-repeated.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(more_maybe_bounds)] - -trait Trait {} -fn foo(_: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - -fn main() {} diff --git a/tests/ui/traits/maybe-polarity-repeated.stderr b/tests/ui/traits/maybe-polarity-repeated.stderr deleted file mode 100644 index 4fa1dc45bda85..0000000000000 --- a/tests/ui/traits/maybe-polarity-repeated.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/maybe-polarity-repeated.rs:4:11 - | -LL | fn foo(_: T) {} - | ^^^^^^ ^^^^^^ - -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-polarity-repeated.rs:4:11 - | -LL | fn foo(_: T) {} - | ^^^^^^ - -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-polarity-repeated.rs:4:20 - | -LL | fn foo(_: T) {} - | ^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0203`. diff --git a/tests/ui/traits/wf-object/maybe-bound.rs b/tests/ui/traits/wf-object/maybe-bound.rs index 17771e976ef3b..917dbd706b59a 100644 --- a/tests/ui/traits/wf-object/maybe-bound.rs +++ b/tests/ui/traits/wf-object/maybe-bound.rs @@ -1,18 +1,18 @@ -// Test that `dyn ... + ?Sized + ...` is okay (though `?Sized` has no effect in trait objects). +// Test that relaxed `Sized` bounds are rejected in trait object types. trait Foo {} type _0 = dyn ?Sized + Foo; -//~^ ERROR `?Trait` is not permitted in trait object types +//~^ ERROR relaxed bounds are not permitted in trait object types type _1 = dyn Foo + ?Sized; -//~^ ERROR `?Trait` is not permitted in trait object types +//~^ ERROR relaxed bounds are not permitted in trait object types type _2 = dyn Foo + ?Sized + ?Sized; -//~^ ERROR `?Trait` is not permitted in trait object types -//~| ERROR `?Trait` is not permitted in trait object types +//~^ ERROR relaxed bounds are not permitted in trait object types +//~| ERROR relaxed bounds are not permitted in trait object types type _3 = dyn ?Sized + Foo; -//~^ ERROR `?Trait` is not permitted in trait object types +//~^ ERROR relaxed bounds are not permitted in trait object types fn main() {} diff --git a/tests/ui/traits/wf-object/maybe-bound.stderr b/tests/ui/traits/wf-object/maybe-bound.stderr index be7afabd0d01d..cacb9dfc84d41 100644 --- a/tests/ui/traits/wf-object/maybe-bound.stderr +++ b/tests/ui/traits/wf-object/maybe-bound.stderr @@ -1,4 +1,4 @@ -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/maybe-bound.rs:5:15 | LL | type _0 = dyn ?Sized + Foo; @@ -7,7 +7,7 @@ LL | type _0 = dyn ?Sized + Foo; = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/maybe-bound.rs:8:21 | LL | type _1 = dyn Foo + ?Sized; @@ -16,7 +16,7 @@ LL | type _1 = dyn Foo + ?Sized; = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/maybe-bound.rs:11:21 | LL | type _2 = dyn Foo + ?Sized + ?Sized; @@ -25,7 +25,7 @@ LL | type _2 = dyn Foo + ?Sized + ?Sized; = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/maybe-bound.rs:11:30 | LL | type _2 = dyn Foo + ?Sized + ?Sized; @@ -34,7 +34,7 @@ LL | type _2 = dyn Foo + ?Sized + ?Sized; = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/maybe-bound.rs:15:15 | LL | type _3 = dyn ?Sized + Foo; diff --git a/tests/ui/traits/wf-object/only-maybe-bound.rs b/tests/ui/traits/wf-object/only-maybe-bound.rs index 3e6db3e997c9b..96360e0331cdb 100644 --- a/tests/ui/traits/wf-object/only-maybe-bound.rs +++ b/tests/ui/traits/wf-object/only-maybe-bound.rs @@ -2,6 +2,6 @@ type _0 = dyn ?Sized; //~^ ERROR at least one trait is required for an object type [E0224] -//~| ERROR ?Trait` is not permitted in trait object types +//~| 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 index 26269476eaaee..d52728e209ec4 100644 --- a/tests/ui/traits/wf-object/only-maybe-bound.stderr +++ b/tests/ui/traits/wf-object/only-maybe-bound.stderr @@ -1,4 +1,4 @@ -error[E0658]: `?Trait` is not permitted in trait object types +error[E0658]: relaxed bounds are not permitted in trait object types --> $DIR/only-maybe-bound.rs:3:15 | LL | type _0 = dyn ?Sized; diff --git a/tests/ui/unsized/maybe-bounds-where.rs b/tests/ui/unsized/maybe-bounds-where.rs deleted file mode 100644 index 4c4141631a7c5..0000000000000 --- a/tests/ui/unsized/maybe-bounds-where.rs +++ /dev/null @@ -1,28 +0,0 @@ -struct S1(T) where (T): ?Sized; -//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared - -struct S2(T) where u8: ?Sized; -//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared - -struct S3(T) where &'static T: ?Sized; -//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared - -trait Trait<'a> {} - -struct S4(T) where for<'a> T: ?Trait<'a>; -//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared -//~| ERROR relaxing a default bound only does something for `?Sized` - -struct S5(*const T) where T: ?Trait<'static> + ?Sized; -//~^ ERROR type parameter has more than one relaxed default bound -//~| ERROR relaxing a default bound only does something for `?Sized` - -impl S1 { - fn f() where T: ?Sized {} - //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared -} - -fn main() { - let u = vec![1, 2, 3]; - let _s: S5<[u8]> = S5(&u[..]); // OK -} diff --git a/tests/ui/unsized/maybe-bounds-where.stderr b/tests/ui/unsized/maybe-bounds-where.stderr deleted file mode 100644 index fb6d37c29660a..0000000000000 --- a/tests/ui/unsized/maybe-bounds-where.stderr +++ /dev/null @@ -1,70 +0,0 @@ -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:1:28 - | -LL | struct S1(T) where (T): ?Sized; - | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:4:27 - | -LL | struct S2(T) where u8: ?Sized; - | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:7:35 - | -LL | struct S3(T) where &'static T: ?Sized; - | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:12:34 - | -LL | struct S4(T) where for<'a> T: ?Trait<'a>; - | ^^^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:21:21 - | -LL | fn f() where T: ?Sized {} - | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-bounds-where.rs:12:34 - | -LL | struct S4(T) where for<'a> T: ?Trait<'a>; - | ^^^^^^^^^^ - -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/maybe-bounds-where.rs:16:33 - | -LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; - | ^^^^^^^^^^^^^^^ ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-bounds-where.rs:16:33 - | -LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; - | ^^^^^^^^^^^^^^^ - -error: aborting due to 8 previous errors - -Some errors have detailed explanations: E0203, E0658. -For more information about an error, try `rustc --explain E0203`. diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.rs b/tests/ui/unsized/relaxed-bounds-invalid-places.rs new file mode 100644 index 0000000000000..95ba0089a67ac --- /dev/null +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.rs @@ -0,0 +1,26 @@ +// Test that relaxed bounds can only be placed on type parameters defined by the closest item +// (ignoring relaxed bounds inside `impl Trait` and in associated type defs here). + +struct S1(T) where (T): ?Sized; //~ ERROR this relaxed bound is not permitted here + +struct S2(T) where u8: ?Sized; //~ ERROR this relaxed bound is not permitted here + +struct S3(T) where &'static T: ?Sized; //~ ERROR this relaxed bound is not permitted here + +trait Trait<'a> {} + +struct S4(T) where for<'a> T: ?Trait<'a>; +//~^ ERROR this relaxed bound is not permitted here +//~| ERROR bound modifier `?` can only be applied to `Sized` + +struct S5(*const T) where T: ?Trait<'static> + ?Sized; +//~^ ERROR bound modifier `?` can only be applied to `Sized` + +impl S1 { + fn f() where T: ?Sized {} //~ ERROR this relaxed bound is not permitted here +} + +fn main() { + let u = vec![1, 2, 3]; + let _s: S5<[u8]> = S5(&u[..]); // OK +} diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr new file mode 100644 index 0000000000000..e2621b86c933f --- /dev/null +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr @@ -0,0 +1,65 @@ +error[E0658]: this relaxed bound is not permitted here + --> $DIR/relaxed-bounds-invalid-places.rs:4:28 + | +LL | struct S1(T) where (T): ?Sized; + | ^^^^^^ + | + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + +error[E0658]: this relaxed bound is not permitted here + --> $DIR/relaxed-bounds-invalid-places.rs:6:27 + | +LL | struct S2(T) where u8: ?Sized; + | ^^^^^^ + | + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + +error[E0658]: this relaxed bound is not permitted here + --> $DIR/relaxed-bounds-invalid-places.rs:8:35 + | +LL | struct S3(T) where &'static T: ?Sized; + | ^^^^^^ + | + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + +error[E0658]: this relaxed bound is not permitted here + --> $DIR/relaxed-bounds-invalid-places.rs:12:34 + | +LL | struct S4(T) where for<'a> T: ?Trait<'a>; + | ^^^^^^^^^^ + | + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + +error[E0658]: this relaxed bound is not permitted here + --> $DIR/relaxed-bounds-invalid-places.rs:20:21 + | +LL | fn f() where T: ?Sized {} + | ^^^^^^ + | + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/relaxed-bounds-invalid-places.rs:12:34 + | +LL | struct S4(T) where for<'a> T: ?Trait<'a>; + | ^^^^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/relaxed-bounds-invalid-places.rs:16:33 + | +LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; + | ^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`.