diff options
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs | 39 | ||||
| -rw-r--r-- | src/test/ui/suggestions/issue-97677.rs | 6 | ||||
| -rw-r--r-- | src/test/ui/suggestions/issue-97677.stderr | 16 | ||||
| -rw-r--r-- | src/test/ui/suggestions/issue-97760.rs | 9 | ||||
| -rw-r--r-- | src/test/ui/suggestions/issue-97760.stderr | 18 |
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`. |
