mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Handle desugaring in impl trait bound suggestion
This commit is contained in:
parent
1b6b06a03a
commit
b76c9be7f5
@ -254,27 +254,21 @@ fn suggest_restriction(
|
||||
let pred = trait_ref.without_const().to_predicate(tcx).to_string();
|
||||
let pred = pred.replace(&impl_trait_str, &type_param_name);
|
||||
let mut sugg = vec![
|
||||
// Find the last of the generic parameters contained within the span of
|
||||
// the generics
|
||||
match generics
|
||||
.params
|
||||
.iter()
|
||||
.filter(|p| match p.kind {
|
||||
hir::GenericParamKind::Type {
|
||||
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
|
||||
..
|
||||
} => false,
|
||||
_ => true,
|
||||
})
|
||||
.last()
|
||||
.map(|p| p.bounds_span().unwrap_or(p.span))
|
||||
.filter(|&span| generics.span.contains(span) && span.desugaring_kind().is_none())
|
||||
.max_by_key(|span| span.hi())
|
||||
{
|
||||
// `fn foo(t: impl Trait)`
|
||||
// ^ suggest `<T: Trait>` here
|
||||
None => (generics.span, format!("<{}>", type_param)),
|
||||
// `fn foo<A>(t: impl Trait)`
|
||||
// ^^^ suggest `<A, T: Trait>` here
|
||||
Some(param) => (
|
||||
param.bounds_span().unwrap_or(param.span).shrink_to_hi(),
|
||||
format!(", {}", type_param),
|
||||
),
|
||||
Some(span) => (span.shrink_to_hi(), format!(", {}", type_param)),
|
||||
},
|
||||
// `fn foo(t: impl Trait)`
|
||||
// ^ suggest `where <T as Trait>::A: Bound`
|
||||
|
@ -39,6 +39,14 @@ fn bak(constraints: impl Iterator + std::fmt::Debug) {
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn baw<>(constraints: impl Iterator) {
|
||||
for constraint in constraints {
|
||||
qux(constraint);
|
||||
//~^ ERROR `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
|
||||
}
|
||||
}
|
||||
|
||||
fn qux(_: impl std::fmt::Debug) {}
|
||||
|
||||
fn main() {}
|
||||
|
@ -73,6 +73,21 @@ help: introduce a type parameter with a trait bound instead of using `impl Trait
|
||||
LL | fn bak<I: Iterator + std::fmt::Debug>(constraints: I) where <I as Iterator>::Item: Debug {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
|
||||
--> $DIR/impl-trait-with-missing-bounds.rs:45:13
|
||||
|
|
||||
LL | qux(constraint);
|
||||
| ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
||||
...
|
||||
LL | fn qux(_: impl std::fmt::Debug) {}
|
||||
| --------------- required by this bound in `qux`
|
||||
|
|
||||
= help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
|
||||
help: introduce a type parameter with a trait bound instead of using `impl Trait`
|
||||
|
|
||||
LL | fn baw<I: Iterator>(constraints: I) where <I as Iterator>::Item: Debug {
|
||||
| ^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -0,0 +1,32 @@
|
||||
// Regression test: if we suggest replacing an `impl Trait` argument to an async
|
||||
// fn with a named type parameter in order to add bounds, the suggested function
|
||||
// signature should be well-formed.
|
||||
//
|
||||
// edition:2018
|
||||
|
||||
trait Foo {
|
||||
type Bar;
|
||||
fn bar(&self) -> Self::Bar;
|
||||
}
|
||||
|
||||
async fn run(_: &(), foo: impl Foo) -> std::io::Result<()> {
|
||||
let bar = foo.bar();
|
||||
assert_is_send(&bar);
|
||||
//~^ ERROR: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Test our handling of cases where there is a generic parameter list in the
|
||||
// source, but only synthetic generic parameters
|
||||
async fn run2< >(_: &(), foo: impl Foo) -> std::io::Result<()> {
|
||||
let bar = foo.bar();
|
||||
assert_is_send(&bar);
|
||||
//~^ ERROR: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn assert_is_send<T: Send>(_: &T) {}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,33 @@
|
||||
error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
|
||||
--> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:14:20
|
||||
|
|
||||
LL | assert_is_send(&bar);
|
||||
| ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
|
||||
...
|
||||
LL | fn assert_is_send<T: Send>(_: &T) {}
|
||||
| ---- required by this bound in `assert_is_send`
|
||||
|
|
||||
= help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar`
|
||||
help: introduce a type parameter with a trait bound instead of using `impl Trait`
|
||||
|
|
||||
LL | async fn run<F: Foo>(_: &(), foo: F) -> std::io::Result<()> where <F as Foo>::Bar: Send {
|
||||
| ^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
|
||||
--> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:24:20
|
||||
|
|
||||
LL | assert_is_send(&bar);
|
||||
| ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
|
||||
...
|
||||
LL | fn assert_is_send<T: Send>(_: &T) {}
|
||||
| ---- required by this bound in `assert_is_send`
|
||||
|
|
||||
= help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar`
|
||||
help: introduce a type parameter with a trait bound instead of using `impl Trait`
|
||||
|
|
||||
LL | async fn run2<F: Foo>(_: &(), foo: F) -> std::io::Result<()> where <F as Foo>::Bar: Send {
|
||||
| ^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user