1
Fork 0

Rollup merge of #116296 - compiler-errors:default-return, r=estebank

More accurately point to where default return type should go

When getting the "default return type" span, instead of pointing to the low span of the next token, point to the high span of the previous token. This:

1. Makes forming return type suggestions more uniform, since we expect them all in the same place.
2. Arguably makes labels easier to understand, since we're pointing to where the implicit `-> ()` would've gone, rather than the starting brace or the semicolon.

r? ```@estebank```
This commit is contained in:
Jubilee 2023-10-05 00:56:29 -07:00 committed by GitHub
commit cfce3a919d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 105 additions and 89 deletions

View file

@ -1189,7 +1189,7 @@ fn report_trait_method_mismatch<'tcx>(
let ap = Applicability::MachineApplicable; let ap = Applicability::MachineApplicable;
match sig.decl.output { match sig.decl.output {
hir::FnRetTy::DefaultReturn(sp) => { hir::FnRetTy::DefaultReturn(sp) => {
let sugg = format!("-> {} ", trait_sig.output()); let sugg = format!(" -> {}", trait_sig.output());
diag.span_suggestion_verbose(sp, msg, sugg, ap); diag.span_suggestion_verbose(sp, msg, sugg, ap);
} }
hir::FnRetTy::Return(hir_ty) => { hir::FnRetTy::Return(hir_ty) => {

View file

@ -113,7 +113,11 @@ pub(super) fn check_fn<'a, 'tcx>(
fcx.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); fcx.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); let return_or_body_span = match decl.output {
hir::FnRetTy::DefaultReturn(_) => body.value.span,
hir::FnRetTy::Return(ty) => ty.span,
};
fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
fcx.check_return_expr(&body.value, false); fcx.check_return_expr(&body.value, false);
// We insert the deferred_generator_interiors entry after visiting the body. // We insert the deferred_generator_interiors entry after visiting the body.

View file

@ -110,7 +110,7 @@ pub struct AddressOfTemporaryTaken {
pub enum AddReturnTypeSuggestion { pub enum AddReturnTypeSuggestion {
#[suggestion( #[suggestion(
hir_typeck_add_return_type_add, hir_typeck_add_return_type_add,
code = "-> {found} ", code = " -> {found}",
applicability = "machine-applicable" applicability = "machine-applicable"
)] )]
Add { Add {
@ -120,7 +120,7 @@ pub enum AddReturnTypeSuggestion {
}, },
#[suggestion( #[suggestion(
hir_typeck_add_return_type_missing_here, hir_typeck_add_return_type_missing_here,
code = "-> _ ", code = " -> _",
applicability = "has-placeholders" applicability = "has-placeholders"
)] )]
MissingHere { MissingHere {

View file

@ -782,8 +782,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
} }
hir::FnRetTy::Return(hir_ty) => { hir::FnRetTy::Return(hir_ty) => {
let span = hir_ty.span;
if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind
&& let hir::Node::Item(hir::Item { && let hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(op_ty), kind: hir::ItemKind::OpaqueTy(op_ty),
@ -799,14 +797,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?found); debug!(?found);
if found.is_suggestable(self.tcx, false) { if found.is_suggestable(self.tcx, false) {
if term.span.is_empty() { if term.span.is_empty() {
err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() }); err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span: term.span, found: found.to_string() });
return true; return true;
} else { } else {
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span, expected }); err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span: term.span, expected });
} }
} }
} } else {
// Only point to return type if the expected type is the return type, as if they // Only point to return type if the expected type is the return type, as if they
// are not, the expectation must have been caused by something else. // are not, the expectation must have been caused by something else.
debug!("return type {:?}", hir_ty); debug!("return type {:?}", hir_ty);
@ -815,14 +812,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("expected type {:?}", expected); debug!("expected type {:?}", expected);
let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into()); let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
let ty = Binder::bind_with_vars(ty, bound_vars); let ty = Binder::bind_with_vars(ty, bound_vars);
let ty = self.normalize(span, ty); let ty = self.normalize(hir_ty.span, ty);
let ty = self.tcx.erase_late_bound_regions(ty); let ty = self.tcx.erase_late_bound_regions(ty);
if self.can_coerce(expected, ty) { if self.can_coerce(expected, ty) {
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span, expected }); err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected });
self.try_suggest_return_impl_trait(err, expected, ty, fn_id); self.try_suggest_return_impl_trait(err, expected, ty, fn_id);
return true; return true;
} }
} }
}
_ => {} _ => {}
} }
false false

View file

