about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs57
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs2
-rw-r--r--tests/ui/issues/issue-37534.rs6
-rw-r--r--tests/ui/issues/issue-37534.stderr12
-rw-r--r--tests/ui/issues/issue-87199.rs6
-rw-r--r--tests/ui/issues/issue-87199.stderr18
-rw-r--r--tests/ui/unsized/maybe-bounds-where.rs4
-rw-r--r--tests/ui/unsized/maybe-bounds-where.stderr16
8 files changed, 63 insertions, 58 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index 711da6db5ac..3e700f2da86 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -8,6 +8,7 @@ use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt};
 use rustc_span::symbol::Ident;
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_trait_selection::traits;
+use smallvec::SmallVec;
 
 use crate::astconv::{
     AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter,
@@ -28,15 +29,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
         let tcx = self.tcx();
 
         // Try to find an unbound in bounds.
-        let mut unbound = None;
+        let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
         let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
             for ab in ast_bounds {
                 if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
-                    if unbound.is_none() {
-                        unbound = Some(&ptr.trait_ref);
-                    } else {
-                        tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds { span });
-                    }
+                    unbounds.push(ptr)
                 }
             }
         };
@@ -51,33 +48,41 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
             }
         }
 
+        if unbounds.len() > 1 {
+            tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds {
+                spans: unbounds.iter().map(|ptr| ptr.span).collect(),
+            });
+        }
+
         let sized_def_id = tcx.lang_items().sized_trait();
-        match (&sized_def_id, unbound) {
-            (Some(sized_def_id), Some(tpb))
-                if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) =>
-            {
-                // There was in fact a `?Sized` bound, return without doing anything
-                return;
-            }
-            (_, Some(_)) => {
-                // There was a `?Trait` bound, but it was not `?Sized`; warn.
-                tcx.sess.span_warn(
-                    span,
-                    "default bound relaxed for a type parameter, but \
-                        this does nothing because the given bound is not \
-                        a default; only `?Sized` is supported",
-                );
-                // Otherwise, add implicitly sized if `Sized` is available.
-            }
-            _ => {
-                // There was no `?Sized` bound; add implicitly sized if `Sized` is available.
+
+        let mut seen_sized_unbound = false;
+        for unbound in unbounds {
+            if let Some(sized_def_id) = sized_def_id {
+                if unbound.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) {
+                    seen_sized_unbound = true;
+                    continue;
+                }
             }
+            // There was a `?Trait` bound, but it was not `?Sized`; warn.
+            tcx.sess.span_warn(
+                unbound.span,
+                "relaxing a default bound only does something for `?Sized`; \
+                all other traits are not bound by default",
+            );
         }
+
+        // If the above loop finished there was no `?Sized` bound; add implicitly sized if `Sized` is available.
         if sized_def_id.is_none() {
             // No lang item for `Sized`, so we can't add it as a bound.
             return;
         }
