diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 513512b9f6b..062533f3d09 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -70,8 +70,8 @@ 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; -use syntax::parse::token::{self, Token}; +use syntax::parse::token::{self, Nonterminal, Token}; +use syntax::parse::ParseSess; use syntax::visit::{self, Visitor}; use syntax_pos::Span; @@ -87,6 +87,8 @@ pub struct LoweringContext<'a> { resolver: &'a mut dyn Resolver, + parser: &'static dyn Parser, + /// The items being lowered are collected here. items: BTreeMap, @@ -181,6 +183,13 @@ pub trait Resolver { fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool; } +/// HACK(Centril): there is a cyclic dependency between the parser and lowering +/// if we don't have this trait. To avoid that dependency so that librustc is +/// independent of the parser, we use type erasure here. +pub trait Parser { + fn nt_to_tokenstream(&self, nt: &Nonterminal, sess: &ParseSess, span: Span) -> TokenStream; +} + /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, /// and if so, what meaning it has. #[derive(Debug)] @@ -237,6 +246,7 @@ pub fn lower_crate( dep_graph: &DepGraph, krate: &Crate, resolver: &mut dyn Resolver, + parser: &'static dyn Parser, ) -> hir::Crate { // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to @@ -250,6 +260,7 @@ pub fn lower_crate( sess, cstore, resolver, + parser, items: BTreeMap::new(), trait_items: BTreeMap::new(), impl_items: BTreeMap::new(), @@ -1023,10 +1034,7 @@ impl<'a> LoweringContext<'a> { fn lower_token(&mut self, token: Token) -> TokenStream { match token.kind { token::Interpolated(nt) => { - // FIXME(Centril): Consider indirection `(parse_sess.nt_to_tokenstream)(...)` - // to hack around the current hack that requires `nt_to_tokenstream` to live - // in the parser. - let tts = parse::nt_to_tokenstream(&nt, &self.sess.parse_sess, token.span); + let tts = self.parser.nt_to_tokenstream(&nt, &self.sess.parse_sess, token.span); self.lower_token_stream(tts) } _ => TokenTree::Token(token).into(), diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index a1dc5b01aba..5078379e920 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -5,7 +5,7 @@ use crate::proc_macro_decls; use log::{info, warn, log_enabled}; use rustc::dep_graph::DepGraph; use rustc::hir; -use rustc::hir::lowering::lower_crate; +use rustc::hir::lowering::{lower_crate, Parser}; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; @@ -38,9 +38,12 @@ use syntax::early_buffered_lints::BufferedEarlyLint; use syntax::ext::base::{NamedSyntaxExtension, ExtCtxt}; use syntax::mut_visit::MutVisitor; use syntax::parse::{self, PResult}; +use syntax::parse::token::Nonterminal; +use syntax::parse::ParseSess; +use syntax::tokenstream::TokenStream; use syntax::util::node_count::NodeCounter; use syntax::symbol::Symbol; -use syntax_pos::FileName; +use syntax_pos::{FileName, Span}; use syntax_ext; use rustc_serialize::json; @@ -532,6 +535,16 @@ fn configure_and_expand_inner<'a>( Ok((krate, resolver)) } +fn parser() -> &'static dyn Parser { + struct Parse; + impl Parser for Parse { + fn nt_to_tokenstream(&self, nt: &Nonterminal, sess: &ParseSess, span: Span) -> TokenStream { + syntax::parse::nt_to_tokenstream(nt, sess, span) + } + } + &Parse +} + pub fn lower_to_hir( sess: &Session, cstore: &CStore, @@ -541,7 +554,7 @@ pub fn lower_to_hir( ) -> Result { // Lower AST to HIR. let hir_forest = time(sess, "lowering AST -> HIR", || { - let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver); + let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver, parser()); if sess.opts.debugging_opts.hir_stats { hir_stats::print_hir_stats(&hir_crate);