diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast_lowering/messages.ftl | 4 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/errors.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 32 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/path.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/path.rs | 5 |
6 files changed, 67 insertions, 32 deletions
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 1b91c33742d..5f1726f7f0a 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -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 diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index f31e2db051d..d402c5abc19 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -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)] diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1c69937eed0..13edcc10c9e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -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() { diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 55d06477313..6b6244b05aa 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -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() { diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 173c68b3a72..5bf1a11954e 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -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)] diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index c24305ea9a8..7698df3b554 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -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)) |
