Skip to content

Commit 3dced6f

Browse files
authored
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. #37637 (comment)) -- we'll have to wait for `TokenStream`'s API to improve. Fixes #37637. r? @nrc
2 parents bc1cc1d + 67eeb0a commit 3dced6f

File tree

5 files changed

+82
-2
lines changed

5 files changed

+82
-2
lines changed

src/librustc_resolve/macros.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use {Module, Resolver};
11+
use {Module, ModuleKind, Resolver};
1212
use build_reduced_graph::BuildReducedGraphVisitor;
1313
use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
1414
use rustc::hir::def::{Def, Export};
@@ -22,7 +22,9 @@ use syntax::ext::base::{NormalTT, SyntaxExtension};
2222
use syntax::ext::expand::Expansion;
2323
use syntax::ext::hygiene::Mark;
2424
use syntax::ext::tt::macro_rules;
25+
use syntax::fold::Folder;
2526
use syntax::parse::token::intern;
27+
use syntax::ptr::P;
2628
use syntax::util::lev_distance::find_best_match_for_name;
2729
use syntax::visit::Visitor;
2830
use syntax_pos::Span;
@@ -99,6 +101,31 @@ impl<'a> base::Resolver for Resolver<'a> {
99101
mark
100102
}
101103

104+
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> {
105+
struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>);
106+
107+
impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
108+
fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
109+
let ident = path.segments[0].identifier;
110+
if &ident.name.as_str() == "$crate" {
111+
path.global = true;
112+
let module = self.0.resolve_crate_var(ident.ctxt);
113+
if module.is_local() {
114+
path.segments.remove(0);
115+
} else {
116+
path.segments[0].identifier = match module.kind {
117+
ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name),
118+
_ => unreachable!(),
119+
};
120+
}
121+
}
122+
path
123+
}
124+
}
125+
126+
EliminateCrateVar(self).fold_item(item).expect_one("")
127+
}
128+
102129
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) {
103130
let invocation = self.invocations[&mark];
104131
self.collect_def_ids(invocation, expansion);

src/libsyntax/ext/base.rs

+2
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ pub type NamedSyntaxExtension = (Name, SyntaxExtension);
517517
pub trait Resolver {
518518
fn next_node_id(&mut self) -> ast::NodeId;
519519
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
520+
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
520521

521522
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion);
522523
fn add_macro(&mut self, scope: Mark, def: ast::MacroDef, export: bool);
@@ -539,6 +540,7 @@ pub struct DummyResolver;
539540
impl Resolver for DummyResolver {
540541
fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID }
541542
fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
543+
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
542544

543545
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
544546
fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef, _export: bool) {}

src/libsyntax_ext/deriving/custom.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl MultiItemModifier for CustomDerive {
7373
// Mark attributes as known, and used.
7474
MarkAttrs(&self.attrs).visit_item(&item);
7575

76-
let input = __internal::new_token_stream(item.clone());
76+
let input = __internal::new_token_stream(ecx.resolver.eliminate_crate_var(item.clone()));
7777
let res = __internal::set_parse_sess(&ecx.parse_sess, || {
7878
let inner = self.inner;
7979
panic::catch_unwind(panic::AssertUnwindSafe(|| inner(input)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// no-prefer-dynamic
12+
13+
#![crate_type = "proc-macro"]
14+
#![feature(proc_macro)]
15+
#![feature(proc_macro_lib)]
16+
17+
extern crate proc_macro;
18+
19+
use proc_macro::TokenStream;
20+
21+
#[proc_macro_derive(Double)]
22+
pub fn derive(input: TokenStream) -> TokenStream {
23+
format!("mod foo {{ {} }}", input.to_string()).parse().unwrap()
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:double.rs
12+
13+
#![feature(proc_macro)]
14+
#![allow(unused)]
15+
16+
#[macro_use]
17+
extern crate double;
18+
19+
struct Foo;
20+
21+
macro_rules! m { () => {
22+
#[derive(Double)]
23+
struct Bar($crate::Foo);
24+
} }
25+
m!();
26+
27+
fn main() {}

0 commit comments

Comments
 (0)