Rollup merge of #127129 - compiler-errors:full-expr-span, r=jieyouxu

Use full expr span for return suggestion on type error/ambiguity

We sometimes use parts of an expression rather than the whole thing for an obligation span. For example, a method obligation will just point to the path segment corresponding to the `method` in `rcvr.method(args)`.

So let's not use that assuming it'll point to the *whole* expression span, which we can access from the expr hir id we store in `ObligationCauseCode::WhereClauseInExpr`.

Fixes #127109
This commit is contained in:
Guillaume Gomez 2024-07-01 20:29:58 +02:00 committed by GitHub
commit 61fe6b6c0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 56 additions and 16 deletions

View File

@ -2042,7 +2042,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
if block_num > 1 && found_semi { if block_num > 1 && found_semi {
err.span_suggestion_verbose( err.span_suggestion_verbose(
span.shrink_to_lo(), // use the span of the *whole* expr
self.tcx.hir().span(binding_hir_id).shrink_to_lo(),
"you might have meant to return this to infer its type parameters", "you might have meant to return this to infer its type parameters",
"return ", "return ",
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,

View File

@ -1,3 +1,5 @@
//@ edition:2018
// > Suggest returning tail expressions that match return type // > Suggest returning tail expressions that match return type
// > // >
// > Some newcomers are confused by the behavior of tail expressions, // > Some newcomers are confused by the behavior of tail expressions,
@ -8,24 +10,24 @@
// //
// This test was amended to also serve as a regression test for #92308, where // This test was amended to also serve as a regression test for #92308, where
// this suggestion would not trigger with async functions. // this suggestion would not trigger with async functions.
//
//@ edition:2018
fn main() { fn main() {
} }
fn foo(x: bool) -> Result<f64, i32> { fn foo(x: bool) -> Result<f64, i32> {
if x { if x {
Err(42) //~ ERROR mismatched types Err(42)
//| HELP you might have meant to return this value //~^ ERROR mismatched types
//~| HELP you might have meant to return this value
} }
Ok(42.0) Ok(42.0)
} }
async fn bar(x: bool) -> Result<f64, i32> { async fn bar(x: bool) -> Result<f64, i32> {
if x { if x {
Err(42) //~ ERROR mismatched types Err(42)
//| HELP you might have meant to return this value //~^ ERROR mismatched types
//~| HELP you might have meant to return this value
} }
Ok(42.0) Ok(42.0)
} }
@ -40,8 +42,26 @@ impl<T> Identity for T {
async fn foo2() -> i32 { async fn foo2() -> i32 {
if true { if true {
1i32 //~ ERROR mismatched types 1i32
//| HELP you might have meant to return this value //~^ ERROR mismatched types
//~| HELP you might have meant to return this value
} }
0 0
} }
struct Receiver;
impl Receiver {
fn generic<T>(self) -> Option<T> {
None
}
}
fn method() -> Option<i32> {
if true {
Receiver.generic();
//~^ ERROR type annotations needed
//~| HELP consider specifying the generic argument
//~| HELP you might have meant to return this to infer its type parameters
}
None
}

View File

@ -1,10 +1,11 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/tail-expr-as-potential-return.rs:27:9 --> $DIR/tail-expr-as-potential-return.rs:28:9
| |
LL | / if x { LL | / if x {
LL | | Err(42) LL | | Err(42)
| | ^^^^^^^ expected `()`, found `Result<_, {integer}>` | | ^^^^^^^ expected `()`, found `Result<_, {integer}>`
LL | | //| HELP you might have meant to return this value LL | |
LL | |
LL | | } LL | | }
| |_____- expected this to be `()` | |_____- expected this to be `()`
| |
@ -16,12 +17,13 @@ LL | return Err(42);
| ++++++ + | ++++++ +
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/tail-expr-as-potential-return.rs:43:9 --> $DIR/tail-expr-as-potential-return.rs:45:9
| |
LL | / if true { LL | / if true {
LL | | 1i32 LL | | 1i32
| | ^^^^ expected `()`, found `i32` | | ^^^^ expected `()`, found `i32`
LL | | //| HELP you might have meant to return this value LL | |
LL | |
LL | | } LL | | }
| |_____- expected this to be `()` | |_____- expected this to be `()`
| |
@ -36,7 +38,8 @@ error[E0308]: mismatched types
LL | / if x { LL | / if x {
LL | | Err(42) LL | | Err(42)
| | ^^^^^^^ expected `()`, found `Result<_, {integer}>` | | ^^^^^^^ expected `()`, found `Result<_, {integer}>`
LL | | //| HELP you might have meant to return this value LL | |
LL | |
LL | | } LL | | }
| |_____- expected this to be `()` | |_____- expected this to be `()`
| |
@ -47,6 +50,22 @@ help: you might have meant to return this value
LL | return Err(42); LL | return Err(42);
| ++++++ + | ++++++ +
error: aborting due to 3 previous errors error[E0282]: type annotations needed
--> $DIR/tail-expr-as-potential-return.rs:60:18
|
LL | Receiver.generic();
| ^^^^^^^ cannot infer type of the type parameter `T` declared on the method `generic`
|
help: consider specifying the generic argument
|
LL | Receiver.generic::<T>();
| +++++
help: you might have meant to return this to infer its type parameters
|
LL | return Receiver.generic();
| ++++++
For more information about this error, try `rustc --explain E0308`. error: aborting due to 4 previous errors
Some errors have detailed explanations: E0282, E0308.
For more information about an error, try `rustc --explain E0282`.