about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLieselotte <52315535+she3py@users.noreply.github.com>2023-09-08 06:23:56 +0200
committerLieselotte <52315535+she3py@users.noreply.github.com>2023-09-08 06:52:17 +0200
commit96c96645c7bb70a73ced2046df8fe083ad2ae3fc (patch)
tree82f938d5d1a0ef23e2c31e0529afb80fe2e28146
parent1e746d7741d44551e9378daf13b8797322aa0b74 (diff)
downloadrust-96c96645c7bb70a73ced2046df8fe083ad2ae3fc.tar.gz
rust-96c96645c7bb70a73ced2046df8fe083ad2ae3fc.zip
Improve "associated type not found" diagnostics
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs53
-rw-r--r--tests/ui/associated-consts/assoc-const-eq-missing.stderr12
-rw-r--r--tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr4
-rw-r--r--tests/ui/associated-types/associated-types-path-1.stderr4
-rw-r--r--tests/ui/associated-types/issue-23595-2.stderr2
-rw-r--r--tests/ui/error-codes/E0220.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr4
-rw-r--r--tests/ui/lifetimes/issue-95023.stderr2
10 files changed, 69 insertions, 22 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 6082d446979..26bd3b0f6a9 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -110,16 +110,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     {
         // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a
         // valid span, so we point at the whole path segment instead.
-        let span = if assoc_name.span != DUMMY_SP { assoc_name.span } else { span };
+        let is_dummy = assoc_name.span == DUMMY_SP;
+
         let mut err = struct_span_err!(
             self.tcx().sess,
-            span,
+            if is_dummy { span } else { assoc_name.span },
             E0220,
             "associated type `{}` not found for `{}`",
             assoc_name,
             ty_param_name
         );
 
+        if is_dummy {
+            err.span_label(span, format!("associated type `{assoc_name}` not found"));
+            return err.emit();
+        }
+
         let all_candidate_names: Vec<_> = all_candidates()
             .flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
             .filter_map(|item| {
@@ -131,10 +137,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             })
             .collect();
 
-        if let (Some(suggested_name), true) = (
-            find_best_match_for_name(&all_candidate_names, assoc_name.name, None),
-            assoc_name.span != DUMMY_SP,
-        ) {
+        if let Some(suggested_name) =
+            find_best_match_for_name(&all_candidate_names, assoc_name.name, None)
+        {
             err.span_suggestion(
                 assoc_name.span,
                 "there is an associated type with a similar name",
@@ -172,10 +177,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             })
             .collect();
 
-        if let (Some(suggested_name), true) = (
-            find_best_match_for_name(&wider_candidate_names, assoc_name.name, None),
-            assoc_name.span != DUMMY_SP,
-        ) {
+        if let Some(suggested_name) =
+            find_best_match_for_name(&wider_candidate_names, assoc_name.name, None)
+        {
             if let [best_trait] = visible_traits
                 .iter()
                 .filter(|trait_def_id| {
@@ -197,7 +201,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
 
-        err.span_label(span, format!("associated type `{assoc_name}` not found"));
+        // If we still couldn't find any associated type, just list them all.
+
+        if all_candidate_names.is_empty() {
+            err.help(format!(
+                "`{ty_param_name}` has no associated type, try removing `{assoc_name}`"
+            ));
+            return err.emit();
+        }
+
+        let msg = if all_candidate_names.len() > 1 {
+            format!("`{ty_param_name}` has the following associated types")
+        } else {
+            format!("`{ty_param_name}` has the following associated type")
+        };
+
+        let applicability = if self.tcx().features().associated_type_defaults {
+            Applicability::Unspecified // `type A = Self::B` would suggest `type A = Self::A`
+        } else {
+            Applicability::MaybeIncorrect
+        };
+
+        err.span_suggestions(
+            assoc_name.span,
+            msg,
+            all_candidate_names.iter().map(|symbol| symbol.to_string()),
+            applicability,
+        );
+
         err.emit()
     }
 
diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.stderr b/tests/ui/associated-consts/assoc-const-eq-missing.stderr
index b4bd6456c85..9cd3865fc3b 100644
--- a/tests/ui/associated-consts/assoc-const-eq-missing.stderr
+++ b/tests/ui/associated-consts/assoc-const-eq-missing.stderr
@@ -2,19 +2,25 @@ error[E0220]: associated type `Z` not found for `Foo`
   --> $DIR/assoc-const-eq-missing.rs:15:16
    |
 LL | fn foo1<F: Foo<Z=3>>() {}
-   |                ^ associated type `Z` not found
+   |                ^
+   |
+   = help: `Foo` has no associated type, try removing `Z`
 
 error[E0220]: associated type `Z` not found for `Foo`
   --> $DIR/assoc-const-eq-missing.rs:17:16
    |
 LL | fn foo2<F: Foo<Z=usize>>() {}
-   |                ^ associated type `Z` not found
+   |                ^
+   |
+   = help: `Foo` has no associated type, try removing `Z`
 
 error[E0220]: associated type `Z` not found for `Foo`
   --> $DIR/assoc-const-eq-missing.rs:19:16
    |
 LL | fn foo3<F: Foo<Z=5>>() {}
-   |                ^ associated type `Z` not found
+   |                ^
+   |
+   = help: `Foo` has no associated type, try removing `Z`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr b/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr
index bc2807b0396..a964c9df2c5 100644
--- a/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr
+++ b/tests/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr
@@ -8,7 +8,9 @@ error[E0220]: associated type `Item` not found for `M`
   --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8
    |
 LL |     M::Item: Temp,
-   |        ^^^^ associated type `Item` not found
+   |        ^^^^
+   |
+   = help: `M` has no associated type, try removing `Item`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-types/associated-types-path-1.stderr b/tests/ui/associated-types/associated-types-path-1.stderr
index a67f77e37c7..195740359a3 100644
--- a/tests/ui/associated-types/associated-types-path-1.stderr
+++ b/tests/ui/associated-types/associated-types-path-1.stderr
@@ -2,7 +2,9 @@ error[E0220]: associated type `A` not found for `T`
   --> $DIR/associated-types-path-1.rs:10:26
    |
 LL | pub fn f1<T>(a: T, x: T::A) {}
-   |                          ^ associated type `A` not found
+   |                          ^
+   |
+   = help: `T` has no associated type, try removing `A`
 
 error[E0221]: ambiguous associated type `A` in bounds of `T`
   --> $DIR/associated-types-path-1.rs:11:34
diff --git a/tests/ui/associated-types/issue-23595-2.stderr b/tests/ui/associated-types/issue-23595-2.stderr
index dded673f6ee..73effa9f955 100644
--- a/tests/ui/associated-types/issue-23595-2.stderr
+++ b/tests/ui/associated-types/issue-23595-2.stderr
@@ -2,7 +2,7 @@ error[E0220]: associated type `anything_here_kills_it` not found for `Self`
   --> $DIR/issue-23595-2.rs:6:22
    |
 LL |     type B = C<Self::anything_here_kills_it>;
-   |                      ^^^^^^^^^^^^^^^^^^^^^^ associated type `anything_here_kills_it` not found
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: `Self` has the following associated type: `B`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/error-codes/E0220.stderr b/tests/ui/error-codes/E0220.stderr
index 11763ce788d..e03eadacae4 100644
--- a/tests/ui/error-codes/E0220.stderr
+++ b/tests/ui/error-codes/E0220.stderr
@@ -2,7 +2,7 @@ error[E0220]: associated type `F` not found for `Trait`
   --> $DIR/E0220.rs:5:22
    |
 LL | type Foo = dyn Trait<F=i32>;
-   |                      ^ associated type `F` not found
+   |                      ^ help: `Trait` has the following associated type: `Bar`
 
 error[E0191]: the value of the associated type `Bar` (from trait `Trait`) must be specified
   --> $DIR/E0220.rs:5:16
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
index 1bdb2574ead..012913fd0e0 100644
--- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
@@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait`
   --> $DIR/feature-gate-return_type_notation.rs:14:17
    |
 LL | fn foo<T: Trait<m(): Send>>() {}
-   |                 ^ associated type `m` not found
+   |                 ^
+   |
+   = help: `Trait` has no associated type, try removing `m`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr
index ce39f6b2971..68cf8e36fcc 100644
--- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_current.stderr
@@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait`
   --> $DIR/feature-gate-return_type_notation.rs:17:17
    |
 LL | fn foo<T: Trait<m(): Send>>() {}
-   |                 ^ associated type `m` not found
+   |                 ^
+   |
+   = help: `Trait` has no associated type, try removing `m`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr
index ce39f6b2971..68cf8e36fcc 100644
--- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg_next.stderr
@@ -19,7 +19,9 @@ error[E0220]: associated type `m` not found for `Trait`
   --> $DIR/feature-gate-return_type_notation.rs:17:17
    |
 LL | fn foo<T: Trait<m(): Send>>() {}
-   |                 ^ associated type `m` not found
+   |                 ^
+   |
+   = help: `Trait` has no associated type, try removing `m`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr
index 5b93eff8614..6361d8ad30b 100644
--- a/tests/ui/lifetimes/issue-95023.stderr
+++ b/tests/ui/lifetimes/issue-95023.stderr
@@ -36,7 +36,7 @@ error[E0220]: associated type `B` not found for `Self`
   --> $DIR/issue-95023.rs:6:44
    |
 LL |     fn foo<const N: usize>(&self) -> Self::B<{N}>;
-   |                                            ^ associated type `B` not found
+   |                                            ^ help: `Self` has the following associated type: `Output`
 
 error: aborting due to 5 previous errors