@ -194,13 +194,13 @@ impl<'a> SourceKindMultiSuggestion<'a> {
data: &'a FnRetTy<'a>, data: &'a FnRetTy<'a>,
should_wrap_expr: Option<Span>, should_wrap_expr: Option<Span>,
) -> Self { ) -> Self {
let (arrow, post) = match data { let arrow = match data {
FnRetTy::DefaultReturn(_) => ("-> ", " "), FnRetTy::DefaultReturn(_) => " -> ",
_ => ("", ""), _ => "",
}; };
let (start_span, start_span_code, end_span) = match should_wrap_expr { let (start_span, start_span_code, end_span) = match should_wrap_expr {
Some(end_span) => (data.span(), format!("{arrow}{ty_info}{post}{{ "), Some(end_span)), Some(end_span) => (data.span(), format!("{arrow}{ty_info} {{"), Some(end_span)),
None => (data.span(), format!("{arrow}{ty_info}{post}"), None), None => (data.span(), format!("{arrow}{ty_info}"), None),
}; };
Self::ClosureReturn { start_span, start_span_code, end_span } Self::ClosureReturn { start_span, start_span_code, end_span }
} }

View file

@ -247,7 +247,7 @@ impl<'a> Parser<'a> {
)?; )?;
FnRetTy::Ty(ty) FnRetTy::Ty(ty)
} else { } else {
FnRetTy::Default(self.token.span.shrink_to_lo()) FnRetTy::Default(self.prev_token.span.shrink_to_hi())
}) })
} }

View file

