Rollup merge of #130911 - notriddle:notriddle/suggest-wrap-parens-fn-pointer, r=compiler-errors
diagnostics: wrap fn cast suggestions in parens when needed Fixes #121632
This commit is contained in:
commit
6b0c897499
12 changed files with 115 additions and 11 deletions
|
@ -33,7 +33,8 @@ use tracing::{debug, instrument};
|
||||||
use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote};
|
use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote};
|
||||||
use super::suggestions::get_explanation_based_on_obligation;
|
use super::suggestions::get_explanation_based_on_obligation;
|
||||||
use super::{
|
use super::{
|
||||||
ArgKind, CandidateSimilarity, GetSafeTransmuteErrorAndReason, ImplCandidate, UnsatisfiedConst,
|
ArgKind, CandidateSimilarity, FindExprBySpan, GetSafeTransmuteErrorAndReason, ImplCandidate,
|
||||||
|
UnsatisfiedConst,
|
||||||
};
|
};
|
||||||
use crate::error_reporting::TypeErrCtxt;
|
use crate::error_reporting::TypeErrCtxt;
|
||||||
use crate::error_reporting::infer::TyCategory;
|
use crate::error_reporting::infer::TyCategory;
|
||||||
|
@ -378,14 +379,34 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
if let (ty::FnPtr(..), ty::FnDef(..)) =
|
if let (ty::FnPtr(..), ty::FnDef(..)) =
|
||||||
(cand.self_ty().kind(), main_trait_ref.self_ty().skip_binder().kind())
|
(cand.self_ty().kind(), main_trait_ref.self_ty().skip_binder().kind())
|
||||||
{
|
{
|
||||||
err.span_suggestion(
|
// Wrap method receivers and `&`-references in parens
|
||||||
span.shrink_to_hi(),
|
let suggestion = if self.tcx.sess.source_map().span_look_ahead(span, ".", Some(50)).is_some() {
|
||||||
|
vec![
|
||||||
|
(span.shrink_to_lo(), format!("(")),
|
||||||
|
(span.shrink_to_hi(), format!(" as {})", cand.self_ty())),
|
||||||
|
]
|
||||||
|
} else if let Some(body) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) {
|
||||||
|
let mut expr_finder = FindExprBySpan::new(span, self.tcx);
|
||||||
|
expr_finder.visit_expr(body.value);
|
||||||
|
if let Some(expr) = expr_finder.result &&
|
||||||
|
let hir::ExprKind::AddrOf(_, _, expr) = expr.kind {
|
||||||
|
vec![
|
||||||
|
(expr.span.shrink_to_lo(), format!("(")),
|
||||||
|
(expr.span.shrink_to_hi(), format!(" as {})", cand.self_ty())),
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
vec![(span.shrink_to_hi(), format!(" as {}", cand.self_ty()))]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vec![(span.shrink_to_hi(), format!(" as {}", cand.self_ty()))]
|
||||||
|
};
|
||||||
|
err.multipart_suggestion(
|
||||||
format!(
|
format!(
|
||||||
"the trait `{}` is implemented for fn pointer `{}`, try casting using `as`",
|
"the trait `{}` is implemented for fn pointer `{}`, try casting using `as`",
|
||||||
cand.print_trait_sugared(),
|
cand.print_trait_sugared(),
|
||||||
cand.self_ty(),
|
cand.self_ty(),
|
||||||
),
|
),
|
||||||
format!(" as {}", cand.self_ty()),
|
suggestion,
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
true
|
true
|
||||||
|
|
|
@ -4076,7 +4076,6 @@ ui/traits/issue-96664.rs
|
||||||
ui/traits/issue-96665.rs
|
ui/traits/issue-96665.rs
|
||||||
ui/traits/issue-97576.rs
|
ui/traits/issue-97576.rs
|
||||||
ui/traits/issue-97695-double-trivial-bound.rs
|
ui/traits/issue-97695-double-trivial-bound.rs
|
||||||
ui/traits/issue-99875.rs
|
|
||||||
ui/traits/next-solver/coherence/issue-102048.rs
|
ui/traits/next-solver/coherence/issue-102048.rs
|
||||||
ui/traits/next-solver/issue-118950-root-region.rs
|
ui/traits/next-solver/issue-118950-root-region.rs
|
||||||
ui/traits/object/issue-33140-traitobject-crate.rs
|
ui/traits/object/issue-33140-traitobject-crate.rs
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0277]: the trait bound `fn(Argument) -> Return {function}: Trait` is not satisfied
|
error[E0277]: the trait bound `fn(Argument) -> Return {function}: Trait` is not satisfied
|
||||||
--> $DIR/issue-99875.rs:12:11
|
--> $DIR/bare-fn-no-impl-fn-ptr-99875.rs:12:11
|
||||||
|
|
|
|
||||||
LL | takes(function);
|
LL | takes(function);
|
||||||
| ----- ^^^^^^^^ the trait `Trait` is not implemented for fn item `fn(Argument) -> Return {function}`
|
| ----- ^^^^^^^^ the trait `Trait` is not implemented for fn item `fn(Argument) -> Return {function}`
|
||||||
|
@ -7,7 +7,7 @@ LL | takes(function);
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
note: required by a bound in `takes`
|
note: required by a bound in `takes`
|
||||||
--> $DIR/issue-99875.rs:9:18
|
--> $DIR/bare-fn-no-impl-fn-ptr-99875.rs:9:18
|
||||||
|
|
|
|
||||||
LL | fn takes(_: impl Trait) {}
|
LL | fn takes(_: impl Trait) {}
|
||||||
| ^^^^^ required by this bound in `takes`
|
| ^^^^^ required by this bound in `takes`
|
||||||
|
@ -16,17 +16,17 @@ help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`,
|
||||||
LL | takes(function as fn(Argument) -> Return);
|
LL | takes(function as fn(Argument) -> Return);
|
||||||
| +++++++++++++++++++++++++
|
| +++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0277]: the trait bound `{closure@$DIR/issue-99875.rs:14:11: 14:34}: Trait` is not satisfied
|
error[E0277]: the trait bound `{closure@$DIR/bare-fn-no-impl-fn-ptr-99875.rs:14:11: 14:34}: Trait` is not satisfied
|
||||||
--> $DIR/issue-99875.rs:14:11
|
--> $DIR/bare-fn-no-impl-fn-ptr-99875.rs:14:11
|
||||||
|
|
|
|
||||||
LL | takes(|_: Argument| -> Return { todo!() });
|
LL | takes(|_: Argument| -> Return { todo!() });
|
||||||
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `{closure@$DIR/issue-99875.rs:14:11: 14:34}`
|
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `{closure@$DIR/bare-fn-no-impl-fn-ptr-99875.rs:14:11: 14:34}`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
|
= help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
|
||||||
note: required by a bound in `takes`
|
note: required by a bound in `takes`
|
||||||
--> $DIR/issue-99875.rs:9:18
|
--> $DIR/bare-fn-no-impl-fn-ptr-99875.rs:9:18
|
||||||
|
|
|
|
||||||
LL | fn takes(_: impl Trait) {}
|
LL | fn takes(_: impl Trait) {}
|
||||||
| ^^^^^ required by this bound in `takes`
|
| ^^^^^ required by this bound in `takes`
|
15
tests/ui/traits/fn-pointer/suggest-wrap-parens-method.fixed
Normal file
15
tests/ui/traits/fn-pointer/suggest-wrap-parens-method.fixed
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//@ run-rustfix
|
||||||
|
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
impl Foo for fn() {}
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
fn do_stuff(&self) where Self: Foo {}
|
||||||
|
}
|
||||||
|
impl<T> Bar for T {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
(main as fn()).do_stuff();
|
||||||
|
//~^ ERROR the trait bound
|
||||||
|
}
|
15
tests/ui/traits/fn-pointer/suggest-wrap-parens-method.rs
Normal file
15
tests/ui/traits/fn-pointer/suggest-wrap-parens-method.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//@ run-rustfix
|
||||||
|
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
impl Foo for fn() {}
|
||||||
|
|
||||||
|
trait Bar {
|
||||||
|
fn do_stuff(&self) where Self: Foo {}
|
||||||
|
}
|
||||||
|
impl<T> Bar for T {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
main.do_stuff();
|
||||||
|
//~^ ERROR the trait bound
|
||||||
|
}
|
19
tests/ui/traits/fn-pointer/suggest-wrap-parens-method.stderr
Normal file
19
tests/ui/traits/fn-pointer/suggest-wrap-parens-method.stderr
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
error[E0277]: the trait bound `fn() {main}: Foo` is not satisfied
|
||||||
|
--> $DIR/suggest-wrap-parens-method.rs:13:10
|
||||||
|
|
|
||||||
|
LL | main.do_stuff();
|
||||||
|
| ^^^^^^^^ the trait `Foo` is not implemented for fn item `fn() {main}`
|
||||||
|
|
|
||||||
|
note: required by a bound in `Bar::do_stuff`
|
||||||
|
--> $DIR/suggest-wrap-parens-method.rs:8:36
|
||||||
|
|
|
||||||
|
LL | fn do_stuff(&self) where Self: Foo {}
|
||||||
|
| ^^^ required by this bound in `Bar::do_stuff`
|
||||||
|
help: the trait `Foo` is implemented for fn pointer `fn()`, try casting using `as`
|
||||||
|
|
|
||||||
|
LL | (main as fn()).do_stuff();
|
||||||
|
| + ++++++++
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
10
tests/ui/traits/fn-pointer/suggest-wrap-parens.fixed
Normal file
10
tests/ui/traits/fn-pointer/suggest-wrap-parens.fixed
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
//@ run-rustfix
|
||||||
|
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
impl Foo for fn() {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _x: &dyn Foo = &(main as fn());
|
||||||
|
//~^ ERROR the trait bound
|
||||||
|
}
|
10
tests/ui/traits/fn-pointer/suggest-wrap-parens.rs
Normal file
10
tests/ui/traits/fn-pointer/suggest-wrap-parens.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
//@ run-rustfix
|
||||||
|
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
impl Foo for fn() {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _x: &dyn Foo = &main;
|
||||||
|
//~^ ERROR the trait bound
|
||||||
|
}
|
15
tests/ui/traits/fn-pointer/suggest-wrap-parens.stderr
Normal file
15
tests/ui/traits/fn-pointer/suggest-wrap-parens.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0277]: the trait bound `fn() {main}: Foo` is not satisfied
|
||||||
|
--> $DIR/suggest-wrap-parens.rs:8:24
|
||||||
|
|
|
||||||
|
LL | let _x: &dyn Foo = &main;
|
||||||
|
| ^^^^^ the trait `Foo` is not implemented for fn item `fn() {main}`
|
||||||
|
|
|
||||||
|
= note: required for the cast from `&fn() {main}` to `&dyn Foo`
|
||||||
|
help: the trait `Foo` is implemented for fn pointer `fn()`, try casting using `as`
|
||||||
|
|
|
||||||
|
LL | let _x: &dyn Foo = &(main as fn());
|
||||||
|
| + ++++++++
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Add table
Add a link
Reference in a new issue