Skip to content

Avoid pointing out return span if it has nothing to do with type error #100130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion compiler/rustc_typeck/src/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1478,6 +1478,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
// type)
(self.final_ty.unwrap_or(self.expected_ty), expression_ty)
};
let (expected, found) = fcx.resolve_vars_if_possible((expected, found));

let mut err;
let mut unsized_return = false;
Expand Down Expand Up @@ -1648,9 +1649,30 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
);
}

if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) {
let ret_coercion_span = fcx.ret_coercion_span.get();

if let Some(sp) = ret_coercion_span
// If the closure has an explicit return type annotation, or if
// the closure's return type has been inferred from outside
// requirements (such as an Fn* trait bound), then a type error
// may occur at the first return expression we see in the closure
// (if it conflicts with the declared return type). Skip adding a
// note in this case, since it would be incorrect.
&& !fcx.return_type_pre_known
{
err.span_note(
sp,
&format!(
"return type inferred to be `{}` here",
expected
),
);
}

if let (Some(sp), Some(fn_output)) = (ret_coercion_span, fn_output) {
self.add_impl_trait_explanation(&mut err, cause, fcx, expected, sp, fn_output);
}

err
}

Expand Down
22 changes: 0 additions & 22 deletions compiler/rustc_typeck/src/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.note_type_is_not_clone(err, expected, expr_ty, expr);
self.note_need_for_fn_pointer(err, expected, expr_ty);
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
self.report_closure_inferred_return_type(err, expected);
}

// Requires that the two types unify, and prints an error message if
Expand Down Expand Up @@ -1418,25 +1417,4 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => false,
}
}

// Report the type inferred by the return statement.
fn report_closure_inferred_return_type(&self, err: &mut Diagnostic, expected: Ty<'tcx>) {
if let Some(sp) = self.ret_coercion_span.get()
// If the closure has an explicit return type annotation, or if
// the closure's return type has been inferred from outside
// requirements (such as an Fn* trait bound), then a type error
// may occur at the first return expression we see in the closure
// (if it conflicts with the declared return type). Skip adding a
// note in this case, since it would be incorrect.
&& !self.return_type_pre_known
{
err.span_note(
sp,
&format!(
"return type inferred to be `{}` here",
self.resolve_vars_if_possible(expected)
),
);
}
}
}
5 changes: 0 additions & 5 deletions src/test/ui/closures/issue-84128.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ LL | Foo(())
| |
| arguments to this struct are incorrect
|
note: return type inferred to be `{integer}` here
--> $DIR/issue-84128.rs:10:20
|
LL | return Foo(0);
| ^^^^^^
note: tuple struct defined here
--> $DIR/issue-84128.rs:5:8
|
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/expr/if/if-branch-types.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ LL | let x = if true { 10i32 } else { 10u32 };
| ----- ^^^^^ expected `i32`, found `u32`
| |
| expected because of this
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | let x = if true { 10i32 } else { 10i32 };
| ~~~

error: aborting due to previous error

Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/expr/if/if-else-type-mismatch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ LL | | 2u32
| | ^^^^ expected `i32`, found `u32`
LL | | };
| |_____- `if` and `else` have incompatible types
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | 2i32
| ~~~

error[E0308]: `if` and `else` have incompatible types
--> $DIR/if-else-type-mismatch.rs:8:38
Expand All @@ -18,6 +23,11 @@ LL | let _ = if true { 42i32 } else { 42u32 };
| ----- ^^^^^ expected `i32`, found `u32`
| |
| expected because of this
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | let _ = if true { 42i32 } else { 42i32 };
| ~~~

error[E0308]: `if` and `else` have incompatible types
--> $DIR/if-else-type-mismatch.rs:13:9
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ note: return type inferred to be `Result<{integer}, _>` here
|
LL | return Ok(6);
| ^^^^^
help: try wrapping the expression in a variant of `Result`
|
LL | Ok(5)
| +++ +
LL | Err(5)
| ++++ +

