about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-01-03 23:40:49 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-01-04 00:46:33 +0000
commit698dfc322fd42fa4dff71474aba7cdf691a459a6 (patch)
tree14d608a069d1f5eed3ddce414d0bde968afab3d7
parent78ef94618b037e18d01644638eaf41ecfa5def04 (diff)
downloadrust-698dfc322fd42fa4dff71474aba7cdf691a459a6.tar.gz
rust-698dfc322fd42fa4dff71474aba7cdf691a459a6.zip
Silence redundant warning when E0038 will be emitted
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/lint.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/object_safety.rs1
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs4
-rw-r--r--tests/rustdoc-ui/issues/issue-105742.stderr4
-rw-r--r--tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed4
-rw-r--r--tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs4
-rw-r--r--tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr24
-rw-r--r--tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr4
-rw-r--r--tests/ui/traits/issue-28576.stderr4
11 files changed, 49 insertions, 29 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index f17f19bb77c..d22c4fe201d 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -605,7 +605,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let violations =
                     object_safety_violations_for_assoc_item(tcx, trait_def_id, *assoc_item);
                 if !violations.is_empty() {
-                    report_object_safety_error(tcx, *span, trait_def_id, &violations).emit();
+                    report_object_safety_error(tcx, *span, None, trait_def_id, &violations).emit();
                     object_safety_violations = true;
                 }
             }
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
index d26f3d5ee91..6675f517cfa 100644
--- a/compiler/rustc_hir_analysis/src/astconv/lint.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -122,6 +122,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     ],
                     Applicability::MachineApplicable,
                 );
+            } else {
+                // We'll emit the object safety error already, with a structured suggestion.
+                diag.downgrade_to_delayed_bug();
             }
             return true;
         }
