about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-02-16 17:08:12 +0100
committerGitHub <noreply@github.com>2024-02-16 17:08:12 +0100
commit670bdbf8083760f5df1b1a3f4d24cdb395491790 (patch)
tree1189a3a532962ec2908f41f1b0e846189b62bce8
parente5a743c4c2b7f5404ee4e0c0d66a6bbe8cbf5c98 (diff)
parent220e8a7484de6fd4e2679a3f6577ba879be73204 (diff)
downloadrust-670bdbf8083760f5df1b1a3f4d24cdb395491790.tar.gz
rust-670bdbf8083760f5df1b1a3f4d24cdb395491790.zip
Rollup merge of #121111 - trevyn:associated-type-suggestion, r=davidtwco
For E0038, suggest associated type if available

Closes #116434
-rw-r--r--compiler/rustc_errors/src/lib.rs1
-rw-r--r--compiler/rustc_resolve/src/late.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs9
-rw-r--r--tests/ui/suggestions/issue-116434-2015.rs6
-rw-r--r--tests/ui/suggestions/issue-116434-2015.stderr16
-rw-r--r--tests/ui/suggestions/issue-116434-2021.rs2
-rw-r--r--tests/ui/suggestions/issue-116434-2021.stderr12
7 files changed, 58 insertions, 6 deletions
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 7c6caf442dc..b9b257856e6 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -526,6 +526,7 @@ pub enum StashKey {
     MaybeFruTypo,
     CallAssocMethod,
     TraitMissingMethod,
+    AssociatedTypeSuggestion,
     OpaqueHiddenTypeMismatch,
     MaybeForgetReturn,
     /// Query cycle detected, stashing in favor of a better error.
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 6bd221ff058..3ea4df1d2a4 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -18,6 +18,7 @@ use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::{
     codes::*, struct_span_code_err, Applicability, DiagnosticArgValue, ErrCode, IntoDiagnosticArg,
+    StashKey,
 };
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
@@ -3890,6 +3891,23 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             finalize,
         ) {
             Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => {
+                // if we also have an associated type that matches the ident, stash a suggestion
+                if let Some(items) = self.diagnostic_metadata.current_trait_assoc_items
+                    && let [Segment { ident, .. }] = path
+                    && items.iter().any(|item| {
+                        item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_))
+                    })
+                {
+                    let mut diag = self.r.tcx.dcx().struct_allow("");
+                    diag.span_suggestion_verbose(
+                        path_span.shrink_to_lo(),
+                        "there is an associated type with the same name",
+                        "Self::",
+                        Applicability::MaybeIncorrect,
+                    );
+                    diag.stash(path_span, StashKey::AssociatedTypeSuggestion);
+                }
+
                 if source.is_expected(res) || res == Res::Err {
                     partial_res
                 } else {
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 68b1a0d4e61..661a444d049 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
@@ -2993,6 +2993,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 &mut Default::default(),
             );
             self.suggest_unsized_bound_if_applicable(err, obligation);
+            if let Some(span) = err.span.primary_span()
+                && let Some(mut diag) =
+                    self.tcx.dcx().steal_diagnostic(span, StashKey::AssociatedTypeSuggestion)
+                && let Ok(ref mut s1) = err.suggestions
+                && let Ok(ref mut s2) = diag.suggestions
+            {
+                s1.append(s2);
+                diag.cancel()
+            }
         }
     }
 
diff --git a/tests/ui/suggestions/issue-116434-2015.rs b/tests/ui/suggestions/issue-116434-2015.rs
index 614fc27b771..a53e2a044e9 100644
--- a/tests/ui/suggestions/issue-116434-2015.rs
+++ b/tests/ui/suggestions/issue-116434-2015.rs
@@ -3,9 +3,12 @@ trait Foo {
     fn foo() -> Clone;
     //~^ WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
     //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+    //~| HELP if this is an object-safe trait, use `dyn`
     //~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
     //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+    //~| HELP if this is an object-safe trait, use `dyn`
     //~| ERROR the trait `Clone` cannot be made into an object [E0038]
+    //~| HELP there is an associated type with the same name
 }
 
 trait DbHandle: Sized {}
