about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2025-07-18 12:24:56 +0200
committerLeón Orell Valerian Liehr <me@fmease.dev>2025-07-18 12:24:56 +0200
commitcdc3d701cb4ff37e9d0c96c1c68b2e8789c19441 (patch)
tree508b765b23ec32b6988c64e88f6f373e86313624 /compiler/rustc_hir_analysis/src
parent879f62bb3c23b7a90ac71bb217056fd49ff8dafb (diff)
downloadrust-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.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs26
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);