From 2ce0b665d37bceddb29e6dbd45172299380e13f7 Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Wed, 18 Jun 2025 15:35:22 +0200 Subject: HIR ty lowering: Simplify signature of `lower_poly_trait_ref` --- .../src/hir_ty_lowering/bounds.rs | 6 +----- .../src/hir_ty_lowering/dyn_compatibility.rs | 24 ++++++++-------------- .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 13 +++++++----- 3 files changed, 17 insertions(+), 26 deletions(-) (limited to 'compiler/rustc_hir_analysis/src') 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 9a752aeccdd..b59ff863383 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -482,12 +482,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 364ad38556b..474025e07af 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 @@ -18,9 +18,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. @@ -38,24 +36,18 @@ 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 { + for poly_trait_ref in hir_bounds.iter() { + if let hir::BoundPolarity::Maybe(_) = poly_trait_ref.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, - trait_bound.modifiers.constness, - hir::BoundPolarity::Positive, + 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/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index a5bd7c1a34a..5521f97059b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -747,17 +747,20 @@ 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 { + // 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 trait_segment = trait_ref.path.segments.last().unwrap(); -- cgit 1.4.1-3-g733a5 From 10d7e5faf20d019568de77503cb13f0203296d02 Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Wed, 18 Jun 2025 16:43:38 +0200 Subject: HIR ty lowering: Validate relaxed bounds in trait object types Only relevant to the internal feature `more_maybe_bounds`. --- .../src/hir_ty_lowering/dyn_compatibility.rs | 3 --- .../maybe-bounds-in-dyn-traits.rs | 4 ++++ .../maybe-bounds-in-dyn-traits.stderr | 25 ++++++++++++++++++++-- 3 files changed, 27 insertions(+), 5 deletions(-) (limited to 'compiler/rustc_hir_analysis/src') 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 474025e07af..813353c12aa 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 @@ -37,9 +37,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut user_written_bounds = Vec::new(); let mut potential_assoc_types = Vec::new(); for poly_trait_ref in hir_bounds.iter() { - if let hir::BoundPolarity::Maybe(_) = poly_trait_ref.modifiers.polarity { - continue; - } let result = self.lower_poly_trait_ref( poly_trait_ref, dummy_self, 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 5069cd256b2..e7cca41a47e 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 48745e40268..350233b7cbe 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`. -- cgit 1.4.1-3-g733a5 From 9788f59bbf893965db98dc633e64e4405414b698 Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Wed, 18 Jun 2025 17:02:51 +0200 Subject: Update comment about `where Ty:` We no longer move trait predicates where the self ty is a ty param to "the bounds of a ty param". --- compiler/rustc_hir_analysis/src/collect/predicates_of.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index f2f1560d8b2..cc53919626e 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -267,20 +267,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()), -- cgit 1.4.1-3-g733a5 From 879f62bb3c23b7a90ac71bb217056fd49ff8dafb Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Thu, 19 Jun 2025 18:41:57 +0200 Subject: Reword diagnostic about relaxing non-`Sized` bound * The phrasing "only does something for" made sense back when this diagnostic was a (hard) warning. Now however, it's simply a hard error and thus completely rules out "doing something". * The primary message was way too long * The new wording more closely mirrors the wording we use for applying other bound modifiers (like `const` and `async`) to incompatible traits. * "all other traits are not bound by default" is no longer accurate under Sized Hierarchy. E.g., traits and assoc tys are (currently) bounded by `MetaSized` by default but can't be relaxed using `?MetaSized` (instead, you relax it by adding `PointeeSized`). * I've decided against adding any diagnositic notes or suggestions for now like "trait `Trait` can't be relaxed as it's not bound by default" which would be incorrect for `MetaSized` and assoc tys as mentioned above) or "consider changing `?MetaSized` to `PointeeSized`" as the Sized Hierarchy impl is still WIP) --- .../src/hir_ty_lowering/bounds.rs | 27 +++++++++---- .../src/hir_ty_lowering/errors.rs | 47 ++++++++++------------ .../feature-gate-more-maybe-bounds.rs | 8 ++-- .../feature-gate-more-maybe-bounds.stderr | 8 ++-- tests/ui/impl-trait/opt-out-bound-not-satisfied.rs | 4 +- .../impl-trait/opt-out-bound-not-satisfied.stderr | 4 +- tests/ui/issues/issue-37534.rs | 2 +- tests/ui/issues/issue-37534.stderr | 2 +- tests/ui/issues/issue-87199.rs | 8 ++-- tests/ui/issues/issue-87199.stderr | 8 ++-- tests/ui/sized-hierarchy/default-bound.rs | 4 +- tests/ui/sized-hierarchy/default-bound.stderr | 4 +- tests/ui/trait-bounds/maybe-bound-has-path-args.rs | 2 +- .../trait-bounds/maybe-bound-has-path-args.stderr | 2 +- tests/ui/trait-bounds/maybe-bound-with-assoc.rs | 4 +- .../ui/trait-bounds/maybe-bound-with-assoc.stderr | 4 +- tests/ui/trait-bounds/more_maybe_bounds.rs | 29 +++++++++++++ tests/ui/trait-bounds/more_maybe_bounds.stderr | 20 +++++++++ tests/ui/traits/maybe-polarity-pass.rs | 25 ------------ tests/ui/traits/maybe-polarity-pass.stderr | 20 --------- tests/ui/traits/maybe-polarity-repeated.rs | 4 +- tests/ui/traits/maybe-polarity-repeated.stderr | 4 +- tests/ui/unsized/relaxed-bounds-invalid-places.rs | 4 +- .../unsized/relaxed-bounds-invalid-places.stderr | 4 +- 24 files changed, 131 insertions(+), 117 deletions(-) create mode 100644 tests/ui/trait-bounds/more_maybe_bounds.rs create mode 100644 tests/ui/trait-bounds/more_maybe_bounds.stderr delete mode 100644 tests/ui/traits/maybe-polarity-pass.rs delete mode 100644 tests/ui/traits/maybe-polarity-pass.stderr (limited to 'compiler/rustc_hir_analysis/src') 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 b59ff863383..dbd22fabab8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -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>( @@ -209,9 +209,22 @@ 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: Since we only call this validation function here in this function, we only + // fully validate relaxed bounds in contexts where we perform + // "sized elaboration". In most cases that doesn't matter because we *usually* + // reject such relaxed bounds outright during AST lowering. + // However, this can easily get out of sync! Ideally, we would perform this step + // where we are guaranteed to catch *all* bounds like in + // `Self::lower_poly_trait_ref`. List of concrete issues: + // FIXME(more_maybe_bounds): We don't call this for e.g., trait object tys or + // supertrait bounds! + // FIXME(trait_alias, #143122): We don't call it for the RHS. Arguably however, + // AST lowering should reject them outright. + // FIXME(associated_type_bounds): We don't call this for them. However, AST + // lowering should reject them outright (#135229). + 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); 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 5d85a3f8455..8c99a41f626 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,26 +35,24 @@ 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 multiple 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 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 { + seen_repeat |= !unique_bounds.insert(trait_def_id); } } - if unbounds.len() > 1 { + if relaxed_bounds.len() > 1 { let err = errors::MultipleRelaxedDefaultBounds { - spans: unbounds.iter().map(|ptr| ptr.span).collect(), + spans: relaxed_bounds.iter().map(|ptr| ptr.span).collect(), }; if seen_repeat { @@ -64,24 +62,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; } - 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/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs index 3066967f87e..7c9d88462f6 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs @@ -9,14 +9,14 @@ fn foo(_: Box) {} //~^ 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 +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` 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 35b5b80d69e..c6d940db57b 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr @@ -27,13 +27,13 @@ LL | fn bar(_: T) {} = 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 +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 +error: bound modifier `?` can only be applied to `Sized` --> $DIR/feature-gate-more-maybe-bounds.rs:10:21 | LL | fn bar(_: T) {} @@ -45,13 +45,13 @@ error[E0203]: type parameter has more than one relaxed default bound, only one i LL | fn baz(_ : 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/feature-gate-more-maybe-bounds.rs:17:11 | LL | fn baz(_ : 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/feature-gate-more-maybe-bounds.rs:17:20 | LL | fn baz(_ : T) {} 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 27c493a13bf..7e0e1eadf9c 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 dc4314c58ad..f99d6a7e5f6 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 09d60b7786b..63f6479ae2e 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 3219854bc70..08607354203 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 4e4e35c6a71..dd9dfc74ca3 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 acc4e84779c..8a930a3d704 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/sized-hierarchy/default-bound.rs b/tests/ui/sized-hierarchy/default-bound.rs index 12b2eb2b5c1..bbb2c6d96ba 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 22f0fa29d3e..0a4ea6f44d8 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/trait-bounds/maybe-bound-has-path-args.rs b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs index e5abcae5d21..14a26670497 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 dc55b26c918..bf968b05af0 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 9127c2de16d..e123f18474d 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 36a1e0ade20..b2ae0584aff 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 00000000000..61b630479ac --- /dev/null +++ b/tests/ui/trait-bounds/more_maybe_bounds.rs @@ -0,0 +1,29 @@ +// FIXME(more_maybe_bounds): Even under `more_maybe_bounds` / `-Zexperimental-default-bounds`, +// trying to relax non-default bounds should still be an error in all contexts! As you can see +// there are placed like supertrait bounds and trait object types where we currently don't perform +// this check. +#![feature(auto_traits, more_maybe_bounds, negative_impls)] + +trait Trait1 {} +auto trait Trait2 {} + +// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`. +trait Trait3: ?Trait1 {} +trait Trait4 where Self: Trait1 {} + +// FIXME: `?Trait2` should be rejected, `Trait2` isn't marked `#[lang = "default_traitN"]`. +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 00000000000..09c9fc31165 --- /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:16:20 + | +LL | fn bar(_: &T) {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to default traits like `Sized` + --> $DIR/more_maybe_bounds.rs:16:30 + | +LL | fn bar(_: &T) {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to default traits like `Sized` + --> $DIR/more_maybe_bounds.rs:16:40 + | +LL | fn bar(_: &T) {} + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/traits/maybe-polarity-pass.rs b/tests/ui/traits/maybe-polarity-pass.rs deleted file mode 100644 index 1ccd52bc169..00000000000 --- 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 1f378dd665a..00000000000 --- 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 index fd1ef567b3e..962e3d5dbc5 100644 --- a/tests/ui/traits/maybe-polarity-repeated.rs +++ b/tests/ui/traits/maybe-polarity-repeated.rs @@ -3,7 +3,7 @@ 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 +//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` +//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` fn main() {} diff --git a/tests/ui/traits/maybe-polarity-repeated.stderr b/tests/ui/traits/maybe-polarity-repeated.stderr index 4fa1dc45bda..de16c147180 100644 --- a/tests/ui/traits/maybe-polarity-repeated.stderr +++ b/tests/ui/traits/maybe-polarity-repeated.stderr @@ -4,13 +4,13 @@ error[E0203]: type parameter has more than one relaxed default bound, only one i LL | fn foo(_: 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 default traits like `Sized` --> $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 +error: bound modifier `?` can only be applied to default traits like `Sized` --> $DIR/maybe-polarity-repeated.rs:4:20 | LL | fn foo(_: T) {} diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.rs b/tests/ui/unsized/relaxed-bounds-invalid-places.rs index e9f39d5f211..64d4523ac49 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.rs +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.rs @@ -13,11 +13,11 @@ trait Trait<'a> {} struct S4(T) where for<'a> T: ?Trait<'a>; //~^ ERROR this relaxed bound is not permitted here -//~| ERROR relaxing a default bound only does something for `?Sized` +//~| ERROR bound modifier `?` can only be applied to `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` +//~| ERROR bound modifier `?` can only be applied to `Sized` impl S1 { fn f() where T: ?Sized {} //~ ERROR this relaxed bound is not permitted here diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr index a08dc15058a..cfa0d274b26 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr @@ -64,7 +64,7 @@ error: relaxed bounds are not permitted in trait object types LL | type O2 = dyn ?Sized + ?Sized + Tr; | ^^^^^^ -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/relaxed-bounds-invalid-places.rs:14:34 | LL | struct S4(T) where for<'a> T: ?Trait<'a>; @@ -79,7 +79,7 @@ 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 +error: bound modifier `?` can only be applied to `Sized` --> $DIR/relaxed-bounds-invalid-places.rs:18:33 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; -- cgit 1.4.1-3-g733a5 From cdc3d701cb4ff37e9d0c96c1c68b2e8789c19441 Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Fri, 18 Jul 2025 12:24:56 +0200 Subject: Don't reject *multiple* relaxed bounds, reject *duplicate* ones. Having multiple relaxed bounds like `?Sized + ?Iterator` is actually *fine*. We actually want to reject *duplicate* relaxed bounds like `?Sized + ?Sized` because these most certainly represent a user error. Note that this doesn't mean that we accept more code because a bound like `?Iterator` is still invalid as it's not relaxing a *default* trait and the only way to define / use more default bounds is under the experimental and internal feature `more_maybe_bounds` plus `lang_items` plus unstable flag `-Zexperimental-default-bounds` (historical context: for the longest time, bounds like `?Iterator` were actually allowed and lead to a hard warning). Ultimately, this simply *reframes* the diagnostic. The scope of `more_maybe_bounds` / `-Zexperimental-default-bounds` remains unchanged as well. --- .../rustc_error_codes/src/error_codes/E0203.md | 10 +- compiler/rustc_hir_analysis/messages.ftl | 3 - compiler/rustc_hir_analysis/src/errors.rs | 7 - .../src/hir_ty_lowering/errors.rs | 26 ++- .../feature-gate-more-maybe-bounds.rs | 10 +- .../feature-gate-more-maybe-bounds.stderr | 30 +--- ...uggestionf-for-repeated-unsized-bound-127441.rs | 39 ---- ...stionf-for-repeated-unsized-bound-127441.stderr | 196 --------------------- tests/ui/trait-bounds/duplicate-relaxed-bounds.rs | 22 +++ .../trait-bounds/duplicate-relaxed-bounds.stderr | 47 +++++ .../ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs | 38 ++++ .../fix-dyn-sized-fn-param-sugg.stderr | 196 +++++++++++++++++++++ tests/ui/trait-bounds/more_maybe_bounds.rs | 2 +- tests/ui/traits/maybe-polarity-repeated.rs | 9 - tests/ui/traits/maybe-polarity-repeated.stderr | 21 --- tests/ui/unsized/relaxed-bounds-invalid-places.rs | 4 +- .../unsized/relaxed-bounds-invalid-places.stderr | 22 +-- 17 files changed, 330 insertions(+), 352 deletions(-) delete mode 100644 tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs delete mode 100644 tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr create mode 100644 tests/ui/trait-bounds/duplicate-relaxed-bounds.rs create mode 100644 tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr create mode 100644 tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs create mode 100644 tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr delete mode 100644 tests/ui/traits/maybe-polarity-repeated.rs delete mode 100644 tests/ui/traits/maybe-polarity-repeated.stderr (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_error_codes/src/error_codes/E0203.md b/compiler/rustc_error_codes/src/error_codes/E0203.md index 1edb519275f..a4dceedbf1f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0203.md +++ b/compiler/rustc_error_codes/src/error_codes/E0203.md @@ -1,15 +1,15 @@ -Having multiple relaxed default bounds is unsupported. +Having duplicate relaxed default bounds is unsupported. Erroneous code example: ```compile_fail,E0203 -struct Bad{ - inner: T +struct Bad{ + inner: T, } ``` -Here the type `T` cannot have a relaxed bound for multiple default traits -(`Sized` and `Send`). This can be fixed by only using one relaxed bound. +Here the type parameter `T` cannot have duplicate relaxed bounds for default +trait `Sized`. This can be fixed by only using one relaxed bound: ``` struct Good{ diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index a20becbe7e8..90cb1727034 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/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index eb65050c17c..3283ce95ee0 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -278,13 +278,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/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 8c99a41f626..3db78db931a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -35,31 +35,29 @@ use crate::fluent_generated as fluent; use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Check for multiple relaxed bounds and relaxed bounds of non-default traits. + /// Check for duplicate relaxed bounds and relaxed bounds of non-default traits. pub(crate) fn check_and_report_invalid_relaxed_bounds( &self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>, ) { let tcx = self.tcx(); - let mut unique_bounds = FxIndexSet::default(); - let mut seen_repeat = false; + let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default(); + for bound in &relaxed_bounds { if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res { - seen_repeat |= !unique_bounds.insert(trait_def_id); + grouped_bounds.entry(trait_def_id).or_default().push(bound.span); } } - if relaxed_bounds.len() > 1 { - let err = errors::MultipleRelaxedDefaultBounds { - spans: relaxed_bounds.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(); + } } let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, DUMMY_SP); 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 7c9d88462f6..9c727ae3aad 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs @@ -8,15 +8,7 @@ trait Trait4 where Self: ?Trait1 {} //~ ERROR this relaxed bound is not permitte fn foo(_: Box) {} //~^ 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 bound modifier `?` can only be applied to `Sized` -//~| ERROR bound modifier `?` can only be applied to `Sized` - -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 bound modifier `?` can only be applied to `Sized` +//~^ ERROR bound modifier `?` can only be applied to `Sized` //~| ERROR bound modifier `?` can only be applied to `Sized` fn 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 c6d940db57b..da6ad5f16e2 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr @@ -18,15 +18,6 @@ error: relaxed bounds are not permitted in trait object types LL | fn foo(_: Box) {} | ^^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/feature-gate-more-maybe-bounds.rs:10:11 - | -LL | fn bar(_: T) {} - | ^^^^^^^ ^^^^^^^ - | - = 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: bound modifier `?` can only be applied to `Sized` --> $DIR/feature-gate-more-maybe-bounds.rs:10:11 | @@ -39,24 +30,5 @@ error: bound modifier `?` can only be applied to `Sized` 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:17:11 - | -LL | fn baz(_ : T) {} - | ^^^^^^ ^^^^^^ - -error: bound modifier `?` can only be applied to `Sized` - --> $DIR/feature-gate-more-maybe-bounds.rs:17:11 - | -LL | fn baz(_ : T) {} - | ^^^^^^ - -error: bound modifier `?` can only be applied to `Sized` - --> $DIR/feature-gate-more-maybe-bounds.rs:17:20 - | -LL | fn baz(_ : T) {} - | ^^^^^^ - -error: aborting due to 9 previous errors +error: aborting due to 5 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/bad-suggestionf-for-repeated-unsized-bound-127441.rs deleted file mode 100644 index e6d7f74880f..00000000000 --- a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Regression test for #127441 - -// Tests that we make the correct suggestion -// in case there are more than one `?Sized` -// bounds on a function parameter - -use std::fmt::Debug; - -fn foo1(a: T) {} -//~^ ERROR he 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 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 - -fn foo4(a: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| 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 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 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 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/bad-suggestionf-for-repeated-unsized-bound-127441.stderr deleted file mode 100644 index 363f52d6df8..00000000000 --- a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr +++ /dev/null @@ -1,196 +0,0 @@ -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 - | -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 - | -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 - | -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 - | -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 - | -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 - | -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 - | -LL | fn foo1(a: T) {} - | - ^ doesn't have a size known at compile-time - | | - | this type parameter needs to be `Sized` - | - = help: unsized fn params are gated as an unstable feature -help: consider removing the `?Sized` bound to make the type parameter `Sized` - | -LL - fn foo1(a: T) {} -LL + fn foo1(a: T) {} - | -help: function arguments must have a statically known size, borrowed types always have a known size - | -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 - | -LL | fn foo2(a: T) {} - | - ^ doesn't have a size known at compile-time - | | - | this type parameter needs to be `Sized` - | - = help: unsized fn params are gated as an unstable feature -help: consider removing the `?Sized` bound to make the type parameter `Sized` - | -LL - fn foo2(a: T) {} -LL + fn foo2(a: T) {} - | -help: function arguments must have a statically known size, borrowed types always have a known size - | -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 - | -LL | fn foo3(a: T) {} - | - ^ doesn't have a size known at compile-time - | | - | this type parameter needs to be `Sized` - | - = help: unsized fn params are gated as an unstable feature -help: consider restricting type parameters - | -LL - fn foo3(a: T) {} -LL + fn foo3(a: T) {} - | -help: function arguments must have a statically known size, borrowed types always have a known size - | -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 - | -LL | fn foo4(a: T) {} - | - ^ doesn't have a size known at compile-time - | | - | this type parameter needs to be `Sized` - | - = help: unsized fn params are gated as an unstable feature -help: consider restricting type parameters - | -LL - fn foo4(a: T) {} -LL + fn foo4(a: T) {} - | -help: function arguments must have a statically known size, borrowed types always have a known size - | -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 - | -LL | fn foo5(_: impl ?Sized) {} - | ^^^^^^^^^^^ - | | - | doesn't have a size known at compile-time - | this type parameter needs to be `Sized` - | - = help: unsized fn params are gated as an unstable feature -help: consider replacing `?Sized` with `Sized` - | -LL - fn foo5(_: impl ?Sized) {} -LL + fn foo5(_: impl Sized) {} - | -help: function arguments must have a statically known size, borrowed types always have a known size - | -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 - | -LL | fn foo6(_: impl ?Sized + ?Sized) {} - | ^^^^^^^^^^^^^^^^^^^^ - | | - | doesn't have a size known at compile-time - | this type parameter needs to be `Sized` - | - = help: unsized fn params are gated as an unstable feature -help: consider restricting type parameters - | -LL - fn foo6(_: impl ?Sized + ?Sized) {} -LL + fn foo6(_: impl Sized) {} - | -help: function arguments must have a statically known size, borrowed types always have a known size - | -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 - | -LL | fn foo7(_: impl ?Sized + ?Sized + Debug) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | doesn't have a size known at compile-time - | this type parameter needs to be `Sized` - | - = help: unsized fn params are gated as an unstable feature -help: consider restricting type parameters - | -LL - fn foo7(_: impl ?Sized + ?Sized + Debug) {} -LL + fn foo7(_: impl Debug) {} - | -help: function arguments must have a statically known size, borrowed types always have a known size - | -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 - | -LL | fn foo8(_: impl ?Sized + Debug + ?Sized ) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | doesn't have a size known at compile-time - | this type parameter needs to be `Sized` - | - = help: unsized fn params are gated as an unstable feature -help: consider restricting type parameters - | -LL - fn foo8(_: impl ?Sized + Debug + ?Sized ) {} -LL + fn foo8(_: impl Debug ) {} - | -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn foo8(_: &impl ?Sized + Debug + ?Sized ) {} - | + - -error: aborting due to 14 previous errors - -Some errors have detailed explanations: E0203, E0277. -For more information about an error, try `rustc --explain E0203`. 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 00000000000..a1681ddec77 --- /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 00000000000..ccc723fc7a6 --- /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:19: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/fix-dyn-sized-fn-param-sugg.rs b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs new file mode 100644 index 00000000000..1aa36207bc3 --- /dev/null +++ b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs @@ -0,0 +1,38 @@ +// 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 the size for values of type `T` cannot be known at compilation time + +fn foo2(a: T) {} +//~^ ERROR duplicate relaxed `Sized` bounds +//~| ERROR the size for values of type `T` cannot be known at compilation time + +fn foo3(a: T) {} +//~^ ERROR duplicate relaxed `Sized` bounds +//~| ERROR the size for values of type `T` cannot be known at compilation time + +fn foo4(a: T) {} +//~^ 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 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 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 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/fix-dyn-sized-fn-param-sugg.stderr b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr new file mode 100644 index 00000000000..7a9c2f043ac --- /dev/null +++ b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr @@ -0,0 +1,196 @@ +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:11:12 + | +LL | fn foo2(a: T) {} + | ^^^^^^ ^^^^^^ + +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:15:12 + | +LL | fn foo3(a: T) {} + | ^^^^^^ ^^^^^^ + +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:19:12 + | +LL | fn foo4(a: T) {} + | ^^^^^^ ^^^^^^ + +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:26:17 + | +LL | fn foo6(_: impl ?Sized + ?Sized) {} + | ^^^^^^ ^^^^^^ + +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]: 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/fix-dyn-sized-fn-param-sugg.rs:8:23 + | +LL | fn foo1(a: T) {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn foo1(a: T) {} +LL + fn foo1(a: T) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo1(a: &T) {} + | + + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:11:32 + | +LL | fn foo2(a: T) {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn foo2(a: T) {} +LL + fn foo2(a: T) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo2(a: &T) {} + | + + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:15:40 + | +LL | fn foo3(a: T) {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider restricting type parameters + | +LL - fn foo3(a: T) {} +LL + fn foo3(a: T) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo3(a: &T) {} + | + + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:19:41 + | +LL | fn foo4(a: T) {} + | - ^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider restricting type parameters + | +LL - fn foo4(a: T) {} +LL + fn foo4(a: T) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo4(a: &T) {} + | + + +error[E0277]: the size for values of type `impl ?Sized` cannot be known at compilation time + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:23:12 + | +LL | fn foo5(_: impl ?Sized) {} + | ^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | this type parameter needs to be `Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider replacing `?Sized` with `Sized` + | +LL - fn foo5(_: impl ?Sized) {} +LL + fn foo5(_: impl Sized) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo5(_: &impl ?Sized) {} + | + + +error[E0277]: the size for values of type `impl ?Sized + ?Sized` cannot be known at compilation time + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:26:12 + | +LL | fn foo6(_: impl ?Sized + ?Sized) {} + | ^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | this type parameter needs to be `Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider restricting type parameters + | +LL - fn foo6(_: impl ?Sized + ?Sized) {} +LL + fn foo6(_: impl Sized) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +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/fix-dyn-sized-fn-param-sugg.rs:30:12 + | +LL | fn foo7(_: impl ?Sized + ?Sized + Debug) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | this type parameter needs to be `Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider restricting type parameters + | +LL - fn foo7(_: impl ?Sized + ?Sized + Debug) {} +LL + fn foo7(_: impl Debug) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +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/fix-dyn-sized-fn-param-sugg.rs:34:12 + | +LL | fn foo8(_: impl ?Sized + Debug + ?Sized ) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | this type parameter needs to be `Sized` + | + = help: unsized fn params are gated as an unstable feature +help: consider restricting type parameters + | +LL - fn foo8(_: impl ?Sized + Debug + ?Sized ) {} +LL + fn foo8(_: impl Debug ) {} + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo8(_: &impl ?Sized + Debug + ?Sized ) {} + | + + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0203, E0277. +For more information about an error, try `rustc --explain E0203`. diff --git a/tests/ui/trait-bounds/more_maybe_bounds.rs b/tests/ui/trait-bounds/more_maybe_bounds.rs index 61b630479ac..47348b0a0dd 100644 --- a/tests/ui/trait-bounds/more_maybe_bounds.rs +++ b/tests/ui/trait-bounds/more_maybe_bounds.rs @@ -1,6 +1,6 @@ // FIXME(more_maybe_bounds): Even under `more_maybe_bounds` / `-Zexperimental-default-bounds`, // trying to relax non-default bounds should still be an error in all contexts! As you can see -// there are placed like supertrait bounds and trait object types where we currently don't perform +// there are places like supertrait bounds and trait object types where we currently don't perform // this check. #![feature(auto_traits, more_maybe_bounds, negative_impls)] diff --git a/tests/ui/traits/maybe-polarity-repeated.rs b/tests/ui/traits/maybe-polarity-repeated.rs deleted file mode 100644 index 962e3d5dbc5..00000000000 --- 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 bound modifier `?` can only be applied to default traits like `Sized` -//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` - -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 de16c147180..00000000000 --- 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: bound modifier `?` can only be applied to default traits like `Sized` - --> $DIR/maybe-polarity-repeated.rs:4:11 - | -LL | fn foo(_: T) {} - | ^^^^^^ - -error: bound modifier `?` can only be applied to default traits like `Sized` - --> $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/unsized/relaxed-bounds-invalid-places.rs b/tests/ui/unsized/relaxed-bounds-invalid-places.rs index 64d4523ac49..b8eda1e7786 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.rs +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.rs @@ -16,8 +16,7 @@ struct S4(T) where for<'a> T: ?Trait<'a>; //~| ERROR bound modifier `?` can only be applied to `Sized` struct S5(*const T) where T: ?Trait<'static> + ?Sized; -//~^ ERROR type parameter has more than one relaxed default bound -//~| ERROR bound modifier `?` can only be applied to `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 @@ -33,4 +32,3 @@ type O2 = dyn ?Sized + ?Sized + Tr; //~| ERROR relaxed bounds are not permitted in trait object types fn main() {} - diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr index cfa0d274b26..30285d62693 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr @@ -31,7 +31,7 @@ LL | struct S4(T) where for<'a> T: ?Trait<'a>; = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item error: this relaxed bound is not permitted here - --> $DIR/relaxed-bounds-invalid-places.rs:23:21 + --> $DIR/relaxed-bounds-invalid-places.rs:22:21 | LL | fn f() where T: ?Sized {} | ^^^^^^ @@ -39,7 +39,7 @@ LL | fn f() where T: ?Sized {} = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item error: relaxed bounds are not permitted in supertrait bounds - --> $DIR/relaxed-bounds-invalid-places.rs:26:11 + --> $DIR/relaxed-bounds-invalid-places.rs:25:11 | LL | trait Tr: ?Sized {} | ^^^^^^ @@ -47,19 +47,19 @@ LL | trait Tr: ?Sized {} = note: traits are `?Sized` by default error: relaxed bounds are not permitted in trait object types - --> $DIR/relaxed-bounds-invalid-places.rs:30:20 + --> $DIR/relaxed-bounds-invalid-places.rs:29:20 | LL | type O1 = dyn Tr + ?Sized; | ^^^^^^ error: relaxed bounds are not permitted in trait object types - --> $DIR/relaxed-bounds-invalid-places.rs:31:15 + --> $DIR/relaxed-bounds-invalid-places.rs:30:15 | LL | type O2 = dyn ?Sized + ?Sized + Tr; | ^^^^^^ error: relaxed bounds are not permitted in trait object types - --> $DIR/relaxed-bounds-invalid-places.rs:31:24 + --> $DIR/relaxed-bounds-invalid-places.rs:30:24 | LL | type O2 = dyn ?Sized + ?Sized + Tr; | ^^^^^^ @@ -70,21 +70,11 @@ error: bound modifier `?` can only be applied to `Sized` 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/relaxed-bounds-invalid-places.rs:18: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: bound modifier `?` can only be applied to `Sized` --> $DIR/relaxed-bounds-invalid-places.rs:18:33 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 11 previous errors -For more information about this error, try `rustc --explain E0203`. -- cgit 1.4.1-3-g733a5 From 82a02aefe07092c737c852daccebf49ca25507e3 Mon Sep 17 00:00:00 2001 From: León Orell Valerian Liehr Date: Fri, 20 Jun 2025 23:13:11 +0200 Subject: HIR ty lowering: Validate `PointeeSized` bounds --- compiler/rustc_hir_analysis/messages.ftl | 2 - compiler/rustc_hir_analysis/src/errors.rs | 7 -- .../src/hir_ty_lowering/bounds.rs | 36 ++-------- .../src/hir_ty_lowering/dyn_compatibility.rs | 8 --- .../src/hir_ty_lowering/errors.rs | 6 +- .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 49 +++++++------- tests/ui/sized-hierarchy/pointee-validation.rs | 20 ++++++ tests/ui/sized-hierarchy/pointee-validation.stderr | 76 ++++++++++++++++++++++ .../ui/sized-hierarchy/reject-dyn-pointeesized.rs | 4 +- .../sized-hierarchy/reject-dyn-pointeesized.stderr | 5 +- 10 files changed, 135 insertions(+), 78 deletions(-) create mode 100644 tests/ui/sized-hierarchy/pointee-validation.rs create mode 100644 tests/ui/sized-hierarchy/pointee-validation.stderr (limited to 'compiler/rustc_hir_analysis/src') diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 90cb1727034..7f55f9b2303 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -445,8 +445,6 @@ hir_analysis_parenthesized_fn_trait_expansion = hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind} .label = not allowed in type signatures -hir_analysis_pointee_sized_trait_object = `PointeeSized` cannot be used with trait objects - hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias .label = `Self` is not a generic argument, but an alias to the type of the {$what} diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 3283ce95ee0..5e75a42e824 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -311,13 +311,6 @@ pub(crate) struct TraitObjectDeclaredWithNoTraits { pub trait_alias_span: Option, } -#[derive(Diagnostic)] -#[diag(hir_analysis_pointee_sized_trait_object)] -pub(crate) struct PointeeSizedTraitObject { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)] pub(crate) struct AmbiguousLifetimeBound { 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 dbd22fabab8..d7a827c649d 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::{CRATE_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, @@ -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 @@ -193,8 +175,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return; } - 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 { @@ -244,7 +226,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); } } @@ -476,10 +458,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 { 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 813353c12aa..76bb59e3f09 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 @@ -2,7 +2,6 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan; @@ -70,13 +69,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let guar = self.report_trait_object_addition_traits(®ular_traits); return Ty::new_error(tcx, guar); } - // We don't support `PointeeSized` principals - let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); - if regular_traits.iter().any(|(pred, _)| pred.def_id() == pointee_sized_did) { - let guar = self.report_pointee_sized_trait_object(span); - return Ty::new_error(tcx, guar); - } - // Don't create a dyn trait if we have errors in the principal. if let Err(guar) = regular_traits.error_reported() { return Ty::new_error(tcx, guar); 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 3db78db931a..287a5532f01 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -29,7 +29,7 @@ use tracing::debug; use super::InherentAssocCandidate; use crate::errors::{ self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams, - ParenthesizedFnTraitExpansion, PointeeSizedTraitObject, TraitObjectDeclaredWithNoTraits, + ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits, }; use crate::fluent_generated as fluent; use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; @@ -1405,10 +1405,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }) } - - pub(super) fn report_pointee_sized_trait_object(&self, span: Span) -> ErrorGuaranteed { - self.dcx().emit_err(PointeeSizedTraitObject { span }) - } } /// Emit an error for the given associated item constraint. 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 5521f97059b..78794cd8eb6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -755,6 +755,8 @@ impl<'tcx> dyn HirTyLowerer<'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 } = @@ -762,6 +764,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let hir::TraitBoundModifiers { constness, polarity } = modifiers; let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); + + // Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the `middle::ty` IR + // as they denote the *absence* of a default bound. However, we can't bail out early here since + // we still need to perform several validation steps (see below). Instead, simply "pour" all + // resulting bounds "down the drain", i.e., into a new `Vec` that just gets dropped at the end. + let (polarity, bounds) = match polarity { + rustc_ast::BoundPolarity::Positive + if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) => + { + // To elaborate on the comment directly above, regarding `PointeeSized` specifically, + // we don't "reify" such bounds to avoid trait system limitations -- namely, + // non-global where-clauses being preferred over item bounds (where `PointeeSized` + // bounds would be proven) -- which can result in errors when a `PointeeSized` + // supertrait / bound / predicate is added to some items. + (ty::PredicatePolarity::Positive, &mut Vec::new()) + } + rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds), + rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds), + rustc_ast::BoundPolarity::Maybe(_) => { + (ty::PredicatePolarity::Positive, &mut Vec::new()) + } + }; + let trait_segment = trait_ref.path.segments.last().unwrap(); let _ = self.prohibit_generic_args( @@ -778,7 +803,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 +813,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 +915,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/sized-hierarchy/pointee-validation.rs b/tests/ui/sized-hierarchy/pointee-validation.rs new file mode 100644 index 00000000000..dfc28829e08 --- /dev/null +++ b/tests/ui/sized-hierarchy/pointee-validation.rs @@ -0,0 +1,20 @@ +// 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 T where (): PointeeSized<(), Undefined = ()>; +//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied +//~| ERROR associated type `Undefined` not found for `PointeeSized` + +const fn test() where T: const PointeeSized, U: [const] PointeeSized {} +//~^ ERROR `const` can only be applied to `const` traits +//~| ERROR `const` can only be applied to `const` traits +//~| ERROR const trait impls are experimental +//~| ERROR `[const]` can only be applied to `const` traits +//~| ERROR `[const]` can only be applied to `const` 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 00000000000..a056d548356 --- /dev/null +++ b/tests/ui/sized-hierarchy/pointee-validation.stderr @@ -0,0 +1,76 @@ +error[E0658]: const trait impls are experimental + --> $DIR/pointee-validation.rs:12:32 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^ + | + = note: see issue #143874 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[E0658]: const trait impls are experimental + --> $DIR/pointee-validation.rs:12:55 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^^^ + | + = note: see issue #143874 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:20 + | +LL | struct T where (): PointeeSized<(), Undefined = ()>; + | ^^^^^^^^^^^^-------------------- help: remove the unnecessary generics + | | + | expected 0 generic arguments + +error[E0220]: associated type `Undefined` not found for `PointeeSized` + --> $DIR/pointee-validation.rs:8:37 + | +LL | struct T where (): PointeeSized<(), Undefined = ()>; + | ^^^^^^^^^ associated type `Undefined` not found + +error: `const` can only be applied to `const` traits + --> $DIR/pointee-validation.rs:12:32 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^ can't be applied to `PointeeSized` + | +note: `PointeeSized` can't be used with `const` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + +error: `[const]` can only be applied to `const` traits + --> $DIR/pointee-validation.rs:12:55 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^^^ can't be applied to `PointeeSized` + | +note: `PointeeSized` can't be used with `[const]` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + +error: `const` can only be applied to `const` traits + --> $DIR/pointee-validation.rs:12:32 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^ can't be applied to `PointeeSized` + | +note: `PointeeSized` can't be used with `const` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `[const]` can only be applied to `const` traits + --> $DIR/pointee-validation.rs:12:55 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^^^ can't be applied to `PointeeSized` + | +note: `PointeeSized` can't be used with `[const]` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 8 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/sized-hierarchy/reject-dyn-pointeesized.rs b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs index ece1702679d..89e4c15371d 100644 --- a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs +++ b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs @@ -3,7 +3,7 @@ use std::marker::PointeeSized; type Foo = dyn PointeeSized; -//~^ ERROR `PointeeSized` cannot be used with trait objects +//~^ ERROR at least one trait is required for an object type fn foo(f: &Foo) {} @@ -12,5 +12,5 @@ fn main() { let x = main; let y: Box = x; -//~^ ERROR `PointeeSized` cannot be used with trait objects +//~^ ERROR at least one trait is required for an object type } diff --git a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr index a833c6952fd..616b2400f86 100644 --- a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr +++ b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr @@ -1,10 +1,10 @@ -error: `PointeeSized` cannot be used with trait objects +error[E0224]: at least one trait is required for an object type --> $DIR/reject-dyn-pointeesized.rs:5:12 | LL | type Foo = dyn PointeeSized; | ^^^^^^^^^^^^^^^^ -error: `PointeeSized` cannot be used with trait objects +error[E0224]: at least one trait is required for an object type --> $DIR/reject-dyn-pointeesized.rs:14:16 | LL | let y: Box = x; @@ -12,3 +12,4 @@ LL | let y: Box = x; error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0224`. -- cgit 1.4.1-3-g733a5