mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
Properly replace impl Trait
in fn args, turn {integer} to i32
This commit is contained in:
parent
55805ab473
commit
38d7e2734f
@ -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),
|
||||
|
6
src/test/ui/suggestions/issue-97677.rs
Normal file
6
src/test/ui/suggestions/issue-97677.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn add_ten<N>(n: N) -> N {
|
||||
n + 10
|
||||
//~^ ERROR cannot add `{integer}` to `N`
|
||||
}
|
||||
|
||||
fn main() {}
|
16
src/test/ui/suggestions/issue-97677.stderr
Normal file
16
src/test/ui/suggestions/issue-97677.stderr
Normal file
@ -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`.
|
9
src/test/ui/suggestions/issue-97760.rs
Normal file
9
src/test/ui/suggestions/issue-97760.rs
Normal file
@ -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() {}
|
18
src/test/ui/suggestions/issue-97760.stderr
Normal file
18
src/test/ui/suggestions/issue-97760.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user