diff options
| author | León Orell Valerian Liehr <me@fmease.dev> | 2025-07-18 12:24:56 +0200 |
|---|---|---|
| committer | León Orell Valerian Liehr <me@fmease.dev> | 2025-07-18 12:24:56 +0200 |
| commit | cdc3d701cb4ff37e9d0c96c1c68b2e8789c19441 (patch) | |
| tree | 508b765b23ec32b6988c64e88f6f373e86313624 /compiler/rustc_hir_analysis/src | |
| parent | 879f62bb3c23b7a90ac71bb217056fd49ff8dafb (diff) | |
| download | rust-cdc3d701cb4ff37e9d0c96c1c68b2e8789c19441.tar.gz rust-cdc3d701cb4ff37e9d0c96c1c68b2e8789c19441.zip | |
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.
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/errors.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs | 26 |
2 files changed, 12 insertions, 21 deletions
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 @@ -279,13 +279,6 @@ pub(crate) struct CopyImplOnTypeWithDtor { } #[derive(Diagnostic)] -#[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)] -pub(crate) struct MultipleRelaxedDefaultBounds { - #[primary_span] - pub spans: Vec<Span>, -} - -#[derive(Diagnostic)] #[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)] pub(crate) struct CopyImplOnNonAdt { #[primary_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 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); |
