Skip to content

Commit d69aed1

Browse files
Properly replace impl Trait in fn args, turn {integer} to i32
1 parent 119d314 commit d69aed1

File tree

5 files changed

+76
-12
lines changed

5 files changed

+76
-12
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -370,21 +370,34 @@ fn suggest_restriction<'tcx>(
370370
// but instead we choose to suggest replacing all instances of `impl Trait` with `T`
371371
// where `T: Trait`.
372372
let mut ty_spans = vec![];
373-
let impl_trait_str = format!("impl {}", bound_str);
374373
for input in fn_sig.decl.inputs {
375-
if let hir::TyKind::Path(hir::QPath::Resolved(
376-
None,
377-
hir::Path { segments: [segment], .. },
378-
)) = input.kind
379-
{
380-
if segment.ident.as_str() == impl_trait_str.as_str() {
381-
// `fn foo(t: impl Trait)`
382-
// ^^^^^^^^^^ get this to suggest `T` instead
374+
struct ReplaceImplTraitVisitor<'a> {
375+
ty_spans: &'a mut Vec<Span>,
376+
bound_str: &'a str,
377+
}
378+
impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
379+
fn visit_ty(&mut self, t: &'hir hir::Ty<'hir>) {
380+
if let hir::TyKind::Path(hir::QPath::Resolved(
381+
None,
382+
hir::Path { segments: [segment], .. },
383+
)) = t.kind
384+
{
385+
if segment.ident.as_str().strip_prefix("impl ").map(|s| s.trim_start())
386+
== Some(self.bound_str)
387+
{
388+
// `fn foo(t: impl Trait)`
389+
// ^^^^^^^^^^ get this to suggest `T` instead
383390

384-
// There might be more than one `impl Trait`.
385-
ty_spans.push(input.span);
391+
// There might be more than one `impl Trait`.
392+
self.ty_spans.push(t.span);
393+
return;
394+
}
395+
}
396+
hir::intravisit::walk_ty(self, t);
386397
}
387398
}
399+
ReplaceImplTraitVisitor { ty_spans: &mut ty_spans, bound_str: &bound_str }
400+
.visit_ty(input);
388401
}
389402

390403
let type_param_name = generics.params.next_type_param_name(Some(&bound_str));
@@ -394,7 +407,7 @@ fn suggest_restriction<'tcx>(
394407
// FIXME: modify the `trait_pred` instead of string shenanigans.
395408
// Turn `<impl Trait as Foo>::Bar: Qux` into `<T as Foo>::Bar: Qux`.
396409
let pred = trait_pred.to_predicate(tcx).to_string();
397-
let pred = pred.replace(&impl_trait_str, &type_param_name);
410+
let pred = pred.replace(&format!("impl {}", bound_str), &type_param_name);
398411
let mut sugg = vec![
399412
if let Some(span) = generics.span_for_param_suggestion() {
400413
(span, format!(", {}", type_param))
@@ -458,6 +471,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
458471
trait_pred: ty::PolyTraitPredicate<'tcx>,
459472
body_id: hir::HirId,
460473
) {
474+
let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
475+
461476
let self_ty = trait_pred.skip_binder().self_ty();
462477
let (param_ty, projection) = match self_ty.kind() {
463478
ty::Param(_) => (true, None),
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn add_ten<N>(n: N) -> N {
2+
n + 10
3+
//~^ ERROR cannot add `{integer}` to `N`
4+
}
5+
6+
fn main() {}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0369]: cannot add `{integer}` to `N`
2+
--> $DIR/issue-97677.rs:2:7
3+
|
4+
LL | n + 10
5+
| - ^ -- {integer}
6+
| |
7+
| N
8+
|
9+
help: consider restricting type parameter `N`
10+
|
11+
LL | fn add_ten<N: std::ops::Add<i32>>(n: N) -> N {
12+
| ++++++++++++++++++++
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0369`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pub fn print_values(values: &impl IntoIterator)
2+
where {
3+
for x in values.into_iter() {
4+
println!("{x}");
5+
//~^ ERROR <impl IntoIterator as IntoIterator>::Item` doesn't implement `std::fmt::Display
6+
}
7+
}
8+
9+
fn main() {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0277]: `<impl IntoIterator as IntoIterator>::Item` doesn't implement `std::fmt::Display`
2+
--> $DIR/issue-97760.rs:4:20
3+
|
4+
LL | println!("{x}");
5+
| ^ `<impl IntoIterator as IntoIterator>::Item` cannot be formatted with the default formatter
6+
|
7+
= help: the trait `std::fmt::Display` is not implemented for `<impl IntoIterator as IntoIterator>::Item`
8+
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
9+
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
10+
help: introduce a type parameter with a trait bound instead of using `impl Trait`
11+
|
12+
LL ~ pub fn print_values<I: IntoIterator>(values: &I)
13+
LL ~ where <I as IntoIterator>::Item: std::fmt::Display {
14+
|
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)