@ -102,14 +102,10 @@ pub(super) fn check(
]), ]),
("None", "unwrap_or_else", _) => match args[0].kind { ("None", "unwrap_or_else", _) => match args[0].kind {
hir::ExprKind::Closure(hir::Closure { hir::ExprKind::Closure(hir::Closure {
fn_decl: body,
hir::FnDecl {
output: hir::FnRetTy::DefaultReturn(span) | hir::FnRetTy::Return(hir::Ty { span, .. }),
..
},
.. ..
}) => Some(vec![ }) => Some(vec![
(expr.span.with_hi(span.hi()), String::new()), (expr.span.with_hi(cx.tcx.hir().body(*body).value.span.lo()), String::new()),
(expr.span.with_lo(args[0].span.hi()), String::new()), (expr.span.with_lo(args[0].span.hi()), String::new()),
]), ]),
_ => None, _ => None,

View file

@ -2,7 +2,7 @@ error: this function has too many arguments (11/10)
--> $DIR/too_many_arguments.rs:4:1 --> $DIR/too_many_arguments.rs:4:1
| |
LL | fn too_many(p1: u8, p2: u8, p3: u8, p4: u8, p5: u8, p6: u8, p7: u8, p8: u8, p9: u8, p10: u8, p11: u8) {} LL | fn too_many(p1: u8, p2: u8, p3: u8, p4: u8, p5: u8, p6: u8, p7: u8, p8: u8, p9: u8, p10: u8, p11: u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `-D clippy::too-many-arguments` implied by `-D warnings` = note: `-D clippy::too-many-arguments` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]` = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]`

View file

@ -2,7 +2,7 @@ error: this function has too many arguments (8/7)
--> $DIR/functions.rs:8:1 --> $DIR/functions.rs:8:1
| |
LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} LL | fn bad(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `-D clippy::too-many-arguments` implied by `-D warnings` = note: `-D clippy::too-many-arguments` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]` = help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]`
@ -17,7 +17,7 @@ LL | | two: u32,
... | ... |
LL | | eight: () LL | | eight: ()
LL | | ) { LL | | ) {
| |__^ | |_^
error: this function has too many arguments (8/7) error: this function has too many arguments (8/7)
--> $DIR/functions.rs:48:5 --> $DIR/functions.rs:48:5
@ -29,7 +29,7 @@ error: this function has too many arguments (8/7)
--> $DIR/functions.rs:58:5 --> $DIR/functions.rs:58:5
| |
LL | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {} LL | fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this public function might dereference a raw pointer but is not marked `unsafe` error: this public function might dereference a raw pointer but is not marked `unsafe`
--> $DIR/functions.rs:68:34 --> $DIR/functions.rs:68:34

View file

@ -4,7 +4,7 @@ error: this unit-returning function has a `#[must_use]` attribute
LL | #[must_use] LL | #[must_use]
| ----------- help: remove the attribute | ----------- help: remove the attribute
LL | pub fn must_use_default() {} LL | pub fn must_use_default() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `-D clippy::must-use-unit` implied by `-D warnings` = note: `-D clippy::must-use-unit` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::must_use_unit)]` = help: to override `-D warnings` add `#[allow(clippy::must_use_unit)]`
@ -23,7 +23,7 @@ error: this unit-returning function has a `#[must_use]` attribute
LL | #[must_use = "With note"] LL | #[must_use = "With note"]
| ------------------------- help: remove the attribute | ------------------------- help: remove the attribute
LL | pub fn must_use_with_note() {} LL | pub fn must_use_with_note() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -2599,7 +2599,8 @@ fn rewrite_fn_base(
if where_clause_str.is_empty() { if where_clause_str.is_empty() {
if let ast::FnRetTy::Default(ret_span) = fd.output { if let ast::FnRetTy::Default(ret_span) = fd.output {
match recover_missing_comment_in_span( match recover_missing_comment_in_span(
mk_sp(params_span.hi(), ret_span.hi()), // from after the closing paren to right before block or semicolon
mk_sp(ret_span.lo(), span.hi()),
shape, shape,
context, context,
last_line_width(&result), last_line_width(&result),

View file

@ -1,5 +1,5 @@
error: implicit types in closure signatures are forbidden when `for<...>` is present error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-return.rs:4:34 --> $DIR/implicit-return.rs:4:33
| |
LL | let _f = for<'a> |_: &'a ()| {}; LL | let _f = for<'a> |_: &'a ()| {};
| ------- ^ | ------- ^

View file

@ -41,7 +41,7 @@ LL | let _ = for<'a> |x: &'a ()| -> &() { x };
| ^ explicit lifetime name needed here | ^ explicit lifetime name needed here
error: implicit types in closure signatures are forbidden when `for<...>` is present error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/implicit-stuff.rs:5:22 --> $DIR/implicit-stuff.rs:5:21
| |
LL | let _ = for<> || {}; LL | let _ = for<> || {};
| ----- ^ | ----- ^

View file

@ -28,7 +28,7 @@ LL | fn foo(self);
found signature `fn(Box<MyFuture>)` found signature `fn(Box<MyFuture>)`
error[E0053]: method `bar` has an incompatible type for trait error[E0053]: method `bar` has an incompatible type for trait
--> $DIR/bad-self-type.rs:24:18 --> $DIR/bad-self-type.rs:24:17
| |
LL | fn bar(self) {} LL | fn bar(self) {}
| ^ expected `Option<()>`, found `()` | ^ expected `Option<()>`, found `()`

View file

@ -30,7 +30,7 @@ LL | fn bar() {}
= note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
help: replace the return type so that it matches the trait help: replace the return type so that it matches the trait
| |
LL | fn bar() -> impl Sized {} LL | fn bar()-> impl Sized {}
| +++++++++++++ | +++++++++++++
error: impl trait in impl method signature does not match trait method signature error: impl trait in impl method signature does not match trait method signature

View file

@ -1,5 +1,5 @@
error[E0308]: lang item `start` function has wrong type error[E0308]: lang item `start` function has wrong type
--> $DIR/start_lang_item_args.rs:29:84 --> $DIR/start_lang_item_args.rs:29:83
| |
LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {} LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
| ^ expected `isize`, found `()` | ^ expected `isize`, found `()`

View file

@ -25,7 +25,7 @@ LL | for <Foo>::Bar in x {}
= help: consider removing `for<...>` = help: consider removing `for<...>`
error: implicit types in closure signatures are forbidden when `for<...>` is present error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/recover-quantified-closure.rs:2:25 --> $DIR/recover-quantified-closure.rs:2:24
| |
LL | for<'a> |x: &'a u8| *x + 1; LL | for<'a> |x: &'a u8| *x + 1;
| ------- ^ | ------- ^

View file

@ -0,0 +1,14 @@
// edition: 2021
// run-rustfix
#![allow(unused)]
// Make sure we don't ICE when suggesting a return type
// for an async fn that has late-bound vars...
async fn ice(_: &i32) -> bool {
true
//~^ ERROR mismatched types
}
fn main() {}

View file

@ -1,4 +1,7 @@
// edition: 2021 // edition: 2021
// run-rustfix
#![allow(unused)]
// Make sure we don't ICE when suggesting a return type // Make sure we don't ICE when suggesting a return type
// for an async fn that has late-bound vars... // for an async fn that has late-bound vars...

View file

@ -1,8 +1,8 @@
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/suggest-ret-on-async-w-late.rs:7:5 --> $DIR/suggest-ret-on-async-w-late.rs:10:5
| |
LL | async fn ice(_: &i32) { LL | async fn ice(_: &i32) {
| --------------------- help: try adding a return type: `-> bool` | - help: try adding a return type: `-> bool`
LL | true LL | true
| ^^^^ expected `()`, found `bool` | ^^^^ expected `()`, found `bool`

View file

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5 --> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5
| |
LL | async fn hello() { LL | async fn hello() {
| ---------------- help: try adding a return type: `-> i32` | - help: try adding a return type: `-> i32`
LL | 0 LL | 0
| ^ expected `()`, found integer | ^ expected `()`, found integer
@ -10,7 +10,7 @@ error[E0308]: mismatched types
--> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5 --> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5
| |
LL | async fn world() -> () { LL | async fn world() -> () {
| ---------------------- expected `()` because of return type | -- expected `()` because of return type
LL | 0 LL | 0
| ^ expected `()`, found integer | ^ expected `()`, found integer