Skip to content

Tweak invalid RTN errors #137824

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 1 commit into from
Mar 2, 2025
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
4 changes: 2 additions & 2 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 18 additions & 3 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,24 +372,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)]
Expand Down
32 changes: 20 additions & 12 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
34 changes: 21 additions & 13 deletions compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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()
{
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,11 +378,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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 `..`

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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: `()`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know why we were suggesting () before. That wasn't correct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably because I forgot to change it when () changed to (..). Lots of different places needed to get modified, so I just forgot one.

| ^^^^^
|
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`.
7 changes: 6 additions & 1 deletion tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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(..);
|
Comment on lines +18 to +22
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This suggestion is unfortunate, but the error itself shouldn't be emitted in this case, as the previous E0573 should preclude it.


error: return type notation not allowed in this position yet
--> $DIR/let-binding-init-expr-as-ty.rs:2:14
Expand Down
Loading