@@ -145,6 +148,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
             if !is_object_safe {
                 diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
+                // We'll emit the object safety error already, with a structured suggestion.
+                diag.downgrade_to_delayed_bug();
             } else {
                 let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind {
                     // There are more than one trait bound, we need surrounding parentheses.
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index a614d4abf25..8a3df79cb25 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -140,6 +140,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let reported = report_object_safety_error(
                     tcx,
                     span,
+                    Some(hir_id),
                     item.trait_ref().def_id(),
                     &object_safety_violations,
                 )
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index d89c205da3f..4aabe5c2922 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -2,9 +2,10 @@ use super::ObjectSafetyViolation;
 
 use crate::infer::InferCtxt;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{struct_span_err, DiagnosticBuilder, MultiSpan};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::intravisit::Map;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::Span;
@@ -42,6 +43,7 @@ impl<'tcx> InferCtxt<'tcx> {
 pub fn report_object_safety_error<'tcx>(
     tcx: TyCtxt<'tcx>,
     span: Span,
+    hir_id: Option<hir::HirId>,
     trait_def_id: DefId,
     violations: &[ObjectSafetyViolation],
 ) -> DiagnosticBuilder<'tcx> {
@@ -59,6 +61,24 @@ pub fn report_object_safety_error<'tcx>(
     );
     err.span_label(span, format!("`{trait_str}` cannot be made into an object"));
 
+    if let Some(hir_id) = hir_id
+        && let Some(hir::Node::Ty(ty)) = tcx.hir().find(hir_id)
+        && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind
+    {
+        let mut hir_id = hir_id;
+        while let hir::Node::Ty(ty) = tcx.hir().get_parent(hir_id) {
+            hir_id = ty.hir_id;
+        }
+        if tcx.hir().get_parent(hir_id).fn_sig().is_some() {
+            // Do not suggest `impl Trait` when dealing with things like super-traits.
+            err.span_suggestion_verbose(
+                ty.span.until(trait_ref.span),
+                "consider using an opaque type instead",
+                "impl ",
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
     let mut reported_violations = FxIndexSet::default();
     let mut multi_span = vec![];
     let mut messages = vec![];
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index d2598b0defe..81e02a0b17e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -816,7 +816,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                     ty::PredicateKind::ObjectSafe(trait_def_id) => {
                         let violations = self.tcx.object_safety_violations(trait_def_id);
-                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
+                        report_object_safety_error(self.tcx, span, None, trait_def_id, violations)
                     }
 
                     ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => {
@@ -924,7 +924,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
             TraitNotObjectSafe(did) => {
                 let violations = self.tcx.object_safety_violations(did);
-                report_object_safety_error(self.tcx, span, did, violations)
+                report_object_safety_error(self.tcx, span, None, did, violations)
             }
 
             SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => {
diff --git a/tests/rustdoc-ui/issues/issue-105742.stderr b/tests/rustdoc-ui/issues/issue-105742.stderr
index ad1020a1f08..d5a9031075f 100644
--- a/tests/rustdoc-ui/issues/issue-105742.stderr
+++ b/tests/rustdoc-ui/issues/issue-105742.stderr
@@ -323,6 +323,10 @@ LL | ||     Output = <Self as SVec>::Item> as SVec>::Item,
 LL | |
 LL | |  > {
    | |__^ ...because it uses `Self` as a type parameter
+help: consider using an opaque type instead
+   |
+LL | pub fn next<'a, T>(s: &'a mut impl SVec<Item = T, Output = T>) {
+   |                               ~~~~
 
 error[E0107]: missing generics for associated type `SVec::Item`
   --> $DIR/issue-105742.rs:15:21
diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed
index 9720a781eb8..e95b982966d 100644
--- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed
+++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed
@@ -1,9 +1,7 @@
 // run-rustfix
 #![deny(bare_trait_objects)]
 fn ord_prefer_dot(s: String) -> impl Ord {
-    //~^ ERROR trait objects without an explicit `dyn` are deprecated
-    //~| ERROR the trait `Ord` cannot be made into an object
-    //~| WARNING this is accepted in the current edition (Rust 2015)
+    //~^ ERROR the trait `Ord` cannot be made into an object
     (s.starts_with("."), s)
 }
 fn main() {
diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs
index 31d6e336ccf..fdf7e0a77aa 100644
--- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs
+++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs
@@ -1,9 +1,7 @@
 // run-rustfix
 #![deny(bare_trait_objects)]
 fn ord_prefer_dot(s: String) -> Ord {
-    //~^ ERROR trait objects without an explicit `dyn` are deprecated
-    //~| ERROR the trait `Ord` cannot be made into an object
-    //~| WARNING this is accepted in the current edition (Rust 2015)
+    //~^ ERROR the trait `Ord` cannot be made into an object
     (s.starts_with("."), s)
 }
 fn main() {
diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr
index 468a570a0f9..2c499d240ab 100644
--- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr
+++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr
@@ -1,21 +1,3 @@
-error: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
-   |
-LL | fn ord_prefer_dot(s: String) -> Ord {
-   |                                 ^^^
-   |
-   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
-note: the lint level is defined here
-  --> $DIR/bare-trait-dont-suggest-dyn.rs:2:9
-   |
-LL | #![deny(bare_trait_objects)]
-   |         ^^^^^^^^^^^^^^^^^^
-help: `Ord` is not object safe, use `impl Ord` to return an opaque type, as long as you return a single underlying type
-   |
-LL | fn ord_prefer_dot(s: String) -> impl Ord {
-   |                                 ++++
-
 error[E0038]: the trait `Ord` cannot be made into an object
   --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
    |
@@ -29,7 +11,11 @@ note: for a trait to be "object safe" it needs to allow building a vtable to all
   ::: $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: the trait cannot be made into an object because it uses `Self` as a type parameter
+help: consider using an opaque type instead
+   |
+LL | fn ord_prefer_dot(s: String) -> impl Ord {
+   |                                 ++++
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr
index 08df069275a..fc476691d01 100644
--- a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr
+++ b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr
@@ -11,6 +11,10 @@ LL | trait Baz : Bar<Self> {
    |       ---   ^^^^^^^^^ ...because it uses `Self` as a type parameter
    |       |
    |       this trait cannot be made into an object...
+help: consider using an opaque type instead
+   |
+LL | fn make_baz<T:Baz>(t: &T) -> &impl Baz {
+   |                               ~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr
index 9fe50864642..3b45a510341 100644
--- a/tests/ui/traits/issue-28576.stderr
+++ b/tests/ui/traits/issue-28576.stderr
@@ -14,6 +14,10 @@ LL | pub trait Bar: Foo<Assoc=()> {
    |           |    |   ...because it uses `Self` as a type parameter
    |           |    ...because it uses `Self` as a type parameter
    |           this trait cannot be made into an object...
+help: consider using an opaque type instead
+   |
+LL |            impl Bar
+   |            ~~~~
 
 error: aborting due to 1 previous error