about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-08-07 15:59:36 +0200
committerGitHub <noreply@github.com>2024-08-07 15:59:36 +0200
commit493233ce290e32fe6cc4aa08099014def6fd8388 (patch)
tree2475db54afe8de414cad15b0f3c6c148f74ecb18 /compiler/rustc_trait_selection/src
parenta6caceee4d32a00aaa6b572a302060a6ffecfa17 (diff)
parent2c83c99058e8b2ae12013469b6c4fde27b648874 (diff)
downloadrust-493233ce290e32fe6cc4aa08099014def6fd8388.tar.gz
rust-493233ce290e32fe6cc4aa08099014def6fd8388.zip
Rollup merge of #128527 - estebank:ambiguity-suggestion, r=Nadrieril
More information for fully-qualified suggestion when there are multiple impls

```
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
  --> $DIR/E0283.rs:30:21
   |
LL |     fn create() -> u32;
   |     ------------------- `Coroutine::create` defined here
...
LL |     let cont: u32 = Coroutine::create();
   |                     ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
   |
help: use a fully-qualified path to a specific available implementation
   |
LL |     let cont: u32 = <Impl as Coroutine>::create();
   |                     ++++++++          +
LL |     let cont: u32 = <AnotherImpl as Coroutine>::create();
   |                     +++++++++++++++          +
```
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs70
1 files changed, 49 insertions, 21 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
index 72a4d4c1205..9ab47057859 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
@@ -388,39 +388,67 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 trait_impls.non_blanket_impls().values().flatten().count();
                             // If there is only one implementation of the trait, suggest using it.
                             // Otherwise, use a placeholder comment for the implementation.
-                            let (message, self_type) = if non_blanket_impl_count == 1 {
+                            let (message, self_types) = if non_blanket_impl_count == 1 {
                                 (
                                     "use the fully-qualified path to the only available \
                                      implementation",
-                                    format!(
+                                    vec![format!(
                                         "{}",
                                         self.tcx.type_of(impl_def_id).instantiate_identity()
-                                    ),
+                                    )],
+                                )
+                            } else if non_blanket_impl_count < 20 {
+                                (
+                                    "use a fully-qualified path to one of the available \
+                                     implementations",
+                                    trait_impls
+                                        .non_blanket_impls()
+                                        .values()
+                                        .flatten()
+                                        .map(|id| {
+                                            format!(
+                                                "{}",
+                                                self.tcx.type_of(id).instantiate_identity()
+                                            )
+                                        })
+                                        .collect::<Vec<String>>(),
                                 )
                             } else {
                                 (
                                     "use a fully-qualified path to a specific available \
                                      implementation",
-                                    "/* self type */".to_string(),
+                                    vec!["/* self type */".to_string()],
                                 )
                             };
-                            let mut suggestions =
-                                vec![(path.span.shrink_to_lo(), format!("<{self_type} as "))];
-                            if let Some(generic_arg) = trait_path_segment.args {
-                                let between_span =
-                                    trait_path_segment.ident.span.between(generic_arg.span_ext);
-                                // get rid of :: between Trait and <type>
-                                // must be '::' between them, otherwise the parser won't accept the code
-                                suggestions.push((between_span, "".to_string()));
-                                suggestions
-                                    .push((generic_arg.span_ext.shrink_to_hi(), ">".to_string()));
-                            } else {
-                                suggestions.push((
-                                    trait_path_segment.ident.span.shrink_to_hi(),
-                                    ">".to_string(),
-                                ));
-                            }
-                            err.multipart_suggestion(
+                            let suggestions: Vec<_> = self_types
+                                .into_iter()
+                                .map(|self_type| {
+                                    let mut suggestions = vec![(
+                                        path.span.shrink_to_lo(),
+                                        format!("<{self_type} as "),
+                                    )];
+                                    if let Some(generic_arg) = trait_path_segment.args {
+                                        let between_span = trait_path_segment
+                                            .ident
+                                            .span
+                                            .between(generic_arg.span_ext);
+                                        // get rid of :: between Trait and <type>
+                                        // must be '::' between them, otherwise the parser won't accept the code
+                                        suggestions.push((between_span, "".to_string()));
+                                        suggestions.push((
+                                            generic_arg.span_ext.shrink_to_hi(),
+                                            ">".to_string(),
+                                        ));
+                                    } else {
+                                        suggestions.push((
+                                            trait_path_segment.ident.span.shrink_to_hi(),
+                                            ">".to_string(),
+                                        ));
+                                    }
+                                    suggestions
+                                })
+                                .collect();
+                            err.multipart_suggestions(
                                 message,
                                 suggestions,
                                 Applicability::MaybeIncorrect,