mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-19 10:24:16 +00:00
Auto merge of #37645 - jseyfried:fix_crate_var_in_custom_derives, r=nrc
Fix regression involving custom derives on items with `$crate` The regression was introduced in #37213. I believe we cannot make the improvements from #37213 work with the current custom derive setup (c.f. https://github.com/rust-lang/rust/issues/37637#issuecomment-258959145) -- we'll have to wait for `TokenStream`'s API to improve. Fixes #37637. r? @nrc
This commit is contained in:
commit
3dced6f71e
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use {Module, Resolver};
|
||||
use {Module, ModuleKind, Resolver};
|
||||
use build_reduced_graph::BuildReducedGraphVisitor;
|
||||
use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
|
||||
use rustc::hir::def::{Def, Export};
|
||||
@ -22,7 +22,9 @@ use syntax::ext::base::{NormalTT, SyntaxExtension};
|
||||
use syntax::ext::expand::Expansion;
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::ext::tt::macro_rules;
|
||||
use syntax::fold::Folder;
|
||||
use syntax::parse::token::intern;
|
||||
use syntax::ptr::P;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use syntax::visit::Visitor;
|
||||
use syntax_pos::Span;
|
||||
@ -99,6 +101,31 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||
mark
|
||||
}
|
||||
|
||||
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> {
|
||||
struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>);
|
||||
|
||||
impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
|
||||
fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
|
||||
let ident = path.segments[0].identifier;
|
||||
if &ident.name.as_str() == "$crate" {
|
||||
path.global = true;
|
||||
let module = self.0.resolve_crate_var(ident.ctxt);
|
||||
if module.is_local() {
|
||||
path.segments.remove(0);
|
||||
} else {
|
||||
path.segments[0].identifier = match module.kind {
|
||||
ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
path
|
||||
}
|
||||
}
|
||||
|
||||
EliminateCrateVar(self).fold_item(item).expect_one("")
|
||||
}
|
||||
|
||||
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) {
|
||||
let invocation = self.invocations[&mark];
|
||||
self.collect_def_ids(invocation, expansion);
|
||||
|
@ -517,6 +517,7 @@ pub type NamedSyntaxExtension = (Name, SyntaxExtension);
|
||||
pub trait Resolver {
|
||||
fn next_node_id(&mut self) -> ast::NodeId;
|
||||
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
|
||||
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
|
||||
|
||||
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion);
|
||||
fn add_macro(&mut self, scope: Mark, def: ast::MacroDef, export: bool);
|
||||
@ -539,6 +540,7 @@ pub struct DummyResolver;
|
||||
impl Resolver for DummyResolver {
|
||||
fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID }
|
||||
fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
|
||||
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
|
||||
|
||||
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
|
||||
fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef, _export: bool) {}
|
||||
|
@ -73,7 +73,7 @@ impl MultiItemModifier for CustomDerive {
|
||||
// Mark attributes as known, and used.
|
||||
MarkAttrs(&self.attrs).visit_item(&item);
|
||||
|
||||
let input = __internal::new_token_stream(item.clone());
|
||||
let input = __internal::new_token_stream(ecx.resolver.eliminate_crate_var(item.clone()));
|
||||
let res = __internal::set_parse_sess(&ecx.parse_sess, || {
|
||||
let inner = self.inner;
|
||||
panic::catch_unwind(panic::AssertUnwindSafe(|| inner(input)))
|
||||
|
24
src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs
Normal file
24
src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![crate_type = "proc-macro"]
|
||||
#![feature(proc_macro)]
|
||||
#![feature(proc_macro_lib)]
|
||||
|
||||
extern crate proc_macro;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro_derive(Double)]
|
||||
pub fn derive(input: TokenStream) -> TokenStream {
|
||||
format!("mod foo {{ {} }}", input.to_string()).parse().unwrap()
|
||||
}
|
27
src/test/run-pass-fulldeps/proc-macro/crate-var.rs
Normal file
27
src/test/run-pass-fulldeps/proc-macro/crate-var.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:double.rs
|
||||
|
||||
#![feature(proc_macro)]
|
||||
#![allow(unused)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate double;
|
||||
|
||||
struct Foo;
|
||||
|
||||
macro_rules! m { () => {
|
||||
#[derive(Double)]
|
||||
struct Bar($crate::Foo);
|
||||
} }
|
||||
m!();
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user