diff options
Diffstat (limited to 'compiler/rustc_ast_lowering/src')
| -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 |
3 files changed, 59 insertions, 28 deletions
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() { |
