diff --git a/Cargo.lock b/Cargo.lock index c867bb4ceaa9e..31edb773fc0ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4045,6 +4045,7 @@ dependencies = [ "rustc_feature", "rustc_hir", "rustc_index", + "rustc_macros", "rustc_metadata", "rustc_middle", "rustc_query_system", diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 4c7ce30097c95..1df5bf1a22037 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -54,6 +54,9 @@ parser_invalid_logical_operator = `{$incorrect}` is not a logical operator parser_tilde_is_not_unary_operator = `~` cannot be used as a unary operator .suggestion = use `!` to perform bitwise not +parser_unexpected_if_with_if = unexpected `if` in the condition expression + .suggestion = remove the `if` + parser_unexpected_token_after_not = unexpected {$negated_desc} after identifier parser_unexpected_token_after_not_bitwise = use `!` to perform bitwise not parser_unexpected_token_after_not_logical = use `!` to perform logical negation diff --git a/compiler/rustc_error_messages/locales/en-US/resolve.ftl b/compiler/rustc_error_messages/locales/en-US/resolve.ftl new file mode 100644 index 0000000000000..817bb83ed786a --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/resolve.ftl @@ -0,0 +1,211 @@ +resolve_parent_module_reset_for_binding = + parent module is reset for binding + +resolve_ampersand_used_without_explicit_lifetime_name = + `&` without an explicit lifetime name cannot be used here + .note = explicit lifetime name needed here + +resolve_underscore_lifetime_name_cannot_be_used_here = + `'_` cannot be used here + .note = `'_` is a reserved lifetime name + +resolve_crate_may_not_be_imported = + `$crate` may not be imported + +resolve_crate_root_imports_must_be_named_explicitly = + crate root imports need to be explicitly named: `use crate as name;` + +resolve_generic_params_from_outer_function = + can't use generic parameters from outer function + .label = use of generic parameter from outer function + .suggestion = try using a local generic parameter instead + +resolve_self_type_implicitly_declared_by_impl = + `Self` type implicitly declared here, by this `impl` + +resolve_cannot_use_self_type_here = + can't use `Self` here + +resolve_use_a_type_here_instead = + use a type here instead + +resolve_type_param_from_outer_fn = + type parameter from outer function + +resolve_const_param_from_outer_fn = + const parameter from outer function + +resolve_try_using_local_generic_parameter = + try using a local generic parameter instead + +resolve_try_adding_local_generic_param_on_method = + try adding a local generic parameter in this method instead + +resolve_help_try_using_local_generic_param = + try using a local generic paramter instead + +resolve_name_is_already_used_as_generic_parameter = + the name `{$name}` is already used for a generic parameter in this item's generic parameters + .label = already used + .first_use_of_name = first use of `{$name}` + +resolve_method_not_member_of_trait = + method `{$method}` is not a member of trait `{$trait_}` + .label = not a member of trait `{$trait_}` + +resolve_associated_fn_with_similar_name_exists = + there is an associated function with a similar name + +resolve_type_not_member_of_trait = + type `{$type_}` is not a member of trait `{$trait_}` + .label = not a member of trait `{$trait_}` + +resolve_associated_type_with_similar_name_exists = + there is an associated type with a similar name + +resolve_const_not_member_of_trait = + const `{$const_}` is not a member of trait `{$trait_}` + .label = not a member of trait `{$trait_}` + +resolve_associated_const_with_similar_name_exists = + there is an associated constant with a similar name + +resolve_variable_bound_with_different_mode = + variable `{$variable_name}` is bound inconsistently across alternatives separated by `|` + .label = bound in different ways + .first_binding_span = first binding + +resolve_ident_bound_more_than_once_in_parameter_list = + identifier `{$identifier}` is bound more than once in this parameter list + .label = used as parameter more than once + +resolve_ident_bound_more_than_once_in_same_pattern = + identifier `{$identifier}` is bound more than once in the same pattern + .label = used in a pattern more than once + +resolve_undeclared_label = + use of undeclared label `{$name}` + .label = undeclared label `{$name}` + +resolve_label_with_similar_name_reachable = + a label with a similar name is reachable + +resolve_try_using_similarly_named_label = + try using similarly named label + +resolve_unreachable_label_with_similar_name_exists = + a label with a similar name exists but is unreachable + +resolve_self_import_can_only_appear_once_in_the_list = + `self` import can only appear once in an import list + .label = can only appear once in an import list + +resolve_self_import_only_in_import_list_with_non_empty_prefix = + `self` import can only appear in an import list with a non-empty prefix + .label = can only appear in an import list with a non-empty prefix + +resolve_cannot_capture_dynamic_environment_in_fn_item = + can't capture dynamic environment in a fn item + .help = use the `|| {"{"} ... {"}"}` closure form instead + +resolve_attempt_to_use_non_constant_value_in_constant = + attempt to use a non-constant value in a constant + +resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion = + consider using `{$suggestion}` instead of `{$current}` + +resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion = + non-constant value + +resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion = + this would need to be a `{$suggestion}` + +resolve_self_imports_only_allowed_within = + `self` imports are only allowed within a {"{"} {"}"} list + +resolve_self_imports_only_allowed_within_suggestion = + consider importing the module directly + +resolve_self_imports_only_allowed_within_multipart_suggestion = + alternatively, use the multi-path `use` syntax to import `self` + +resolve_binding_shadows_something_unacceptable = + {$shadowing_binding}s cannot shadow {$shadowed_binding}s + .label = cannot be named the same as {$article} {$shadowed_binding} + .label_shadowed_binding = the {$shadowed_binding} `{$name}` is {$participle} here + +resolve_binding_shadows_something_unacceptable_suggestion = + try specify the pattern arguments + +resolve_forward_declared_generic_param = + generic parameters with a default cannot use forward declared identifiers + .label = defaulted generic parameters cannot be forward declared + +resolve_param_in_ty_of_const_param = + the type of const parameters must not depend on other generic parameters + .label = the type must not depend on the parameter `{$name}` + +resolve_self_in_generic_param_default = + generic parameters cannot use `Self` in their defaults + .label = `Self` in generic parameter default + +resolve_param_in_non_trivial_anon_const = + generic parameters may not be used in const operations + .label = cannot perform const operation using `{$name}` + +resolve_param_in_non_trivial_anon_const_help = + use `#![feature(generic_const_exprs)]` to allow generic const expressions + +resolve_param_in_non_trivial_anon_const_sub_type = + type parameters may not be used in const expressions + +resolve_param_in_non_trivial_anon_const_sub_non_type = + const parameters may only be used as standalone arguments, i.e. `{$name}` + +resolve_unreachable_label = + use of unreachable label `{$name}` + .label = unreachable label `{$name}` + .label_definition_span = unreachable label defined here + .note = labels are unreachable through functions, closures, async blocks and modules + +resolve_unreachable_label_suggestion_use_similarly_named = + try using similarly named label + +resolve_unreachable_label_similar_name_reachable = + a label with a similar name is reachable + +resolve_unreachable_label_similar_name_unreachable = + a label with a similar name exists but is also unreachable + +resolve_trait_impl_mismatch = + item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}` + .label = does not match trait + .label_trait_item = item in trait + +resolve_invalid_asm_sym = + invalid `sym` operand + .label = is a local variable + .help = `sym` operands must refer to either a function or a static + +resolve_trait_impl_duplicate = + duplicate definitions with name `{$name}`: + .label = duplicate definition + .old_span_label = previous definition here + .trait_item_span = item in trait + +resolve_relative_2018 = + relative paths are not supported in visibilities in 2018 edition or later + .suggestion = try + +resolve_ancestor_only = + visibilities can only be restricted to ancestor modules + +resolve_expected_found = + expected module, found {$res} `{$path_str}` + .label = not a module + +resolve_indeterminate = + cannot determine resolution for the visibility + +resolve_module_only = + visibility must resolve to a module diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 0b1b75471a661..9c71f0906b5ec 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -63,6 +63,7 @@ fluent_messages! { plugin_impl => "../locales/en-US/plugin_impl.ftl", privacy => "../locales/en-US/privacy.ftl", query_system => "../locales/en-US/query_system.ftl", + resolve => "../locales/en-US/resolve.ftl", save_analysis => "../locales/en-US/save_analysis.ftl", session => "../locales/en-US/session.ftl", symbol_mangling => "../locales/en-US/symbol_mangling.ftl", diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index c6035705e39fa..ee68344805f4c 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -211,6 +211,12 @@ impl IntoDiagnosticArg for DiagnosticSymbolList { } } +impl IntoDiagnosticArg for hir::def::Res { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Borrowed(self.descr())) + } +} + impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> { let mut diag; diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index a55224d10972a..230d250ff88cb 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -95,6 +95,14 @@ macro_rules! language_item_table { } } + /// Returns the name of the `LangItem` enum variant. + // This method is used by Clippy for internal lints. + pub fn variant_name(self) -> &'static str { + match self { + $( LangItem::$variant => stringify!($variant), )* + } + } + pub fn target(self) -> Target { match self { $( LangItem::$variant => $target, )* diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index ae0dbad8b08d7..bd9cd53e11578 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -144,7 +144,7 @@ impl fmt::Display for InvalidProgramInfo<'_> { AlreadyReported(ErrorGuaranteed { .. }) => { write!( f, - "an error has already been reported elsewhere (this sould not usually be printed)" + "an error has already been reported elsewhere (this should not usually be printed)" ) } Layout(ref err) => write!(f, "{err}"), diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 724d92254a455..211450250fdf4 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1219,3 +1219,11 @@ pub(crate) struct FnPtrWithGenericsSugg { pub arity: usize, pub for_param_list_exists: bool, } + +#[derive(Diagnostic)] +#[diag(parser_unexpected_if_with_if)] +pub(crate) struct UnexpectedIfWithIf( + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")] + pub Span, +); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index c9629ea49e0bf..634e45c848069 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -21,8 +21,8 @@ use crate::errors::{ NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields, RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere, - StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedTokenAfterLabel, - UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, + StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedIfWithIf, + UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses, }; use crate::maybe_recover_from_interpolated_ty_qpath; use core::mem; @@ -2231,6 +2231,7 @@ impl<'a> Parser<'a> { if let Some(block) = recover_block_from_condition(self) { block } else { + self.error_on_extra_if(&cond)?; // Parse block, which will always fail, but we can add a nice note to the error self.parse_block().map_err(|mut err| { err.span_note( @@ -2367,6 +2368,16 @@ impl<'a> Parser<'a> { }); } + fn error_on_extra_if(&mut self, cond: &P) -> PResult<'a, ()> { + if let ExprKind::Binary(Spanned { span: binop_span, node: binop}, _, right) = &cond.kind && + let BinOpKind::And = binop && + let ExprKind::If(cond, ..) = &right.kind { + Err(self.sess.create_err(UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo())))) + } else { + Ok(()) + } + } + /// Parses `for in ` (`for` token already eaten). fn parse_for_expr(&mut self, opt_label: Option