-        bounds.push_sized(tcx, self_ty, span);
+        if seen_sized_unbound {
+            // There was in fact a `?Sized` bound, return without doing anything
+        } else {
+            // There was no `?Sized` bound; add implicitly sized if `Sized` is available.
+            bounds.push_sized(tcx, self_ty, span);
+        }
     }
 
     /// This helper takes a *converted* parameter type (`param_ty`)
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 6a2db1d0627..dd83b5b6f2c 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -96,7 +96,7 @@ pub struct CopyImplOnTypeWithDtor {
 #[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")]
 pub struct MultipleRelaxedDefaultBounds {
     #[primary_span]
-    pub span: Span,
+    pub spans: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
diff --git a/tests/ui/issues/issue-37534.rs b/tests/ui/issues/issue-37534.rs
index 1e67e9a8158..40f7186db09 100644
--- a/tests/ui/issues/issue-37534.rs
+++ b/tests/ui/issues/issue-37534.rs
@@ -1,6 +1,6 @@
-struct Foo<T: ?Hash> { }
+struct Foo<T: ?Hash> {}
 //~^ ERROR expected trait, found derive macro `Hash`
 //~^^ ERROR parameter `T` is never used
-//~^^^ WARN default bound relaxed for a type parameter, but this does nothing
+//~^^^ WARN relaxing a default bound only does something for `?Sized`
 
-fn main() { }
+fn main() {}
diff --git a/tests/ui/issues/issue-37534.stderr b/tests/ui/issues/issue-37534.stderr
index 7d3dd8800bd..03fea2c1648 100644
--- a/tests/ui/issues/issue-37534.stderr
+++ b/tests/ui/issues/issue-37534.stderr
@@ -1,7 +1,7 @@
 error[E0404]: expected trait, found derive macro `Hash`
   --> $DIR/issue-37534.rs:1:16
    |
-LL | struct Foo<T: ?Hash> { }
+LL | struct Foo<T: ?Hash> {}
    |                ^^^^ not a trait
    |
 help: consider importing this trait instead
@@ -9,16 +9,16 @@ help: consider importing this trait instead
 LL + use std::hash::Hash;
    |
 
-warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
-  --> $DIR/issue-37534.rs:1:12
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/issue-37534.rs:1:15
    |
-LL | struct Foo<T: ?Hash> { }
-   |            ^
+LL | struct Foo<T: ?Hash> {}
+   |               ^^^^^
 
 error[E0392]: parameter `T` is never used
   --> $DIR/issue-37534.rs:1:12
    |
-LL | struct Foo<T: ?Hash> { }
+LL | struct Foo<T: ?Hash> {}
    |            ^ unused parameter
    |
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
diff --git a/tests/ui/issues/issue-87199.rs b/tests/ui/issues/issue-87199.rs
index a80a64a2f87..d16d4067673 100644
--- a/tests/ui/issues/issue-87199.rs
+++ b/tests/ui/issues/issue-87199.rs
@@ -6,11 +6,11 @@
 
 // Check that these function definitions only emit warnings, not errors
 fn arg<T: ?Send>(_: T) {}
-//~^ warning: default bound relaxed for a type parameter, but this does nothing
+//~^ warning: relaxing a default bound only does something for `?Sized`
 fn ref_arg<T: ?Send>(_: &T) {}
-//~^ warning: default bound relaxed for a type parameter, but this does nothing
+//~^ warning: relaxing a default bound only does something for `?Sized`
 fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
-//~^ warning: default bound relaxed for a type parameter, but this does nothing
+//~^ warning: relaxing a default bound only does something for `?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 67949b37d40..e02cd7fcfa9 100644
--- a/tests/ui/issues/issue-87199.stderr
+++ b/tests/ui/issues/issue-87199.stderr
@@ -1,20 +1,20 @@
-warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
-  --> $DIR/issue-87199.rs:8:8
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/issue-87199.rs:8:11
    |
 LL | fn arg<T: ?Send>(_: T) {}
-   |        ^
+   |           ^^^^^
 
-warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
-  --> $DIR/issue-87199.rs:10:12
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/issue-87199.rs:10:15
    |
 LL | fn ref_arg<T: ?Send>(_: &T) {}
-   |            ^
+   |               ^^^^^
 
-warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
-  --> $DIR/issue-87199.rs:12:13
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/issue-87199.rs:12:40
    |
 LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() }
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                        ^^^^^
 
 error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
   --> $DIR/issue-87199.rs:18:15
diff --git a/tests/ui/unsized/maybe-bounds-where.rs b/tests/ui/unsized/maybe-bounds-where.rs
index d7af0c42480..7e82a3eb449 100644
--- a/tests/ui/unsized/maybe-bounds-where.rs
+++ b/tests/ui/unsized/maybe-bounds-where.rs
@@ -11,11 +11,11 @@ trait Trait<'a> {}
 
 struct S4<T>(T) where for<'a> T: ?Trait<'a>;
 //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
-//~| WARN default bound relaxed for a type parameter
+//~| WARN relaxing a default bound only does something for `?Sized`
 
 struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
 //~^ ERROR type parameter has more than one relaxed default bound
-//~| WARN default bound relaxed for a type parameter
+//~| WARN relaxing a default bound only does something for `?Sized`
 
 impl<T> S1<T> {
     fn f() where T: ?Sized {}
diff --git a/tests/ui/unsized/maybe-bounds-where.stderr b/tests/ui/unsized/maybe-bounds-where.stderr
index 39bc1b88e56..683bd387bb2 100644
--- a/tests/ui/unsized/maybe-bounds-where.stderr
+++ b/tests/ui/unsized/maybe-bounds-where.stderr
@@ -28,23 +28,23 @@ error: `?Trait` bounds are only permitted at the point where a type parameter is
 LL |     fn f() where T: ?Sized {}
    |                     ^^^^^^
 
-warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
-  --> $DIR/maybe-bounds-where.rs:12:11
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-bounds-where.rs:12:34
    |
 LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
-   |           ^
+   |                                  ^^^^^^^^^^
 
 error[E0203]: type parameter has more than one relaxed default bound, only one is supported
-  --> $DIR/maybe-bounds-where.rs:16:11
+  --> $DIR/maybe-bounds-where.rs:16:33
    |
 LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
-   |           ^
+   |                                 ^^^^^^^^^^^^^^^   ^^^^^^
 
-warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
-  --> $DIR/maybe-bounds-where.rs:16:11
+warning: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/maybe-bounds-where.rs:16:33
    |
 LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
-   |           ^
+   |                                 ^^^^^^^^^^^^^^^
 
 error: aborting due to 6 previous errors; 2 warnings emitted