Auto merge of #65433 - Centril:rollup-rzvry15, r=Centril
Rollup of 4 pull requests
Successful merges:
- #64035 (Stabilize proc macros generating `macro_rules` items)
- #65376 (syntax: misc extractions)
- #65426 (Remove custom `PartialEq` impls for `LocalInternedString`.)
- #65428 (Refactor: Rename `db` locals to `diag`)
Failed merges:
r? @ghost
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 747848e..ab5a3c0 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -67,11 +67,11 @@
use syntax::ext::base::SpecialDerives;
use syntax::ext::hygiene::ExpnId;
use syntax::print::pprust;
-use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned};
-use syntax::symbol::{kw, sym, Symbol};
use syntax::tokenstream::{TokenStream, TokenTree};
use syntax::parse::token::{self, Nonterminal, Token};
-use syntax::parse::ParseSess;
+use syntax::sess::ParseSess;
+use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned};
+use syntax::symbol::{kw, sym, Symbol};
use syntax::visit::{self, Visitor};
use syntax_pos::Span;
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 6cffaa8..b852098 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1,10 +1,10 @@
use rustc_target::spec::abi::Abi;
use syntax::ast;
use syntax::source_map::{SourceMap, Spanned};
-use syntax::parse::ParseSess;
use syntax::print::pp::{self, Breaks};
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
use syntax::print::pprust::{self, Comments, PrintState};
+use syntax::sess::ParseSess;
use syntax::symbol::kw;
use syntax::util::parser::{self, AssocOp, Fixity};
use syntax_pos::{self, BytePos, FileName};
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 197ca19..8943fc3 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -56,7 +56,7 @@
#![feature(test)]
#![feature(in_band_lifetimes)]
#![feature(crate_visibility_modifier)]
-#![feature(proc_macro_hygiene)]
+#![cfg_attr(bootstrap, feature(proc_macro_hygiene))]
#![feature(log_syntax)]
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 2517141..675e3bb 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -16,8 +16,9 @@
use syntax::ast::{self, IntTy, UintTy, MetaItemKind};
use syntax::source_map::{FileName, FilePathMapping};
use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
-use syntax::parse::{ParseSess, new_parser_from_source_str};
+use syntax::parse::new_parser_from_source_str;
use syntax::parse::token;
+use syntax::sess::ParseSess;
use syntax::symbol::{sym, Symbol};
use syntax::feature_gate::UnstableFeatures;
use syntax::source_map::SourceMap;
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index fa2902e..c59df14 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -28,7 +28,7 @@
use syntax::feature_gate::{self, AttributeType};
use syntax::json::JsonEmitter;
use syntax::source_map;
-use syntax::parse::{self, ParseSess};
+use syntax::sess::ParseSess;
use syntax::symbol::Symbol;
use syntax_pos::{MultiSpan, Span};
use crate::util::profiling::{SelfProfiler, SelfProfilerRef};
@@ -1159,7 +1159,7 @@
);
let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
- let parse_sess = parse::ParseSess::with_span_handler(
+ let parse_sess = ParseSess::with_span_handler(
span_diagnostic,
source_map,
);
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index ef3b115..5339134 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -1667,13 +1667,13 @@
}
impl Emitter for SharedEmitter {
- fn emit_diagnostic(&mut self, db: &rustc_errors::Diagnostic) {
+ fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
- msg: db.message(),
- code: db.code.clone(),
- lvl: db.level,
+ msg: diag.message(),
+ code: diag.code.clone(),
+ lvl: diag.level,
})));
- for child in &db.children {
+ for child in &diag.children {
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
msg: child.message(),
code: None,
diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs
index 16a1a28..491bc2a 100644
--- a/src/librustc_errors/annotate_snippet_emitter_writer.rs
+++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs
@@ -31,19 +31,19 @@
impl Emitter for AnnotateSnippetEmitterWriter {
/// The entry point for the diagnostics generation
- fn emit_diagnostic(&mut self, db: &Diagnostic) {
- let mut children = db.children.clone();
- let (mut primary_span, suggestions) = self.primary_span_formatted(&db);
+ fn emit_diagnostic(&mut self, diag: &Diagnostic) {
+ let mut children = diag.children.clone();
+ let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
self.fix_multispans_in_std_macros(&self.source_map,
&mut primary_span,
&mut children,
- &db.level,
+ &diag.level,
self.external_macro_backtrace);
- self.emit_messages_default(&db.level,
- db.message(),
- &db.code,
+ self.emit_messages_default(&diag.level,
+ diag.message(),
+ &diag.code,
&primary_span,
&children,
&suggestions);
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 8440009..1e48678 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -180,7 +180,7 @@
/// Emitter trait for emitting errors.
pub trait Emitter {
/// Emit a structured diagnostic.
- fn emit_diagnostic(&mut self, db: &Diagnostic);
+ fn emit_diagnostic(&mut self, diag: &Diagnostic);
/// Emit a notification that an artifact has been output.
/// This is currently only supported for the JSON format,
@@ -206,10 +206,10 @@
/// we return the original `primary_span` and the original suggestions.
fn primary_span_formatted<'a>(
&mut self,
- db: &'a Diagnostic,
+ diag: &'a Diagnostic,
) -> (MultiSpan, &'a [CodeSuggestion]) {
- let mut primary_span = db.span.clone();
- if let Some((sugg, rest)) = db.suggestions.split_first() {
+ let mut primary_span = diag.span.clone();
+ if let Some((sugg, rest)) = diag.suggestions.split_first() {
if rest.is_empty() &&
// ^ if there is only one suggestion
// don't display multi-suggestions as labels
@@ -260,10 +260,10 @@
// to be consistent. We could try to figure out if we can
// make one (or the first one) inline, but that would give
// undue importance to a semi-random suggestion
- (primary_span, &db.suggestions)
+ (primary_span, &diag.suggestions)
}
} else {
- (primary_span, &db.suggestions)
+ (primary_span, &diag.suggestions)
}
}
@@ -401,19 +401,19 @@
self.sm.as_ref()
}
- fn emit_diagnostic(&mut self, db: &Diagnostic) {
- let mut children = db.children.clone();
- let (mut primary_span, suggestions) = self.primary_span_formatted(&db);
+ fn emit_diagnostic(&mut self, diag: &Diagnostic) {
+ let mut children = diag.children.clone();
+ let (mut primary_span, suggestions) = self.primary_span_formatted(&diag);
self.fix_multispans_in_std_macros(&self.sm,
&mut primary_span,
&mut children,
- &db.level,
+ &diag.level,
self.external_macro_backtrace);
- self.emit_messages_default(&db.level,
- &db.styled_message(),
- &db.code,
+ self.emit_messages_default(&diag.level,
+ &diag.styled_message(),
+ &diag.code,
&primary_span,
&children,
&suggestions);
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index da3b52a..706f52d 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -9,7 +9,7 @@
use syntax::symbol::{Symbol, sym};
use syntax::ast::{MetaItem, MetaItemKind, NestedMetaItem, LitKind};
-use syntax::parse::ParseSess;
+use syntax::sess::ParseSess;
use syntax::feature_gate::Features;
use syntax_pos::Span;
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 5d86ee9..30c9453 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -14,7 +14,7 @@
use syntax::source_map::{SourceMap, FilePathMapping};
use syntax::parse::lexer;
use syntax::parse::token::{self, Token};
-use syntax::parse;
+use syntax::sess::ParseSess;
use syntax::symbol::{kw, sym};
use syntax_pos::{Span, FileName};
@@ -33,7 +33,7 @@
class, tooltip).unwrap();
}
- let sess = parse::ParseSess::new(FilePathMapping::empty());
+ let sess = ParseSess::new(FilePathMapping::empty());
let fm = sess.source_map().new_source_file(
FileName::Custom(String::from("rustdoc-highlighting")),
src.to_owned(),
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index 32044e4..10e15ab 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -1,6 +1,7 @@
use errors::Applicability;
use syntax::parse::lexer::{StringReader as Lexer};
-use syntax::parse::{ParseSess, token};
+use syntax::parse::token;
+use syntax::sess::ParseSess;
use syntax::source_map::FilePathMapping;
use syntax_pos::{InnerSpan, FileName};
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 05e6f36..0be6340 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -394,7 +394,7 @@
// Uses libsyntax to parse the doctest and find if there's a main fn and the extern
// crate already is included.
let (already_has_main, already_has_extern_crate, found_macro) = with_globals(edition, || {
- use crate::syntax::{parse::{self, ParseSess}, source_map::FilePathMapping};
+ use crate::syntax::{parse, sess::ParseSess, source_map::FilePathMapping};
use errors::emitter::EmitterWriter;
use errors::Handler;
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index efc4825..1fe698c 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -4,8 +4,8 @@
use crate::early_buffered_lints::BufferedEarlyLintId;
use crate::ext::base::ExtCtxt;
use crate::feature_gate::{Features, GatedCfg};
-use crate::parse::ParseSess;
use crate::print::pprust;
+use crate::sess::ParseSess;
use errors::{Applicability, Handler};
use syntax_pos::hygiene::Transparency;
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index c2c883f..d291e50 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -16,9 +16,10 @@
use crate::source_map::{BytePos, Spanned, DUMMY_SP};
use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
use crate::parse::parser::Parser;
-use crate::parse::{ParseSess, PResult};
+use crate::parse::PResult;
use crate::parse::token::{self, Token};
use crate::ptr::P;
+use crate::sess::ParseSess;
use crate::symbol::{sym, Symbol};
use crate::ThinVec;
use crate::tokenstream::{TokenStream, TokenTree, DelimSpan};
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 2923cc8..2099d01 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -10,8 +10,9 @@
use crate::ast;
use crate::edition::Edition;
use crate::mut_visit::*;
-use crate::parse::{token, ParseSess};
+use crate::parse::token;
use crate::ptr::P;
+use crate::sess::ParseSess;
use crate::symbol::sym;
use crate::util::map_in_place::MapInPlace;
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 583fb3f..01be564 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -5,9 +5,10 @@
use crate::ext::expand::{self, AstFragment, Invocation};
use crate::ext::hygiene::ExpnId;
use crate::mut_visit::{self, MutVisitor};
-use crate::parse::{self, parser, ParseSess, DirectoryOwnership};
+use crate::parse::{self, parser, DirectoryOwnership};
use crate::parse::token;
use crate::ptr::P;
+use crate::sess::ParseSess;
use crate::symbol::{kw, sym, Ident, Symbol};
use crate::{ThinVec, MACRO_ARGUMENTS};
use crate::tokenstream::{self, TokenStream};
@@ -892,7 +893,7 @@
/// when a macro expansion occurs, the resulting nodes have the `backtrace()
/// -> expn_data` of their expansion context stored into their span.
pub struct ExtCtxt<'a> {
- pub parse_sess: &'a parse::ParseSess,
+ pub parse_sess: &'a ParseSess,
pub ecfg: expand::ExpansionConfig<'a>,
pub root_path: PathBuf,
pub resolver: &'a mut dyn Resolver,
@@ -901,7 +902,7 @@
}
impl<'a> ExtCtxt<'a> {
- pub fn new(parse_sess: &'a parse::ParseSess,
+ pub fn new(parse_sess: &'a ParseSess,
ecfg: expand::ExpansionConfig<'a>,
resolver: &'a mut dyn Resolver)
-> ExtCtxt<'a> {
@@ -935,7 +936,7 @@
parse::stream_to_parser(self.parse_sess, stream, MACRO_ARGUMENTS)
}
pub fn source_map(&self) -> &'a SourceMap { self.parse_sess.source_map() }
- pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
+ pub fn parse_sess(&self) -> &'a ParseSess { self.parse_sess }
pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config }
pub fn call_site(&self) -> Span {
self.current_expansion.id.expn_data().call_site
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 9fcd918..2559e87 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -10,14 +10,14 @@
use crate::ext::placeholders::{placeholder, PlaceholderExpander};
use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
use crate::mut_visit::*;
-use crate::parse::{DirectoryOwnership, PResult, ParseSess};
+use crate::parse::{DirectoryOwnership, PResult};
use crate::parse::token;
use crate::parse::parser::Parser;
use crate::print::pprust;
use crate::ptr::P;
use crate::symbol::{sym, Symbol};
use crate::tokenstream::{TokenStream, TokenTree};
-use crate::visit::{self, Visitor};
+use crate::visit::Visitor;
use crate::util::map_in_place::MapInPlace;
use errors::{Applicability, FatalError};
@@ -577,10 +577,7 @@
SyntaxExtensionKind::Bang(expander) => {
self.gate_proc_macro_expansion_kind(span, fragment_kind);
let tok_result = expander.expand(self.cx, span, mac.stream());
- let result =
- self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span);
- self.gate_proc_macro_expansion(span, &result);
- result
+ self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
}
SyntaxExtensionKind::LegacyBang(expander) => {
let prev = self.cx.current_expansion.prior_type_ascription;
@@ -624,10 +621,7 @@
})), DUMMY_SP).into();
let input = self.extract_proc_macro_attr_input(attr.item.tokens, span);
let tok_result = expander.expand(self.cx, span, input, item_tok);
- let res =
- self.parse_ast_fragment(tok_result, fragment_kind, &attr.item.path, span);
- self.gate_proc_macro_expansion(span, &res);
- res
+ self.parse_ast_fragment(tok_result, fragment_kind, &attr.item.path, span)
}
SyntaxExtensionKind::LegacyAttr(expander) => {
match attr.parse_meta(self.cx.parse_sess) {
@@ -718,41 +712,6 @@
);
}
- fn gate_proc_macro_expansion(&self, span: Span, fragment: &AstFragment) {
- if self.cx.ecfg.proc_macro_hygiene() {
- return
- }
-
- fragment.visit_with(&mut DisallowMacros {
- span,
- parse_sess: self.cx.parse_sess,
- });
-
- struct DisallowMacros<'a> {
- span: Span,
- parse_sess: &'a ParseSess,
- }
-
- impl<'ast, 'a> Visitor<'ast> for DisallowMacros<'a> {
- fn visit_item(&mut self, i: &'ast ast::Item) {
- if let ast::ItemKind::MacroDef(_) = i.kind {
- emit_feature_err(
- self.parse_sess,
- sym::proc_macro_hygiene,
- self.span,
- GateIssue::Language,
- "procedural macros cannot expand to macro definitions",
- );
- }
- visit::walk_item(self, i);
- }
-
- fn visit_mac(&mut self, _mac: &'ast ast::Mac) {
- // ...
- }
- }
- }
-
fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
let kind = match kind {
AstFragmentKind::Expr |
diff --git a/src/libsyntax/ext/mbe/macro_check.rs b/src/libsyntax/ext/mbe/macro_check.rs
index 97074f5..aabaff4 100644
--- a/src/libsyntax/ext/mbe/macro_check.rs
+++ b/src/libsyntax/ext/mbe/macro_check.rs
@@ -109,7 +109,7 @@
use crate::ext::mbe::{KleeneToken, TokenTree};
use crate::parse::token::TokenKind;
use crate::parse::token::{DelimToken, Token};
-use crate::parse::ParseSess;
+use crate::sess::ParseSess;
use crate::symbol::{kw, sym};
use rustc_data_structures::fx::FxHashMap;
diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs
index 0cb5eff..ff382c3 100644
--- a/src/libsyntax/ext/mbe/macro_parser.rs
+++ b/src/libsyntax/ext/mbe/macro_parser.rs
@@ -76,10 +76,11 @@
use crate::ast::{Ident, Name};
use crate::ext::mbe::{self, TokenTree};
-use crate::parse::{Directory, ParseSess, PResult};
+use crate::parse::{Directory, PResult};
use crate::parse::parser::{Parser, PathStyle};
use crate::parse::token::{self, DocComment, Nonterminal, Token};
use crate::print::pprust;
+use crate::sess::ParseSess;
use crate::symbol::{kw, sym, Symbol};
use crate::tokenstream::{DelimSpan, TokenStream};
diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs
index e4fc269..b422329 100644
--- a/src/libsyntax/ext/mbe/macro_rules.rs
+++ b/src/libsyntax/ext/mbe/macro_rules.rs
@@ -14,8 +14,9 @@
use crate::parse::parser::Parser;
use crate::parse::token::TokenKind::*;
use crate::parse::token::{self, NtTT, Token};
-use crate::parse::{Directory, ParseSess};
+use crate::parse::Directory;
use crate::print::pprust;
+use crate::sess::ParseSess;
use crate::symbol::{kw, sym, Symbol};
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
diff --git a/src/libsyntax/ext/mbe/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs
index 8cb85bd..3cec4bc 100644
--- a/src/libsyntax/ext/mbe/quoted.rs
+++ b/src/libsyntax/ext/mbe/quoted.rs
@@ -2,8 +2,8 @@
use crate::ext::mbe::macro_parser;
use crate::ext::mbe::{TokenTree, KleeneOp, KleeneToken, SequenceRepetition, Delimited};
use crate::parse::token::{self, Token};
-use crate::parse::ParseSess;
use crate::print::pprust;
+use crate::sess::ParseSess;
use crate::symbol::kw;
use crate::tokenstream;
diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs
index 08142ba..300523c 100644
--- a/src/libsyntax/ext/proc_macro_server.rs
+++ b/src/libsyntax/ext/proc_macro_server.rs
@@ -1,8 +1,9 @@
use crate::ast;
use crate::ext::base::ExtCtxt;
-use crate::parse::{self, token, ParseSess};
+use crate::parse::{self, token};
use crate::parse::lexer::comments;
use crate::print::pprust;
+use crate::sess::ParseSess;
use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
use errors::Diagnostic;
diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs
index ab1620b..043a2ff 100644
--- a/src/libsyntax/feature_gate/builtin_attrs.rs
+++ b/src/libsyntax/feature_gate/builtin_attrs.rs
@@ -9,8 +9,8 @@
use crate::ast;
use crate::attr::AttributeTemplate;
+use crate::sess::ParseSess;
use crate::symbol::{Symbol, sym};
-use crate::parse::ParseSess;
use syntax_pos::Span;
use rustc_data_structures::fx::FxHashMap;
diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs
index 6008f8f..c07b605 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/libsyntax/feature_gate/check.rs
@@ -5,14 +5,14 @@
use crate::ast::{
self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind,
- PatKind, RangeEnd,
+ PatKind, RangeEnd, VariantData,
};
use crate::attr::{self, check_builtin_attribute};
use crate::source_map::Spanned;
use crate::edition::{ALL_EDITIONS, Edition};
use crate::visit::{self, FnKind, Visitor};
-use crate::parse::{token, ParseSess};
-use crate::parse::parser::Parser;
+use crate::parse::token;
+use crate::sess::ParseSess;
use crate::symbol::{Symbol, sym};
use crate::tokenstream::TokenTree;
@@ -246,6 +246,51 @@
Abi::System => {}
}
}
+
+ fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
+ let has_fields = variants.iter().any(|variant| match variant.data {
+ VariantData::Tuple(..) | VariantData::Struct(..) => true,
+ VariantData::Unit(..) => false,
+ });
+
+ let discriminant_spans = variants.iter().filter(|variant| match variant.data {
+ VariantData::Tuple(..) | VariantData::Struct(..) => false,
+ VariantData::Unit(..) => true,
+ })
+ .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
+ .collect::<Vec<_>>();
+
+ if !discriminant_spans.is_empty() && has_fields {
+ let mut err = feature_err(
+ self.parse_sess,
+ sym::arbitrary_enum_discriminant,
+ discriminant_spans.clone(),
+ crate::feature_gate::GateIssue::Language,
+ "custom discriminant values are not allowed in enums with tuple or struct variants",
+ );
+ for sp in discriminant_spans {
+ err.span_label(sp, "disallowed custom discriminant");
+ }
+ for variant in variants.iter() {
+ match &variant.data {
+ VariantData::Struct(..) => {
+ err.span_label(
+ variant.span,
+ "struct variant defined here",
+ );
+ }
+ VariantData::Tuple(..) => {
+ err.span_label(
+ variant.span,
+ "tuple variant defined here",
+ );
+ }
+ VariantData::Unit(..) => {}
+ }
+ }
+ err.emit();
+ }
+ }
}
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
@@ -353,7 +398,7 @@
let has_feature = self.features.arbitrary_enum_discriminant;
if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
- Parser::maybe_report_invalid_custom_discriminants(self.parse_sess, &variants);
+ self.maybe_report_invalid_custom_discriminants(&variants);
}
}
@@ -769,7 +814,7 @@
}
if let Some(allowed) = allow_features.as_ref() {
- if allowed.iter().find(|f| *f == name.as_str()).is_none() {
+ if allowed.iter().find(|&f| f == &name.as_str() as &str).is_none() {
span_err!(span_handler, mi.span(), E0725,
"the feature `{}` is not in the list of allowed features",
name);
diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs
index 4cf9874..e329678 100644
--- a/src/libsyntax/json.rs
+++ b/src/libsyntax/json.rs
@@ -89,8 +89,8 @@
}
impl Emitter for JsonEmitter {
- fn emit_diagnostic(&mut self, db: &errors::Diagnostic) {
- let data = Diagnostic::from_errors_diagnostic(db, self);
+ fn emit_diagnostic(&mut self, diag: &errors::Diagnostic) {
+ let data = Diagnostic::from_errors_diagnostic(diag, self);
let result = if self.pretty {
writeln!(&mut self.dst, "{}", as_pretty_json(&data))
} else {
@@ -209,10 +209,10 @@
}
impl Diagnostic {
- fn from_errors_diagnostic(db: &errors::Diagnostic,
+ fn from_errors_diagnostic(diag: &errors::Diagnostic,
je: &JsonEmitter)
-> Diagnostic {
- let sugg = db.suggestions.iter().map(|sugg| {
+ let sugg = diag.suggestions.iter().map(|sugg| {
Diagnostic {
message: sugg.msg.clone(),
code: None,
@@ -241,30 +241,30 @@
let output = buf.clone();
je.json_rendered.new_emitter(
Box::new(buf), Some(je.sm.clone()), false, None, je.external_macro_backtrace
- ).ui_testing(je.ui_testing).emit_diagnostic(db);
+ ).ui_testing(je.ui_testing).emit_diagnostic(diag);
let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();
let output = String::from_utf8(output).unwrap();
Diagnostic {
- message: db.message(),
- code: DiagnosticCode::map_opt_string(db.code.clone(), je),
- level: db.level.to_str(),
- spans: DiagnosticSpan::from_multispan(&db.span, je),
- children: db.children.iter().map(|c| {
+ message: diag.message(),
+ code: DiagnosticCode::map_opt_string(diag.code.clone(), je),
+ level: diag.level.to_str(),
+ spans: DiagnosticSpan::from_multispan(&diag.span, je),
+ children: diag.children.iter().map(|c| {
Diagnostic::from_sub_diagnostic(c, je)
}).chain(sugg).collect(),
rendered: Some(output),
}
}
- fn from_sub_diagnostic(db: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic {
+ fn from_sub_diagnostic(diag: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic {
Diagnostic {
- message: db.message(),
+ message: diag.message(),
code: None,
- level: db.level.to_str(),
- spans: db.render_span.as_ref()
+ level: diag.level.to_str(),
+ spans: diag.render_span.as_ref()
.map(|sp| DiagnosticSpan::from_multispan(sp, je))
- .unwrap_or_else(|| DiagnosticSpan::from_multispan(&db.span, je)),
+ .unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, je)),
children: vec![],
rendered: None,
}
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 09a4779..fa75f56 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -147,6 +147,7 @@
pub mod show_span;
pub use syntax_pos::edition;
pub use syntax_pos::symbol;
+pub mod sess;
pub mod tokenstream;
pub mod visit;
diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs
index 0bbd675..943838d 100644
--- a/src/libsyntax/parse/diagnostics.rs
+++ b/src/libsyntax/parse/diagnostics.rs
@@ -1,9 +1,8 @@
use crate::ast::{
self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind,
- Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData,
+ Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind,
};
-use crate::feature_gate::feature_err;
-use crate::parse::{SeqSep, PResult, Parser, ParseSess};
+use crate::parse::{SeqSep, PResult, Parser};
use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType};
use crate::parse::token::{self, TokenKind};
use crate::print::pprust;
@@ -715,55 +714,7 @@
}
}
- crate fn maybe_report_invalid_custom_discriminants(
- sess: &ParseSess,
- variants: &[ast::Variant],
- ) {
- let has_fields = variants.iter().any(|variant| match variant.data {
- VariantData::Tuple(..) | VariantData::Struct(..) => true,
- VariantData::Unit(..) => false,
- });
-
- let discriminant_spans = variants.iter().filter(|variant| match variant.data {
- VariantData::Tuple(..) | VariantData::Struct(..) => false,
- VariantData::Unit(..) => true,
- })
- .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
- .collect::<Vec<_>>();
-
- if !discriminant_spans.is_empty() && has_fields {
- let mut err = feature_err(
- sess,
- sym::arbitrary_enum_discriminant,
- discriminant_spans.clone(),
- crate::feature_gate::GateIssue::Language,
- "custom discriminant values are not allowed in enums with tuple or struct variants",
- );
- for sp in discriminant_spans {
- err.span_label(sp, "disallowed custom discriminant");
- }
- for variant in variants.iter() {
- match &variant.data {
- VariantData::Struct(..) => {
- err.span_label(
- variant.span,
- "struct variant defined here",
- );
- }
- VariantData::Tuple(..) => {
- err.span_label(
- variant.span,
- "tuple variant defined here",
- );
- }
- VariantData::Unit(..) => {}
- }
- }
- err.emit();
- }
- }
-
- crate fn maybe_recover_from_bad_type_plus(
+ pub(super) fn maybe_recover_from_bad_type_plus(
&mut self,
allow_plus: bool,
ty: &Ty,
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index ac3fead..e6dc9a4 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1,5 +1,5 @@
-use crate::parse::ParseSess;
use crate::parse::token::{self, Token, TokenKind};
+use crate::sess::ParseSess;
use crate::symbol::{sym, Symbol};
use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char};
diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs
index 56a79bf..14e1696 100644
--- a/src/libsyntax/parse/literal.rs
+++ b/src/libsyntax/parse/literal.rs
@@ -1,14 +1,10 @@
//! Code related to parsing literals.
use crate::ast::{self, Lit, LitKind};
-use crate::parse::parser::Parser;
-use crate::parse::PResult;
-use crate::parse::token::{self, Token, TokenKind};
-use crate::print::pprust;
+use crate::parse::token::{self, Token};
use crate::symbol::{kw, sym, Symbol};
use crate::tokenstream::{TokenStream, TokenTree};
-use errors::{Applicability, Handler};
use log::debug;
use rustc_data_structures::sync::Lrc;
use syntax_pos::Span;
@@ -28,72 +24,6 @@
IntTooLarge,
}
-impl LitError {
- fn report(&self, diag: &Handler, lit: token::Lit, span: Span) {
- let token::Lit { kind, suffix, .. } = lit;
- match *self {
- // `NotLiteral` is not an error by itself, so we don't report
- // it and give the parser opportunity to try something else.
- LitError::NotLiteral => {}
- // `LexerError` *is* an error, but it was already reported
- // by lexer, so here we don't report it the second time.
- LitError::LexerError => {}
- LitError::InvalidSuffix => {
- expect_no_suffix(
- diag, span, &format!("{} {} literal", kind.article(), kind.descr()), suffix
- );
- }
- LitError::InvalidIntSuffix => {
- let suf = suffix.expect("suffix error with no suffix").as_str();
- if looks_like_width_suffix(&['i', 'u'], &suf) {
- // If it looks like a width, try to be helpful.
- let msg = format!("invalid width `{}` for integer literal", &suf[1..]);
- diag.struct_span_err(span, &msg)
- .help("valid widths are 8, 16, 32, 64 and 128")
- .emit();
- } else {
- let msg = format!("invalid suffix `{}` for integer literal", suf);
- diag.struct_span_err(span, &msg)
- .span_label(span, format!("invalid suffix `{}`", suf))
- .help("the suffix must be one of the integral types (`u32`, `isize`, etc)")
- .emit();
- }
- }
- LitError::InvalidFloatSuffix => {
- let suf = suffix.expect("suffix error with no suffix").as_str();
- if looks_like_width_suffix(&['f'], &suf) {
- // If it looks like a width, try to be helpful.
- let msg = format!("invalid width `{}` for float literal", &suf[1..]);
- diag.struct_span_err(span, &msg)
- .help("valid widths are 32 and 64")
- .emit();
- } else {
- let msg = format!("invalid suffix `{}` for float literal", suf);
- diag.struct_span_err(span, &msg)
- .span_label(span, format!("invalid suffix `{}`", suf))
- .help("valid suffixes are `f32` and `f64`")
- .emit();
- }
- }
- LitError::NonDecimalFloat(base) => {
- let descr = match base {
- 16 => "hexadecimal",
- 8 => "octal",
- 2 => "binary",
- _ => unreachable!(),
- };
- diag.struct_span_err(span, &format!("{} float literal is not supported", descr))
- .span_label(span, "not supported")
- .emit();
- }
- LitError::IntTooLarge => {
- diag.struct_span_err(span, "integer literal is too large")
- .emit();
- }
- }
- }
-}
-
impl LitKind {
/// Converts literal token into a semantic literal.
fn from_lit_token(lit: token::Lit) -> Result<LitKind, LitError> {
@@ -204,7 +134,7 @@
let (kind, symbol, suffix) = match *self {
LitKind::Str(symbol, ast::StrStyle::Cooked) => {
// Don't re-intern unless the escaped string is different.
- let s = &symbol.as_str();
+ let s: &str = &symbol.as_str();
let escaped = s.escape_default().to_string();
let symbol = if escaped == *s { symbol } else { Symbol::intern(&escaped) };
(token::Str, symbol, None)
@@ -254,7 +184,7 @@
impl Lit {
/// Converts literal token into an AST literal.
- fn from_lit_token(token: token::Lit, span: Span) -> Result<Lit, LitError> {
+ crate fn from_lit_token(token: token::Lit, span: Span) -> Result<Lit, LitError> {
Ok(Lit { token, kind: LitKind::from_lit_token(token)?, span })
}
@@ -296,99 +226,6 @@
}
}
-impl<'a> Parser<'a> {
- /// Matches `lit = true | false | token_lit`.
- crate fn parse_lit(&mut self) -> PResult<'a, Lit> {
- let mut recovered = None;
- if self.token == token::Dot {
- // Attempt to recover `.4` as `0.4`.
- recovered = self.look_ahead(1, |next_token| {
- if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix })
- = next_token.kind {
- if self.token.span.hi() == next_token.span.lo() {
- let s = String::from("0.") + &symbol.as_str();
- let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
- return Some(Token::new(kind, self.token.span.to(next_token.span)));
- }
- }
- None
- });
- if let Some(token) = &recovered {
- self.bump();
- self.diagnostic()
- .struct_span_err(token.span, "float literals must have an integer part")
- .span_suggestion(
- token.span,
- "must have an integer part",
- pprust::token_to_string(token),
- Applicability::MachineApplicable,
- )
- .emit();
- }
- }
-
- let token = recovered.as_ref().unwrap_or(&self.token);
- match Lit::from_token(token) {
- Ok(lit) => {
- self.bump();
- Ok(lit)
- }
- Err(LitError::NotLiteral) => {
- let msg = format!("unexpected token: {}", self.this_token_descr());
- Err(self.span_fatal(token.span, &msg))
- }
- Err(err) => {
- let (lit, span) = (token.expect_lit(), token.span);
- self.bump();
- err.report(&self.sess.span_diagnostic, lit, span);
- // Pack possible quotes and prefixes from the original literal into
- // the error literal's symbol so they can be pretty-printed faithfully.
- let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
- let symbol = Symbol::intern(&suffixless_lit.to_string());
- let lit = token::Lit::new(token::Err, symbol, lit.suffix);
- Lit::from_lit_token(lit, span).map_err(|_| unreachable!())
- }
- }
- }
-}
-
-crate fn expect_no_suffix(diag: &Handler, sp: Span, kind: &str, suffix: Option<Symbol>) {
- if let Some(suf) = suffix {
- let mut err = if kind == "a tuple index" &&
- [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf) {
- // #59553: warn instead of reject out of hand to allow the fix to percolate
- // through the ecosystem when people fix their macros
- let mut err = diag.struct_span_warn(
- sp,
- &format!("suffixes on {} are invalid", kind),
- );
- err.note(&format!(
- "`{}` is *temporarily* accepted on tuple index fields as it was \
- incorrectly accepted on stable for a few releases",
- suf,
- ));
- err.help(
- "on proc macros, you'll want to use `syn::Index::from` or \
- `proc_macro::Literal::*_unsuffixed` for code that will desugar \
- to tuple field access",
- );
- err.note(
- "for more context, see https://github.com/rust-lang/rust/issues/60210",
- );
- err
- } else {
- diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
- };
- err.span_label(sp, format!("invalid suffix `{}`", suf));
- err.emit();
- }
-}
-
-// Checks if `s` looks like i32 or u1234 etc.
-fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
- s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
-}
-
fn strip_underscores(symbol: Symbol) -> Symbol {
// Do not allocate a new string unless necessary.
let s = symbol.as_str();
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 0df695d..cb90caab 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -1,26 +1,20 @@
//! The main parser interface.
-use crate::ast::{self, CrateConfig, NodeId};
-use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId};
-use crate::source_map::{SourceMap, FilePathMapping};
-use crate::feature_gate::UnstableFeatures;
+use crate::ast;
use crate::parse::parser::{Parser, emit_unclosed_delims};
use crate::parse::token::{Nonterminal, TokenKind};
use crate::tokenstream::{self, TokenStream, TokenTree};
use crate::print::pprust;
-use crate::symbol::Symbol;
+use crate::sess::ParseSess;
-use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder};
-use rustc_data_structures::fx::{FxHashSet, FxHashMap};
+use errors::{FatalError, Level, Diagnostic, DiagnosticBuilder};
#[cfg(target_arch = "x86_64")]
use rustc_data_structures::static_assert_size;
-use rustc_data_structures::sync::{Lrc, Lock, Once};
-use syntax_pos::{Span, SourceFile, FileName, MultiSpan};
-use syntax_pos::edition::Edition;
-use syntax_pos::hygiene::ExpnId;
+use rustc_data_structures::sync::Lrc;
+use syntax_pos::{Span, SourceFile, FileName};
use std::borrow::Cow;
-use std::path::{Path, PathBuf};
+use std::path::Path;
use std::str;
use log::info;
@@ -46,112 +40,6 @@
#[cfg(target_arch = "x86_64")]
static_assert_size!(PResult<'_, bool>, 16);
-/// Collected spans during parsing for places where a certain feature was
-/// used and should be feature gated accordingly in `check_crate`.
-#[derive(Default)]
-pub struct GatedSpans {
- /// Spans collected for gating `let_chains`, e.g. `if a && let b = c {}`.
- pub let_chains: Lock<Vec<Span>>,
- /// Spans collected for gating `async_closure`, e.g. `async || ..`.
- pub async_closure: Lock<Vec<Span>>,
- /// Spans collected for gating `yield e?` expressions (`generators` gate).
- pub yields: Lock<Vec<Span>>,
- /// Spans collected for gating `or_patterns`, e.g. `Some(Foo | Bar)`.
- pub or_patterns: Lock<Vec<Span>>,
- /// Spans collected for gating `const_extern_fn`, e.g. `const extern fn foo`.
- pub const_extern_fn: Lock<Vec<Span>>,
-}
-
-/// Info about a parsing session.
-pub struct ParseSess {
- pub span_diagnostic: Handler,
- pub unstable_features: UnstableFeatures,
- pub config: CrateConfig,
- pub edition: Edition,
- pub missing_fragment_specifiers: Lock<FxHashSet<Span>>,
- /// Places where raw identifiers were used. This is used for feature-gating raw identifiers.
- pub raw_identifier_spans: Lock<Vec<Span>>,
- /// Used to determine and report recursive module inclusions.
- included_mod_stack: Lock<Vec<PathBuf>>,
- source_map: Lrc<SourceMap>,
- pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
- /// Contains the spans of block expressions that could have been incomplete based on the
- /// operation token that followed it, but that the parser cannot identify without further
- /// analysis.
- pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>,
- pub injected_crate_name: Once<Symbol>,
- pub gated_spans: GatedSpans,
-}
-
-impl ParseSess {
- pub fn new(file_path_mapping: FilePathMapping) -> Self {
- let cm = Lrc::new(SourceMap::new(file_path_mapping));
- let handler = Handler::with_tty_emitter(
- ColorConfig::Auto,
- true,
- None,
- Some(cm.clone()),
- );
- ParseSess::with_span_handler(handler, cm)
- }
-
- pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> Self {
- Self {
- span_diagnostic: handler,
- unstable_features: UnstableFeatures::from_environment(),
- config: FxHashSet::default(),
- edition: ExpnId::root().expn_data().edition,
- missing_fragment_specifiers: Lock::new(FxHashSet::default()),
- raw_identifier_spans: Lock::new(Vec::new()),
- included_mod_stack: Lock::new(vec![]),
- source_map,
- buffered_lints: Lock::new(vec![]),
- ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
- injected_crate_name: Once::new(),
- gated_spans: GatedSpans::default(),
- }
- }
-
- #[inline]
- pub fn source_map(&self) -> &SourceMap {
- &self.source_map
- }
-
- pub fn buffer_lint<S: Into<MultiSpan>>(&self,
- lint_id: BufferedEarlyLintId,
- span: S,
- id: NodeId,
- msg: &str,
- ) {
- self.buffered_lints.with_lock(|buffered_lints| {
- buffered_lints.push(BufferedEarlyLint{
- span: span.into(),
- id,
- msg: msg.into(),
- lint_id,
- });
- });
- }
-
- /// Extend an error with a suggestion to wrap an expression with parentheses to allow the
- /// parser to continue parsing the following operation as part of the same expression.
- pub fn expr_parentheses_needed(
- &self,
- err: &mut DiagnosticBuilder<'_>,
- span: Span,
- alt_snippet: Option<String>,
- ) {
- if let Some(snippet) = self.source_map().span_to_snippet(span).ok().or(alt_snippet) {
- err.span_suggestion(
- span,
- "parentheses are required to parse this as an expression",
- format!("({})", snippet),
- Applicability::MachineApplicable,
- );
- }
- }
-}
-
#[derive(Clone)]
pub struct Directory<'a> {
pub path: Cow<'a, Path>,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 478cfef..8638376 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -15,12 +15,13 @@
self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident,
IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
};
-use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep, literal, token};
+use crate::parse::{PResult, Directory, DirectoryOwnership, SeqSep};
use crate::parse::lexer::UnmatchedBrace;
use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
-use crate::parse::token::{Token, TokenKind, DelimToken};
+use crate::parse::token::{self, Token, TokenKind, DelimToken};
use crate::print::pprust;
use crate::ptr::P;
+use crate::sess::ParseSess;
use crate::source_map::respan;
use crate::symbol::{kw, sym, Symbol};
use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
@@ -637,10 +638,6 @@
}
}
- fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<ast::Name>) {
- literal::expect_no_suffix(&self.sess.span_diagnostic, sp, kind, suffix)
- }
-
/// Attempts to consume a `<`. If `<<` is seen, replaces it with a single
/// `<` and continue. If `<-` is seen, replaces it with a single `<`
/// and continue. If a `<` is not seen, returns false.
@@ -1366,7 +1363,7 @@
],
Applicability::MaybeIncorrect,
).span_suggestion(
- self.sess.source_map.next_point(self.prev_span),
+ self.sess.source_map().next_point(self.prev_span),
"add a semicolon",
';'.to_string(),
Applicability::MaybeIncorrect,
diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs
index 660bf9b..dd0fd83 100644
--- a/src/libsyntax/parse/parser/expr.rs
+++ b/src/libsyntax/parse/parser/expr.rs
@@ -1,17 +1,17 @@
-use super::{
- Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode, SemiColonMode,
- SeqSep, TokenExpectType,
-};
+use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode};
+use super::{SemiColonMode, SeqSep, TokenExpectType};
use super::pat::{GateOr, PARAM_EXPECTED};
+use crate::parse::literal::LitError;
+
use crate::ast::{
self, DUMMY_NODE_ID, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode,
Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm, Ty, TyKind,
- FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field,
+ FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, Lit,
};
use crate::maybe_recover_from_interpolated_ty_qpath;
use crate::parse::classify;
-use crate::parse::token::{self, Token};
+use crate::parse::token::{self, Token, TokenKind};
use crate::parse::diagnostics::Error;
use crate::print::pprust;
use crate::ptr::P;
@@ -20,6 +20,7 @@
use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par};
use errors::Applicability;
+use syntax_pos::Symbol;
use std::mem;
use rustc_data_structures::thin_vec::ThinVec;
@@ -1072,6 +1073,165 @@
self.maybe_recover_from_bad_qpath(expr, true)
}
+ /// Matches `lit = true | false | token_lit`.
+ crate fn parse_lit(&mut self) -> PResult<'a, Lit> {
+ let mut recovered = None;
+ if self.token == token::Dot {
+ // Attempt to recover `.4` as `0.4`.
+ recovered = self.look_ahead(1, |next_token| {
+ if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix })
+ = next_token.kind {
+ if self.token.span.hi() == next_token.span.lo() {
+ let s = String::from("0.") + &symbol.as_str();
+ let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
+ return Some(Token::new(kind, self.token.span.to(next_token.span)));
+ }
+ }
+ None
+ });
+ if let Some(token) = &recovered {
+ self.bump();
+ self.struct_span_err(token.span, "float literals must have an integer part")
+ .span_suggestion(
+ token.span,
+ "must have an integer part",
+ pprust::token_to_string(token),
+ Applicability::MachineApplicable,
+ )
+ .emit();
+ }
+ }
+
+ let token = recovered.as_ref().unwrap_or(&self.token);
+ match Lit::from_token(token) {
+ Ok(lit) => {
+ self.bump();
+ Ok(lit)
+ }
+ Err(LitError::NotLiteral) => {
+ let msg = format!("unexpected token: {}", self.this_token_descr());
+ Err(self.span_fatal(token.span, &msg))
+ }
+ Err(err) => {
+ let (lit, span) = (token.expect_lit(), token.span);
+ self.bump();
+ self.error_literal_from_token(err, lit, span);
+ // Pack possible quotes and prefixes from the original literal into
+ // the error literal's symbol so they can be pretty-printed faithfully.
+ let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
+ let symbol = Symbol::intern(&suffixless_lit.to_string());
+ let lit = token::Lit::new(token::Err, symbol, lit.suffix);
+ Lit::from_lit_token(lit, span).map_err(|_| unreachable!())
+ }
+ }
+ }
+
+ fn error_literal_from_token(&self, err: LitError, lit: token::Lit, span: Span) {
+ // Checks if `s` looks like i32 or u1234 etc.
+ fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
+ s.len() > 1
+ && s.starts_with(first_chars)
+ && s[1..].chars().all(|c| c.is_ascii_digit())
+ }
+
+ let token::Lit { kind, suffix, .. } = lit;
+ match err {
+ // `NotLiteral` is not an error by itself, so we don't report
+ // it and give the parser opportunity to try something else.
+ LitError::NotLiteral => {}
+ // `LexerError` *is* an error, but it was already reported
+ // by lexer, so here we don't report it the second time.
+ LitError::LexerError => {}
+ LitError::InvalidSuffix => {
+ self.expect_no_suffix(
+ span,
+ &format!("{} {} literal", kind.article(), kind.descr()),
+ suffix,
+ );
+ }
+ LitError::InvalidIntSuffix => {
+ let suf = suffix.expect("suffix error with no suffix").as_str();
+ if looks_like_width_suffix(&['i', 'u'], &suf) {
+ // If it looks like a width, try to be helpful.
+ let msg = format!("invalid width `{}` for integer literal", &suf[1..]);
+ self.struct_span_err(span, &msg)
+ .help("valid widths are 8, 16, 32, 64 and 128")
+ .emit();
+ } else {
+ let msg = format!("invalid suffix `{}` for integer literal", suf);
+ self.struct_span_err(span, &msg)
+ .span_label(span, format!("invalid suffix `{}`", suf))
+ .help("the suffix must be one of the integral types (`u32`, `isize`, etc)")
+ .emit();
+ }
+ }
+ LitError::InvalidFloatSuffix => {
+ let suf = suffix.expect("suffix error with no suffix").as_str();
+ if looks_like_width_suffix(&['f'], &suf) {
+ // If it looks like a width, try to be helpful.
+ let msg = format!("invalid width `{}` for float literal", &suf[1..]);
+ self.struct_span_err(span, &msg)
+ .help("valid widths are 32 and 64")
+ .emit();
+ } else {
+ let msg = format!("invalid suffix `{}` for float literal", suf);
+ self.struct_span_err(span, &msg)
+ .span_label(span, format!("invalid suffix `{}`", suf))
+ .help("valid suffixes are `f32` and `f64`")
+ .emit();
+ }
+ }
+ LitError::NonDecimalFloat(base) => {
+ let descr = match base {
+ 16 => "hexadecimal",
+ 8 => "octal",
+ 2 => "binary",
+ _ => unreachable!(),
+ };
+ self.struct_span_err(span, &format!("{} float literal is not supported", descr))
+ .span_label(span, "not supported")
+ .emit();
+ }
+ LitError::IntTooLarge => {
+ self.struct_span_err(span, "integer literal is too large")
+ .emit();
+ }
+ }
+ }
+
+ pub(super) fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<Symbol>) {
+ if let Some(suf) = suffix {
+ let mut err = if kind == "a tuple index"
+ && [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf)
+ {
+ // #59553: warn instead of reject out of hand to allow the fix to percolate
+ // through the ecosystem when people fix their macros
+ let mut err = self.sess.span_diagnostic.struct_span_warn(
+ sp,
+ &format!("suffixes on {} are invalid", kind),
+ );
+ err.note(&format!(
+ "`{}` is *temporarily* accepted on tuple index fields as it was \
+ incorrectly accepted on stable for a few releases",
+ suf,
+ ));
+ err.help(
+ "on proc macros, you'll want to use `syn::Index::from` or \
+ `proc_macro::Literal::*_unsuffixed` for code that will desugar \
+ to tuple field access",
+ );
+ err.note(
+ "for more context, see https://github.com/rust-lang/rust/issues/60210",
+ );
+ err
+ } else {
+ self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
+ };
+ err.span_label(sp, format!("invalid suffix `{}`", suf));
+ err.emit();
+ }
+ }
+
/// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
crate fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
maybe_whole_expr!(self);
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 68dd90b..136fc35 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -6,10 +6,11 @@
use crate::source_map::{self, SourceMap, Spanned};
use crate::parse::token::{self, BinOpToken, DelimToken, Nonterminal, Token, TokenKind};
use crate::parse::lexer::comments;
-use crate::parse::{self, ParseSess};
+use crate::parse;
use crate::print::pp::{self, Breaks};
use crate::print::pp::Breaks::{Consistent, Inconsistent};
use crate::ptr::P;
+use crate::sess::ParseSess;
use crate::symbol::{kw, sym};
use crate::tokenstream::{self, TokenStream, TokenTree};
diff --git a/src/libsyntax/sess.rs b/src/libsyntax/sess.rs
new file mode 100644
index 0000000..e49d395
--- /dev/null
+++ b/src/libsyntax/sess.rs
@@ -0,0 +1,124 @@
+//! Contains `ParseSess` which holds state living beyond what one `Parser` might.
+//! It also serves as an input to the parser itself.
+
+use crate::ast::{CrateConfig, NodeId};
+use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId};
+use crate::source_map::{SourceMap, FilePathMapping};
+use crate::feature_gate::UnstableFeatures;
+
+use errors::{Applicability, Handler, ColorConfig, DiagnosticBuilder};
+use rustc_data_structures::fx::{FxHashSet, FxHashMap};
+use rustc_data_structures::sync::{Lrc, Lock, Once};
+use syntax_pos::{Symbol, Span, MultiSpan};
+use syntax_pos::edition::Edition;
+use syntax_pos::hygiene::ExpnId;
+
+use std::path::PathBuf;
+use std::str;
+
+/// Collected spans during parsing for places where a certain feature was
+/// used and should be feature gated accordingly in `check_crate`.
+#[derive(Default)]
+crate struct GatedSpans {
+ /// Spans collected for gating `let_chains`, e.g. `if a && let b = c {}`.
+ crate let_chains: Lock<Vec<Span>>,
+ /// Spans collected for gating `async_closure`, e.g. `async || ..`.
+ crate async_closure: Lock<Vec<Span>>,
+ /// Spans collected for gating `yield e?` expressions (`generators` gate).
+ crate yields: Lock<Vec<Span>>,
+ /// Spans collected for gating `or_patterns`, e.g. `Some(Foo | Bar)`.
+ crate or_patterns: Lock<Vec<Span>>,
+ /// Spans collected for gating `const_extern_fn`, e.g. `const extern fn foo`.
+ crate const_extern_fn: Lock<Vec<Span>>,
+}
+
+/// Info about a parsing session.
+pub struct ParseSess {
+ pub span_diagnostic: Handler,
+ crate unstable_features: UnstableFeatures,
+ pub config: CrateConfig,
+ pub edition: Edition,
+ pub missing_fragment_specifiers: Lock<FxHashSet<Span>>,
+ /// Places where raw identifiers were used. This is used for feature-gating raw identifiers.
+ pub raw_identifier_spans: Lock<Vec<Span>>,
+ /// Used to determine and report recursive module inclusions.
+ pub(super) included_mod_stack: Lock<Vec<PathBuf>>,
+ source_map: Lrc<SourceMap>,
+ pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
+ /// Contains the spans of block expressions that could have been incomplete based on the
+ /// operation token that followed it, but that the parser cannot identify without further
+ /// analysis.
+ pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>,
+ pub injected_crate_name: Once<Symbol>,
+ crate gated_spans: GatedSpans,
+}
+
+impl ParseSess {
+ pub fn new(file_path_mapping: FilePathMapping) -> Self {
+ let cm = Lrc::new(SourceMap::new(file_path_mapping));
+ let handler = Handler::with_tty_emitter(
+ ColorConfig::Auto,
+ true,
+ None,
+ Some(cm.clone()),
+ );
+ ParseSess::with_span_handler(handler, cm)
+ }
+
+ pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> Self {
+ Self {
+ span_diagnostic: handler,
+ unstable_features: UnstableFeatures::from_environment(),
+ config: FxHashSet::default(),
+ edition: ExpnId::root().expn_data().edition,
+ missing_fragment_specifiers: Lock::new(FxHashSet::default()),
+ raw_identifier_spans: Lock::new(Vec::new()),
+ included_mod_stack: Lock::new(vec![]),
+ source_map,
+ buffered_lints: Lock::new(vec![]),
+ ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
+ injected_crate_name: Once::new(),
+ gated_spans: GatedSpans::default(),
+ }
+ }
+
+ #[inline]
+ pub fn source_map(&self) -> &SourceMap {
+ &self.source_map
+ }
+
+ pub fn buffer_lint(
+ &self,
+ lint_id: BufferedEarlyLintId,
+ span: impl Into<MultiSpan>,
+ id: NodeId,
+ msg: &str,
+ ) {
+ self.buffered_lints.with_lock(|buffered_lints| {
+ buffered_lints.push(BufferedEarlyLint{
+ span: span.into(),
+ id,
+ msg: msg.into(),
+ lint_id,
+ });
+ });
+ }
+
+ /// Extend an error with a suggestion to wrap an expression with parentheses to allow the
+ /// parser to continue parsing the following operation as part of the same expression.
+ pub fn expr_parentheses_needed(
+ &self,
+ err: &mut DiagnosticBuilder<'_>,
+ span: Span,
+ alt_snippet: Option<String>,
+ ) {
+ if let Some(snippet) = self.source_map().span_to_snippet(span).ok().or(alt_snippet) {
+ err.span_suggestion(
+ span,
+ "parentheses are required to parse this as an expression",
+ format!("({})", snippet),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+}
diff --git a/src/libsyntax/tests.rs b/src/libsyntax/tests.rs
index f510ac9..fbcf368 100644
--- a/src/libsyntax/tests.rs
+++ b/src/libsyntax/tests.rs
@@ -1,7 +1,8 @@
use crate::{ast, panictry};
-use crate::parse::{ParseSess, PResult, source_file_to_stream};
+use crate::parse::{PResult, source_file_to_stream};
use crate::parse::new_parser_from_source_str;
use crate::parse::parser::Parser;
+use crate::sess::ParseSess;
use crate::source_map::{SourceMap, FilePathMapping};
use crate::tokenstream::TokenStream;
use crate::with_default_globals;
diff --git a/src/libsyntax_ext/cmdline_attrs.rs b/src/libsyntax_ext/cmdline_attrs.rs
index 203c4a8..2c31597 100644
--- a/src/libsyntax_ext/cmdline_attrs.rs
+++ b/src/libsyntax_ext/cmdline_attrs.rs
@@ -3,7 +3,8 @@
use syntax::ast::{self, AttrItem, AttrStyle};
use syntax::attr::mk_attr;
use syntax::panictry;
-use syntax::parse::{self, token, ParseSess};
+use syntax::parse::{self, token};
+use syntax::sess::ParseSess;
use syntax_pos::FileName;
pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate {
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index abdcb6c..9c3ec06 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -190,8 +190,8 @@
use syntax::source_map::respan;
use syntax::util::map_in_place::MapInPlace;
use syntax::ptr::P;
+use syntax::sess::ParseSess;
use syntax::symbol::{Symbol, kw, sym};
-use syntax::parse::ParseSess;
use syntax_pos::{Span};
use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs
index 1d48e82..1b70688 100644
--- a/src/libsyntax_ext/proc_macro_harness.rs
+++ b/src/libsyntax_ext/proc_macro_harness.rs
@@ -6,9 +6,9 @@
use syntax::ext::base::ExtCtxt;
use syntax::ext::expand::{AstFragment, ExpansionConfig};
use syntax::ext::proc_macro::is_proc_macro_attr;
-use syntax::parse::ParseSess;
use syntax::print::pprust;
use syntax::ptr::P;
+use syntax::sess::ParseSess;
use syntax::symbol::{kw, sym};
use syntax::visit::{self, Visitor};
use syntax_pos::{Span, DUMMY_SP};
diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs
index c577b1e..4f17acf 100644
--- a/src/libsyntax_ext/standard_library_imports.rs
+++ b/src/libsyntax_ext/standard_library_imports.rs
@@ -3,8 +3,8 @@
use syntax::ext::expand::ExpansionConfig;
use syntax::ext::hygiene::AstPass;
use syntax::ext::base::{ExtCtxt, Resolver};
-use syntax::parse::ParseSess;
use syntax::ptr::P;
+use syntax::sess::ParseSess;
use syntax::symbol::{Ident, Symbol, kw, sym};
use syntax_pos::DUMMY_SP;
diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs
index f79ad14..0bb279c 100644
--- a/src/libsyntax_ext/test_harness.rs
+++ b/src/libsyntax_ext/test_harness.rs
@@ -10,8 +10,8 @@
use syntax::ext::expand::{AstFragment, ExpansionConfig};
use syntax::feature_gate::Features;
use syntax::mut_visit::{*, ExpectOne};
-use syntax::parse::ParseSess;
use syntax::ptr::P;
+use syntax::sess::ParseSess;
use syntax::source_map::respan;
use syntax::symbol::{sym, Symbol};
use syntax_pos::{Span, DUMMY_SP};
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 30ee9b9..7f7c5cb 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -12,7 +12,7 @@
#![feature(non_exhaustive)]
#![feature(optin_builtin_traits)]
#![feature(rustc_attrs)]
-#![feature(proc_macro_hygiene)]
+#![cfg_attr(bootstrap, feature(proc_macro_hygiene))]
#![feature(specialization)]
#![feature(step_trait)]
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index c37efde..8298edb 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -1202,30 +1202,6 @@
}
}
-impl std::cmp::PartialEq<LocalInternedString> for str {
- fn eq(&self, other: &LocalInternedString) -> bool {
- self == other.string
- }
-}
-
-impl<'a> std::cmp::PartialEq<LocalInternedString> for &'a str {
- fn eq(&self, other: &LocalInternedString) -> bool {
- *self == other.string
- }
-}
-
-impl std::cmp::PartialEq<LocalInternedString> for String {
- fn eq(&self, other: &LocalInternedString) -> bool {
- self == other.string
- }
-}
-
-impl<'a> std::cmp::PartialEq<LocalInternedString> for &'a String {
- fn eq(&self, other: &LocalInternedString) -> bool {
- *self == other.string
- }
-}
-
impl !Send for LocalInternedString {}
impl !Sync for LocalInternedString {}
diff --git a/src/test/ui-fulldeps/ast_stmt_expr_attr.rs b/src/test/ui-fulldeps/ast_stmt_expr_attr.rs
index 6c5f539..5479119 100644
--- a/src/test/ui-fulldeps/ast_stmt_expr_attr.rs
+++ b/src/test/ui-fulldeps/ast_stmt_expr_attr.rs
@@ -10,9 +10,10 @@
use syntax::ast::*;
use syntax::attr::*;
use syntax::ast;
+use syntax::sess::ParseSess;
use syntax::source_map::{FilePathMapping, FileName};
use syntax::parse;
-use syntax::parse::{ParseSess, PResult};
+use syntax::parse::PResult;
use syntax::parse::new_parser_from_source_str;
use syntax::parse::parser::Parser;
use syntax::parse::token;
diff --git a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs
index 8631bcc..ac97ec7 100644
--- a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs
+++ b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs
@@ -7,8 +7,9 @@
extern crate syntax;
use std::path::Path;
+use syntax::sess::ParseSess;
use syntax::source_map::FilePathMapping;
-use syntax::parse::{self, ParseSess};
+use syntax::parse;
#[path = "mod_dir_simple/test.rs"]
mod gravy;
diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
index d4aff73..932a173 100644
--- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -24,14 +24,14 @@
use rustc_data_structures::thin_vec::ThinVec;
use syntax::ast::*;
+use syntax::sess::ParseSess;
use syntax::source_map::{Spanned, DUMMY_SP, FileName};
use syntax::source_map::FilePathMapping;
use syntax::mut_visit::{self, MutVisitor, visit_clobber};
-use syntax::parse::{self, ParseSess};
+use syntax::parse;
use syntax::print::pprust;
use syntax::ptr::P;
-
fn parse_expr(ps: &ParseSess, src: &str) -> Option<P<Expr>> {
let src_as_string = src.to_string();
diff --git a/src/test/ui/macros/same-sequence-span.rs b/src/test/ui/macros/same-sequence-span.rs
index a4f70b6..e0bb4d9 100644
--- a/src/test/ui/macros/same-sequence-span.rs
+++ b/src/test/ui/macros/same-sequence-span.rs
@@ -4,7 +4,6 @@
// left-hand side of a macro definition behave as if they had unique spans, and in particular that
// they don't crash the compiler.
-#![feature(proc_macro_hygiene)]
#![allow(unused_macros)]
extern crate proc_macro_sequence;
diff --git a/src/test/ui/macros/same-sequence-span.stderr b/src/test/ui/macros/same-sequence-span.stderr
index 0eef4a2..896f579 100644
--- a/src/test/ui/macros/same-sequence-span.stderr
+++ b/src/test/ui/macros/same-sequence-span.stderr
@@ -1,5 +1,5 @@
error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments
- --> $DIR/same-sequence-span.rs:15:18
+ --> $DIR/same-sequence-span.rs:14:18
|
LL | (1 $x:expr $($y:tt,)*
| ^^^^^ not allowed after `expr` fragments
@@ -7,7 +7,7 @@
= note: allowed there are: `=>`, `,` or `;`
error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments
- --> $DIR/same-sequence-span.rs:16:18
+ --> $DIR/same-sequence-span.rs:15:18
|
LL | $(= $z:tt)*
| ^ not allowed after `expr` fragments
@@ -15,7 +15,7 @@
= note: allowed there are: `=>`, `,` or `;`
error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments
- --> $DIR/same-sequence-span.rs:20:1
+ --> $DIR/same-sequence-span.rs:19:1
|
LL | proc_macro_sequence::make_foo!();
| ^--------------------------------
@@ -30,7 +30,7 @@
= note: allowed there are: `=>`, `,` or `;`
error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments
- --> $DIR/same-sequence-span.rs:20:1
+ --> $DIR/same-sequence-span.rs:19:1
|
LL | proc_macro_sequence::make_foo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs
new file mode 100644
index 0000000..548fefe
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs
@@ -0,0 +1,23 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn gen_macro_rules(_: TokenStream) -> TokenStream {
+ "
+ macro_rules! generated {() => {
+ struct ItemDef;
+ let local_def = 0;
+
+ ItemUse; // OK
+ local_use; // ERROR
+ break 'label_use; // ERROR
+
+ type DollarCrate = $crate::ItemUse; // OK
+ }}
+ ".parse().unwrap()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/more-gates.rs b/src/test/ui/proc-macro/auxiliary/more-gates.rs
deleted file mode 100644
index 6b609ea..0000000
--- a/src/test/ui/proc-macro/auxiliary/more-gates.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::*;
-
-#[proc_macro_attribute]
-pub fn attr2mac1(_: TokenStream, _: TokenStream) -> TokenStream {
- "macro_rules! foo1 { (a) => (a) }".parse().unwrap()
-}
-
-#[proc_macro_attribute]
-pub fn attr2mac2(_: TokenStream, _: TokenStream) -> TokenStream {
- "macro foo2(a) { a }".parse().unwrap()
-}
-
-#[proc_macro]
-pub fn mac2mac1(_: TokenStream) -> TokenStream {
- "macro_rules! foo3 { (a) => (a) }".parse().unwrap()
-}
-
-#[proc_macro]
-pub fn mac2mac2(_: TokenStream) -> TokenStream {
- "macro foo4(a) { a }".parse().unwrap()
-}
-
-#[proc_macro]
-pub fn tricky(_: TokenStream) -> TokenStream {
- "fn foo() {
- macro_rules! foo { (a) => (a) }
- }".parse().unwrap()
-}
diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs b/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs
new file mode 100644
index 0000000..195bda8
--- /dev/null
+++ b/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs
@@ -0,0 +1,23 @@
+// `macro_rules` items produced by transparent macros have correct hygiene in basic cases.
+// Local variables and labels are hygienic, items are not hygienic.
+// `$crate` refers to the crate that defines `macro_rules` and not the outer transparent macro.
+
+// aux-build:gen-macro-rules-hygiene.rs
+
+#[macro_use]
+extern crate gen_macro_rules_hygiene;
+
+struct ItemUse;
+
+gen_macro_rules!();
+//~^ ERROR use of undeclared label `'label_use`
+//~| ERROR cannot find value `local_use` in this scope
+
+fn main() {
+ 'label_use: loop {
+ let local_use = 1;
+ generated!();
+ ItemDef; // OK
+ local_def; //~ ERROR cannot find value `local_def` in this scope
+ }
+}
diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr
new file mode 100644
index 0000000..ecebdfa
--- /dev/null
+++ b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr
@@ -0,0 +1,28 @@
+error[E0426]: use of undeclared label `'label_use`
+ --> $DIR/gen-macro-rules-hygiene.rs:12:1
+ |
+LL | gen_macro_rules!();
+ | ^^^^^^^^^^^^^^^^^^^ undeclared label `'label_use`
+...
+LL | generated!();
+ | ------------- in this macro invocation
+
+error[E0425]: cannot find value `local_use` in this scope
+ --> $DIR/gen-macro-rules-hygiene.rs:12:1
+ |
+LL | gen_macro_rules!();
+ | ^^^^^^^^^^^^^^^^^^^ not found in this scope
+...
+LL | generated!();
+ | ------------- in this macro invocation
+
+error[E0425]: cannot find value `local_def` in this scope
+ --> $DIR/gen-macro-rules-hygiene.rs:21:9
+ |
+LL | local_def;
+ | ^^^^^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0425, E0426.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/more-gates.rs b/src/test/ui/proc-macro/more-gates.rs
deleted file mode 100644
index b870b43..0000000
--- a/src/test/ui/proc-macro/more-gates.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// aux-build:more-gates.rs
-
-#![feature(decl_macro)]
-
-extern crate more_gates as foo;
-
-use foo::*;
-
-#[attr2mac1]
-//~^ ERROR: cannot expand to macro definitions
-pub fn a() {}
-#[attr2mac2]
-//~^ ERROR: cannot expand to macro definitions
-pub fn a() {}
-
-mac2mac1!(); //~ ERROR: cannot expand to macro definitions
-mac2mac2!(); //~ ERROR: cannot expand to macro definitions
-
-tricky!();
-//~^ ERROR: cannot expand to macro definitions
-
-fn main() {}
diff --git a/src/test/ui/proc-macro/more-gates.stderr b/src/test/ui/proc-macro/more-gates.stderr
deleted file mode 100644
index ad96f78..0000000
--- a/src/test/ui/proc-macro/more-gates.stderr
+++ /dev/null
@@ -1,48 +0,0 @@
-error[E0658]: procedural macros cannot expand to macro definitions
- --> $DIR/more-gates.rs:9:1
- |
-LL | #[attr2mac1]
- | ^^^^^^^^^^^^
- |
- = note: for more information, see https://github.com/rust-lang/rust/issues/54727
- = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
-
-error[E0658]: procedural macros cannot expand to macro definitions
- --> $DIR/more-gates.rs:12:1
- |
-LL | #[attr2mac2]
- | ^^^^^^^^^^^^
- |
- = note: for more information, see https://github.com/rust-lang/rust/issues/54727
- = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
-
-error[E0658]: procedural macros cannot expand to macro definitions
- --> $DIR/more-gates.rs:16:1
- |
-LL | mac2mac1!();
- | ^^^^^^^^^^^^
- |
- = note: for more information, see https://github.com/rust-lang/rust/issues/54727
- = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
-
-error[E0658]: procedural macros cannot expand to macro definitions
- --> $DIR/more-gates.rs:17:1
- |
-LL | mac2mac2!();
- | ^^^^^^^^^^^^
- |
- = note: for more information, see https://github.com/rust-lang/rust/issues/54727
- = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
-
-error[E0658]: procedural macros cannot expand to macro definitions
- --> $DIR/more-gates.rs:19:1
- |
-LL | tricky!();
- | ^^^^^^^^^^
- |
- = note: for more information, see https://github.com/rust-lang/rust/issues/54727
- = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0658`.