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;
match sig.decl.output {
hir::FnRetTy::DefaultReturn(sp) => {
let sugg = format!("-> {} ", trait_sig.output());
let sugg = format!(" -> {}", trait_sig.output());
diag.span_suggestion_verbose(sp, msg, sugg, ap);
}
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.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);
// We insert the deferred_generator_interiors entry after visiting the body.

View file

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

View file

@ -782,8 +782,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
hir::FnRetTy::Return(hir_ty) => {
let span = hir_ty.span;
if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind
&& let hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(op_ty),
@ -799,14 +797,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?found);
if found.is_suggestable(self.tcx, false) {
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;
} 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
// are not, the expectation must have been caused by something else.
debug!("return type {:?}", hir_ty);
@ -815,14 +812,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("expected type {:?}", expected);
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 = self.normalize(span, ty);
let ty = self.normalize(hir_ty.span, ty);
let ty = self.tcx.erase_late_bound_regions(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);
return true;
}
}
}
_ => {}
}
false

View file

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

View file

@ -247,7 +247,7 @@ impl<'a> Parser<'a> {
)?;
FnRetTy::Ty(ty)
} 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 {
hir::ExprKind::Closure(hir::Closure {
fn_decl:
hir::FnDecl {
output: hir::FnRetTy::DefaultReturn(span) | hir::FnRetTy::Return(hir::Ty { span, .. }),
..
},
body,
..
}) => 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()),
]),
_ => None,

View file

@ -2,7 +2,7 @@ error: this function has too many arguments (11/10)
--> $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) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::too-many-arguments` implied by `-D warnings`
= 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
|
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`
= help: to override `-D warnings` add `#[allow(clippy::too_many_arguments)]`
@ -17,7 +17,7 @@ LL | | two: u32,
... |
LL | | eight: ()
LL | | ) {
| |__^
| |_^
error: this function has too many arguments (8/7)
--> $DIR/functions.rs:48:5
@ -29,7 +29,7 @@ error: this function has too many arguments (8/7)
--> $DIR/functions.rs:58:5
|
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`
--> $DIR/functions.rs:68:34

View file

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

View file

@ -2599,7 +2599,8 @@ fn rewrite_fn_base(
if where_clause_str.is_empty() {
if let ast::FnRetTy::Default(ret_span) = fd.output {
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,
context,
last_line_width(&result),

View file

@ -1,5 +1,5 @@
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 ()| {};
| ------- ^

View file

@ -41,7 +41,7 @@ LL | let _ = for<'a> |x: &'a ()| -> &() { x };
| ^ explicit lifetime name needed here
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<> || {};
| ----- ^

View file

@ -28,7 +28,7 @@ LL | fn foo(self);
found signature `fn(Box<MyFuture>)`
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) {}
| ^ 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
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

View file

@ -1,5 +1,5 @@
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) {}
| ^ expected `isize`, found `()`

View file

@ -25,7 +25,7 @@ LL | for <Foo>::Bar in x {}
= help: consider removing `for<...>`
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;
| ------- ^

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
// run-rustfix
#![allow(unused)]
// Make sure we don't ICE when suggesting a return type
// for an async fn that has late-bound vars...

View file

@ -1,8 +1,8 @@
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) {
| --------------------- help: try adding a return type: `-> bool`
| - help: try adding a return type: `-> bool`
LL | true
| ^^^^ expected `()`, found `bool`

View file

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