error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:7:5: 7:7] as Generator>::Return == i32`
--> $DIR/type-mismatch-signature-deduction.rs:5:13
Expand Down
7 changes: 6 additions & 1 deletion src/test/ui/impl-trait/equality.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ error[E0308]: mismatched types
--> $DIR/equality.rs:15:5
|
LL | fn two(x: bool) -> impl Foo {
| -------- expected `_` because of return type
| -------- expected `i32` because of return type
...
LL | 0_u32
| ^^^^^ expected `i32`, found `u32`
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | 0_i32
| ~~~

error[E0277]: cannot add `impl Foo` to `u32`
--> $DIR/equality.rs:24:11
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5
|
LL | fn can() -> impl NotObjectSafe {
| ------------------ expected `_` because of return type
| ------------------ expected `A` because of return type
...
LL | B
| ^ expected struct `A`, found struct `B`
Expand All @@ -11,7 +11,7 @@ error[E0308]: mismatched types
--> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5
|
LL | fn cat() -> impl ObjectSafe {
| --------------- expected `_` because of return type
| --------------- expected `A` because of return type
...
LL | B
| ^ expected struct `A`, found struct `B`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,43 @@ error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
|
LL | fn foo() -> impl std::fmt::Display {
| ---------------------- expected `_` because of return type
| ---------------------- expected `i32` because of return type
...
LL | 1u32
| ^^^^ expected `i32`, found `u32`
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | 1i32
| ~~~

error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:12:16
|
LL | fn bar() -> impl std::fmt::Display {
| ---------------------- expected `_` because of return type
| ---------------------- expected `i32` because of return type
...
LL | return 1u32;
| ^^^^ expected `i32`, found `u32`
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | return 1i32;
| ~~~

error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:20:9
|
LL | fn baz() -> impl std::fmt::Display {
| ---------------------- expected `_` because of return type
| ---------------------- expected `i32` because of return type
...
LL | 1u32
| ^^^^ expected `i32`, found `u32`
|
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
LL | }.try_into().unwrap()
| ++++++++++++++++++++

error[E0308]: `if` and `else` have incompatible types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:28:9
Expand All @@ -36,36 +51,56 @@ LL | | 1u32
| | ^^^^ expected `i32`, found `u32`
LL | | }
| |_____- `if` and `else` have incompatible types
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | 1i32
| ~~~

error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:35:14
|
LL | fn bat() -> impl std::fmt::Display {
| ---------------------- expected `_` because of return type
| ---------------------- expected `i32` because of return type
...
LL | _ => 1u32,
| ^^^^ expected `i32`, found `u32`
|
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
LL | }.try_into().unwrap()
| ++++++++++++++++++++

error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:40:5
|
LL | fn can() -> impl std::fmt::Display {
| ---------------------- expected `_` because of return type
| ---------------------- expected `i32` because of return type
LL | / match 13 {
LL | | 0 => return 0i32,
LL | | 1 => 1u32,
LL | | _ => 2u32,
LL | | }
| |_____^ expected `i32`, found `u32`
|
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
LL | }.try_into().unwrap()
| ++++++++++++++++++++

error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:53:13
|
LL | fn cat() -> impl std::fmt::Display {
| ---------------------- expected `_` because of return type
| ---------------------- expected `i32` because of return type
...
LL | 1u32
| ^^^^ expected `i32`, found `u32`
|
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
LL | }.try_into().unwrap()
| ++++++++++++++++++++

error[E0308]: `match` arms have incompatible types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:61:14
Expand All @@ -78,6 +113,11 @@ LL | | 1 => 1u32,
LL | | _ => 2u32,
LL | | }
| |_____- `match` arms have incompatible types
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | 1 => 1i32,
| ~~~

error[E0308]: `if` and `else` have incompatible types
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:97:9
Expand All @@ -90,6 +130,11 @@ LL | | 1u32
| | ^^^^ expected `i32`, found `u32`
LL | | }
| |_____- `if` and `else` have incompatible types
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | 1i32
| ~~~

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13
Expand Down Expand Up @@ -125,6 +170,11 @@ LL | | 1 => 1u32,
LL | | _ => 2u32,
LL | | }
| |_____- `match` arms have incompatible types
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | 1 => 1i32,
| ~~~

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13
Expand Down Expand Up @@ -164,6 +214,11 @@ LL | | 1u32
| | ^^^^ expected `i32`, found `u32`
LL | | }
| |_____- `if` and `else` have incompatible types
|
help: change the type of the numeric literal from `u32` to `i32`
|
LL | 1i32
| ~~~

error[E0746]: return type cannot have an unboxed trait object
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:85:13
Expand Down
18 changes: 18 additions & 0 deletions src/test/ui/mismatched_types/dont-point-return-on-E0308.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// edition:2021

async fn f(_: &()) {}
//~^ NOTE function defined here
//~| NOTE
// Second note is the span of the underlined argument, I think...

fn main() {
(|| async {
Err::<(), ()>(())?;
f(());
//~^ ERROR mismatched types
//~| NOTE arguments to this function are incorrect
//~| NOTE expected `&()`, found `()`
//~| HELP consider borrowing here
Ok::<(), ()>(())
})();
}
19 changes: 19 additions & 0 deletions src/test/ui/mismatched_types/dont-point-return-on-E0308.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0308]: mismatched types
--> $DIR/dont-point-return-on-E0308.rs:11:11
|
LL | f(());
| - ^^
| | |
| | expected `&()`, found `()`
| | help: consider borrowing here: `&()`
| arguments to this function are incorrect
|
note: function defined here
--> $DIR/dont-point-return-on-E0308.rs:3:10
|
LL | async fn f(_: &()) {}
| ^ ------

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
5 changes: 5 additions & 0 deletions src/test/ui/mismatched_types/issue-84976.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error[E0308]: mismatched types
|
LL | length = { foo(&length) };
| ^^^^^^^^^^^^ expected `u32`, found `i32`
|
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
|
LL | length = { foo(&length).try_into().unwrap() };
| ++++++++++++++++++++

error[E0308]: mismatched types
--> $DIR/issue-84976.rs:17:14
Expand Down
3 changes: 3 additions & 0 deletions src/test/ui/reify-intrinsic.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ LL | std::intrinsics::unlikely,
|
= note: expected fn item `extern "rust-intrinsic" fn(_) -> _ {likely}`
found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}`
= note: different `fn` items always have unique types, even if their signatures are the same
= help: change the expected type to be function pointer `extern "rust-intrinsic" fn(bool) -> bool`
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `likely as extern "rust-intrinsic" fn(bool) -> bool`

error: aborting due to 3 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/type-alias-impl-trait/issue-74280.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-74280.rs:9:5
|
LL | fn test() -> Test {
| ---- expected `_` because of return type
| ---- expected `()` because of return type
LL | let y = || -> Test { () };
LL | 7
| ^ expected `()`, found integer
Expand Down