@@ -15,9 +18,12 @@ trait DbInterface {
     fn handle() -> DbHandle;
     //~^ WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
     //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+    //~| HELP if this is an object-safe trait, use `dyn`
     //~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
     //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+    //~| HELP if this is an object-safe trait, use `dyn`
     //~| ERROR the trait `DbHandle` cannot be made into an object [E0038]
+    //~| HELP there is an associated type with the same name
 }
 
 fn main() {}
diff --git a/tests/ui/suggestions/issue-116434-2015.stderr b/tests/ui/suggestions/issue-116434-2015.stderr
index 2d87029b6eb..73a1cfa9c1d 100644
--- a/tests/ui/suggestions/issue-116434-2015.stderr
+++ b/tests/ui/suggestions/issue-116434-2015.stderr
@@ -13,7 +13,7 @@ LL |     fn foo() -> dyn Clone;
    |                 +++
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/issue-116434-2015.rs:15:20
+  --> $DIR/issue-116434-2015.rs:18:20
    |
 LL |     fn handle() -> DbHandle;
    |                    ^^^^^^^^
@@ -47,9 +47,13 @@ LL |     fn foo() -> Clone;
    |
    = note: the trait cannot be made into an object because it requires `Self: Sized`
    = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+help: there is an associated type with the same name
+   |
+LL |     fn foo() -> Self::Clone;
+   |                 ++++++
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/issue-116434-2015.rs:15:20
+  --> $DIR/issue-116434-2015.rs:18:20
    |
 LL |     fn handle() -> DbHandle;
    |                    ^^^^^^^^
@@ -63,18 +67,22 @@ LL |     fn handle() -> dyn DbHandle;
    |                    +++
 
 error[E0038]: the trait `DbHandle` cannot be made into an object
-  --> $DIR/issue-116434-2015.rs:15:20
+  --> $DIR/issue-116434-2015.rs:18:20
    |
 LL |     fn handle() -> DbHandle;
    |                    ^^^^^^^^ `DbHandle` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-116434-2015.rs:11:17
+  --> $DIR/issue-116434-2015.rs:14:17
    |
 LL | trait DbHandle: Sized {}
    |       --------  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+help: there is an associated type with the same name
+   |
+LL |     fn handle() -> Self::DbHandle;
+   |                    ++++++
 
 error: aborting due to 2 previous errors; 4 warnings emitted
 
diff --git a/tests/ui/suggestions/issue-116434-2021.rs b/tests/ui/suggestions/issue-116434-2021.rs
index 74c30e0cc1f..e7159bc2f3c 100644
--- a/tests/ui/suggestions/issue-116434-2021.rs
+++ b/tests/ui/suggestions/issue-116434-2021.rs
@@ -4,6 +4,7 @@ trait Foo {
     type Clone;
     fn foo() -> Clone;
     //~^ ERROR the trait `Clone` cannot be made into an object [E0038]
+    //~| HELP there is an associated type with the same name
 }
 
 trait DbHandle: Sized {}
@@ -12,6 +13,7 @@ trait DbInterface {
     type DbHandle;
     fn handle() -> DbHandle;
     //~^ ERROR the trait `DbHandle` cannot be made into an object [E0038]
+    //~| HELP there is an associated type with the same name
 }
 
 fn main() {}
diff --git a/tests/ui/suggestions/issue-116434-2021.stderr b/tests/ui/suggestions/issue-116434-2021.stderr
index 43ad82d484a..a10d6ef6da4 100644
--- a/tests/ui/suggestions/issue-116434-2021.stderr
+++ b/tests/ui/suggestions/issue-116434-2021.stderr
@@ -6,20 +6,28 @@ LL |     fn foo() -> Clone;
    |
    = note: the trait cannot be made into an object because it requires `Self: Sized`
    = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+help: there is an associated type with the same name
+   |
+LL |     fn foo() -> Self::Clone;
+   |                 ++++++
 
 error[E0038]: the trait `DbHandle` cannot be made into an object
-  --> $DIR/issue-116434-2021.rs:13:20
+  --> $DIR/issue-116434-2021.rs:14:20
    |
 LL |     fn handle() -> DbHandle;
    |                    ^^^^^^^^ `DbHandle` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-116434-2021.rs:9:17
+  --> $DIR/issue-116434-2021.rs:10:17
    |
 LL | trait DbHandle: Sized {}
    |       --------  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
+help: there is an associated type with the same name
+   |
+LL |     fn handle() -> Self::DbHandle;
+   |                    ++++++
 
 error: aborting due to 2 previous errors