Rollup merge of #137824 - estebank:rtn-sugg, r=compiler-errors
Tweak invalid RTN errors Make suggestions verbose. When encountering `method(type)` bound, suggest `method(..)` instead of `method()`. ``` error: argument types not allowed with return type notation --> $DIR/bad-inputs-and-output.rs:9:23 | LL | fn foo<T: Trait<method(i32): Send>>() {} | ^^^^^ | help: remove the input types | LL - fn foo<T: Trait<method(i32): Send>>() {} LL + fn foo<T: Trait<method(..): Send>>() {} | ``` When encountering both return type and arg list that isn't `..`, suggest replacing both. ``` error: return type not allowed with return type notation --> $DIR/bad-inputs-and-output.rs:12:25 | LL | fn bar<T: Trait<method() -> (): Send>>() {} | ^^^^^^ | help: use the right argument notation and remove the return type | LL - fn bar<T: Trait<method() -> (): Send>>() {} LL + fn bar<T: Trait<method(..): Send>>() {} | ``` When encountering a return type, suggest removing it including the leading whitespace. ``` error: return type not allowed with return type notation --> $DIR/bad-inputs-and-output.rs:24:45 | LL | fn bay_path<T: Trait>() where T::method(..) -> (): Send {} | ^^^^^ | help: remove the return type | LL - fn bay_path<T: Trait>() where T::method(..) -> (): Send {} LL + fn bay_path<T: Trait>() where T::method(..): Send {} | ``` r? ``@compiler-errors``
This commit is contained in:
commit
a500a43367
9 changed files with 133 additions and 44 deletions
|
@ -37,11 +37,11 @@ ast_lowering_bad_return_type_notation_inputs =
|
|||
.suggestion = remove the input types
|
||||
|
||||
ast_lowering_bad_return_type_notation_needs_dots = return type notation arguments must be elided with `..`
|
||||
.suggestion = add `..`
|
||||
.suggestion = use the correct syntax by adding `..` to the arguments
|
||||
|
||||
ast_lowering_bad_return_type_notation_output =
|
||||
return type not allowed with return type notation
|
||||
.suggestion = remove the return type
|
||||
ast_lowering_bad_return_type_notation_output_suggestion = use the right argument notation and remove the return type
|
||||
|
||||
ast_lowering_bad_return_type_notation_position = return type notation not allowed in this position yet
|
||||
|
||||
|
|
|
@ -373,24 +373,39 @@ pub(crate) struct InclusiveRangeWithNoEnd {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
ast_lowering_bad_return_type_notation_output_suggestion,
|
||||
applicability = "machine-applicable",
|
||||
style = "verbose"
|
||||
)]
|
||||
/// Given `T: Tr<m() -> Ret>` or `T: Tr<m(Ty) -> Ret>`, suggest `T: Tr<m(..)>`.
|
||||
pub(crate) struct RTNSuggestion {
|
||||
#[suggestion_part(code = "")]
|
||||
pub output: Span,
|
||||
#[suggestion_part(code = "(..)")]
|
||||
pub input: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub(crate) enum BadReturnTypeNotation {
|
||||
#[diag(ast_lowering_bad_return_type_notation_inputs)]
|
||||
Inputs {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "()", applicability = "maybe-incorrect")]
|
||||
#[suggestion(code = "(..)", applicability = "machine-applicable", style = "verbose")]
|
||||
span: Span,
|
||||
},
|
||||
#[diag(ast_lowering_bad_return_type_notation_output)]
|
||||
Output {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "", applicability = "maybe-incorrect")]
|
||||
span: Span,
|
||||
#[subdiagnostic]
|
||||
suggestion: RTNSuggestion,
|
||||
},
|
||||
#[diag(ast_lowering_bad_return_type_notation_needs_dots)]
|
||||
NeedsDots {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "(..)", applicability = "maybe-incorrect")]
|
||||
#[suggestion(code = "(..)", applicability = "machine-applicable", style = "verbose")]
|
||||
span: Span,
|
||||
},
|
||||
#[diag(ast_lowering_bad_return_type_notation_position)]
|
||||
|
|
|
@ -926,19 +926,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
if let Some(first_char) = constraint.ident.as_str().chars().next()
|
||||
&& first_char.is_ascii_lowercase()
|
||||
{
|
||||
let mut err = if !data.inputs.is_empty() {
|
||||
self.dcx().create_err(errors::BadReturnTypeNotation::Inputs {
|
||||
span: data.inputs_span,
|
||||
})
|
||||
} else if let FnRetTy::Ty(ty) = &data.output {
|
||||
self.dcx().create_err(errors::BadReturnTypeNotation::Output {
|
||||
span: data.inputs_span.shrink_to_hi().to(ty.span),
|
||||
})
|
||||
} else {
|
||||
self.dcx().create_err(errors::BadReturnTypeNotation::NeedsDots {
|
||||
span: data.inputs_span,
|
||||
})
|
||||
tracing::info!(?data, ?data.inputs);
|
||||
let err = match (&data.inputs[..], &data.output) {
|
||||
([_, ..], FnRetTy::Default(_)) => {
|
||||
errors::BadReturnTypeNotation::Inputs { span: data.inputs_span }
|
||||
}
|
||||
([], FnRetTy::Default(_)) => {
|
||||
errors::BadReturnTypeNotation::NeedsDots { span: data.inputs_span }
|
||||
}
|
||||
// The case `T: Trait<method(..) -> Ret>` is handled in the parser.
|
||||
(_, FnRetTy::Ty(ty)) => {
|
||||
let span = data.inputs_span.shrink_to_hi().to(ty.span);
|
||||
errors::BadReturnTypeNotation::Output {
|
||||
span,
|
||||
suggestion: errors::RTNSuggestion {
|
||||
output: span,
|
||||
input: data.inputs_span,
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
let mut err = self.dcx().create_err(err);
|
||||
if !self.tcx.features().return_type_notation()
|
||||
&& self.tcx.sess.is_nightly_build()
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ use tracing::{debug, instrument};
|
|||
|
||||
use super::errors::{
|
||||
AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, BadReturnTypeNotation,
|
||||
GenericTypeWithParentheses, UseAngleBrackets,
|
||||
GenericTypeWithParentheses, RTNSuggestion, UseAngleBrackets,
|
||||
};
|
||||
use super::{
|
||||
AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, ImplTraitPosition,
|
||||
|
@ -268,19 +268,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
GenericArgs::Parenthesized(data) => match generic_args_mode {
|
||||
GenericArgsMode::ReturnTypeNotation => {
|
||||
let mut err = if !data.inputs.is_empty() {
|
||||
self.dcx().create_err(BadReturnTypeNotation::Inputs {
|
||||
span: data.inputs_span,
|
||||
})
|
||||
} else if let FnRetTy::Ty(ty) = &data.output {
|
||||
self.dcx().create_err(BadReturnTypeNotation::Output {
|
||||
span: data.inputs_span.shrink_to_hi().to(ty.span),
|
||||
})
|
||||
} else {
|
||||
self.dcx().create_err(BadReturnTypeNotation::NeedsDots {
|
||||
span: data.inputs_span,
|
||||
})
|
||||
tracing::info!(?data, ?data.inputs);
|
||||
let err = match (&data.inputs[..], &data.output) {
|
||||
([_, ..], FnRetTy::Default(_)) => {
|
||||
BadReturnTypeNotation::Inputs { span: data.inputs_span }
|
||||
}
|
||||
([], FnRetTy::Default(_)) => {
|
||||
BadReturnTypeNotation::NeedsDots { span: data.inputs_span }
|
||||
}
|
||||
// The case `T: Trait<method(..) -> Ret>` is handled in the parser.
|
||||
(_, FnRetTy::Ty(ty)) => {
|
||||
let span = data.inputs_span.shrink_to_hi().to(ty.span);
|
||||
BadReturnTypeNotation::Output {
|
||||
span,
|
||||
suggestion: RTNSuggestion {
|
||||
output: span,
|
||||
input: data.inputs_span,
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
let mut err = self.dcx().create_err(err);
|
||||
if !self.tcx.features().return_type_notation()
|
||||
&& self.tcx.sess.is_nightly_build()
|
||||
{
|
||||
|
|
|
@ -2922,8 +2922,9 @@ pub(crate) struct AddBoxNew {
|
|||
#[diag(parse_bad_return_type_notation_output)]
|
||||
pub(crate) struct BadReturnTypeNotationOutput {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")]
|
||||
pub span: Span,
|
||||
#[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")]
|
||||
pub suggestion: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
@ -382,11 +382,14 @@ impl<'a> Parser<'a> {
|
|||
|
||||
self.psess.gated_spans.gate(sym::return_type_notation, span);
|
||||
|
||||
let prev_lo = self.prev_token.span.shrink_to_hi();
|
||||
if self.eat_noexpect(&token::RArrow) {
|
||||
let lo = self.prev_token.span;
|
||||
let ty = self.parse_ty()?;
|
||||
let span = lo.to(ty.span);
|
||||
let suggestion = prev_lo.to(ty.span);
|
||||
self.dcx()
|
||||
.emit_err(errors::BadReturnTypeNotationOutput { span: lo.to(ty.span) });
|
||||
.emit_err(errors::BadReturnTypeNotationOutput { span, suggestion });
|
||||
}
|
||||
|
||||
P(ast::GenericArgs::ParenthesizedElided(span))
|
||||
|
|
|
@ -21,6 +21,9 @@ fn foo_path<T: Trait>() where T::method(i32): Send {}
|
|||
fn bar_path<T: Trait>() where T::method() -> (): Send {}
|
||||
//~^ ERROR return type not allowed with return type notation
|
||||
|
||||
fn bay_path<T: Trait>() where T::method(..) -> (): Send {}
|
||||
//~^ ERROR return type not allowed with return type notation
|
||||
|
||||
fn baz_path<T: Trait>() where T::method(): Send {}
|
||||
//~^ ERROR return type notation arguments must be elided with `..`
|
||||
|
||||
|
|
|
@ -1,17 +1,29 @@
|
|||
error: return type not allowed with return type notation
|
||||
--> $DIR/bad-inputs-and-output.rs:24:45
|
||||
|
|
||||
LL | fn bay_path<T: Trait>() where T::method(..) -> (): Send {}
|
||||
| ^^^^^
|
||||
|
|
||||
help: remove the return type
|
||||
|
|
||||
LL - fn bay_path<T: Trait>() where T::method(..) -> (): Send {}
|
||||
LL + fn bay_path<T: Trait>() where T::method(..): Send {}
|
||||
|
|
||||
|
||||
error[E0575]: expected associated type, found associated function `Trait::method`
|
||||
--> $DIR/bad-inputs-and-output.rs:27:36
|
||||
--> $DIR/bad-inputs-and-output.rs:30:36
|
||||
|
|
||||
LL | fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type
|
||||
|
||||
error[E0575]: expected associated type, found associated function `Trait::method`
|
||||
--> $DIR/bad-inputs-and-output.rs:30:36
|
||||
--> $DIR/bad-inputs-and-output.rs:33:36
|
||||
|
|
||||
LL | fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type
|
||||
|
||||
error[E0575]: expected associated type, found associated function `Trait::method`
|
||||
--> $DIR/bad-inputs-and-output.rs:33:36
|
||||
--> $DIR/bad-inputs-and-output.rs:36:36
|
||||
|
|
||||
LL | fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ not a associated type
|
||||
|
@ -20,38 +32,72 @@ error: argument types not allowed with return type notation
|
|||
--> $DIR/bad-inputs-and-output.rs:9:23
|
||||
|
|
||||
LL | fn foo<T: Trait<method(i32): Send>>() {}
|
||||
| ^^^^^ help: remove the input types: `()`
|
||||
| ^^^^^
|
||||
|
|
||||
help: remove the input types
|
||||
|
|
||||
LL - fn foo<T: Trait<method(i32): Send>>() {}
|
||||
LL + fn foo<T: Trait<method(..): Send>>() {}
|
||||
|
|
||||
|
||||
error: return type not allowed with return type notation
|
||||
--> $DIR/bad-inputs-and-output.rs:12:25
|
||||
|
|
||||
LL | fn bar<T: Trait<method() -> (): Send>>() {}
|
||||
| ^^^^^^ help: remove the return type
|
||||
| ^^^^^^
|
||||
|
|
||||
help: use the right argument notation and remove the return type
|
||||
|
|
||||
LL - fn bar<T: Trait<method() -> (): Send>>() {}
|
||||
LL + fn bar<T: Trait<method(..): Send>>() {}
|
||||
|
|
||||
|
||||
error: return type notation arguments must be elided with `..`
|
||||
--> $DIR/bad-inputs-and-output.rs:15:23
|
||||
|
|
||||
LL | fn baz<T: Trait<method(): Send>>() {}
|
||||
| ^^ help: add `..`: `(..)`
|
||||
| ^^
|
||||
|
|
||||
help: use the correct syntax by adding `..` to the arguments
|
||||
|
|
||||
LL | fn baz<T: Trait<method(..): Send>>() {}
|
||||
| ++
|
||||
|
||||
error: argument types not allowed with return type notation
|
||||
--> $DIR/bad-inputs-and-output.rs:18:40
|
||||
|
|
||||
LL | fn foo_path<T: Trait>() where T::method(i32): Send {}
|
||||
| ^^^^^ help: remove the input types: `()`
|
||||
| ^^^^^
|
||||
|
|
||||
help: remove the input types
|
||||
|
|
||||
LL - fn foo_path<T: Trait>() where T::method(i32): Send {}
|
||||
LL + fn foo_path<T: Trait>() where T::method(..): Send {}
|
||||
|
|
||||
|
||||
error: return type not allowed with return type notation
|
||||
--> $DIR/bad-inputs-and-output.rs:21:42
|
||||
|
|
||||
LL | fn bar_path<T: Trait>() where T::method() -> (): Send {}
|
||||
| ^^^^^^ help: remove the return type
|
||||
| ^^^^^^
|
||||
|
|
||||
help: use the right argument notation and remove the return type
|
||||
|
|
||||
LL - fn bar_path<T: Trait>() where T::method() -> (): Send {}
|
||||
LL + fn bar_path<T: Trait>() where T::method(..): Send {}
|
||||
|
|
||||
|
||||
error: return type notation arguments must be elided with `..`
|
||||
--> $DIR/bad-inputs-and-output.rs:24:40
|
||||
--> $DIR/bad-inputs-and-output.rs:27:40
|
||||
|
|
||||
LL | fn baz_path<T: Trait>() where T::method(): Send {}
|
||||
| ^^ help: add `..`: `(..)`
|
||||
| ^^
|
||||
|
|
||||
help: use the correct syntax by adding `..` to the arguments
|
||||
|
|
||||
LL | fn baz_path<T: Trait>() where T::method(..): Send {}
|
||||
| ++
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0575`.
|
||||
|
|
|
@ -10,11 +10,16 @@ error: argument types not allowed with return type notation
|
|||
--> $DIR/let-binding-init-expr-as-ty.rs:2:26
|
||||
|
|
||||
LL | let foo: i32::from_be(num);
|
||||
| ^^^^^ help: remove the input types: `()`
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
|
||||
= help: add `#![feature(return_type_notation)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
help: remove the input types
|
||||
|
|
||||
LL - let foo: i32::from_be(num);
|
||||
LL + let foo: i32::from_be(..);
|
||||
|
|
||||
|
||||
error: return type notation not allowed in this position yet
|
||||
--> $DIR/let-binding-init-expr-as-ty.rs:2:14
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue