提交 dfa6c25a 编写于 作者: J Jeffrey Seyfried

Fix hygiene bug.

上级 560a5da9
......@@ -95,7 +95,7 @@ fn from_str(src: &str) -> Result<TokenStream, LexError> {
// notify the expansion info that it is unhygienic
let mark = Mark::fresh(mark);
mark.set_expn_info(expn_info);
let span = call_site.with_ctxt(SyntaxContext::empty().apply_mark(mark));
let span = call_site.with_ctxt(call_site.ctxt().apply_mark(mark));
let stream = parse::parse_stream_from_source_str(name, src, sess, Some(span));
Ok(__internal::token_stream_wrap(stream))
})
......
......@@ -575,7 +575,8 @@ pub fn create_def_with_parent(&mut self,
self.node_to_def_index.insert(node_id, index);
}
if expansion.is_modern() {
let expansion = expansion.modern();
if expansion != Mark::root() {
self.expansions.insert(index, expansion);
}
......
......@@ -1560,6 +1560,15 @@ fn per_ns<T, F: FnMut(&mut Self, Namespace) -> T>(&mut self, mut f: F) -> PerNS<
}
}
fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
loop {
match self.macro_defs.get(&ctxt.outer()) {
Some(&def_id) => return def_id,
None => ctxt.remove_mark(),
};
}
}
/// Entry point to crate resolution.
pub fn resolve_crate(&mut self, krate: &Crate) {
ImportResolver { resolver: self }.finalize_imports();
......@@ -1663,7 +1672,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
module = match self.ribs[ns][i].kind {
ModuleRibKind(module) => module,
MacroDefinition(def) if def == self.macro_defs[&ident.ctxt.outer()] => {
MacroDefinition(def) if def == self.macro_def(ident.ctxt) => {
// If an invocation of this macro created `ident`, give up on `ident`
// and switch to `ident`'s source from the macro definition.
ident.ctxt.remove_mark();
......@@ -1830,7 +1839,7 @@ fn search_label<P, R>(&self, mut ident: Ident, pred: P) -> Option<R>
// If an invocation of this macro created `ident`, give up on `ident`
// and switch to `ident`'s source from the macro definition.
MacroDefinition(def) => {
if def == self.macro_defs[&ident.ctxt.outer()] {
if def == self.macro_def(ident.ctxt) {
ident.ctxt.remove_mark();
}
}
......
......@@ -73,6 +73,13 @@ impl<'a> StringReader<'a> {
fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
unwrap_or!(self.override_span, Span::new(lo, hi, NO_EXPANSION))
}
fn mk_ident(&self, string: &str) -> Ident {
let mut ident = Ident::from_str(string);
if let Some(span) = self.override_span {
ident.ctxt = span.ctxt();
}
ident
}
fn next_token(&mut self) -> TokenAndSpan where Self: Sized {
let res = self.try_next_token();
......@@ -1103,7 +1110,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
token::Underscore
} else {
// FIXME: perform NFKC normalization here. (Issue #2253)
token::Ident(Ident::from_str(string))
token::Ident(self.mk_ident(string))
}
}));
}
......@@ -1286,13 +1293,13 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
// expansion purposes. See #12512 for the gory details of why
// this is necessary.
let ident = self.with_str_from(start, |lifetime_name| {
Ident::from_str(&format!("'{}", lifetime_name))
self.mk_ident(&format!("'{}", lifetime_name))
});
// Conjure up a "keyword checking ident" to make sure that
// the lifetime name is not a keyword.
let keyword_checking_ident = self.with_str_from(start, |lifetime_name| {
Ident::from_str(lifetime_name)
self.mk_ident(lifetime_name)
});
let keyword_checking_token = &token::Ident(keyword_checking_ident);
let last_bpos = self.pos;
......
......@@ -23,5 +23,5 @@ fn main() {
bang_proc_macro2!();
//~^ ERROR cannot find value `foobar2` in this scope
//~^^ did you mean `foobar`?
println!("{}", x);
println!("{}", x); //~ ERROR cannot find value `x` in this scope
}
// Copyright 2017 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)]
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_derive(Test)]
pub fn derive(_input: TokenStream) -> TokenStream {
"fn f(s: S) { s.x }".parse().unwrap()
}
#[proc_macro_attribute]
pub fn attr_test(_attr: TokenStream, input: TokenStream) -> TokenStream {
input
}
// Copyright 2017 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:issue-42708.rs
// ignore-stage1
#![feature(decl_macro, proc_macro)]
#![allow(unused)]
extern crate issue_42708;
macro m() {
#[derive(issue_42708::Test)]
struct S { x: () }
#[issue_42708::attr_test]
struct S2 { x: () }
#[derive(Clone)]
struct S3 { x: () }
fn g(s: S, s2: S2, s3: S3) {
(s.x, s2.x, s3.x);
}
}
m!();
fn main() {}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册