about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs39
-rw-r--r--src/test/ui/suggestions/issue-97677.rs6
-rw-r--r--src/test/ui/suggestions/issue-97677.stderr16
-rw-r--r--src/test/ui/suggestions/issue-97760.rs9
-rw-r--r--src/test/ui/suggestions/issue-97760.stderr18
5 files changed, 76 insertions, 12 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index fbdc7215856..adfa6e98568 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -372,21 +372,34 @@ fn suggest_restriction<'tcx>(
         // but instead we choose to suggest replacing all instances of `impl Trait` with `T`
         // where `T: Trait`.
         let mut ty_spans = vec![];
-        let impl_trait_str = format!("impl {}", bound_str);
         for input in fn_sig.decl.inputs {
-            if let hir::TyKind::Path(hir::QPath::Resolved(
-                None,
-                hir::Path { segments: [segment], .. },
-            )) = input.kind
-            {
-                if segment.ident.as_str() == impl_trait_str.as_str() {
-                    // `fn foo(t: impl Trait)`
-                    //            ^^^^^^^^^^ get this to suggest `T` instead
+            struct ReplaceImplTraitVisitor<'a> {
+                ty_spans: &'a mut Vec<Span>,
+                bound_str: &'a str,
+            }
+            impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
+                fn visit_ty(&mut self, t: &'hir hir::Ty<'hir>) {
+                    if let hir::TyKind::Path(hir::QPath::Resolved(
+                        None,
+                        hir::Path { segments: [segment], .. },
+                    )) = t.kind
+                    {
+                        if segment.ident.as_str().strip_prefix("impl ").map(|s| s.trim_start())
+                            == Some(self.bound_str)
+                        {
+                            // `fn foo(t: impl Trait)`
+                            //            ^^^^^^^^^^ get this to suggest `T` instead
 
-                    // There might be more than one `impl Trait`.
-                    ty_spans.push(input.span);
+                            // There might be more than one `impl Trait`.
+                            self.ty_spans.push(t.span);
+                            return;
+                        }
+                    }
+                    hir::intravisit::walk_ty(self, t);
                 }
             }
+            ReplaceImplTraitVisitor { ty_spans: &mut ty_spans, bound_str: &bound_str }
+                .visit_ty(input);
         }
 
         let type_param_name = generics.params.next_type_param_name(Some(&bound_str));
@@ -396,7 +409,7 @@ fn suggest_restriction<'tcx>(
         // FIXME: modify the `trait_pred` instead of string shenanigans.
         // Turn `<impl Trait as Foo>::Bar: Qux` into `<T as Foo>::Bar: Qux`.
         let pred = trait_pred.to_predicate(tcx).to_string();
-        let pred = pred.replace(&impl_trait_str, &type_param_name);
+        let pred = pred.replace(&format!("impl {}", bound_str), &type_param_name);
         let mut sugg = vec![
             if let Some(span) = generics.span_for_param_suggestion() {
                 (span, format!(", {}", type_param))
@@ -460,6 +473,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
         body_id: hir::HirId,
     ) {
+        let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
+
         let self_ty = trait_pred.skip_binder().self_ty();
         let (param_ty, projection) = match self_ty.kind() {
             ty::Param(_) => (true, None),
diff --git a/src/test/ui/suggestions/issue-97677.rs b/src/test/ui/suggestions/issue-97677.rs
new file mode 100644
index 00000000000..a4c3b1350b8
--- /dev/null
+++ b/src/test/ui/suggestions/issue-97677.rs
@@ -0,0 +1,6 @@
+fn add_ten<N>(n: N) -> N {
+    n + 10
+    //~^ ERROR cannot add `{integer}` to `N`
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-97677.stderr b/src/test/ui/suggestions/issue-97677.stderr
new file mode 100644
index 00000000000..ea563ea844d
--- /dev/null
+++ b/src/test/ui/suggestions/issue-97677.stderr
@@ -0,0 +1,16 @@
+error[E0369]: cannot add `{integer}` to `N`
+  --> $DIR/issue-97677.rs:2:7
+   |
+LL |     n + 10
+   |     - ^ -- {integer}
+   |     |
+   |     N
+   |
+help: consider restricting type parameter `N`
+   |
+LL | fn add_ten<N: std::ops::Add<i32>>(n: N) -> N {
+   |             ++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/suggestions/issue-97760.rs b/src/test/ui/suggestions/issue-97760.rs
new file mode 100644
index 00000000000..cf9c3c58dca
--- /dev/null
+++ b/src/test/ui/suggestions/issue-97760.rs
@@ -0,0 +1,9 @@
+pub fn print_values(values: &impl IntoIterator)
+where {
+    for x in values.into_iter() {
+        println!("{x}");
+        //~^ ERROR <impl IntoIterator as IntoIterator>::Item` doesn't implement `std::fmt::Display
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-97760.stderr b/src/test/ui/suggestions/issue-97760.stderr
new file mode 100644
index 00000000000..459556bddae
--- /dev/null
+++ b/src/test/ui/suggestions/issue-97760.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `<impl IntoIterator as IntoIterator>::Item` doesn't implement `std::fmt::Display`
+  --> $DIR/issue-97760.rs:4:20
+   |
+LL |         println!("{x}");
+   |                    ^ `<impl IntoIterator as IntoIterator>::Item` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `<impl IntoIterator as IntoIterator>::Item`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+   |
+LL ~ pub fn print_values<I: IntoIterator>(values: &I)
+LL ~ where <I as IntoIterator>::Item: std::fmt::Display {
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.