diff options
Diffstat (limited to 'compiler/rustc_expand/src')
20 files changed, 398 insertions, 419 deletions
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c4d2a374f0c..8b5a22d1914 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -14,14 +14,11 @@ use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind use rustc_attr::{self as attr, Deprecation, Stability}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{self, Lrc}; -use rustc_errors::{ - Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic, - MultiSpan, PResult, -}; +use rustc_errors::{Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, PResult}; use rustc_feature::Features; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools}; -use rustc_parse::{self, parser, MACRO_ARGUMENTS}; +use rustc_parse::{parser, MACRO_ARGUMENTS}; use rustc_session::errors::report_lit_error; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; @@ -777,7 +774,7 @@ impl SyntaxExtension { attrs: &[ast::Attribute], ) -> SyntaxExtension { let allow_internal_unstable = - attr::allow_internal_unstable(sess, &attrs).collect::<Vec<Symbol>>(); + attr::allow_internal_unstable(sess, attrs).collect::<Vec<Symbol>>(); let allow_internal_unsafe = attr::contains_name(attrs, sym::allow_internal_unsafe); let local_inner_macros = attr::find_by_name(attrs, sym::macro_export) @@ -790,23 +787,23 @@ impl SyntaxExtension { .map(|attr| { // Override `helper_attrs` passed above if it's a built-in macro, // marking `proc_macro_derive` macros as built-in is not a realistic use case. - parse_macro_name_and_helper_attrs(sess.diagnostic(), attr, "built-in").map_or_else( + parse_macro_name_and_helper_attrs(sess.dcx(), attr, "built-in").map_or_else( || (Some(name), Vec::new()), |(name, helper_attrs)| (Some(name), helper_attrs), ) }) .unwrap_or_else(|| (None, helper_attrs)); - let stability = attr::find_stability(&sess, attrs, span); - let const_stability = attr::find_const_stability(&sess, attrs, span); - let body_stability = attr::find_body_stability(&sess, attrs); + let stability = attr::find_stability(sess, attrs, span); + let const_stability = attr::find_const_stability(sess, attrs, span); + let body_stability = attr::find_body_stability(sess, attrs); if let Some((_, sp)) = const_stability { - sess.emit_err(errors::MacroConstStability { + sess.dcx().emit_err(errors::MacroConstStability { span: sp, head_span: sess.source_map().guess_head_span(span), }); } if let Some((_, sp)) = body_stability { - sess.emit_err(errors::MacroBodyStability { + sess.dcx().emit_err(errors::MacroBodyStability { span: sp, head_span: sess.source_map().guess_head_span(span), }); @@ -818,7 +815,7 @@ impl SyntaxExtension { allow_internal_unstable: (!allow_internal_unstable.is_empty()) .then(|| allow_internal_unstable.into()), stability: stability.map(|(s, _)| s), - deprecation: attr::find_deprecation(&sess, features, attrs).map(|(d, _)| d), + deprecation: attr::find_deprecation(sess, features, attrs).map(|(d, _)| d), helper_attrs, edition, builtin_name, @@ -1058,6 +1055,10 @@ impl<'a> ExtCtxt<'a> { } } + pub fn dcx(&self) -> &'a DiagCtxt { + self.sess.dcx() + } + /// Returns a `Folder` for deeply expanding all macros in an AST node. pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> { expand::MacroExpander::new(self, false) @@ -1112,50 +1113,9 @@ impl<'a> ExtCtxt<'a> { self.current_expansion.id.expansion_cause() } - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_err<S: Into<MultiSpan>>( - &self, - sp: S, - msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - self.sess.parse_sess.span_diagnostic.struct_span_err(sp, msg) - } - - #[track_caller] - pub fn create_err( - &self, - err: impl IntoDiagnostic<'a>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - self.sess.create_err(err) - } - - #[track_caller] - pub fn emit_err(&self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed { - self.sess.emit_err(err) - } - - /// Emit `msg` attached to `sp`, without immediately stopping - /// compilation. - /// - /// Compilation will be stopped in the near future (at the end of - /// the macro expansion phase). - #[rustc_lint_diagnostics] - #[track_caller] - pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) { - self.sess.parse_sess.span_diagnostic.span_err(sp, msg); - } - #[rustc_lint_diagnostics] - #[track_caller] - pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) { - self.sess.parse_sess.span_diagnostic.span_warn(sp, msg); - } - pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<String>) -> ! { - self.sess.parse_sess.span_diagnostic.span_bug(sp, msg); - } pub fn trace_macros_diag(&mut self) { for (span, notes) in self.expansions.iter() { - let mut db = self.sess.parse_sess.create_note(errors::TraceMacro { span: *span }); + let mut db = self.dcx().create_note(errors::TraceMacro { span: *span }); for note in notes { db.note(note.clone()); } @@ -1164,9 +1124,6 @@ impl<'a> ExtCtxt<'a> { // Fixme: does this result in errors? self.expansions.clear(); } - pub fn bug(&self, msg: &'static str) -> ! { - self.sess.parse_sess.span_diagnostic.bug(msg); - } pub fn trace_macros(&self) -> bool { self.ecfg.trace_mac } @@ -1209,11 +1166,10 @@ pub fn resolve_path( .expect("attempting to resolve a file path in an external file"), FileName::DocTest(path, _) => path, other => { - return Err(errors::ResolveRelativePath { + return Err(parse_sess.dcx.create_err(errors::ResolveRelativePath { span, path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(), - } - .into_diagnostic(&parse_sess.span_diagnostic)); + })); } }; result.pop(); @@ -1235,7 +1191,7 @@ pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt<'_>, expr: P<ast::Expr>, err_msg: &'static str, -) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a, ErrorGuaranteed>, bool)>> { +) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a>, bool)>> { // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); @@ -1244,7 +1200,7 @@ pub fn expr_to_spanned_string<'a>( ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) { Ok(ast::LitKind::Str(s, style)) => return Ok((s, style, expr.span)), Ok(ast::LitKind::ByteStr(..)) => { - let mut err = cx.struct_span_err(expr.span, err_msg); + let mut err = cx.dcx().struct_span_err(expr.span, err_msg); let span = expr.span.shrink_to_lo(); err.span_suggestion( span.with_hi(span.lo() + BytePos(1)), @@ -1259,10 +1215,10 @@ pub fn expr_to_spanned_string<'a>( report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span); None } - _ => Some((cx.struct_span_err(expr.span, err_msg), false)), + _ => Some((cx.dcx().struct_span_err(expr.span, err_msg), false)), }, ast::ExprKind::Err => None, - _ => Some((cx.struct_span_err(expr.span, err_msg), false)), + _ => Some((cx.dcx().struct_span_err(expr.span, err_msg), false)), }) } @@ -1286,12 +1242,11 @@ pub fn expr_to_string( /// Non-fatally assert that `tts` is empty. Note that this function /// returns even when `tts` is non-empty, macros that *need* to stop -/// compilation should call -/// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be -/// done as rarely as possible). +/// compilation should call `cx.diagnostic().abort_if_errors()` +/// (this should be done as rarely as possible). pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) { if !tts.is_empty() { - cx.emit_err(errors::TakesNoArguments { span, name }); + cx.dcx().emit_err(errors::TakesNoArguments { span, name }); } } @@ -1319,14 +1274,14 @@ pub fn get_single_str_from_tts( ) -> Option<Symbol> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { - cx.emit_err(errors::OnlyOneArgument { span, name }); + cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); return None; } let ret = parse_expr(&mut p)?; let _ = p.eat(&token::Comma); if p.token != token::Eof { - cx.emit_err(errors::OnlyOneArgument { span, name }); + cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); } expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s) } @@ -1348,7 +1303,7 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> Option<Vec< continue; } if p.token != token::Eof { - cx.emit_err(errors::ExpectedCommaInList { span: p.token.span }); + cx.dcx().emit_err(errors::ExpectedCommaInList { span: p.token.span }); return None; } } @@ -1356,7 +1311,7 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> Option<Vec< } pub fn parse_macro_name_and_helper_attrs( - diag: &rustc_errors::Handler, + dcx: &rustc_errors::DiagCtxt, attr: &Attribute, macro_type: &str, ) -> Option<(Symbol, Vec<Symbol>)> { @@ -1365,23 +1320,23 @@ pub fn parse_macro_name_and_helper_attrs( // `#[proc_macro_derive(Foo, attributes(A, ..))]` let list = attr.meta_item_list()?; if list.len() != 1 && list.len() != 2 { - diag.emit_err(errors::AttrNoArguments { span: attr.span }); + dcx.emit_err(errors::AttrNoArguments { span: attr.span }); return None; } let Some(trait_attr) = list[0].meta_item() else { - diag.emit_err(errors::NotAMetaItem { span: list[0].span() }); + dcx.emit_err(errors::NotAMetaItem { span: list[0].span() }); return None; }; let trait_ident = match trait_attr.ident() { Some(trait_ident) if trait_attr.is_word() => trait_ident, _ => { - diag.emit_err(errors::OnlyOneWord { span: trait_attr.span }); + dcx.emit_err(errors::OnlyOneWord { span: trait_attr.span }); return None; } }; if !trait_ident.name.can_be_raw() { - diag.emit_err(errors::CannotBeNameOfMacro { + dcx.emit_err(errors::CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type, @@ -1391,29 +1346,29 @@ pub fn parse_macro_name_and_helper_attrs( let attributes_attr = list.get(1); let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { if !attr.has_name(sym::attributes) { - diag.emit_err(errors::ArgumentNotAttributes { span: attr.span() }); + dcx.emit_err(errors::ArgumentNotAttributes { span: attr.span() }); } attr.meta_item_list() .unwrap_or_else(|| { - diag.emit_err(errors::AttributesWrongForm { span: attr.span() }); + dcx.emit_err(errors::AttributesWrongForm { span: attr.span() }); &[] }) .iter() .filter_map(|attr| { let Some(attr) = attr.meta_item() else { - diag.emit_err(errors::AttributeMetaItem { span: attr.span() }); + dcx.emit_err(errors::AttributeMetaItem { span: attr.span() }); return None; }; let ident = match attr.ident() { Some(ident) if attr.is_word() => ident, _ => { - diag.emit_err(errors::AttributeSingleWord { span: attr.span }); + dcx.emit_err(errors::AttributeSingleWord { span: attr.span }); return None; } }; if !ident.name.can_be_raw() { - diag.emit_err(errors::HelperAttributeNameInvalid { + dcx.emit_err(errors::HelperAttributeNameInvalid { span: attr.span, name: ident, }); @@ -1464,7 +1419,7 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool { if crate_matches { sess.buffer_lint_with_diagnostic( - &PROC_MACRO_BACK_COMPAT, + PROC_MACRO_BACK_COMPAT, item.ident.span, ast::CRATE_NODE_ID, "using an old version of `rental`", diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 7de46994434..f9bfebee12e 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -4,7 +4,7 @@ use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, use rustc_ast::{attr, token, util::literal}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use thin_vec::{thin_vec, ThinVec}; impl<'a> ExtCtxt<'a> { @@ -134,10 +134,13 @@ impl<'a> ExtCtxt<'a> { pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound { ast::GenericBound::Trait( self.poly_trait_ref(path.span, path), - if is_const { - ast::TraitBoundModifier::MaybeConst - } else { - ast::TraitBoundModifier::None + ast::TraitBoundModifiers { + polarity: ast::BoundPolarity::Positive, + constness: if is_const { + ast::BoundConstness::Maybe(DUMMY_SP) + } else { + ast::BoundConstness::Never + }, }, ) } @@ -488,7 +491,7 @@ impl<'a> ExtCtxt<'a> { path: ast::Path, field_pats: ThinVec<ast::PatField>, ) -> P<ast::Pat> { - self.pat(span, PatKind::Struct(None, path, field_pats, false)) + self.pat(span, PatKind::Struct(None, path, field_pats, ast::PatFieldsRest::None)) } pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> { self.pat(span, PatKind::Tuple(pats)) @@ -505,7 +508,7 @@ impl<'a> ExtCtxt<'a> { attrs: AttrVec::new(), pat, guard: None, - body: expr, + body: Some(expr), span, id: ast::DUMMY_NODE_ID, is_placeholder: false, @@ -547,7 +550,7 @@ impl<'a> ExtCtxt<'a> { binder: ast::ClosureBinder::NotPresent, capture_clause: ast::CaptureBy::Ref, constness: ast::Const::No, - asyncness: ast::Async::No, + coroutine_kind: None, movability: ast::Movability::Movable, fn_decl, body, diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 0d76b1b2974..2283a3bfc76 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -1,25 +1,22 @@ //! Conditional compilation stripping. use crate::errors::{ - FeatureIncludedInEdition, FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg, - MalformedFeatureAttribute, MalformedFeatureAttributeHelp, RemoveExprNotSupported, + FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg, MalformedFeatureAttribute, + MalformedFeatureAttributeHelp, RemoveExprNotSupported, }; use rustc_ast::ptr::P; use rustc_ast::token::{Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree}; -use rustc_ast::tokenstream::{DelimSpan, Spacing}; +use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, DelimSpacing, DelimSpan, Spacing}; use rustc_ast::tokenstream::{LazyAttrTokenStream, TokenTree}; use rustc_ast::NodeId; use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem}; use rustc_attr as attr; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; -use rustc_data_structures::fx::FxHashSet; use rustc_feature::Features; use rustc_feature::{ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES}; use rustc_parse::validate_attr; use rustc_session::parse::feature_err; use rustc_session::Session; -use rustc_span::edition::ALL_EDITIONS; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use thin_vec::ThinVec; @@ -48,49 +45,13 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) - let mut features = Features::default(); - // The edition from `--edition`. - let crate_edition = sess.edition(); - - // The maximum of (a) the edition from `--edition` and (b) any edition - // umbrella feature-gates declared in the code. - // - E.g. if `crate_edition` is 2015 but `rust_2018_preview` is present, - // `feature_edition` is 2018 - let mut features_edition = crate_edition; - for attr in krate_attrs { - for mi in feature_list(attr) { - if mi.is_word() { - let name = mi.name_or_empty(); - let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied(); - if let Some(edition) = edition - && edition > features_edition - { - features_edition = edition; - } - } - } - } - - // Enable edition-dependent features based on `features_edition`. - // - E.g. enable `test_2018_feature` if `features_edition` is 2018 or higher - let mut edition_enabled_features = FxHashSet::default(); - for f in UNSTABLE_FEATURES { - if let Some(edition) = f.feature.edition - && edition <= features_edition - { - // FIXME(Manishearth) there is currently no way to set lib features by - // edition. - edition_enabled_features.insert(f.feature.name); - (f.set_enabled)(&mut features); - } - } - // Process all features declared in the code. for attr in krate_attrs { for mi in feature_list(attr) { let name = match mi.ident() { Some(ident) if mi.is_word() => ident.name, Some(ident) => { - sess.emit_err(MalformedFeatureAttribute { + sess.dcx().emit_err(MalformedFeatureAttribute { span: mi.span(), help: MalformedFeatureAttributeHelp::Suggestion { span: mi.span(), @@ -100,7 +61,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) - continue; } None => { - sess.emit_err(MalformedFeatureAttribute { + sess.dcx().emit_err(MalformedFeatureAttribute { span: mi.span(), help: MalformedFeatureAttributeHelp::Label { span: mi.span() }, }); @@ -108,41 +69,9 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) - } }; - // If the declared feature is an edition umbrella feature-gate, - // warn if it was redundant w.r.t. `crate_edition`. - // - E.g. warn if `rust_2018_preview` is declared when - // `crate_edition` is 2018 - // - E.g. don't warn if `rust_2018_preview` is declared when - // `crate_edition` is 2015. - if let Some(&edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) { - if edition <= crate_edition { - sess.emit_warning(FeatureIncludedInEdition { - span: mi.span(), - feature: name, - edition, - }); - } - features.set_declared_lang_feature(name, mi.span(), None); - continue; - } - - // If the declared feature is edition-dependent and was already - // enabled due to `feature_edition`, give a warning. - // - E.g. warn if `test_2018_feature` is declared when - // `feature_edition` is 2018 or higher. - if edition_enabled_features.contains(&name) { - sess.emit_warning(FeatureIncludedInEdition { - span: mi.span(), - feature: name, - edition: features_edition, - }); - features.set_declared_lang_feature(name, mi.span(), None); - continue; - } - // If the declared feature has been removed, issue an error. if let Some(f) = REMOVED_FEATURES.iter().find(|f| name == f.feature.name) { - sess.emit_err(FeatureRemoved { + sess.dcx().emit_err(FeatureRemoved { span: mi.span(), reason: f.reason.map(|reason| FeatureRemovedReason { reason }), }); @@ -161,7 +90,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) - // issue an error. if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() { if allowed.iter().all(|f| name.as_str() != f) { - sess.emit_err(FeatureNotAllowed { span: mi.span(), name }); + sess.dcx().emit_err(FeatureNotAllowed { span: mi.span(), name }); continue; } } @@ -242,7 +171,7 @@ impl<'a> StripUnconfigured<'a> { stream.0.iter().all(|tree| match tree { AttrTokenTree::Attributes(_) => false, AttrTokenTree::Token(..) => true, - AttrTokenTree::Delimited(_, _, inner) => can_skip(inner), + AttrTokenTree::Delimited(.., inner) => can_skip(inner), }) } @@ -266,9 +195,9 @@ impl<'a> StripUnconfigured<'a> { None.into_iter() } } - AttrTokenTree::Delimited(sp, delim, mut inner) => { + AttrTokenTree::Delimited(sp, spacing, delim, mut inner) => { inner = self.configure_tokens(&inner); - Some(AttrTokenTree::Delimited(sp, delim, inner)).into_iter() + Some(AttrTokenTree::Delimited(sp, spacing, delim, inner)).into_iter() } AttrTokenTree::Token(ref token, _) if let TokenKind::Interpolated(nt) = &token.kind => @@ -372,27 +301,32 @@ impl<'a> StripUnconfigured<'a> { }; let pound_span = pound_token.span; - let mut trees = vec![AttrTokenTree::Token(pound_token, Spacing::Alone)]; - if attr.style == AttrStyle::Inner { - // For inner attributes, we do the same thing for the `!` in `#![some_attr]` - let TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }, _) = - orig_trees.next().unwrap().clone() - else { - panic!("Bad tokens for attribute {attr:?}"); - }; - trees.push(AttrTokenTree::Token(bang_token, Spacing::Alone)); - } // We don't really have a good span to use for the synthesized `[]` // in `#[attr]`, so just use the span of the `#` token. let bracket_group = AttrTokenTree::Delimited( DelimSpan::from_single(pound_span), + DelimSpacing::new(Spacing::JointHidden, Spacing::Alone), Delimiter::Bracket, item.tokens .as_ref() .unwrap_or_else(|| panic!("Missing tokens for {item:?}")) .to_attr_token_stream(), ); - trees.push(bracket_group); + let trees = if attr.style == AttrStyle::Inner { + // For inner attributes, we do the same thing for the `!` in `#![some_attr]` + let TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }, _) = + orig_trees.next().unwrap().clone() + else { + panic!("Bad tokens for attribute {attr:?}"); + }; + vec![ + AttrTokenTree::Token(pound_token, Spacing::Joint), + AttrTokenTree::Token(bang_token, Spacing::JointHidden), + bracket_group, + ] + } else { + vec![AttrTokenTree::Token(pound_token, Spacing::JointHidden), bracket_group] + }; let tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::new(trees))); let attr = attr::mk_attr_from_item( &self.sess.parse_sess.attr_id_generator, @@ -434,9 +368,9 @@ impl<'a> StripUnconfigured<'a> { } }; ( - parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| { + parse_cfg(&meta_item, self.sess).map_or(true, |meta_item| { attr::cfg_matches( - &meta_item, + meta_item, &self.sess.parse_sess, self.lint_node_id, self.features, @@ -481,7 +415,7 @@ impl<'a> StripUnconfigured<'a> { // N.B., this is intentionally not part of the visit_expr() function // in order for filter_map_expr() to be able to avoid this check if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) { - self.sess.emit_err(RemoveExprNotSupported { span: attr.span }); + self.sess.dcx().emit_err(RemoveExprNotSupported { span: attr.span }); } self.process_cfg_attrs(expr); @@ -493,21 +427,21 @@ pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a Meta let span = meta_item.span; match meta_item.meta_item_list() { None => { - sess.emit_err(InvalidCfg::NotFollowedByParens { span }); + sess.dcx().emit_err(InvalidCfg::NotFollowedByParens { span }); None } Some([]) => { - sess.emit_err(InvalidCfg::NoPredicate { span }); + sess.dcx().emit_err(InvalidCfg::NoPredicate { span }); None } Some([_, .., l]) => { - sess.emit_err(InvalidCfg::MultiplePredicates { span: l.span() }); + sess.dcx().emit_err(InvalidCfg::MultiplePredicates { span: l.span() }); None } Some([single]) => match single.meta_item() { Some(meta_item) => Some(meta_item), None => { - sess.emit_err(InvalidCfg::PredicateLiteral { span: single.span() }); + sess.dcx().emit_err(InvalidCfg::PredicateLiteral { span: single.span() }); None } }, diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index d86632c47fc..2b43fae6852 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -1,7 +1,6 @@ use rustc_ast::ast; use rustc_macros::Diagnostic; use rustc_session::Limit; -use rustc_span::edition::Edition; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent}; use rustc_span::{Span, Symbol}; use std::borrow::Cow; @@ -169,15 +168,6 @@ pub(crate) struct TakesNoArguments<'a> { } #[derive(Diagnostic)] -#[diag(expand_feature_included_in_edition, code = "E0705")] -pub(crate) struct FeatureIncludedInEdition { - #[primary_span] - pub span: Span, - pub feature: Symbol, - pub edition: Edition, -} - -#[derive(Diagnostic)] #[diag(expand_feature_removed, code = "E0557")] pub(crate) struct FeatureRemoved<'a> { #[primary_span] @@ -304,6 +294,8 @@ pub(crate) struct IncompleteParse<'a> { pub label_span: Span, pub macro_path: &'a ast::Path, pub kind_name: &'a str, + #[note(expand_macro_expands_to_match_arm)] + pub expands_to_match_arm: Option<()>, #[suggestion( expand_suggestion_add_semi, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index f87f4aba2b9..676f9f17976 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -93,7 +93,7 @@ macro_rules! ast_fragments { } match self { $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| { - ${ignore(flat_map_ast_elt)} + ${ignore($flat_map_ast_elt)} placeholder(AstFragmentKind::$Kind, *id, None).$make_ast() })),)?)* _ => panic!("unexpected AST fragment kind") @@ -435,7 +435,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { invocations = mem::take(&mut undetermined_invocations); force = !mem::replace(&mut progress, false); if force && self.monotonic { - self.cx.sess.delay_span_bug( + self.cx.dcx().span_delayed_bug( invocations.last().unwrap().0.span(), "expansion entered force mode without producing any errors", ); @@ -513,7 +513,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } ExpandResult::Retry(invoc) => { if force { - self.cx.span_bug( + self.cx.dcx().span_bug( invoc.span(), "expansion entered force mode but is still stuck", ); @@ -611,7 +611,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { limit => limit * 2, }; - self.cx.emit_err(RecursionLimitReached { + self.cx.dcx().emit_err(RecursionLimitReached { span: expn_data.call_site, descr: expn_data.kind.descr(), suggested_limit, @@ -624,7 +624,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { /// A macro's expansion does not fit in this fragment kind. /// For example, a non-type macro in a type position. fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) { - self.cx.emit_err(WrongFragmentKind { span, kind: kind.name(), name: &mac.path }); + self.cx.dcx().emit_err(WrongFragmentKind { span, kind: kind.name(), name: &mac.path }); self.cx.trace_macros_diag(); } @@ -702,7 +702,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; let attr_item = attr.unwrap_normal_item(); if let AttrArgs::Eq(..) = attr_item.args { - self.cx.emit_err(UnsupportedKeyValue { span }); + self.cx.dcx().emit_err(UnsupportedKeyValue { span }); } let inner_tokens = attr_item.args.inner_tokens(); let Ok(tok_result) = expander.expand(self.cx, span, inner_tokens, tokens) @@ -729,7 +729,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { AstFragmentKind::Expr | AstFragmentKind::MethodReceiverExpr ) && items.is_empty() { - self.cx.emit_err(RemoveExprNotSupported { span }); + self.cx.dcx().emit_err(RemoveExprNotSupported { span }); fragment_kind.dummy(span) } else { fragment_kind.expect_from_annotatables(items) @@ -955,12 +955,15 @@ pub fn ensure_complete_parse<'a>( _ => None, }; - parser.sess.emit_err(IncompleteParse { + let expands_to_match_arm = kind_name == "pattern" && parser.token == token::FatArrow; + + parser.dcx().emit_err(IncompleteParse { span: def_site_span, token, label_span: span, macro_path, kind_name, + expands_to_match_arm: expands_to_match_arm.then_some(()), add_semicolon, }); } @@ -1047,7 +1050,7 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { _pos: usize, span: Span, ) { - collector.cx.emit_err(RemoveNodeNotSupported { span, descr: Self::descr() }); + collector.cx.dcx().emit_err(RemoveNodeNotSupported { span, descr: Self::descr() }); } /// All of the names (items) declared by this node. @@ -1096,7 +1099,7 @@ impl InvocationCollectorNode for P<ast::Item> { ModKind::Loaded(_, inline, _) => { // Inline `mod foo { ... }`, but we still need to push directories. let (dir_path, dir_ownership) = mod_dir_path( - &ecx.sess, + ecx.sess, ident, &attrs, &ecx.current_expansion.module, @@ -1111,7 +1114,7 @@ impl InvocationCollectorNode for P<ast::Item> { let old_attrs_len = attrs.len(); let ParsedExternalMod { items, spans, file_path, dir_path, dir_ownership } = parse_external_mod( - &ecx.sess, + ecx.sess, ident, span, &ecx.current_expansion.module, @@ -1168,14 +1171,14 @@ impl InvocationCollectorNode for P<ast::Item> { ast::UseTreeKind::Simple(_) => idents.push(ut.ident()), ast::UseTreeKind::Nested(nested) => { for (ut, _) in nested { - collect_use_tree_leaves(&ut, idents); + collect_use_tree_leaves(ut, idents); } } } } let mut idents = Vec::new(); - collect_use_tree_leaves(&ut, &mut idents); + collect_use_tree_leaves(ut, &mut idents); return idents; } @@ -1531,7 +1534,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> { } } fn pre_flat_map_node_collect_attr(cfg: &StripUnconfigured<'_>, attr: &ast::Attribute) { - cfg.maybe_emit_expr_attr_err(&attr); + cfg.maybe_emit_expr_attr_err(attr); } } @@ -1580,7 +1583,7 @@ struct InvocationCollector<'a, 'b> { impl<'a, 'b> InvocationCollector<'a, 'b> { fn cfg(&self) -> StripUnconfigured<'_> { StripUnconfigured { - sess: &self.cx.sess, + sess: self.cx.sess, features: Some(self.cx.ecfg.features), config_tokens: false, lint_node_id: self.cx.current_expansion.lint_node_id, @@ -1693,7 +1696,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { if attr.is_doc_comment() { self.cx.sess.parse_sess.buffer_lint_with_diagnostic( - &UNUSED_DOC_COMMENTS, + UNUSED_DOC_COMMENTS, current_span, self.cx.current_expansion.lint_node_id, "unused doc comment", @@ -1705,7 +1708,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // eagerly evaluated. if attr_name != sym::cfg && attr_name != sym::cfg_attr { self.cx.sess.parse_sess.buffer_lint_with_diagnostic( - &UNUSED_ATTRIBUTES, + UNUSED_ATTRIBUTES, attr.span, self.cx.current_expansion.lint_node_id, format!("unused attribute `{attr_name}`"), diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index cb084a85e47..bed667048c8 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -23,9 +23,6 @@ extern crate tracing; extern crate proc_macro as pm; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - mod placeholders; mod proc_macro_server; @@ -67,4 +64,4 @@ mod mut_visit { mod tests; } -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs index a43b2a00188..ca4a1f327ad 100644 --- a/compiler/rustc_expand/src/mbe.rs +++ b/compiler/rustc_expand/src/mbe.rs @@ -13,7 +13,7 @@ pub(crate) mod transcribe; use metavar_expr::MetaVarExpr; use rustc_ast::token::{Delimiter, NonterminalKind, Token, TokenKind}; -use rustc_ast::tokenstream::DelimSpan; +use rustc_ast::tokenstream::{DelimSpacing, DelimSpan}; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -68,7 +68,7 @@ pub(crate) enum KleeneOp { enum TokenTree { Token(Token), /// A delimited sequence, e.g. `($e:expr)` (RHS) or `{ $e }` (LHS). - Delimited(DelimSpan, Delimited), + Delimited(DelimSpan, DelimSpacing, Delimited), /// A kleene-style repetition sequence, e.g. `$($e:expr)*` (RHS) or `$($e),*` (LHS). Sequence(DelimSpan, SequenceRepetition), /// e.g., `$var`. @@ -99,7 +99,7 @@ impl TokenTree { TokenTree::Token(Token { span, .. }) | TokenTree::MetaVar(span, _) | TokenTree::MetaVarDecl(span, _, _) => span, - TokenTree::Delimited(span, _) + TokenTree::Delimited(span, ..) | TokenTree::MetaVarExpr(span, _) | TokenTree::Sequence(span, _) => span.entire(), } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 64cf9ced9c1..2746e888b8d 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -34,7 +34,10 @@ pub(super) fn failed_to_match_macro<'cx>( if try_success_result.is_ok() { // Nonterminal parser recovery might turn failed matches into successful ones, // but for that it must have emitted an error already - tracker.cx.sess.delay_span_bug(sp, "Macro matching returned a success on the second try"); + tracker + .cx + .dcx() + .span_delayed_bug(sp, "Macro matching returned a success on the second try"); } if let Some(result) = tracker.result { @@ -49,7 +52,7 @@ pub(super) fn failed_to_match_macro<'cx>( let span = token.span.substitute_dummy(sp); - let mut err = cx.struct_span_err(span, parse_failure_msg(&token)); + let mut err = cx.dcx().struct_span_err(span, parse_failure_msg(&token)); err.span_label(span, label); if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); @@ -151,7 +154,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, Success(_) => { // Nonterminal parser recovery might turn failed matches into successful ones, // but for that it must have emitted an error already - self.cx.sess.delay_span_bug( + self.cx.dcx().span_delayed_bug( self.root_span, "should not collect detailed info for successful macro match", ); @@ -177,7 +180,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, } Error(err_sp, msg) => { let span = err_sp.substitute_dummy(self.root_span); - self.cx.struct_span_err(span, msg.clone()).emit(); + self.cx.dcx().struct_span_err(span, msg.clone()).emit(); self.result = Some(DummyResult::any(span)); } ErrorReported(_) => self.result = Some(DummyResult::any(self.root_span)), @@ -215,7 +218,7 @@ impl<'matcher> Tracker<'matcher> for FailureForwarder { } pub(super) fn emit_frag_parse_err( - mut e: DiagnosticBuilder<'_, rustc_errors::ErrorGuaranteed>, + mut e: DiagnosticBuilder<'_>, parser: &Parser<'_>, orig_parser: &mut Parser<'_>, site_span: Span, @@ -224,11 +227,11 @@ pub(super) fn emit_frag_parse_err( ) { // FIXME(davidtwco): avoid depending on the error message text if parser.token == token::Eof - && let DiagnosticMessage::Str(message) = &e.message[0].0 + && let DiagnosticMessage::Str(message) = &e.messages[0].0 && message.ends_with(", found `<eof>`") { - let msg = &e.message[0]; - e.message[0] = ( + let msg = &e.messages[0]; + e.messages[0] = ( DiagnosticMessage::from(format!( "macro expansion ends with an incomplete expression: {}", message.replace(", found `<eof>`", ""), diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 95f5bb2d2e2..e66cfbe6fb6 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -205,7 +205,7 @@ pub(super) fn check_meta_variables( rhses: &[TokenTree], ) -> bool { if lhses.len() != rhses.len() { - sess.span_diagnostic.span_bug(span, "length mismatch between LHSes and RHSes") + sess.dcx.span_bug(span, "length mismatch between LHSes and RHSes") } let mut valid = true; for (lhs, rhs) in iter::zip(lhses, rhses) { @@ -244,7 +244,7 @@ fn check_binders( // MetaVar(fragment) and not as MetaVarDecl(y, fragment). TokenTree::MetaVar(span, name) => { if macros.is_empty() { - sess.span_diagnostic.span_bug(span, "unexpected MetaVar in lhs"); + sess.dcx.span_bug(span, "unexpected MetaVar in lhs"); } let name = MacroRulesNormalizedIdent::new(name); // There are 3 possibilities: @@ -275,14 +275,13 @@ fn check_binders( ); } if !macros.is_empty() { - sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in nested lhs"); + sess.dcx.span_bug(span, "unexpected MetaVarDecl in nested lhs"); } let name = MacroRulesNormalizedIdent::new(name); if let Some(prev_info) = get_binder_info(macros, binders, name) { // Duplicate binders at the top-level macro definition are errors. The lint is only // for nested macro definitions. - sess.span_diagnostic - .emit_err(errors::DuplicateMatcherBinding { span, prev: prev_info.span }); + sess.dcx.emit_err(errors::DuplicateMatcherBinding { span, prev: prev_info.span }); *valid = false; } else { binders.insert(name, BinderInfo { span, ops: ops.into() }); @@ -290,7 +289,7 @@ fn check_binders( } // `MetaVarExpr` can not appear in the LHS of a macro arm TokenTree::MetaVarExpr(..) => {} - TokenTree::Delimited(_, ref del) => { + TokenTree::Delimited(.., ref del) => { for tt in &del.tts { check_binders(sess, node_id, tt, macros, binders, ops, valid); } @@ -341,7 +340,7 @@ fn check_occurrences( match *rhs { TokenTree::Token(..) => {} TokenTree::MetaVarDecl(span, _name, _kind) => { - sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in rhs") + sess.dcx.span_bug(span, "unexpected MetaVarDecl in rhs") } TokenTree::MetaVar(span, name) => { let name = MacroRulesNormalizedIdent::new(name); @@ -353,7 +352,7 @@ fn check_occurrences( }; check_ops_is_prefix(sess, node_id, macros, binders, ops, dl.entire(), name); } - TokenTree::Delimited(_, ref del) => { + TokenTree::Delimited(.., ref del) => { check_nested_occurrences(sess, node_id, &del.tts, macros, binders, ops, valid); } TokenTree::Sequence(_, ref seq) => { @@ -435,8 +434,8 @@ fn check_nested_occurrences( // We check that the meta-variable is correctly used. check_occurrences(sess, node_id, tt, macros, binders, ops, valid); } - (NestedMacroState::MacroRulesNotName, TokenTree::Delimited(_, del)) - | (NestedMacroState::MacroName, TokenTree::Delimited(_, del)) + (NestedMacroState::MacroRulesNotName, TokenTree::Delimited(.., del)) + | (NestedMacroState::MacroName, TokenTree::Delimited(.., del)) if del.delim == Delimiter::Brace => { let macro_rules = state == NestedMacroState::MacroRulesNotName; @@ -466,7 +465,7 @@ fn check_nested_occurrences( // We check that the meta-variable is correctly used. check_occurrences(sess, node_id, tt, macros, binders, ops, valid); } - (NestedMacroState::MacroName, TokenTree::Delimited(_, del)) + (NestedMacroState::MacroName, TokenTree::Delimited(.., del)) if del.delim == Delimiter::Parenthesis => { state = NestedMacroState::MacroNameParen; @@ -481,7 +480,7 @@ fn check_nested_occurrences( valid, ); } - (NestedMacroState::MacroNameParen, TokenTree::Delimited(_, del)) + (NestedMacroState::MacroNameParen, TokenTree::Delimited(.., del)) if del.delim == Delimiter::Brace => { state = NestedMacroState::Empty; @@ -650,6 +649,6 @@ fn buffer_lint( ) { // Macros loaded from other crates have dummy node ids. if node_id != DUMMY_NODE_ID { - sess.buffer_lint(&META_VARIABLE_MISUSE, span, node_id, message); + sess.buffer_lint(META_VARIABLE_MISUSE, span, node_id, message); } } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 1c78232a0f3..b248a1fe349 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -184,7 +184,7 @@ pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec<MatcherLoc> { TokenTree::Token(token) => { locs.push(MatcherLoc::Token { token: token.clone() }); } - TokenTree::Delimited(span, delimited) => { + TokenTree::Delimited(span, _, delimited) => { let open_token = Token::new(token::OpenDelim(delimited.delim), span.open); let close_token = Token::new(token::CloseDelim(delimited.delim), span.close); @@ -335,7 +335,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize { .map(|tt| match tt { TokenTree::MetaVarDecl(..) => 1, TokenTree::Sequence(_, seq) => seq.num_captures, - TokenTree::Delimited(_, delim) => count_metavar_decls(&delim.tts), + TokenTree::Delimited(.., delim) => count_metavar_decls(&delim.tts), TokenTree::Token(..) => 0, TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(), }) @@ -483,7 +483,7 @@ impl TtParser { if matches!(t, Token { kind: DocComment(..), .. }) { mp.idx += 1; self.cur_mps.push(mp); - } else if token_name_eq(&t, token) { + } else if token_name_eq(t, token) { mp.idx += 1; self.next_mps.push(mp); } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index ebdd3cb547c..e9736d6f2c8 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -207,13 +207,13 @@ fn expand_macro<'cx>( match try_success_result { Ok((i, named_matches)) => { let (rhs, rhs_span): (&mbe::Delimited, DelimSpan) = match &rhses[i] { - mbe::TokenTree::Delimited(span, delimited) => (&delimited, *span), - _ => cx.span_bug(sp, "malformed macro rhs"), + mbe::TokenTree::Delimited(span, _, delimited) => (&delimited, *span), + _ => cx.dcx().span_bug(sp, "malformed macro rhs"), }; let arm_span = rhses[i].span(); // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = match transcribe(cx, &named_matches, &rhs, rhs_span, transparency) { + let mut tts = match transcribe(cx, &named_matches, rhs, rhs_span, transparency) { Ok(tts) => tts, Err(mut err) => { err.emit(); @@ -236,6 +236,13 @@ fn expand_macro<'cx>( target_sp.open = source_sp.open.with_ctxt(ctxt); target_sp.close = source_sp.close.with_ctxt(ctxt); } + ( + TokenTree::Delimited(target_sp, ..), + mbe::TokenTree::MetaVar(source_sp, ..), + ) => { + target_sp.open = source_sp.with_ctxt(ctxt); + target_sp.close = source_sp.with_ctxt(ctxt).shrink_to_hi(); + } _ => { let sp = rhs_tt.span().with_ctxt(ctxt); tt.set_span(sp); @@ -395,7 +402,7 @@ pub fn compile_declarative_macro( }; let dummy_syn_ext = || (mk_syn_ext(Box::new(macro_rules_dummy_expander)), Vec::new()); - let diag = &sess.parse_sess.span_diagnostic; + let dcx = &sess.parse_sess.dcx; let lhs_nm = Ident::new(sym::lhs, def.span); let rhs_nm = Ident::new(sym::rhs, def.span); let tt_spec = Some(NonterminalKind::TT); @@ -475,17 +482,14 @@ pub fn compile_declarative_macro( let s = parse_failure_msg(&token); let sp = token.span.substitute_dummy(def.span); - let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, s); + let mut err = sess.dcx().struct_span_err(sp, s); err.span_label(sp, msg); annotate_doc_comment(&mut err, sess.source_map(), sp); err.emit(); return dummy_syn_ext(); } Error(sp, msg) => { - sess.parse_sess - .span_diagnostic - .struct_span_err(sp.substitute_dummy(def.span), msg) - .emit(); + sess.dcx().struct_span_err(sp.substitute_dummy(def.span), msg).emit(); return dummy_syn_ext(); } ErrorReported(_) => { @@ -511,13 +515,13 @@ pub fn compile_declarative_macro( ) .pop() .unwrap(); - valid &= check_lhs_nt_follows(&sess.parse_sess, &def, &tt); + valid &= check_lhs_nt_follows(&sess.parse_sess, def, &tt); return tt; } - sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") + sess.dcx().span_bug(def.span, "wrong-structured lhs") }) .collect::<Vec<mbe::TokenTree>>(), - _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"), + _ => sess.dcx().span_bug(def.span, "wrong-structured lhs"), }; let rhses = match &argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] { @@ -536,10 +540,10 @@ pub fn compile_declarative_macro( .pop() .unwrap(); } - sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs") + sess.dcx().span_bug(def.span, "wrong-structured rhs") }) .collect::<Vec<mbe::TokenTree>>(), - _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs"), + _ => sess.dcx().span_bug(def.span, "wrong-structured rhs"), }; for rhs in &rhses { @@ -556,10 +560,10 @@ pub fn compile_declarative_macro( let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules); match transparency_error { Some(TransparencyError::UnknownTransparency(value, span)) => { - diag.span_err(span, format!("unknown macro transparency: `{value}`")); + dcx.span_err(span, format!("unknown macro transparency: `{value}`")); } Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => { - diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes"); + dcx.span_err(vec![old_span, new_span], "multiple macro transparency attributes"); } None => {} } @@ -592,10 +596,10 @@ pub fn compile_declarative_macro( .map(|lhs| { // Ignore the delimiters around the matcher. match lhs { - mbe::TokenTree::Delimited(_, delimited) => { + mbe::TokenTree::Delimited(.., delimited) => { mbe::macro_parser::compute_locs(&delimited.tts) } - _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "malformed macro lhs"), + _ => sess.dcx().span_bug(def.span, "malformed macro lhs"), } }) .collect() @@ -618,11 +622,11 @@ pub fn compile_declarative_macro( fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool { // lhs is going to be like TokenTree::Delimited(...), where the // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. - if let mbe::TokenTree::Delimited(_, delimited) = lhs { + if let mbe::TokenTree::Delimited(.., delimited) = lhs { check_matcher(sess, def, &delimited.tts) } else { let msg = "invalid macro matcher; matchers must be contained in balanced delimiters"; - sess.span_diagnostic.span_err(lhs.span(), msg); + sess.dcx.span_err(lhs.span(), msg); false } // we don't abort on errors on rejection, the driver will do that for us @@ -648,10 +652,7 @@ fn is_empty_token_tree(sess: &ParseSess, seq: &mbe::SequenceRepetition) -> bool iter.next(); } let span = t.span.to(now.span); - sess.span_diagnostic.span_note_without_error( - span, - "doc comments are ignored in matcher position", - ); + sess.dcx.span_note(span, "doc comments are ignored in matcher position"); } mbe::TokenTree::Sequence(_, sub_seq) if (sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore @@ -673,7 +674,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool { | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) | TokenTree::MetaVarExpr(..) => (), - TokenTree::Delimited(_, del) => { + TokenTree::Delimited(.., del) => { if !check_lhs_no_empty_seq(sess, &del.tts) { return false; } @@ -681,7 +682,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool { TokenTree::Sequence(span, seq) => { if is_empty_token_tree(sess, seq) { let sp = span.entire(); - sess.span_diagnostic.span_err(sp, "repetition matches empty token tree"); + sess.dcx.span_err(sp, "repetition matches empty token tree"); return false; } if !check_lhs_no_empty_seq(sess, &seq.tts) { @@ -698,7 +699,7 @@ fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool { match *rhs { mbe::TokenTree::Delimited(..) => return true, _ => { - sess.span_diagnostic.span_err(rhs.span(), "macro rhs must be delimited"); + sess.dcx.span_err(rhs.span(), "macro rhs must be delimited"); } } false @@ -707,21 +708,21 @@ fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool { fn check_matcher(sess: &ParseSess, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool { let first_sets = FirstSets::new(matcher); let empty_suffix = TokenSet::empty(); - let err = sess.span_diagnostic.err_count(); + let err = sess.dcx.err_count(); check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix); - err == sess.span_diagnostic.err_count() + err == sess.dcx.err_count() } fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool { match rhs { - mbe::TokenTree::Delimited(_sp, d) => { + mbe::TokenTree::Delimited(.., d) => { let has_compile_error = d.tts.array_windows::<3>().any(|[ident, bang, args]| { if let mbe::TokenTree::Token(ident) = ident && let TokenKind::Ident(ident, _) = ident.kind && ident == sym::compile_error && let mbe::TokenTree::Token(bang) = bang && let TokenKind::Not = bang.kind - && let mbe::TokenTree::Delimited(_, del) = args + && let mbe::TokenTree::Delimited(.., del) = args && del.delim != Delimiter::Invisible { true @@ -778,7 +779,7 @@ impl<'tt> FirstSets<'tt> { | TokenTree::MetaVarExpr(..) => { first.replace_with(TtHandle::TtRef(tt)); } - TokenTree::Delimited(span, delimited) => { + TokenTree::Delimited(span, _, delimited) => { build_recur(sets, &delimited.tts); first.replace_with(TtHandle::from_token_kind( token::OpenDelim(delimited.delim), @@ -847,7 +848,7 @@ impl<'tt> FirstSets<'tt> { first.add_one(TtHandle::TtRef(tt)); return first; } - TokenTree::Delimited(span, delimited) => { + TokenTree::Delimited(span, _, delimited) => { first.add_one(TtHandle::from_token_kind( token::OpenDelim(delimited.delim), span.open, @@ -927,7 +928,7 @@ impl<'tt> TtHandle<'tt> { fn get(&'tt self) -> &'tt mbe::TokenTree { match self { TtHandle::TtRef(tt) => tt, - TtHandle::Token(token_tt) => &token_tt, + TtHandle::Token(token_tt) => token_tt, } } } @@ -1092,7 +1093,7 @@ fn check_matcher_core<'tt>( suffix_first = build_suffix_first(); } } - TokenTree::Delimited(span, d) => { + TokenTree::Delimited(span, _, d) => { let my_suffix = TokenSet::singleton(TtHandle::from_token_kind( token::CloseDelim(d.delim), span.close, @@ -1170,7 +1171,7 @@ fn check_matcher_core<'tt>( Some(NonterminalKind::PatParam { inferred: false }), )); sess.buffer_lint_with_diagnostic( - &RUST_2021_INCOMPATIBLE_OR_PATTERNS, + RUST_2021_INCOMPATIBLE_OR_PATTERNS, span, ast::CRATE_NODE_ID, "the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro", @@ -1188,7 +1189,7 @@ fn check_matcher_core<'tt>( }; let sp = next_token.span(); - let mut err = sess.span_diagnostic.struct_span_err( + let mut err = sess.dcx.struct_span_err( sp, format!( "`${name}:{frag}` {may_be} followed by `{next}`, which \ @@ -1407,7 +1408,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { match tt { - mbe::TokenTree::Token(token) => pprust::token_to_string(&token).into(), + mbe::TokenTree::Token(token) => pprust::token_to_string(token).into(), mbe::TokenTree::MetaVar(_, name) => format!("${name}"), mbe::TokenTree::MetaVarDecl(_, name, Some(kind)) => format!("${name}:{kind}"), mbe::TokenTree::MetaVarDecl(_, name, None) => format!("${name}:"), diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 7cb279a9812..e3dc73d0d85 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -10,9 +10,8 @@ use rustc_span::Span; /// A meta-variable expression, for expansions based on properties of meta-variables. #[derive(Debug, Clone, PartialEq, Encodable, Decodable)] pub(crate) enum MetaVarExpr { - /// The number of repetitions of an identifier, optionally limited to a number - /// of outer-most repetition depths. If the depth limit is `None` then the depth is unlimited. - Count(Ident, Option<usize>), + /// The number of repetitions of an identifier. + Count(Ident, usize), /// Ignore a meta-variable for repetition without expansion. Ignore(Ident), @@ -35,20 +34,23 @@ impl MetaVarExpr { ) -> PResult<'sess, MetaVarExpr> { let mut tts = input.trees(); let ident = parse_ident(&mut tts, sess, outer_span)?; - let Some(TokenTree::Delimited(_, Delimiter::Parenthesis, args)) = tts.next() else { + let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, args)) = tts.next() else { let msg = "meta-variable expression parameter must be wrapped in parentheses"; - return Err(sess.span_diagnostic.struct_span_err(ident.span, msg)); + return Err(sess.dcx.struct_span_err(ident.span, msg)); }; check_trailing_token(&mut tts, sess)?; let mut iter = args.trees(); let rslt = match ident.as_str() { "count" => parse_count(&mut iter, sess, ident.span)?, - "ignore" => MetaVarExpr::Ignore(parse_ident(&mut iter, sess, ident.span)?), + "ignore" => { + eat_dollar(&mut iter, sess, ident.span)?; + MetaVarExpr::Ignore(parse_ident(&mut iter, sess, ident.span)?) + } "index" => MetaVarExpr::Index(parse_depth(&mut iter, sess, ident.span)?), "length" => MetaVarExpr::Length(parse_depth(&mut iter, sess, ident.span)?), _ => { let err_msg = "unrecognized meta-variable expression"; - let mut err = sess.span_diagnostic.struct_span_err(ident.span, err_msg); + let mut err = sess.dcx.struct_span_err(ident.span, err_msg); err.span_suggestion( ident.span, "supported expressions are count, ignore, index and length", @@ -77,7 +79,7 @@ fn check_trailing_token<'sess>( ) -> PResult<'sess, ()> { if let Some(tt) = iter.next() { let mut diag = sess - .span_diagnostic + .dcx .struct_span_err(tt.span(), format!("unexpected token: {}", pprust::tt_to_string(tt))); diag.span_note(tt.span(), "meta-variable expression must not have trailing tokens"); Err(diag) @@ -92,17 +94,18 @@ fn parse_count<'sess>( sess: &'sess ParseSess, span: Span, ) -> PResult<'sess, MetaVarExpr> { + eat_dollar(iter, sess, span)?; let ident = parse_ident(iter, sess, span)?; let depth = if try_eat_comma(iter) { if iter.look_ahead(0).is_none() { - return Err(sess.span_diagnostic.struct_span_err( + return Err(sess.dcx.struct_span_err( span, "`count` followed by a comma must have an associated index indicating its depth", )); } - Some(parse_depth(iter, sess, span)?) + parse_depth(iter, sess, span)? } else { - None + 0 }; Ok(MetaVarExpr::Count(ident, depth)) } @@ -116,7 +119,7 @@ fn parse_depth<'sess>( let Some(tt) = iter.next() else { return Ok(0) }; let TokenTree::Token(token::Token { kind: token::TokenKind::Literal(lit), .. }, _) = tt else { return Err(sess - .span_diagnostic + .dcx .struct_span_err(span, "meta-variable expression depth must be a literal")); }; if let Ok(lit_kind) = LitKind::from_token_lit(*lit) @@ -126,7 +129,7 @@ fn parse_depth<'sess>( Ok(n_usize) } else { let msg = "only unsuffixes integer literals are supported in meta-variable expressions"; - Err(sess.span_diagnostic.struct_span_err(span, msg)) + Err(sess.dcx.struct_span_err(span, msg)) } } @@ -143,9 +146,8 @@ fn parse_ident<'sess>( return Ok(elem); } let token_str = pprust::token_to_string(token); - let mut err = sess - .span_diagnostic - .struct_span_err(span, format!("expected identifier, found `{}`", &token_str)); + let mut err = + sess.dcx.struct_span_err(span, format!("expected identifier, found `{}`", &token_str)); err.span_suggestion( token.span, format!("try removing `{}`", &token_str), @@ -154,7 +156,7 @@ fn parse_ident<'sess>( ); return Err(err); } - Err(sess.span_diagnostic.struct_span_err(span, "expected identifier")) + Err(sess.dcx.struct_span_err(span, "expected identifier")) } /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the @@ -166,3 +168,20 @@ fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool { } false } + +/// Expects that the next item is a dollar sign. +fn eat_dollar<'sess>( + iter: &mut RefTokenTreeCursor<'_>, + sess: &'sess ParseSess, + span: Span, +) -> PResult<'sess, ()> { + if let Some(TokenTree::Token(token::Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0) + { + let _ = iter.next(); + return Ok(()); + } + Err(sess.dcx.struct_span_err( + span, + "meta-variables within meta-variable expressions must be referenced using a dollar sign", + )) +} diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 6546199f5e6..445be01bc97 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -84,7 +84,7 @@ pub(super) fn parse( "invalid fragment specifier `{}`", frag.name ); - sess.span_diagnostic + sess.dcx .struct_span_err(span, msg) .help(VALID_FRAGMENT_NAMES_MSG) .emit(); @@ -116,7 +116,7 @@ pub(super) fn parse( fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess, span: Span) { if !features.macro_metavar_expr { let msg = "meta-variable expressions are unstable"; - feature_err(&sess, sym::macro_metavar_expr, span, msg).emit(); + feature_err(sess, sym::macro_metavar_expr, span, msg).emit(); } } @@ -151,7 +151,7 @@ fn parse_tree<'a>( // during parsing. let mut next = outer_trees.next(); let mut trees: Box<dyn Iterator<Item = &tokenstream::TokenTree>>; - if let Some(tokenstream::TokenTree::Delimited(_, Delimiter::Invisible, tts)) = next { + if let Some(tokenstream::TokenTree::Delimited(.., Delimiter::Invisible, tts)) = next { trees = Box::new(tts.trees()); next = trees.next(); } else { @@ -160,7 +160,7 @@ fn parse_tree<'a>( match next { // `tree` is followed by a delimited set of token trees. - Some(&tokenstream::TokenTree::Delimited(delim_span, delim, ref tts)) => { + Some(&tokenstream::TokenTree::Delimited(delim_span, _, delim, ref tts)) => { if parsing_patterns { if delim != Delimiter::Parenthesis { span_dollar_dollar_or_metavar_in_the_lhs_err( @@ -174,7 +174,7 @@ fn parse_tree<'a>( // The delimiter is `{`. This indicates the beginning // of a meta-variable expression (e.g. `${count(ident)}`). // Try to parse the meta-variable expression. - match MetaVarExpr::parse(&tts, delim_span.entire(), sess) { + match MetaVarExpr::parse(tts, delim_span.entire(), sess) { Err(mut err) => { err.emit(); // Returns early the same read `$` to avoid spanning @@ -195,7 +195,7 @@ fn parse_tree<'a>( _ => { let tok = pprust::token_kind_to_string(&token::OpenDelim(delim)); let msg = format!("expected `(` or `{{`, found `{tok}`"); - sess.span_diagnostic.span_err(delim_span.entire(), msg); + sess.dcx.span_err(delim_span.entire(), msg); } } } @@ -242,11 +242,9 @@ fn parse_tree<'a>( // `tree` is followed by some other token. This is an error. Some(tokenstream::TokenTree::Token(token, _)) => { - let msg = format!( - "expected identifier, found `{}`", - pprust::token_to_string(&token), - ); - sess.span_diagnostic.span_err(token.span, msg); + let msg = + format!("expected identifier, found `{}`", pprust::token_to_string(token),); + sess.dcx.span_err(token.span, msg); TokenTree::MetaVar(token.span, Ident::empty()) } @@ -260,8 +258,9 @@ fn parse_tree<'a>( // `tree` is the beginning of a delimited set of tokens (e.g., `(` or `{`). We need to // descend into the delimited set and further parse it. - &tokenstream::TokenTree::Delimited(span, delim, ref tts) => TokenTree::Delimited( + &tokenstream::TokenTree::Delimited(span, spacing, delim, ref tts) => TokenTree::Delimited( span, + spacing, Delimited { delim, tts: parse(tts, parsing_patterns, sess, node_id, features, edition), @@ -291,7 +290,7 @@ fn parse_kleene_op<'a>( span: Span, ) -> Result<Result<(KleeneOp, Span), Token>, Span> { match input.next() { - Some(tokenstream::TokenTree::Token(token, _)) => match kleene_op(&token) { + Some(tokenstream::TokenTree::Token(token, _)) => match kleene_op(token) { Some(op) => Ok(Ok((op, token.span))), None => Ok(Err(token.clone())), }, @@ -326,7 +325,7 @@ fn parse_sep_and_kleene_op<'a>( // #2 is the `?` Kleene op, which does not take a separator (error) Ok(Ok((KleeneOp::ZeroOrOne, span))) => { // Error! - sess.span_diagnostic.span_err( + sess.dcx.span_err( token.span, "the `?` macro repetition operator does not take a separator", ); @@ -347,7 +346,7 @@ fn parse_sep_and_kleene_op<'a>( }; // If we ever get to this point, we have experienced an "unexpected token" error - sess.span_diagnostic.span_err(span, "expected one of: `*`, `+`, or `?`"); + sess.dcx.span_err(span, "expected one of: `*`, `+`, or `?`"); // Return a dummy (None, KleeneToken::new(KleeneOp::ZeroOrMore, span)) @@ -357,9 +356,8 @@ fn parse_sep_and_kleene_op<'a>( // // For example, `macro_rules! foo { ( ${length()} ) => {} }` fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &ParseSess, token: &Token) { - sess.span_diagnostic - .span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token))); - sess.span_diagnostic.span_note_without_error( + sess.dcx.span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token))); + sess.dcx.span_note( token.span, "`$$` and meta-variable expressions are not allowed inside macro parameter definitions", ); diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 15e7ab3fe3e..f2a9875ffd2 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -7,10 +7,10 @@ use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree, use crate::mbe::{self, MetaVarExpr}; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; -use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_data_structures::fx::FxHashMap; +use rustc_errors::DiagnosticBuilder; use rustc_errors::{pluralize, PResult}; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_span::hygiene::{LocalExpnId, Transparency}; use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent}; use rustc_span::Span; @@ -31,14 +31,24 @@ impl MutVisitor for Marker { /// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). enum Frame<'a> { - Delimited { tts: &'a [mbe::TokenTree], idx: usize, delim: Delimiter, span: DelimSpan }, - Sequence { tts: &'a [mbe::TokenTree], idx: usize, sep: Option<Token> }, + Delimited { + tts: &'a [mbe::TokenTree], + idx: usize, + delim: Delimiter, + span: DelimSpan, + spacing: DelimSpacing, + }, + Sequence { + tts: &'a [mbe::TokenTree], + idx: usize, + sep: Option<Token>, + }, } impl<'a> Frame<'a> { /// Construct a new frame around the delimited set of tokens. - fn new(src: &'a mbe::Delimited, span: DelimSpan) -> Frame<'a> { - Frame::Delimited { tts: &src.tts, idx: 0, delim: src.delim, span } + fn new(src: &'a mbe::Delimited, span: DelimSpan, spacing: DelimSpacing) -> Frame<'a> { + Frame::Delimited { tts: &src.tts, idx: 0, delim: src.delim, span, spacing } } } @@ -89,8 +99,10 @@ pub(super) fn transcribe<'a>( } // We descend into the RHS (`src`), expanding things as we go. This stack contains the things - // we have yet to expand/are still expanding. We start the stack off with the whole RHS. - let mut stack: SmallVec<[Frame<'_>; 1]> = smallvec![Frame::new(&src, src_span)]; + // we have yet to expand/are still expanding. We start the stack off with the whole RHS. The + // choice of spacing values doesn't matter. + let mut stack: SmallVec<[Frame<'_>; 1]> = + smallvec![Frame::new(src, src_span, DelimSpacing::new(Spacing::Alone, Spacing::Alone))]; // As we descend in the RHS, we will need to be able to match nested sequences of matchers. // `repeats` keeps track of where we are in matching at each level, with the last element being @@ -144,14 +156,19 @@ pub(super) fn transcribe<'a>( // We are done processing a Delimited. If this is the top-level delimited, we are // done. Otherwise, we unwind the result_stack to append what we have produced to // any previous results. - Frame::Delimited { delim, span, .. } => { + Frame::Delimited { delim, span, mut spacing, .. } => { + // Hack to force-insert a space after `]` in certain case. + // See discussion of the `hex-literal` crate in #114571. + if delim == Delimiter::Bracket { + spacing.close = Spacing::Alone; + } if result_stack.is_empty() { // No results left to compute! We are back at the top-level. return Ok(TokenStream::new(result)); } // Step back into the parent Delimited. - let tree = TokenTree::Delimited(span, delim, TokenStream::new(result)); + let tree = TokenTree::Delimited(span, spacing, delim, TokenStream::new(result)); result = result_stack.pop().unwrap(); result.push(tree); } @@ -166,9 +183,11 @@ pub(super) fn transcribe<'a>( // and the matches in `interp` have the same shape. Otherwise, either the caller or the // macro writer has made a mistake. seq @ mbe::TokenTree::Sequence(_, delimited) => { - match lockstep_iter_size(&seq, interp, &repeats) { + match lockstep_iter_size(seq, interp, &repeats) { LockstepIterSize::Unconstrained => { - return Err(cx.create_err(NoSyntaxVarsExprRepeat { span: seq.span() })); + return Err(cx + .dcx() + .create_err(NoSyntaxVarsExprRepeat { span: seq.span() })); } LockstepIterSize::Contradiction(msg) => { @@ -176,7 +195,9 @@ pub(super) fn transcribe<'a>( // happens when two meta-variables are used in the same repetition in a // sequence, but they come from different sequence matchers and repeat // different amounts. - return Err(cx.create_err(MetaVarsDifSeqMatchers { span: seq.span(), msg })); + return Err(cx + .dcx() + .create_err(MetaVarsDifSeqMatchers { span: seq.span(), msg })); } LockstepIterSize::Constraint(len, _) => { @@ -190,7 +211,9 @@ pub(super) fn transcribe<'a>( // FIXME: this really ought to be caught at macro definition // time... It happens when the Kleene operator in the matcher and // the body for the same meta-variable do not match. - return Err(cx.create_err(MustRepeatOnce { span: sp.entire() })); + return Err(cx + .dcx() + .create_err(MustRepeatOnce { span: sp.entire() })); } } else { // 0 is the initial counter (we have done 0 repetitions so far). `len` @@ -232,7 +255,7 @@ pub(super) fn transcribe<'a>( } MatchedSeq(..) => { // We were unable to descend far enough. This is an error. - return Err(cx.create_err(VarStillRepeating { span: sp, ident })); + return Err(cx.dcx().create_err(VarStillRepeating { span: sp, ident })); } } } else { @@ -240,7 +263,7 @@ pub(super) fn transcribe<'a>( // with modified syntax context. (I believe this supports nested macros). marker.visit_span(&mut sp); marker.visit_ident(&mut original_ident); - result.push(TokenTree::token_alone(token::Dollar, sp)); + result.push(TokenTree::token_joint_hidden(token::Dollar, sp)); result.push(TokenTree::Token( Token::from_ast_ident(original_ident), Spacing::Alone, @@ -250,7 +273,7 @@ pub(super) fn transcribe<'a>( // Replace meta-variable expressions with the result of their expansion. mbe::TokenTree::MetaVarExpr(sp, expr) => { - transcribe_metavar_expr(cx, expr, interp, &mut marker, &repeats, &mut result, &sp)?; + transcribe_metavar_expr(cx, expr, interp, &mut marker, &repeats, &mut result, sp)?; } // If we are entering a new delimiter, we push its contents to the `stack` to be @@ -258,13 +281,14 @@ pub(super) fn transcribe<'a>( // We will produce all of the results of the inside of the `Delimited` and then we will // jump back out of the Delimited, pop the result_stack and add the new results back to // the previous results (from outside the Delimited). - mbe::TokenTree::Delimited(mut span, delimited) => { + mbe::TokenTree::Delimited(mut span, spacing, delimited) => { mut_visit::visit_delim_span(&mut span, &mut marker); stack.push(Frame::Delimited { tts: &delimited.tts, delim: delimited.delim, idx: 0, span, + spacing: *spacing, }); result_stack.push(mem::take(&mut result)); } @@ -374,7 +398,7 @@ fn lockstep_iter_size( ) -> LockstepIterSize { use mbe::TokenTree; match tree { - TokenTree::Delimited(_, delimited) => { + TokenTree::Delimited(.., delimited) => { delimited.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { size.with(lockstep_iter_size(tt, interpolations, repeats)) }) @@ -422,7 +446,7 @@ fn lockstep_iter_size( /// declared inside a single repetition and the index `1` implies two nested repetitions. fn count_repetitions<'a>( cx: &ExtCtxt<'a>, - depth_opt: Option<usize>, + depth_user: usize, mut matched: &NamedMatch, repeats: &[(usize, usize)], sp: &DelimSpan, @@ -431,37 +455,45 @@ fn count_repetitions<'a>( // (or at the top-level of `matched` if no depth is given). fn count<'a>( cx: &ExtCtxt<'a>, - declared_lhs_depth: usize, - depth_opt: Option<usize>, + depth_curr: usize, + depth_max: usize, matched: &NamedMatch, sp: &DelimSpan, ) -> PResult<'a, usize> { match matched { - MatchedTokenTree(_) | MatchedNonterminal(_) => { - if declared_lhs_depth == 0 { - return Err(cx.create_err(CountRepetitionMisplaced { span: sp.entire() })); - } - match depth_opt { - None => Ok(1), - Some(_) => Err(out_of_bounds_err(cx, declared_lhs_depth, sp.entire(), "count")), - } - } + MatchedTokenTree(_) | MatchedNonterminal(_) => Ok(1), MatchedSeq(named_matches) => { - let new_declared_lhs_depth = declared_lhs_depth + 1; - match depth_opt { - None => named_matches - .iter() - .map(|elem| count(cx, new_declared_lhs_depth, None, elem, sp)) - .sum(), - Some(0) => Ok(named_matches.len()), - Some(depth) => named_matches + if depth_curr == depth_max { + Ok(named_matches.len()) + } else { + named_matches .iter() - .map(|elem| count(cx, new_declared_lhs_depth, Some(depth - 1), elem, sp)) - .sum(), + .map(|elem| count(cx, depth_curr + 1, depth_max, elem, sp)) + .sum() } } } } + + /// Maximum depth + fn depth(counter: usize, matched: &NamedMatch) -> usize { + match matched { + MatchedTokenTree(_) | MatchedNonterminal(_) => counter, + MatchedSeq(named_matches) => { + let rslt = counter + 1; + if let Some(elem) = named_matches.first() { depth(rslt, elem) } else { rslt } + } + } + } + + let depth_max = depth(0, matched) + .checked_sub(1) + .and_then(|el| el.checked_sub(repeats.len())) + .unwrap_or_default(); + if depth_user > depth_max { + return Err(out_of_bounds_err(cx, depth_max + 1, sp.entire(), "count")); + } + // `repeats` records all of the nested levels at which we are currently // matching meta-variables. The meta-var-expr `count($x)` only counts // matches that occur in this "subtree" of the `NamedMatch` where we @@ -473,7 +505,12 @@ fn count_repetitions<'a>( matched = &ads[idx]; } } - count(cx, 0, depth_opt, matched, sp) + + if let MatchedTokenTree(_) | MatchedNonterminal(_) = matched { + return Err(cx.dcx().create_err(CountRepetitionMisplaced { span: sp.entire() })); + } + + count(cx, depth_user, depth_max, matched, sp) } /// Returns a `NamedMatch` item declared on the LHS given an arbitrary [Ident] @@ -487,7 +524,7 @@ where { let span = ident.span; let key = MacroRulesNormalizedIdent::new(ident); - interp.get(&key).ok_or_else(|| cx.create_err(MetaVarExprUnrecognizedVar { span, key })) + interp.get(&key).ok_or_else(|| cx.dcx().create_err(MetaVarExprUnrecognizedVar { span, key })) } /// Used by meta-variable expressions when an user input is out of the actual declared bounds. For @@ -497,7 +534,7 @@ fn out_of_bounds_err<'a>( max: usize, span: Span, ty: &str, -) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +) -> DiagnosticBuilder<'a> { let msg = if max == 0 { format!( "meta-variable expression `{ty}` with depth parameter \ @@ -505,11 +542,11 @@ fn out_of_bounds_err<'a>( ) } else { format!( - "depth parameter on meta-variable expression `{ty}` \ + "depth parameter of meta-variable expression `{ty}` \ must be less than {max}" ) }; - cx.struct_span_err(span, msg) + cx.dcx().struct_span_err(span, msg) } fn transcribe_metavar_expr<'a>( @@ -527,9 +564,9 @@ fn transcribe_metavar_expr<'a>( span }; match *expr { - MetaVarExpr::Count(original_ident, depth_opt) => { + MetaVarExpr::Count(original_ident, depth) => { let matched = matched_from_ident(cx, original_ident, interp)?; - let count = count_repetitions(cx, depth_opt, matched, &repeats, sp)?; + let count = count_repetitions(cx, depth, matched, repeats, sp)?; let tt = TokenTree::token_alone( TokenKind::lit(token::Integer, sym::integer(count), None), visited_span(), diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index df6bdc6952b..60647c3350a 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -43,7 +43,7 @@ pub enum ModError<'a> { ModInBlock(Option<Ident>), FileNotFound(Ident, PathBuf, PathBuf), MultipleCandidates(Ident, PathBuf, PathBuf), - ParserError(DiagnosticBuilder<'a, ErrorGuaranteed>), + ParserError(DiagnosticBuilder<'a>), } pub(crate) fn parse_external_mod( @@ -57,7 +57,7 @@ pub(crate) fn parse_external_mod( // We bail on the first error, but that error does not cause a fatal error... (1) let result: Result<_, ModError<'_>> = try { // Extract the file path and the new ownership. - let mp = mod_file_path(sess, ident, &attrs, &module.dir_path, dir_ownership)?; + let mp = mod_file_path(sess, ident, attrs, &module.dir_path, dir_ownership)?; dir_ownership = mp.dir_ownership; // Ensure file paths are acyclic. @@ -119,7 +119,7 @@ pub(crate) fn mod_dir_path( Inline::No => { // FIXME: This is a subset of `parse_external_mod` without actual parsing, // check whether the logic for unloaded, loaded and inline modules can be unified. - let file_path = mod_file_path(sess, ident, &attrs, &module.dir_path, dir_ownership) + let file_path = mod_file_path(sess, ident, attrs, &module.dir_path, dir_ownership) .map(|mp| { dir_ownership = mp.dir_ownership; mp.file_path @@ -260,14 +260,14 @@ impl ModError<'_> { let modules = paths.join(" -> "); - sess.emit_err(ModuleCircular { span, modules }) + sess.dcx().emit_err(ModuleCircular { span, modules }) } - ModError::ModInBlock(ident) => sess.emit_err(ModuleInBlock { + ModError::ModInBlock(ident) => sess.dcx().emit_err(ModuleInBlock { span, name: ident.map(|name| ModuleInBlockName { span, name }), }), ModError::FileNotFound(name, default_path, secondary_path) => { - sess.emit_err(ModuleFileNotFound { + sess.dcx().emit_err(ModuleFileNotFound { span, name, default_path: default_path.display().to_string(), @@ -275,7 +275,7 @@ impl ModError<'_> { }) } ModError::MultipleCandidates(name, default_path, secondary_path) => { - sess.emit_err(ModuleMultipleCandidates { + sess.dcx().emit_err(ModuleMultipleCandidates { span, name, default_path: default_path.display().to_string(), diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs index bdc20882a9d..7a888250ca1 100644 --- a/compiler/rustc_expand/src/parse/tests.rs +++ b/compiler/rustc_expand/src/parse/tests.rs @@ -4,7 +4,7 @@ use crate::tests::{ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token}; -use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast::visit; use rustc_ast::{self as ast, PatKind}; use rustc_ast_pretty::pprust::item_to_string; @@ -77,14 +77,14 @@ fn string_to_tts_macro() { TokenTree::Token(Token { kind: token::Ident(name_macro_rules, false), .. }, _), TokenTree::Token(Token { kind: token::Not, .. }, _), TokenTree::Token(Token { kind: token::Ident(name_zip, false), .. }, _), - TokenTree::Delimited(_, macro_delim, macro_tts), + TokenTree::Delimited(.., macro_delim, macro_tts), ] if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => { let tts = ¯o_tts.trees().collect::<Vec<_>>(); match &tts[..] { [ - TokenTree::Delimited(_, first_delim, first_tts), + TokenTree::Delimited(.., first_delim, first_tts), TokenTree::Token(Token { kind: token::FatArrow, .. }, _), - TokenTree::Delimited(_, second_delim, second_tts), + TokenTree::Delimited(.., second_delim, second_tts), ] if macro_delim == &Delimiter::Parenthesis => { let tts = &first_tts.trees().collect::<Vec<_>>(); match &tts[..] { @@ -116,27 +116,36 @@ fn string_to_tts_macro() { #[test] fn string_to_tts_1() { create_default_session_globals_then(|| { - let tts = string_to_stream("fn a (b : i32) { b; }".to_string()); + let tts = string_to_stream("fn a(b: i32) { b; }".to_string()); let expected = TokenStream::new(vec![ TokenTree::token_alone(token::Ident(kw::Fn, false), sp(0, 2)), - TokenTree::token_alone(token::Ident(Symbol::intern("a"), false), sp(3, 4)), + TokenTree::token_joint_hidden(token::Ident(Symbol::intern("a"), false), sp(3, 4)), TokenTree::Delimited( - DelimSpan::from_pair(sp(5, 6), sp(13, 14)), + DelimSpan::from_pair(sp(4, 5), sp(11, 12)), + // `JointHidden` because the `(` is followed immediately by + // `b`, `Alone` because the `)` is followed by whitespace. + DelimSpacing::new(Spacing::JointHidden, Spacing::Alone), Delimiter::Parenthesis, TokenStream::new(vec![ - TokenTree::token_alone(token::Ident(Symbol::intern("b"), false), sp(6, 7)), - TokenTree::token_alone(token::Colon, sp(8, 9)), - TokenTree::token_alone(token::Ident(sym::i32, false), sp(10, 13)), + TokenTree::token_joint(token::Ident(Symbol::intern("b"), false), sp(5, 6)), + TokenTree::token_alone(token::Colon, sp(6, 7)), + // `JointHidden` because the `i32` is immediately followed by the `)`. + TokenTree::token_joint_hidden(token::Ident(sym::i32, false), sp(8, 11)), ]) .into(), ), TokenTree::Delimited( - DelimSpan::from_pair(sp(15, 16), sp(20, 21)), + DelimSpan::from_pair(sp(13, 14), sp(18, 19)), + // First `Alone` because the `{` is followed by whitespace, + // second `Alone` because the `}` is followed immediately by + // EOF. + DelimSpacing::new(Spacing::Alone, Spacing::Alone), Delimiter::Brace, TokenStream::new(vec![ - TokenTree::token_joint(token::Ident(Symbol::intern("b"), false), sp(17, 18)), - TokenTree::token_alone(token::Semi, sp(18, 19)), + TokenTree::token_joint(token::Ident(Symbol::intern("b"), false), sp(15, 16)), + // `Alone` because the `;` is followed by whitespace. + TokenTree::token_alone(token::Semi, sp(16, 17)), ]) .into(), ), diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 1292a855230..2c4187031ca 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -119,7 +119,7 @@ pub fn placeholder( }]), AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm { attrs: Default::default(), - body: expr_placeholder(), + body: Some(expr_placeholder()), guard: None, id, pat: pat(), @@ -174,7 +174,7 @@ pub fn placeholder( }]), AstFragmentKind::Variants => AstFragment::Variants(smallvec![ast::Variant { attrs: Default::default(), - data: ast::VariantData::Struct(Default::default(), false), + data: ast::VariantData::Struct { fields: Default::default(), recovered: false }, disr_expr: None, id, ident, diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 39a16259fa6..73a7d433b5c 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -61,7 +61,7 @@ impl base::BangProcMacro for BangProcMacro { let strategy = exec_strategy(ecx); let server = proc_macro_server::Rustc::new(ecx); self.client.run(&strategy, server, input, proc_macro_backtrace).map_err(|e| { - ecx.sess.emit_err(errors::ProcMacroPanicked { + ecx.dcx().emit_err(errors::ProcMacroPanicked { span, message: e .as_str() @@ -93,7 +93,7 @@ impl base::AttrProcMacro for AttrProcMacro { let server = proc_macro_server::Rustc::new(ecx); self.client.run(&strategy, server, annotation, annotated, proc_macro_backtrace).map_err( |e| { - let mut err = ecx.struct_span_err(span, "custom attribute panicked"); + let mut err = ecx.dcx().struct_span_err(span, "custom attribute panicked"); if let Some(s) = e.as_str() { err.help(format!("message: {s}")); } @@ -146,7 +146,7 @@ impl MultiItemModifier for DeriveProcMacro { match self.client.run(&strategy, server, input, proc_macro_backtrace) { Ok(stream) => stream, Err(e) => { - let mut err = ecx.struct_span_err(span, "proc-macro derive panicked"); + let mut err = ecx.dcx().struct_span_err(span, "proc-macro derive panicked"); if let Some(s) = e.as_str() { err.help(format!("message: {s}")); } @@ -156,7 +156,7 @@ impl MultiItemModifier for DeriveProcMacro { } }; - let error_count_before = ecx.sess.parse_sess.span_diagnostic.err_count(); + let error_count_before = ecx.dcx().err_count(); let mut parser = rustc_parse::stream_to_parser(&ecx.sess.parse_sess, stream, Some("proc-macro derive")); let mut items = vec![]; @@ -179,8 +179,8 @@ impl MultiItemModifier for DeriveProcMacro { } // fail if there have been errors emitted - if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before { - ecx.sess.emit_err(errors::ProcMacroDeriveTokens { span }); + if ecx.dcx().err_count() > error_count_before { + ecx.dcx().emit_err(errors::ProcMacroDeriveTokens { span }); } ExpandResult::Ready(items) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 41ec0ed84f7..5eb6aed7253 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -5,7 +5,7 @@ use pm::bridge::{ use pm::{Delimiter, Level}; use rustc_ast as ast; use rustc_ast::token; -use rustc_ast::tokenstream::{self, Spacing::*, TokenStream}; +use rustc_ast::tokenstream::{self, DelimSpacing, Spacing, TokenStream}; use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; @@ -98,7 +98,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre while let Some(tree) = cursor.next() { let (Token { kind, span }, joint) = match tree.clone() { - tokenstream::TokenTree::Delimited(span, delim, tts) => { + tokenstream::TokenTree::Delimited(span, _, delim, tts) => { let delimiter = pm::Delimiter::from_internal(delim); trees.push(TokenTree::Group(Group { delimiter, @@ -111,7 +111,22 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre })); continue; } - tokenstream::TokenTree::Token(token, spacing) => (token, spacing == Joint), + tokenstream::TokenTree::Token(token, spacing) => { + // Do not be tempted to check here that the `spacing` + // values are "correct" w.r.t. the token stream (e.g. that + // `Spacing::Joint` is actually followed by a `Punct` token + // tree). Because the problem in #76399 was introduced that + // way. + // + // This is where the `Hidden` in `JointHidden` applies, + // because the jointness is effectively hidden from proc + // macros. + let joint = match spacing { + Spacing::Alone | Spacing::JointHidden => false, + Spacing::Joint => true, + }; + (token, joint) + } }; // Split the operator into one or more `Punct`s, one per character. @@ -133,7 +148,8 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre } else { span }; - TokenTree::Punct(Punct { ch, joint: if is_final { joint } else { true }, span }) + let joint = if is_final { joint } else { true }; + TokenTree::Punct(Punct { ch, joint, span }) })); }; @@ -268,6 +284,11 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>> fn to_internal(self) -> SmallVec<[tokenstream::TokenTree; 2]> { use rustc_ast::token::*; + // The code below is conservative, using `token_alone`/`Spacing::Alone` + // in most places. When the resulting code is pretty-printed by + // `print_tts` it ends up with spaces between most tokens, which is + // safe but ugly. It's hard in general to do better when working at the + // token level. let (tree, rustc) = self; match tree { TokenTree::Punct(Punct { ch, joint, span }) => { @@ -296,6 +317,11 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>> b'\'' => SingleQuote, _ => unreachable!(), }; + // We never produce `token::Spacing::JointHidden` here, which + // means the pretty-printing of code produced by proc macros is + // ugly, with lots of whitespace between tokens. This is + // unavoidable because `proc_macro::Spacing` only applies to + // `Punct` token trees. smallvec![if joint { tokenstream::TokenTree::token_joint(kind, span) } else { @@ -305,6 +331,7 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>> TokenTree::Group(Group { delimiter, stream, span: DelimSpan { open, close, .. } }) => { smallvec![tokenstream::TokenTree::Delimited( tokenstream::DelimSpan { open, close }, + DelimSpacing::new(Spacing::Alone, Spacing::Alone), delimiter.to_internal(), stream.unwrap_or_default(), )] @@ -322,7 +349,7 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>> let minus = BinOp(BinOpToken::Minus); let symbol = Symbol::intern(&symbol.as_str()[1..]); let integer = TokenKind::lit(token::Integer, symbol, suffix); - let a = tokenstream::TokenTree::token_alone(minus, span); + let a = tokenstream::TokenTree::token_joint_hidden(minus, span); let b = tokenstream::TokenTree::token_alone(integer, span); smallvec![a, b] } @@ -335,7 +362,7 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>> let minus = BinOp(BinOpToken::Minus); let symbol = Symbol::intern(&symbol.as_str()[1..]); let float = TokenKind::lit(token::Float, symbol, suffix); - let a = tokenstream::TokenTree::token_alone(minus, span); + let a = tokenstream::TokenTree::token_joint_hidden(minus, span); let b = tokenstream::TokenTree::token_alone(float, span); smallvec![a, b] } @@ -399,6 +426,10 @@ impl server::Types for Rustc<'_, '_> { } impl server::FreeFunctions for Rustc<'_, '_> { + fn injected_env_var(&mut self, var: &str) -> Option<String> { + self.ecx.sess.opts.logical_env.get(var).cloned() + } + fn track_env_var(&mut self, var: &str, value: Option<&str>) { self.sess() .env_depinfo @@ -468,14 +499,9 @@ impl server::FreeFunctions for Rustc<'_, '_> { rustc_errors::Diagnostic::new(diagnostic.level.to_internal(), diagnostic.message); diag.set_span(MultiSpan::from_spans(diagnostic.spans)); for child in diagnostic.children { - diag.sub( - child.level.to_internal(), - child.message, - MultiSpan::from_spans(child.spans), - None, - ); + diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans)); } - self.sess().span_diagnostic.emit_diagnostic(&mut diag); + self.sess().dcx.emit_diagnostic(diag); } } @@ -546,7 +572,10 @@ impl server::TokenStream for Rustc<'_, '_> { Ok(Self::TokenStream::from_iter([ // FIXME: The span of the `-` token is lost when // parsing, so we cannot faithfully recover it here. - tokenstream::TokenTree::token_alone(token::BinOp(token::Minus), e.span), + tokenstream::TokenTree::token_joint_hidden( + token::BinOp(token::Minus), + e.span, + ), tokenstream::TokenTree::token_alone(token::Literal(*token_lit), e.span), ])) } @@ -784,6 +813,6 @@ impl server::Server for Rustc<'_, '_> { } fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) { - f(&symbol.as_str()) + f(symbol.as_str()) } } diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index 9f52669e188..0b859841828 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -8,7 +8,7 @@ use rustc_span::{BytePos, Span}; use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::EmitterWriter; -use rustc_errors::{Handler, MultiSpan, PResult}; +use rustc_errors::{DiagCtxt, MultiSpan, PResult}; use termcolor::WriteColor; use std::io; @@ -23,7 +23,7 @@ fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> { new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str) } -fn create_test_handler() -> (Handler, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) { +fn create_test_handler() -> (DiagCtxt, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) { let output = Arc::new(Mutex::new(Vec::new())); let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let fallback_bundle = rustc_errors::fallback_fluent_bundle( @@ -33,8 +33,8 @@ fn create_test_handler() -> (Handler, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) { let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), fallback_bundle) .sm(Some(source_map.clone())) .diagnostic_width(Some(140)); - let handler = Handler::with_emitter(Box::new(emitter)); - (handler, source_map, output) + let dcx = DiagCtxt::with_emitter(Box::new(emitter)); + (dcx, source_map, output) } /// Returns the result of parsing the given string via the given callback. @@ -46,7 +46,7 @@ where { let mut p = string_to_parser(&ps, s); let x = f(&mut p).unwrap(); - p.sess.span_diagnostic.abort_if_errors(); + p.sess.dcx.abort_if_errors(); x } @@ -57,7 +57,7 @@ where F: for<'a> FnOnce(&mut Parser<'a>) -> PResult<'a, T>, { let (handler, source_map, output) = create_test_handler(); - let ps = ParseSess::with_span_handler(handler, source_map); + let ps = ParseSess::with_dcx(handler, source_map); let mut p = string_to_parser(&ps, source_str.to_string()); let result = f(&mut p); assert!(result.is_ok()); @@ -135,7 +135,7 @@ pub(crate) fn matches_codepattern(a: &str, b: &str) -> bool { /// Advances the given peekable `Iterator` until it reaches a non-whitespace character. fn scan_for_non_ws_or_end<I: Iterator<Item = char>>(iter: &mut Peekable<I>) { - while iter.peek().copied().map(rustc_lexer::is_whitespace) == Some(true) { + while iter.peek().copied().is_some_and(rustc_lexer::is_whitespace) { iter.next(); } } |
