diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index dab9e7666c23a..47b46cd69d84c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -12,13 +12,14 @@ use rustc_session::config::ExpectedValues; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::UNEXPECTED_CFGS; use rustc_session::parse::{ParseSess, feature_err}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use thin_vec::ThinVec; use crate::context::{AcceptContext, ShouldEmit, Stage}; use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser}; use crate::session_diagnostics::{ AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg, + ParsedDescription, }; use crate::{ AttributeParser, CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, @@ -47,20 +48,19 @@ pub fn parse_cfg<'c, S: Stage>( cx.expected_single_argument(list.span); return None; }; - parse_cfg_entry(cx, single) + parse_cfg_entry(cx, single).ok() } -pub(crate) fn parse_cfg_entry( +pub fn parse_cfg_entry( cx: &mut AcceptContext<'_, '_, S>, item: &MetaItemOrLitParser<'_>, -) -> Option { - Some(match item { +) -> Result { + Ok(match item { MetaItemOrLitParser::MetaItemParser(meta) => match meta.args() { ArgParser::List(list) => match meta.path().word_sym() { Some(sym::not) => { let Some(single) = list.single() else { - cx.expected_single_argument(list.span); - return None; + return Err(cx.expected_single_argument(list.span)); }; CfgEntry::Not(Box::new(parse_cfg_entry(cx, single)?), list.span) } @@ -75,29 +75,24 @@ pub(crate) fn parse_cfg_entry( Some(sym::target) => parse_cfg_entry_target(cx, list, meta.span())?, Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?, _ => { - cx.emit_err(session_diagnostics::InvalidPredicate { + return Err(cx.emit_err(session_diagnostics::InvalidPredicate { span: meta.span(), predicate: meta.path().to_string(), - }); - return None; + })); } }, a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => { let Some(name) = meta.path().word_sym() else { - cx.expected_identifier(meta.path().span()); - return None; + return Err(cx.expected_identifier(meta.path().span())); }; parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)? } }, MetaItemOrLitParser::Lit(lit) => match lit.kind { LitKind::Bool(b) => CfgEntry::Bool(b, lit.span), - _ => { - cx.expected_identifier(lit.span); - return None; - } + _ => return Err(cx.expected_identifier(lit.span)), }, - MetaItemOrLitParser::Err(_, _) => return None, + MetaItemOrLitParser::Err(_, err) => return Err(*err), }) } @@ -105,19 +100,22 @@ fn parse_cfg_entry_version( cx: &mut AcceptContext<'_, '_, S>, list: &MetaItemListParser<'_>, meta_span: Span, -) -> Option { +) -> Result { try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option()); let Some(version) = list.single() else { - cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span }); - return None; + return Err( + cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span }) + ); }; let Some(version_lit) = version.lit() else { - cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() }); - return None; + return Err( + cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() }) + ); }; let Some(version_str) = version_lit.value_str() else { - cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span }); - return None; + return Err( + cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span }) + ); }; let min_version = parse_version(version_str).or_else(|| { @@ -127,14 +125,14 @@ fn parse_cfg_entry_version( None }); - Some(CfgEntry::Version(min_version, list.span)) + Ok(CfgEntry::Version(min_version, list.span)) } fn parse_cfg_entry_target( cx: &mut AcceptContext<'_, '_, S>, list: &MetaItemListParser<'_>, meta_span: Span, -) -> Option { +) -> Result { if let Some(features) = cx.features_option() && !features.cfg_target_compact() { @@ -161,17 +159,16 @@ fn parse_cfg_entry_target( // Then, parse it as a name-value item let Some(name) = sub_item.path().word_sym() else { - cx.expected_identifier(sub_item.path().span()); - return None; + return Err(cx.expected_identifier(sub_item.path().span())); }; let name = Symbol::intern(&format!("target_{name}")); - if let Some(cfg) = + if let Ok(cfg) = parse_name_value(name, sub_item.path().span(), Some(nv), sub_item.span(), cx) { result.push(cfg); } } - Some(CfgEntry::All(result, list.span)) + Ok(CfgEntry::All(result, list.span)) } fn parse_name_value( @@ -180,21 +177,22 @@ fn parse_name_value( value: Option<&NameValueParser>, span: Span, cx: &mut AcceptContext<'_, '_, S>, -) -> Option { +) -> Result { try_gate_cfg(name, span, cx.sess(), cx.features_option()); let value = match value { None => None, Some(value) => { let Some(value_str) = value.value_as_str() else { - cx.expected_string_literal(value.value_span, Some(value.value_as_lit())); - return None; + return Err( + cx.expected_string_literal(value.value_span, Some(value.value_as_lit())) + ); }; Some((value_str, value.value_span)) } }; - Some(CfgEntry::NameValue { name, name_span, value, span }) + Ok(CfgEntry::NameValue { name, name_span, value, span }) } pub fn eval_config_entry( @@ -355,7 +353,8 @@ pub fn parse_cfg_attr( span, attr_span: cfg_attr.span, template: CFG_ATTR_TEMPLATE, - attribute: AttrPath::from_ast(&cfg_attr.get_normal_item().path), + path: AttrPath::from_ast(&cfg_attr.get_normal_item().path), + description: ParsedDescription::Attribute, reason, suggestions: CFG_ATTR_TEMPLATE.suggestions(Some(cfg_attr.style), sym::cfg_attr), }); @@ -398,6 +397,7 @@ fn parse_cfg_attr_internal<'a>( .into_boxed_slice(), span: attribute.span, }, + ParsedDescription::Attribute, pred_span, CRATE_NODE_ID, features, @@ -406,7 +406,8 @@ fn parse_cfg_attr_internal<'a>( parse_cfg_entry, &CFG_ATTR_TEMPLATE, ) - .ok_or_else(|| { + .map_err(|_err: ErrorGuaranteed| { + // We have an `ErrorGuaranteed` so this delayed bug cannot fail, but we need a `Diag` for the `PResult` so we make one anyways let mut diag = sess.dcx().struct_err( "cfg_entry parsing failing with `ShouldEmit::ErrorsAndLints` should emit a error.", ); diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 797d04b914dd5..065ed8959fc75 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -396,7 +396,7 @@ impl LinkParser { ) .emit(); } - *cfg = parse_cfg_entry(cx, link_cfg); + *cfg = parse_cfg_entry(cx, link_cfg).ok(); true } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 15904fd7d3348..773527c96a3a9 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -71,7 +71,9 @@ use crate::attributes::traits::{ use crate::attributes::transparency::TransparencyParser; use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs}; use crate::parser::{ArgParser, PathParser}; -use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem}; +use crate::session_diagnostics::{ + AttributeParseError, AttributeParseErrorReason, ParsedDescription, UnknownMetaItem, +}; use crate::target_checking::AllowedTargets; type GroupType = LazyLock>; @@ -353,6 +355,10 @@ pub struct AcceptContext<'f, 'sess, S: Stage> { /// Whether it is an inner or outer attribute pub(crate) attr_style: AttrStyle, + /// A description of the thing we are parsing using this attribute parser + /// We are not only using these parsers for attributes, but also for macros such as the `cfg!()` macro. + pub(crate) parsed_description: ParsedDescription, + /// The expected structure of the attribute. /// /// Used in reporting errors to give a hint to users what the attribute *should* look like. @@ -431,7 +437,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedStringLiteral { byte_string: actual_literal.and_then(|i| { i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span)) @@ -446,7 +453,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedIntegerLiteral, suggestions: self.suggestions(), }) @@ -457,7 +465,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedList, suggestions: self.suggestions(), }) @@ -468,7 +477,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span: args_span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedNoArgs, suggestions: self.suggestions(), }) @@ -480,7 +490,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedIdentifier, suggestions: self.suggestions(), }) @@ -493,7 +504,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedNameValue(name), suggestions: self.suggestions(), }) @@ -505,7 +517,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::DuplicateKey(key), suggestions: self.suggestions(), }) @@ -518,7 +531,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::UnexpectedLiteral, suggestions: self.suggestions(), }) @@ -529,7 +543,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedSingleArgument, suggestions: self.suggestions(), }) @@ -540,7 +555,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument, suggestions: self.suggestions(), }) @@ -556,7 +572,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: false, @@ -577,7 +594,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: false, @@ -597,7 +615,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { span, attr_span: self.attr_span, template: self.template.clone(), - attribute: self.attr_path.clone(), + path: self.attr_path.clone(), + description: self.parsed_description, reason: AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings: true, diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 953b0ebfaf04f..b7a6a1ef6d667 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -12,6 +12,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use crate::context::{AcceptContext, FinalizeContext, SharedContext, Stage}; use crate::parser::{ArgParser, MetaItemParser, PathParser}; +use crate::session_diagnostics::ParsedDescription; use crate::{Early, Late, OmitDoc, ShouldEmit}; /// Context created once, for example as part of the ast lowering @@ -145,6 +146,7 @@ impl<'sess> AttributeParser<'sess, Early> { normal_attr.item.span(), attr.style, path.get_attribute_path(), + ParsedDescription::Attribute, target_span, target_node_id, features, @@ -163,14 +165,15 @@ impl<'sess> AttributeParser<'sess, Early> { inner_span: Span, attr_style: AttrStyle, attr_path: AttrPath, + parsed_description: ParsedDescription, target_span: Span, target_node_id: NodeId, features: Option<&'sess Features>, emit_errors: ShouldEmit, args: &I, - parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> Option, + parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> T, template: &AttributeTemplate, - ) -> Option { + ) -> T { let mut parser = Self { features, tools: Vec::new(), @@ -190,6 +193,7 @@ impl<'sess> AttributeParser<'sess, Early> { attr_span, inner_span, attr_style, + parsed_description, template, attr_path, }; @@ -310,6 +314,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { attr_span: lower_span(attr.span), inner_span: lower_span(attr.get_normal_item().span()), attr_style: attr.style, + parsed_description: ParsedDescription::Attribute, template: &accept.template, attr_path: path.get_attribute_path(), }; diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index bcd0d674c75f1..2e0c5be587bba 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -106,12 +106,13 @@ mod target_checking; pub mod validate_attr; pub use attributes::cfg::{ - CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, + CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry, }; pub use attributes::cfg_old::*; pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version}; pub use context::{Early, Late, OmitDoc, ShouldEmit}; pub use interface::AttributeParser; pub use lints::emit_attribute_lint; +pub use session_diagnostics::ParsedDescription; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 82bd29218313e..8d783503f7be0 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -610,20 +610,35 @@ pub(crate) enum AttributeParseErrorReason<'a> { ExpectedIdentifier, } +/// A description of a thing that can be parsed using an attribute parser. +#[derive(Copy, Clone)] +pub enum ParsedDescription { + /// Used when parsing attributes. + Attribute, + /// Used when parsing some macros, such as the `cfg!()` macro. + Macro, +} + pub(crate) struct AttributeParseError<'a> { pub(crate) span: Span, pub(crate) attr_span: Span, pub(crate) template: AttributeTemplate, - pub(crate) attribute: AttrPath, + pub(crate) path: AttrPath, + pub(crate) description: ParsedDescription, pub(crate) reason: AttributeParseErrorReason<'a>, pub(crate) suggestions: Vec, } impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let name = self.attribute.to_string(); + let name = self.path.to_string(); + + let description = match self.description { + ParsedDescription::Attribute => "attribute", + ParsedDescription::Macro => "macro", + }; - let mut diag = Diag::new(dcx, level, format!("malformed `{name}` attribute input")); + let mut diag = Diag::new(dcx, level, format!("malformed `{name}` {description} input")); diag.span(self.attr_span); diag.code(E0539); match self.reason { @@ -724,12 +739,12 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { diag.span_label( self.span, format!( - "this attribute is only valid with {quote}{x}{quote} as an argument" + "this {description} is only valid with {quote}{x}{quote} as an argument" ), ); } [first, second] => { - diag.span_label(self.span, format!("this attribute is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument")); + diag.span_label(self.span, format!("this {description} is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument")); } [first @ .., second_to_last, last] => { let mut res = String::new(); @@ -740,7 +755,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { "{quote}{second_to_last}{quote} or {quote}{last}{quote}" )); - diag.span_label(self.span, format!("this attribute is only valid with one of the following arguments: {res}")); + diag.span_label(self.span, format!("this {description} is only valid with one of the following arguments: {res}")); } } } @@ -756,9 +771,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { diag.span_suggestions( self.attr_span, if self.suggestions.len() == 1 { - "must be of the form" + "must be of the form".to_string() } else { - "try changing it to one of the following valid forms of the attribute" + format!("try changing it to one of the following valid forms of the {description}") }, self.suggestions, Applicability::HasPlaceholders, diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index e23c7eebeca1e..f75923bb48f24 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -335,10 +335,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { LocalInfo::User(BindingForm::Var(mir::VarBindingForm { binding_mode: BindingMode(ByRef::No, Mutability::Not), opt_ty_info: Some(sp), + pat_span, .. })) => { if suggest { err.span_note(sp, "the binding is already a mutable borrow"); + err.span_suggestion_verbose( + pat_span.shrink_to_lo(), + "consider making the binding mutable if you need to reborrow \ + multiple times", + "mut ".to_string(), + Applicability::MaybeIncorrect, + ); } } _ => { @@ -356,9 +364,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // give a best effort structured suggestion. err.span_suggestion_verbose( source_info.span.with_hi(source_info.span.lo() + BytePos(5)), - "try removing `&mut` here", + "if there is only one mutable reborrow, remove the `&mut`", "", - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } else { // This can occur with things like `(&mut self).foo()`. diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 85b8ef79c0504..387399668111e 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -2,13 +2,18 @@ //! a literal `true` or `false` based on whether the given cfg matches the //! current compilation environment. -use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; -use rustc_errors::PResult; +use rustc_ast::{AttrStyle, CRATE_NODE_ID, token}; +use rustc_attr_parsing as attr; +use rustc_attr_parsing::parser::MetaItemOrLitParser; +use rustc_attr_parsing::{ + AttributeParser, CFG_TEMPLATE, ParsedDescription, ShouldEmit, parse_cfg_entry, +}; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; +use rustc_hir::AttrPath; +use rustc_hir::attrs::CfgEntry; use rustc_parse::exp; -use rustc_span::Span; -use {rustc_ast as ast, rustc_attr_parsing as attr}; +use rustc_span::{ErrorGuaranteed, Ident, Span}; use crate::errors; @@ -21,38 +26,49 @@ pub(crate) fn expand_cfg( ExpandResult::Ready(match parse_cfg(cx, sp, tts) { Ok(cfg) => { - let matches_cfg = attr::cfg_matches( + let matches_cfg = attr::eval_config_entry( + cx.sess, &cfg, - &cx.sess, cx.current_expansion.lint_node_id, Some(cx.ecfg.features), - ); + ShouldEmit::ErrorsAndLints, + ) + .as_bool(); + MacEager::expr(cx.expr_bool(sp, matches_cfg)) } - Err(err) => { - let guar = err.emit(); - DummyResult::any(sp, guar) - } + Err(guar) => DummyResult::any(sp, guar), }) } -fn parse_cfg<'a>( - cx: &ExtCtxt<'a>, - span: Span, - tts: TokenStream, -) -> PResult<'a, ast::MetaItemInner> { - let mut p = cx.new_parser_from_tts(tts); - - if p.token == token::Eof { - return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span })); +fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result { + let mut parser = cx.new_parser_from_tts(tts); + if parser.token == token::Eof { + return Err(cx.dcx().emit_err(errors::RequiresCfgPattern { span })); } - let cfg = p.parse_meta_item_inner()?; + let meta = MetaItemOrLitParser::parse_single(&mut parser, ShouldEmit::ErrorsAndLints) + .map_err(|diag| diag.emit())?; + let cfg = AttributeParser::parse_single_args( + cx.sess, + span, + span, + AttrStyle::Inner, + AttrPath { segments: vec![Ident::from_str("cfg")].into_boxed_slice(), span }, + ParsedDescription::Macro, + span, + CRATE_NODE_ID, + Some(cx.ecfg.features), + ShouldEmit::ErrorsAndLints, + &meta, + parse_cfg_entry, + &CFG_TEMPLATE, + )?; - let _ = p.eat(exp!(Comma)); + let _ = parser.eat(exp!(Comma)); - if !p.eat(exp!(Eof)) { - return Err(cx.dcx().create_err(errors::OneCfgPattern { span })); + if !parser.eat(exp!(Eof)) { + return Err(cx.dcx().emit_err(errors::OneCfgPattern { span })); } Ok(cfg) diff --git a/compiler/rustc_error_codes/src/error_codes/E0536.md b/compiler/rustc_error_codes/src/error_codes/E0536.md index f00d177394489..c1f43fa741cfa 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0536.md +++ b/compiler/rustc_error_codes/src/error_codes/E0536.md @@ -1,18 +1,22 @@ The `not` cfg-predicate was malformed. -Erroneous code example: +Erroneous code example (using `cargo doc`): -```compile_fail,E0536 +```ignore, E0536 (only triggers on cargo doc) +#![feature(doc_cfg)] +#[doc(cfg(not()))] pub fn main() { - if cfg!(not()) { } + } ``` The `not` predicate expects one cfg-pattern. Example: ``` +#![feature(doc_cfg)] +#[doc(cfg(not(target_os = "linux")))] // ok! pub fn main() { - if cfg!(not(target_os = "linux")) { } // ok! + } ``` diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 25b6d992ab366..d98d6e563645c 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2155,6 +2155,7 @@ impl HumanEmitter { let line_start = sm.lookup_char_pos(parts[0].original_span.lo()).line; let mut lines = complete.lines(); + let lines_len = lines.clone().count(); if lines.clone().next().is_none() { // Account for a suggestion to completely remove a line(s) with whitespace (#94192). let line_end = sm.lookup_char_pos(parts[0].original_span.hi()).line; @@ -2195,6 +2196,7 @@ impl HumanEmitter { if highlight_parts.len() == 1 && line.trim().starts_with("#[") && line.trim().ends_with(']') + && lines_len == 1 { is_item_attribute = true; } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 41fcfbdbfd4bc..620002915fa8d 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use rustc_abi::ExternAbi; -use rustc_ast::Label; +use rustc_ast::{AssignOpKind, Label}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic, @@ -14,9 +14,10 @@ use rustc_hir::ExprKind; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; +use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span, Symbol}; -use crate::fluent_generated as fluent; +use crate::{FnCtxt, fluent_generated as fluent}; #[derive(Diagnostic)] #[diag(hir_typeck_base_expression_double_dot, code = E0797)] @@ -1144,6 +1145,42 @@ impl Diagnostic<'_, G> for NakedFunctionsAsmBlock { } } +pub(crate) fn maybe_emit_plus_equals_diagnostic<'a>( + fnctxt: &FnCtxt<'a, '_>, + assign_op: Spanned, + lhs_expr: &hir::Expr<'_>, +) -> Result<(), Diag<'a>> { + if assign_op.node == hir::AssignOpKind::AddAssign + && let hir::ExprKind::Binary(bin_op, left, right) = &lhs_expr.kind + && bin_op.node == hir::BinOpKind::And + && crate::op::contains_let_in_chain(left) + && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &right.kind + && matches!(path.res, hir::def::Res::Local(_)) + { + let mut err = fnctxt.dcx().struct_span_err( + assign_op.span, + "binary assignment operation `+=` cannot be used in a let chain", + ); + + err.span_label( + lhs_expr.span, + "you are add-assigning the right-hand side expression to the result of this let-chain", + ); + + err.span_label(assign_op.span, "cannot use `+=` in a let chain"); + + err.span_suggestion( + assign_op.span, + "you might have meant to compare with `==` instead of assigning with `+=`", + "==", + Applicability::MaybeIncorrect, + ); + + return Err(err); + } + Ok(()) +} + #[derive(Diagnostic)] #[diag(hir_typeck_naked_functions_must_naked_asm, code = E0787)] pub(crate) struct NakedFunctionsMustNakedAsm { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index e720958746f7a..78b16ffee81cf 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -48,6 +48,7 @@ use crate::errors::{ NoFieldOnVariant, ReturnLikeStatementKind, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive, TypeMismatchFruTypo, YieldExprOutsideOfCoroutine, }; +use crate::op::contains_let_in_chain; use crate::{ BreakableCtxt, CoroutineTypes, Diverges, FnCtxt, GatherLocalsVisitor, Needs, TupleArgumentsFlag, cast, fatally_break_rust, report_unexpected_variant_res, type_error_struct, @@ -1277,6 +1278,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } + // Skip suggestion if LHS contains a let-chain at this would likely be spurious + // cc: https://github.com/rust-lang/rust/issues/147664 + if contains_let_in_chain(lhs) { + return; + } + let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment"); err.code(code); err.span_label(lhs.span, "cannot assign to this expression"); diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index d18aed00a6f6d..a175b3557c47a 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -20,8 +20,8 @@ use {rustc_ast as ast, rustc_hir as hir}; use super::FnCtxt; use super::method::MethodCallee; -use crate::Expectation; use crate::method::TreatNotYetDefinedOpaques; +use crate::{Expectation, errors}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks a `a = b` @@ -308,23 +308,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut path = None; let lhs_ty_str = self.tcx.short_string(lhs_ty, &mut path); let rhs_ty_str = self.tcx.short_string(rhs_ty, &mut path); + let (mut err, output_def_id) = match op { + // Try and detect when `+=` was incorrectly + // used instead of `==` in a let-chain Op::AssignOp(assign_op) => { - let s = assign_op.node.as_str(); - let mut err = struct_span_code_err!( - self.dcx(), - expr.span, - E0368, - "binary assignment operation `{}` cannot be applied to type `{}`", - s, - lhs_ty_str, - ); - err.span_label( - lhs_expr.span, - format!("cannot use `{}` on type `{}`", s, lhs_ty_str), - ); - self.note_unmet_impls_on_type(&mut err, &errors, false); - (err, None) + if let Err(e) = + errors::maybe_emit_plus_equals_diagnostic(&self, assign_op, lhs_expr) + { + (e, None) + } else { + let s = assign_op.node.as_str(); + let mut err = struct_span_code_err!( + self.dcx(), + expr.span, + E0368, + "binary assignment operation `{}` cannot be applied to type `{}`", + s, + lhs_ty_str, + ); + err.span_label( + lhs_expr.span, + format!("cannot use `{}` on type `{}`", s, lhs_ty_str), + ); + self.note_unmet_impls_on_type(&mut err, &errors, false); + (err, None) + } } Op::BinOp(bin_op) => { let message = match bin_op.node { @@ -1084,6 +1093,17 @@ fn lang_item_for_unop(tcx: TyCtxt<'_>, op: hir::UnOp) -> (Symbol, Option) -> bool { + match &expr.kind { + hir::ExprKind::Let(..) => true, + hir::ExprKind::Binary(Spanned { node: hir::BinOpKind::And, .. }, left, right) => { + contains_let_in_chain(left) || contains_let_in_chain(right) + } + _ => false, + } +} + // Binary operator categories. These categories summarize the behavior // with respect to the builtin operations supported. #[derive(Clone, Copy)] diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index d462ff589f0da..dd06c157afc7b 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -175,6 +175,7 @@ resolve_generic_params_from_outer_item = } from outer item .refer_to_type_directly = refer to the type directly here instead .suggestion = try introducing a local generic parameter here + .note = nested items are independent from their parent item for everything except for privacy and name resolution resolve_generic_params_from_outer_item_const = a `const` is a separate item from the item that contains it diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 3020ecb6e7113..2f4a18f9cfa6b 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -558,6 +558,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { has_generic_params, def_kind, inner_item, + current_self_ty, } => { use errs::GenericParamsFromOuterItemLabel as Label; let static_or_const = match def_kind { @@ -595,7 +596,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { sm, self.def_span(def_id), ))); - err.refer_to_type_directly = Some(span); + err.refer_to_type_directly = + current_self_ty.map(|snippet| errs::UseTypeDirectly { span, snippet }); return self.dcx().create_err(err); } Res::Def(DefKind::TyParam, def_id) => { diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 5c5938a3260ed..0bb9909f7cbc4 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -11,14 +11,15 @@ use crate::{Res, fluent_generated as fluent}; #[derive(Diagnostic)] #[diag(resolve_generic_params_from_outer_item, code = E0401)] +#[note] pub(crate) struct GenericParamsFromOuterItem { #[primary_span] #[label] pub(crate) span: Span, #[subdiagnostic] pub(crate) label: Option, - #[label(resolve_refer_to_type_directly)] - pub(crate) refer_to_type_directly: Option, + #[subdiagnostic] + pub(crate) refer_to_type_directly: Option, #[subdiagnostic] pub(crate) sugg: Option, #[subdiagnostic] @@ -68,6 +69,18 @@ pub(crate) struct GenericParamsFromOuterItemSugg { pub(crate) span: Span, pub(crate) snippet: String, } +#[derive(Subdiagnostic)] +#[suggestion( + resolve_refer_to_type_directly, + code = "{snippet}", + applicability = "maybe-incorrect", + style = "verbose" +)] +pub(crate) struct UseTypeDirectly { + #[primary_span] + pub(crate) span: Span, + pub(crate) snippet: String, +} #[derive(Diagnostic)] #[diag(resolve_name_is_already_used_as_generic_parameter, code = E0403)] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 278c0fe35b7d8..f3f0a74d03bc0 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -326,7 +326,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { i, rib_ident, *res, - finalize.map(|finalize| finalize.path_span), + finalize.map(|_| general_span), *original_rib_ident_def, ribs, diag_metadata, @@ -1415,6 +1415,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { has_generic_params, def_kind, inner_item: item, + current_self_ty: diag_metadata + .and_then(|m| m.current_self_type.as_ref()) + .and_then(|ty| { + self.tcx.sess.source_map().span_to_snippet(ty.span).ok() + }), }, ); } @@ -1503,6 +1508,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { has_generic_params, def_kind, inner_item: item, + current_self_ty: diag_metadata + .and_then(|m| m.current_self_type.as_ref()) + .and_then(|ty| { + self.tcx.sess.source_map().span_to_snippet(ty.span).ok() + }), }, ); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0b41a7952797c..41c2e908d084d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -675,7 +675,7 @@ pub(crate) struct DiagMetadata<'ast> { current_trait_assoc_items: Option<&'ast [Box]>, /// The current self type if inside an impl (used for better errors). - current_self_type: Option, + pub(crate) current_self_type: Option, /// The current self item if inside an ADT (used for better errors). current_self_item: Option, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6b671df433b3d..c7f65ff03f823 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -246,6 +246,7 @@ enum ResolutionError<'ra> { has_generic_params: HasGenericParams, def_kind: DefKind, inner_item: Option<(Span, ast::ItemKind)>, + current_self_ty: Option, }, /// Error E0403: the name is already used for a type or const parameter in this generic /// parameter list. diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index d97ee95652530..b5716b51a91c4 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -228,7 +228,7 @@ fn compute_symbol_name<'tcx>( // However, we don't have the wasm import module map there yet. tcx.is_foreign_item(def_id) && tcx.sess.target.is_like_wasm - && tcx.wasm_import_module_map(LOCAL_CRATE).contains_key(&def_id.into()) + && tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id.into()) }; if !wasm_import_module_exception_force_mangling { diff --git a/src/tools/clippy/tests/ui/new_without_default.stderr b/src/tools/clippy/tests/ui/new_without_default.stderr index 1e0d5e2131994..0593dbb00fb6b 100644 --- a/src/tools/clippy/tests/ui/new_without_default.stderr +++ b/src/tools/clippy/tests/ui/new_without_default.stderr @@ -191,7 +191,6 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } -LL | impl NewWithCfg { | error: you should consider adding a `Default` implementation for `NewWith2Cfgs` @@ -212,7 +211,6 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } -LL | impl NewWith2Cfgs { | error: you should consider adding a `Default` implementation for `NewWithExtraneous` @@ -250,7 +248,6 @@ LL + fn default() -> Self { LL + Self::new() LL + } LL + } -LL | impl NewWithCfgAndExtraneous { | error: aborting due to 13 previous errors diff --git a/tests/ui/associated-item/associated-item-duplicate-bounds.stderr b/tests/ui/associated-item/associated-item-duplicate-bounds.stderr index 8898880586c92..9f8faf951940f 100644 --- a/tests/ui/associated-item/associated-item-duplicate-bounds.stderr +++ b/tests/ui/associated-item/associated-item-duplicate-bounds.stderr @@ -2,7 +2,7 @@ error: generic parameters may not be used in const operations --> $DIR/associated-item-duplicate-bounds.rs:7:18 | LL | links: [u32; A::LINKS], // Shouldn't suggest bounds already there. - | ^^^^^^^^ cannot perform const operation using `A` + | ^ cannot perform const operation using `A` | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions diff --git a/tests/ui/borrowck/mut-borrow-of-mut-ref.rs b/tests/ui/borrowck/mut-borrow-of-mut-ref.rs index 477a2aa48d5dc..33954592bf651 100644 --- a/tests/ui/borrowck/mut-borrow-of-mut-ref.rs +++ b/tests/ui/borrowck/mut-borrow-of-mut-ref.rs @@ -2,22 +2,24 @@ #![crate_type = "rlib"] pub fn f(b: &mut i32) { - //~^ ERROR cannot borrow - //~| NOTE not mutable - //~| NOTE the binding is already a mutable borrow + //~^ ERROR: cannot borrow + //~| NOTE: not mutable + //~| NOTE: the binding is already a mutable borrow + //~| HELP: consider making the binding mutable if you need to reborrow multiple times h(&mut b); - //~^ NOTE cannot borrow as mutable - //~| HELP try removing `&mut` here + //~^ NOTE: cannot borrow as mutable + //~| HELP: if there is only one mutable reborrow, remove the `&mut` g(&mut &mut b); - //~^ NOTE cannot borrow as mutable - //~| HELP try removing `&mut` here + //~^ NOTE: cannot borrow as mutable + //~| HELP: if there is only one mutable reborrow, remove the `&mut` } -pub fn g(b: &mut i32) { //~ NOTE the binding is already a mutable borrow +pub fn g(b: &mut i32) { //~ NOTE: the binding is already a mutable borrow + //~^ HELP: consider making the binding mutable if you need to reborrow multiple times h(&mut &mut b); - //~^ ERROR cannot borrow - //~| NOTE cannot borrow as mutable - //~| HELP try removing `&mut` here + //~^ ERROR: cannot borrow + //~| NOTE: cannot borrow as mutable + //~| HELP: if there is only one mutable reborrow, remove the `&mut` } pub fn h(_: &mut i32) {} diff --git a/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr b/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr index f448e009b0e1d..4c4a5e7183935 100644 --- a/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr +++ b/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr @@ -15,36 +15,44 @@ note: the binding is already a mutable borrow | LL | pub fn f(b: &mut i32) { | ^^^^^^^^ -help: try removing `&mut` here +help: consider making the binding mutable if you need to reborrow multiple times + | +LL | pub fn f(mut b: &mut i32) { + | +++ +help: if there is only one mutable reborrow, remove the `&mut` | LL - h(&mut b); LL + h(b); | -help: try removing `&mut` here +help: if there is only one mutable reborrow, remove the `&mut` | LL - g(&mut &mut b); LL + g(&mut b); | error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:17:12 + --> $DIR/mut-borrow-of-mut-ref.rs:19:12 | LL | h(&mut &mut b); | ^^^^^^ cannot borrow as mutable | note: the binding is already a mutable borrow - --> $DIR/mut-borrow-of-mut-ref.rs:16:13 + --> $DIR/mut-borrow-of-mut-ref.rs:17:13 | LL | pub fn g(b: &mut i32) { | ^^^^^^^^ -help: try removing `&mut` here +help: consider making the binding mutable if you need to reborrow multiple times + | +LL | pub fn g(mut b: &mut i32) { + | +++ +help: if there is only one mutable reborrow, remove the `&mut` | LL - h(&mut &mut b); LL + h(&mut b); | error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:34:5 + --> $DIR/mut-borrow-of-mut-ref.rs:36:5 | LL | f.bar(); | ^ cannot borrow as mutable diff --git a/tests/ui/const-generics/argument_order.rs b/tests/ui/const-generics/argument_order.rs index 196d9b8a1e210..f8980c9b54d75 100644 --- a/tests/ui/const-generics/argument_order.rs +++ b/tests/ui/const-generics/argument_order.rs @@ -1,15 +1,17 @@ -struct Bad { +//@ reference: items.generics.syntax.decl-order + +struct Good { arr: [u8; { N }], another: T, } -struct AlsoBad { +struct Bad { //~^ ERROR lifetime parameters must be declared prior a: &'a T, b: &'b U, } fn main() { - let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; + let _: Bad<7, 'static, u32, 'static, 17, u16>; //~^ ERROR lifetime provided when a type was expected } diff --git a/tests/ui/const-generics/argument_order.stderr b/tests/ui/const-generics/argument_order.stderr index 99122c6f5e362..ef6d168d70429 100644 --- a/tests/ui/const-generics/argument_order.stderr +++ b/tests/ui/const-generics/argument_order.stderr @@ -1,14 +1,14 @@ error: lifetime parameters must be declared prior to type and const parameters - --> $DIR/argument_order.rs:6:32 + --> $DIR/argument_order.rs:8:28 | -LL | struct AlsoBad { - | -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, const N: usize, T, const M: usize, U>` +LL | struct Bad { + | -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, const N: usize, T, const M: usize, U>` error[E0747]: lifetime provided when a type was expected - --> $DIR/argument_order.rs:13:23 + --> $DIR/argument_order.rs:15:19 | -LL | let _: AlsoBad<7, 'static, u32, 'static, 17, u16>; - | ^^^^^^^ +LL | let _: Bad<7, 'static, u32, 'static, 17, u16>; + | ^^^^^^^ | = note: lifetime arguments must be provided before type arguments = help: reorder the arguments: lifetimes, then type and consts: `<'a, 'b, N, T, M, U>` diff --git a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr index 3c25dff41aa22..7aab983b6495a 100644 --- a/tests/ui/const-generics/early/const-param-from-outer-fn.stderr +++ b/tests/ui/const-generics/early/const-param-from-outer-fn.stderr @@ -8,6 +8,7 @@ LL | fn bar() -> u32 { LL | X | ^ use of generic parameter from outer item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | fn bar() -> u32 { diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr index edd1a584eab26..e26d12ee447d0 100644 --- a/tests/ui/delegation/target-expr.stderr +++ b/tests/ui/delegation/target-expr.stderr @@ -7,7 +7,9 @@ LL | reuse Trait::static_method { | ------------- generic parameter used in this inner delegated function LL | LL | let _ = T::Default(); - | ^^^^^^^^^^ use of generic parameter from outer item + | ^ use of generic parameter from outer item + | + = note: nested items are independent from their parent item for everything except for privacy and name resolution error[E0434]: can't capture dynamic environment in a fn item --> $DIR/target-expr.rs:26:17 diff --git a/tests/ui/did_you_mean/issue-31424.rs b/tests/ui/did_you_mean/issue-31424.rs index 2821d5b9d8b31..3b3820bfc4af3 100644 --- a/tests/ui/did_you_mean/issue-31424.rs +++ b/tests/ui/did_you_mean/issue-31424.rs @@ -4,17 +4,18 @@ struct Struct; impl Struct { fn foo(&mut self) { - (&mut self).bar(); //~ ERROR cannot borrow - //~^ HELP try removing `&mut` here + (&mut self).bar(); //~ ERROR: cannot borrow + //~^ HELP: try removing `&mut` here } // In this case we could keep the suggestion, but to distinguish the // two cases is pretty hard. It's an obscure case anyway. fn bar(self: &mut Self) { - //~^ WARN function cannot return without recursing - //~^^ HELP a `loop` may express intention better if this is on purpose + //~^ WARN: function cannot return without recursing + //~| HELP: a `loop` may express intention better if this is on purpose + //~| HELP: consider making the binding mutable if you need to reborrow multiple times (&mut self).bar(); //~ ERROR cannot borrow - //~^ HELP try removing `&mut` here + //~^ HELP: try removing `&mut` here } } diff --git a/tests/ui/did_you_mean/issue-31424.stderr b/tests/ui/did_you_mean/issue-31424.stderr index 8fe38bf697287..5752397098cf6 100644 --- a/tests/ui/did_you_mean/issue-31424.stderr +++ b/tests/ui/did_you_mean/issue-31424.stderr @@ -28,7 +28,7 @@ LL | (&mut self).bar(); = note: `#[warn(unconditional_recursion)]` on by default error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable - --> $DIR/issue-31424.rs:16:9 + --> $DIR/issue-31424.rs:17:9 | LL | (&mut self).bar(); | ^^^^^^^^^^^ cannot borrow as mutable @@ -39,10 +39,14 @@ note: the binding is already a mutable borrow LL | fn bar(self: &mut Self) { | ^^^^^^^^^ help: try removing `&mut` here - --> $DIR/issue-31424.rs:16:9 + --> $DIR/issue-31424.rs:17:9 | LL | (&mut self).bar(); | ^^^^^^^^^^^ +help: consider making the binding mutable if you need to reborrow multiple times + | +LL | fn bar(mut self: &mut Self) { + | +++ error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/did_you_mean/issue-34126.rs b/tests/ui/did_you_mean/issue-34126.rs index 53516f4f24713..82ffadbf7d3f7 100644 --- a/tests/ui/did_you_mean/issue-34126.rs +++ b/tests/ui/did_you_mean/issue-34126.rs @@ -3,9 +3,9 @@ struct Z { } impl Z { fn run(&self, z: &mut Z) { } fn start(&mut self) { - self.run(&mut self); //~ ERROR cannot borrow - //~| ERROR cannot borrow - //~| HELP try removing `&mut` here + self.run(&mut self); //~ ERROR: cannot borrow + //~| ERROR: cannot borrow + //~| HELP: if there is only one mutable reborrow, remove the `&mut` } } diff --git a/tests/ui/did_you_mean/issue-34126.stderr b/tests/ui/did_you_mean/issue-34126.stderr index 9f79207062872..ec02dfefaca18 100644 --- a/tests/ui/did_you_mean/issue-34126.stderr +++ b/tests/ui/did_you_mean/issue-34126.stderr @@ -9,7 +9,7 @@ note: the binding is already a mutable borrow | LL | fn start(&mut self) { | ^^^^^^^^^ -help: try removing `&mut` here +help: if there is only one mutable reborrow, remove the `&mut` | LL - self.run(&mut self); LL + self.run(self); diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr index 8daaf09df1592..abd80d636c679 100644 --- a/tests/ui/error-codes/E0401.stderr +++ b/tests/ui/error-codes/E0401.stderr @@ -8,6 +8,7 @@ LL | fn bfnr, W: Fn()>(y: T) { | | | generic parameter used in this inner function | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | fn bfnr, W: Fn()>(y: T) { @@ -25,6 +26,7 @@ LL | fn baz Iterator for A { | ---- `Self` type implicitly declared here, by this `impl` ... LL | fn helper(sel: &Self) -> u8 { - | ------ ^^^^ - | | | - | | use of `Self` from outer item - | | refer to the type directly here instead + | ------ ^^^^ use of `Self` from outer item + | | | `Self` used in this inner function + | + = note: nested items are independent from their parent item for everything except for privacy and name resolution +help: refer to the type directly here instead + | +LL - fn helper(sel: &Self) -> u8 { +LL + fn helper(sel: &A) -> u8 { + | error: aborting due to 3 previous errors diff --git a/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr index fb2d2f247b65b..53408d05a1c18 100644 --- a/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr +++ b/tests/ui/generics/enum-definition-with-outer-generic-parameter-5997.stderr @@ -8,6 +8,7 @@ LL | enum E { V(Z) } | | | generic parameter used in this inner enum | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | enum E { V(Z) } diff --git a/tests/ui/generics/generic-params-nested-fn-scope-error.stderr b/tests/ui/generics/generic-params-nested-fn-scope-error.stderr index f809740ed381f..436f9c9bada19 100644 --- a/tests/ui/generics/generic-params-nested-fn-scope-error.stderr +++ b/tests/ui/generics/generic-params-nested-fn-scope-error.stderr @@ -8,6 +8,7 @@ LL | fn bar(w: [U]) -> U { | | | generic parameter used in this inner function | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | fn bar(w: [U]) -> U { @@ -23,6 +24,7 @@ LL | fn bar(w: [U]) -> U { | | | generic parameter used in this inner function | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | fn bar(w: [U]) -> U { diff --git a/tests/ui/generics/invalid-type-param-default.stderr b/tests/ui/generics/invalid-type-param-default.stderr index 3bec7542ad003..bbae5ba1b1e1e 100644 --- a/tests/ui/generics/invalid-type-param-default.stderr +++ b/tests/ui/generics/invalid-type-param-default.stderr @@ -2,7 +2,7 @@ error[E0128]: generic parameter defaults cannot reference parameters before they --> $DIR/invalid-type-param-default.rs:12:12 | LL | fn mdn(_: T) {} - | ^^^^^^^ cannot reference `T` before it is declared + | ^ cannot reference `T` before it is declared error: defaults for generic parameters are not allowed here --> $DIR/invalid-type-param-default.rs:7:8 diff --git a/tests/ui/generics/issue-98432.stderr b/tests/ui/generics/issue-98432.stderr index a1efee78cb7df..e261416ca2229 100644 --- a/tests/ui/generics/issue-98432.stderr +++ b/tests/ui/generics/issue-98432.stderr @@ -9,6 +9,7 @@ LL | struct _Obligation where T:; | | | generic parameter used in this inner struct | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | struct _Obligation where T:; diff --git a/tests/ui/macros/cfg.rs b/tests/ui/macros/cfg.rs index 50998572274ec..d992ec82e2fd2 100644 --- a/tests/ui/macros/cfg.rs +++ b/tests/ui/macros/cfg.rs @@ -1,6 +1,6 @@ fn main() { cfg!(); //~ ERROR macro requires a cfg-pattern - cfg!(123); //~ ERROR literal in `cfg` predicate value must be a boolean - cfg!(foo = 123); //~ ERROR literal in `cfg` predicate value must be a string + cfg!(123); //~ ERROR malformed `cfg` macro input + cfg!(foo = 123); //~ ERROR malformed `cfg` macro input cfg!(foo, bar); //~ ERROR expected 1 cfg-pattern } diff --git a/tests/ui/macros/cfg.stderr b/tests/ui/macros/cfg.stderr index ad3f9b188ddb9..a153ed9921b33 100644 --- a/tests/ui/macros/cfg.stderr +++ b/tests/ui/macros/cfg.stderr @@ -4,17 +4,27 @@ error: macro requires a cfg-pattern as an argument LL | cfg!(); | ^^^^^^ cfg-pattern required -error[E0565]: literal in `cfg` predicate value must be a boolean - --> $DIR/cfg.rs:3:10 +error[E0539]: malformed `cfg` macro input + --> $DIR/cfg.rs:3:5 | LL | cfg!(123); - | ^^^ + | ^^^^^---^ + | | | + | | expected a valid identifier here + | help: must be of the form: `cfg(predicate)` + | + = note: for more information, visit -error[E0565]: literal in `cfg` predicate value must be a string - --> $DIR/cfg.rs:4:16 +error[E0539]: malformed `cfg` macro input + --> $DIR/cfg.rs:4:5 | LL | cfg!(foo = 123); - | ^^^ + | ^^^^^^^^^^^---^ + | | | + | | expected a string literal here + | help: must be of the form: `cfg(predicate)` + | + = note: for more information, visit error: expected 1 cfg-pattern --> $DIR/cfg.rs:5:5 @@ -24,4 +34,4 @@ LL | cfg!(foo, bar); error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0565`. +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/nll/issue-51191.rs b/tests/ui/nll/issue-51191.rs index 836587d93b84b..c0b0c5eda139f 100644 --- a/tests/ui/nll/issue-51191.rs +++ b/tests/ui/nll/issue-51191.rs @@ -2,16 +2,17 @@ struct Struct; impl Struct { fn bar(self: &mut Self) { - //~^ WARN function cannot return without recursing - //~^^ HELP a `loop` may express intention better if this is on purpose + //~^ WARN: function cannot return without recursing + //~| HELP: a `loop` may express intention better if this is on purpose + //~| HELP: consider making the binding mutable if you need to reborrow multiple times (&mut self).bar(); - //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596] - //~^^ HELP try removing `&mut` here + //~^ ERROR: cannot borrow `self` as mutable, as it is not declared as mutable [E0596] + //~| HELP: try removing `&mut` here } fn imm(self) { //~ HELP consider changing this to be mutable (&mut self).bar(); - //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596] + //~^ ERROR: cannot borrow `self` as mutable, as it is not declared as mutable [E0596] } fn mtbl(mut self) { @@ -20,14 +21,14 @@ impl Struct { fn immref(&self) { (&mut self).bar(); - //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596] - //~^^ ERROR cannot borrow data in a `&` reference as mutable [E0596] + //~^ ERROR: cannot borrow `self` as mutable, as it is not declared as mutable [E0596] + //~| ERROR: cannot borrow data in a `&` reference as mutable [E0596] } fn mtblref(&mut self) { (&mut self).bar(); - //~^ ERROR cannot borrow `self` as mutable, as it is not declared as mutable [E0596] - //~^^ HELP try removing `&mut` here + //~^ ERROR: cannot borrow `self` as mutable, as it is not declared as mutable [E0596] + //~| HELP: try removing `&mut` here } } diff --git a/tests/ui/nll/issue-51191.stderr b/tests/ui/nll/issue-51191.stderr index c14056c3a834b..73f8aab9d1417 100644 --- a/tests/ui/nll/issue-51191.stderr +++ b/tests/ui/nll/issue-51191.stderr @@ -11,7 +11,7 @@ LL | (&mut self).bar(); = note: `#[warn(unconditional_recursion)]` on by default error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable - --> $DIR/issue-51191.rs:7:9 + --> $DIR/issue-51191.rs:8:9 | LL | (&mut self).bar(); | ^^^^^^^^^^^ cannot borrow as mutable @@ -22,13 +22,17 @@ note: the binding is already a mutable borrow LL | fn bar(self: &mut Self) { | ^^^^^^^^^ help: try removing `&mut` here - --> $DIR/issue-51191.rs:7:9 + --> $DIR/issue-51191.rs:8:9 | LL | (&mut self).bar(); | ^^^^^^^^^^^ +help: consider making the binding mutable if you need to reborrow multiple times + | +LL | fn bar(mut self: &mut Self) { + | +++ error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable - --> $DIR/issue-51191.rs:13:9 + --> $DIR/issue-51191.rs:14:9 | LL | (&mut self).bar(); | ^^^^^^^^^^^ cannot borrow as mutable @@ -39,30 +43,30 @@ LL | fn imm(mut self) { | +++ error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable - --> $DIR/issue-51191.rs:22:9 + --> $DIR/issue-51191.rs:23:9 | LL | (&mut self).bar(); | ^^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/issue-51191.rs:22:9 + --> $DIR/issue-51191.rs:23:9 | LL | (&mut self).bar(); | ^^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable - --> $DIR/issue-51191.rs:28:9 + --> $DIR/issue-51191.rs:29:9 | LL | (&mut self).bar(); | ^^^^^^^^^^^ cannot borrow as mutable | note: the binding is already a mutable borrow - --> $DIR/issue-51191.rs:27:16 + --> $DIR/issue-51191.rs:28:16 | LL | fn mtblref(&mut self) { | ^^^^^^^^^ help: try removing `&mut` here - --> $DIR/issue-51191.rs:28:9 + --> $DIR/issue-51191.rs:29:9 | LL | (&mut self).bar(); | ^^^^^^^^^^^ diff --git a/tests/ui/parser/let-chains-assign-add-incorrect.fixed b/tests/ui/parser/let-chains-assign-add-incorrect.fixed new file mode 100644 index 0000000000000..b1abce8bd2df5 --- /dev/null +++ b/tests/ui/parser/let-chains-assign-add-incorrect.fixed @@ -0,0 +1,36 @@ +//@ edition:2024 +//@ run-rustfix + +#![allow(irrefutable_let_patterns)] + +fn test_where_left_is_not_let() { + let y = 2; + if let _ = 1 && true && y == 2 {}; + //~^ ERROR expected expression, found `let` statement + //~| NOTE only supported directly in conditions of `if` and `while` expressions + //~| ERROR mismatched types + //~| NOTE expected `bool`, found integer + //~| NOTE you are add-assigning the right-hand side expression to the result of this let-chain + //~| NOTE expected because this is `bool` + //~| ERROR binary assignment operation `+=` cannot be used in a let chain + //~| NOTE cannot use `+=` in a let chain + //~| HELP you might have meant to compare with `==` instead of assigning with `+=` +} + +fn test_where_left_is_let() { + let y = 2; + if let _ = 1 && y == 2 {}; + //~^ ERROR expected expression, found `let` statement + //~| NOTE only supported directly in conditions of `if` and `while` expressions + //~| ERROR mismatched types + //~| NOTE expected `bool`, found integer + //~| NOTE you are add-assigning the right-hand side expression to the result of this let-chain + //~| ERROR binary assignment operation `+=` cannot be used in a let chain + //~| NOTE cannot use `+=` in a let chain + //~| HELP you might have meant to compare with `==` instead of assigning with `+=` +} + +fn main() { + test_where_left_is_let(); + test_where_left_is_not_let() +} diff --git a/tests/ui/parser/let-chains-assign-add-incorrect.rs b/tests/ui/parser/let-chains-assign-add-incorrect.rs new file mode 100644 index 0000000000000..3b2e5e93d91ac --- /dev/null +++ b/tests/ui/parser/let-chains-assign-add-incorrect.rs @@ -0,0 +1,36 @@ +//@ edition:2024 +//@ run-rustfix + +#![allow(irrefutable_let_patterns)] + +fn test_where_left_is_not_let() { + let y = 2; + if let _ = 1 && true && y += 2 {}; + //~^ ERROR expected expression, found `let` statement + //~| NOTE only supported directly in conditions of `if` and `while` expressions + //~| ERROR mismatched types + //~| NOTE expected `bool`, found integer + //~| NOTE you are add-assigning the right-hand side expression to the result of this let-chain + //~| NOTE expected because this is `bool` + //~| ERROR binary assignment operation `+=` cannot be used in a let chain + //~| NOTE cannot use `+=` in a let chain + //~| HELP you might have meant to compare with `==` instead of assigning with `+=` +} + +fn test_where_left_is_let() { + let y = 2; + if let _ = 1 && y += 2 {}; + //~^ ERROR expected expression, found `let` statement + //~| NOTE only supported directly in conditions of `if` and `while` expressions + //~| ERROR mismatched types + //~| NOTE expected `bool`, found integer + //~| NOTE you are add-assigning the right-hand side expression to the result of this let-chain + //~| ERROR binary assignment operation `+=` cannot be used in a let chain + //~| NOTE cannot use `+=` in a let chain + //~| HELP you might have meant to compare with `==` instead of assigning with `+=` +} + +fn main() { + test_where_left_is_let(); + test_where_left_is_not_let() +} diff --git a/tests/ui/parser/let-chains-assign-add-incorrect.stderr b/tests/ui/parser/let-chains-assign-add-incorrect.stderr new file mode 100644 index 0000000000000..dea8e6a1982b1 --- /dev/null +++ b/tests/ui/parser/let-chains-assign-add-incorrect.stderr @@ -0,0 +1,61 @@ +error: expected expression, found `let` statement + --> $DIR/let-chains-assign-add-incorrect.rs:8:8 + | +LL | if let _ = 1 && true && y += 2 {}; + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/let-chains-assign-add-incorrect.rs:22:8 + | +LL | if let _ = 1 && y += 2 {}; + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error[E0308]: mismatched types + --> $DIR/let-chains-assign-add-incorrect.rs:8:29 + | +LL | if let _ = 1 && true && y += 2 {}; + | ----------------- ^ expected `bool`, found integer + | | + | expected because this is `bool` + +error: binary assignment operation `+=` cannot be used in a let chain + --> $DIR/let-chains-assign-add-incorrect.rs:8:31 + | +LL | if let _ = 1 && true && y += 2 {}; + | ---------------------- ^^ cannot use `+=` in a let chain + | | + | you are add-assigning the right-hand side expression to the result of this let-chain + | +help: you might have meant to compare with `==` instead of assigning with `+=` + | +LL - if let _ = 1 && true && y += 2 {}; +LL + if let _ = 1 && true && y == 2 {}; + | + +error[E0308]: mismatched types + --> $DIR/let-chains-assign-add-incorrect.rs:22:21 + | +LL | if let _ = 1 && y += 2 {}; + | ^ expected `bool`, found integer + +error: binary assignment operation `+=` cannot be used in a let chain + --> $DIR/let-chains-assign-add-incorrect.rs:22:23 + | +LL | if let _ = 1 && y += 2 {}; + | -------------- ^^ cannot use `+=` in a let chain + | | + | you are add-assigning the right-hand side expression to the result of this let-chain + | +help: you might have meant to compare with `==` instead of assigning with `+=` + | +LL - if let _ = 1 && y += 2 {}; +LL + if let _ = 1 && y == 2 {}; + | + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/resolve/bad-type-env-capture.stderr b/tests/ui/resolve/bad-type-env-capture.stderr index c565997ca2a26..ebddd7014748a 100644 --- a/tests/ui/resolve/bad-type-env-capture.stderr +++ b/tests/ui/resolve/bad-type-env-capture.stderr @@ -8,6 +8,7 @@ LL | fn bar(b: T) { } | | | generic parameter used in this inner function | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | fn bar(b: T) { } diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr index bc67e9dce4e3b..8827d1bbb49d3 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr @@ -4,10 +4,11 @@ error[E0401]: can't use generic parameters from outer item LL | fn outer() { // outer function | - type parameter from outer item LL | const K: u32 = T::C; - | - ^^^^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item | | | generic parameter used in this inner constant item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item @@ -17,10 +18,11 @@ LL | impl Tr for T { // outer impl block | - type parameter from outer item LL | const C: u32 = { LL | const I: u32 = T::C; - | - ^^^^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item | | | generic parameter used in this inner constant item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item @@ -29,10 +31,11 @@ error[E0401]: can't use generic parameters from outer item LL | struct S(U32<{ // outer struct | - type parameter from outer item LL | const _: u32 = T::C; - | - ^^^^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item | | | generic parameter used in this inner constant item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr index 3959d117c7c9a..8ff9771b9ade6 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr @@ -4,10 +4,11 @@ error[E0401]: can't use generic parameters from outer item LL | fn outer() { // outer function | - type parameter from outer item LL | const K: u32 = T::C; - | - ^^^^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item | | | generic parameter used in this inner constant item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it help: try introducing a local generic parameter here | @@ -21,10 +22,11 @@ LL | impl Tr for T { // outer impl block | - type parameter from outer item LL | const C: u32 = { LL | const I: u32 = T::C; - | - ^^^^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item | | | generic parameter used in this inner constant item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it help: try introducing a local generic parameter here | @@ -37,10 +39,11 @@ error[E0401]: can't use generic parameters from outer item LL | struct S(U32<{ // outer struct | - type parameter from outer item LL | const _: u32 = T::C; - | - ^^^^ use of generic parameter from outer item + | - ^ use of generic parameter from outer item | | | generic parameter used in this inner constant item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it help: try introducing a local generic parameter here | diff --git a/tests/ui/resolve/issue-12796.stderr b/tests/ui/resolve/issue-12796.stderr index b5828c6f5fc86..af79508689a9d 100644 --- a/tests/ui/resolve/issue-12796.stderr +++ b/tests/ui/resolve/issue-12796.stderr @@ -7,6 +7,8 @@ LL | fn inner(_: &Self) { | | use of `Self` from outer item | | can't use `Self` here | `Self` used in this inner function + | + = note: nested items are independent from their parent item for everything except for privacy and name resolution error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-3021-c.stderr b/tests/ui/resolve/issue-3021-c.stderr index 8c554fd1b97dc..d521d4f4a73ae 100644 --- a/tests/ui/resolve/issue-3021-c.stderr +++ b/tests/ui/resolve/issue-3021-c.stderr @@ -9,6 +9,7 @@ LL | trait U { LL | fn g(&self, x: T) -> T; | ^ use of generic parameter from outer item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | trait U { @@ -25,6 +26,7 @@ LL | trait U { LL | fn g(&self, x: T) -> T; | ^ use of generic parameter from outer item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | trait U { diff --git a/tests/ui/resolve/issue-3214.stderr b/tests/ui/resolve/issue-3214.stderr index ab12676bdd805..573a8ba975c83 100644 --- a/tests/ui/resolve/issue-3214.stderr +++ b/tests/ui/resolve/issue-3214.stderr @@ -8,6 +8,7 @@ LL | struct Foo { LL | x: T, | ^ use of generic parameter from outer item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | struct Foo { diff --git a/tests/ui/resolve/issue-39559.stderr b/tests/ui/resolve/issue-39559.stderr index 0aab54fe59d5b..14c7a6a9f6abf 100644 --- a/tests/ui/resolve/issue-39559.stderr +++ b/tests/ui/resolve/issue-39559.stderr @@ -2,7 +2,7 @@ error: generic parameters may not be used in const operations --> $DIR/issue-39559.rs:14:18 | LL | entries: [T; D::dim()], - | ^^^^^^ cannot perform const operation using `D` + | ^ cannot perform const operation using `D` | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions diff --git a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr index 2d21ed0155a70..6ff8c82ce8ee5 100644 --- a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr +++ b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr @@ -10,6 +10,7 @@ LL | | LL | | } | |_____- generic parameter used in this inner extern block | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `static` is a separate item from the item that contains it error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr index b22bfb719bd50..d3c8095d048a2 100644 --- a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -10,6 +10,7 @@ LL | | LL | | } | |_____- generic parameter used in this inner extern block | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item @@ -22,6 +23,7 @@ LL | static a: *const T = Default::default(); | | | generic parameter used in this inner static item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item @@ -36,6 +38,7 @@ LL | | LL | | } | |_____- generic parameter used in this inner extern block | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item @@ -48,6 +51,7 @@ LL | static a: [u8; N] = [0; N]; | | | generic parameter used in this inner static item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item @@ -60,6 +64,7 @@ LL | static a: [u8; N] = [0; N]; | | | generic parameter used in this inner static item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `static` is a separate item from the item that contains it error: aborting due to 5 previous errors diff --git a/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr b/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr index 00aa645688e7f..69f41dbb910c9 100644 --- a/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr +++ b/tests/ui/resolve/resolve-type-param-in-item-in-trait.stderr @@ -9,6 +9,7 @@ LL | enum Foo { LL | Variance(A) | ^ use of generic parameter from outer item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | enum Foo { @@ -25,6 +26,7 @@ LL | struct Foo(A); | | | generic parameter used in this inner struct | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | struct Foo(A); @@ -41,6 +43,7 @@ LL | struct Foo { a: A } | | | generic parameter used in this inner struct | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | struct Foo { a: A } @@ -57,6 +60,7 @@ LL | fn foo(a: A) { } | | | generic parameter used in this inner function | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | fn foo(a: A) { } diff --git a/tests/ui/resolve/use-self-in-inner-fn.rs b/tests/ui/resolve/use-self-in-inner-fn.rs index ed64ee885271c..c9260ba769d6c 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.rs +++ b/tests/ui/resolve/use-self-in-inner-fn.rs @@ -7,9 +7,32 @@ impl A { //~^ ERROR can't use `Self` from outer item //~| NOTE use of `Self` from outer item //~| NOTE `Self` used in this inner function - //~| NOTE refer to the type directly here instead + //~| HELP refer to the type directly here instead + //~| NOTE nested items are independent from their } } } +enum MyEnum {} + +impl MyEnum { +//~^ NOTE `Self` type implicitly declared here, by this `impl` + fn do_something(result: impl FnOnce()) { + result(); + } + + fn do_something_extra() { + fn inner() { + //~^ NOTE `Self` used in this inner function + Self::do_something(move || {}); + //~^ ERROR can't use `Self` from outer item + //~| NOTE use of `Self` from outer item + //~| HELP refer to the type directly here instead + //~| NOTE nested items are independent from their + MyEnum::do_something(move || {}); + } + inner(); + } +} + fn main() {} diff --git a/tests/ui/resolve/use-self-in-inner-fn.stderr b/tests/ui/resolve/use-self-in-inner-fn.stderr index 645875f6e726d..78c609ba8cb13 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.stderr +++ b/tests/ui/resolve/use-self-in-inner-fn.stderr @@ -5,12 +5,36 @@ LL | impl A { | ---- `Self` type implicitly declared here, by this `impl` ... LL | fn peach(this: &Self) { - | ----- ^^^^ - | | | - | | use of `Self` from outer item - | | refer to the type directly here instead + | ----- ^^^^ use of `Self` from outer item + | | | `Self` used in this inner function + | + = note: nested items are independent from their parent item for everything except for privacy and name resolution +help: refer to the type directly here instead + | +LL - fn peach(this: &Self) { +LL + fn peach(this: &A) { + | + +error[E0401]: can't use `Self` from outer item + --> $DIR/use-self-in-inner-fn.rs:27:13 + | +LL | impl MyEnum { + | ---- `Self` type implicitly declared here, by this `impl` +... +LL | fn inner() { + | ----- `Self` used in this inner function +LL | +LL | Self::do_something(move || {}); + | ^^^^ use of `Self` from outer item + | + = note: nested items are independent from their parent item for everything except for privacy and name resolution +help: refer to the type directly here instead + | +LL - Self::do_something(move || {}); +LL + MyEnum::do_something(move || {}); + | -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/span/E0536.rs b/tests/ui/span/E0536.rs deleted file mode 100644 index ae07336335419..0000000000000 --- a/tests/ui/span/E0536.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub fn main() { - if cfg!(not()) { } //~ ERROR E0536 -} diff --git a/tests/ui/span/E0536.stderr b/tests/ui/span/E0536.stderr deleted file mode 100644 index 6c25f9140a1ab..0000000000000 --- a/tests/ui/span/E0536.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0536]: expected 1 cfg-pattern - --> $DIR/E0536.rs:2:13 - | -LL | if cfg!(not()) { } - | ^^^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0536`. diff --git a/tests/ui/span/E0805.rs b/tests/ui/span/E0805.rs new file mode 100644 index 0000000000000..097f5cd8e586e --- /dev/null +++ b/tests/ui/span/E0805.rs @@ -0,0 +1,3 @@ +pub fn main() { + if cfg!(not()) { } //~ ERROR E0805 +} diff --git a/tests/ui/span/E0805.stderr b/tests/ui/span/E0805.stderr new file mode 100644 index 0000000000000..58c0e31ce0840 --- /dev/null +++ b/tests/ui/span/E0805.stderr @@ -0,0 +1,14 @@ +error[E0805]: malformed `cfg` macro input + --> $DIR/E0805.rs:2:8 + | +LL | if cfg!(not()) { } + | ^^^^^^^^--^ + | | | + | | expected a single argument here + | help: must be of the form: `cfg(predicate)` + | + = note: for more information, visit + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0805`. diff --git a/tests/ui/statics/static-generic-param-soundness.stderr b/tests/ui/statics/static-generic-param-soundness.stderr index 72f65e2bac7cb..32c252246e3e6 100644 --- a/tests/ui/statics/static-generic-param-soundness.stderr +++ b/tests/ui/statics/static-generic-param-soundness.stderr @@ -8,6 +8,7 @@ LL | static a: Bar = Bar::What; | | | generic parameter used in this inner static item | + = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `static` is a separate item from the item that contains it error[E0392]: type parameter `T` is never used diff --git a/tests/ui/type/pattern_types/assoc_const.default.stderr b/tests/ui/type/pattern_types/assoc_const.default.stderr index 8cff0cee7b972..00d5ac6af26b4 100644 --- a/tests/ui/type/pattern_types/assoc_const.default.stderr +++ b/tests/ui/type/pattern_types/assoc_const.default.stderr @@ -20,7 +20,7 @@ error: generic parameters may not be used in const operations --> $DIR/assoc_const.rs:20:40 | LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} - | ^^^^^^^^ cannot perform const operation using `T` + | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions @@ -29,7 +29,7 @@ error: generic parameters may not be used in const operations --> $DIR/assoc_const.rs:20:51 | LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} - | ^^^^^^ cannot perform const operation using `T` + | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions diff --git a/tests/ui/type/type-arg-out-of-scope.stderr b/tests/ui/type/type-arg-out-of-scope.stderr index 3d8850ebccea5..56fecdb338102 100644 --- a/tests/ui/type/type-arg-out-of-scope.stderr +++ b/tests/ui/type/type-arg-out-of-scope.stderr @@ -8,6 +8,7 @@ LL | fn bar(f: Box T>) { } | | | generic parameter used in this inner function | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | fn bar(f: Box T>) { } @@ -23,6 +24,7 @@ LL | fn bar(f: Box T>) { } | | | generic parameter used in this inner function | + = note: nested items are independent from their parent item for everything except for privacy and name resolution help: try introducing a local generic parameter here | LL | fn bar(f: Box T>) { } diff --git a/tests/ui/wasm/auxiliary/link-name-in-foreign-crate.rs b/tests/ui/wasm/auxiliary/link-name-in-foreign-crate.rs new file mode 100644 index 0000000000000..69d508518597e --- /dev/null +++ b/tests/ui/wasm/auxiliary/link-name-in-foreign-crate.rs @@ -0,0 +1,7 @@ +#![no_std] + +#[link(wasm_import_module = "test")] +unsafe extern "C" { + #[link_name = "close"] + pub fn close(x: u32) -> u32; +} diff --git a/tests/ui/wasm/wasm-link-name-in-foreign-crate-respected.rs b/tests/ui/wasm/wasm-link-name-in-foreign-crate-respected.rs new file mode 100644 index 0000000000000..e2ceeb8ae13e2 --- /dev/null +++ b/tests/ui/wasm/wasm-link-name-in-foreign-crate-respected.rs @@ -0,0 +1,22 @@ +//@ only-wasm32 +//@ aux-build:link-name-in-foreign-crate.rs +//@ compile-flags: --crate-type cdylib +//@ build-pass +//@ no-prefer-dynamic + +extern crate link_name_in_foreign_crate; + +// This test that the definition of a function named `close`, which collides +// with the `close` function in libc in theory, is handled correctly in +// cross-crate situations. The `link_name_in_foreign_crate` dependency declares +// `close` from a non-`env` wasm import module and then this crate attempts to +// use the symbol. This should properly ensure that the wasm module name is +// tagged as `test` and the `close` symbol, to LLD, is mangled, to avoid +// colliding with the `close` symbol in libc itself. + +#[unsafe(no_mangle)] +pub extern "C" fn foo() { + unsafe { + link_name_in_foreign_crate::close(1); + } +}