mirror of https://github.com/rust-lang/rust.git
Auto merge of #46550 - jseyfried:cleanup_builtin_hygiene, r=nrc
macros: hygienize use of `core`/`std` in builtin macros Today, if a builtin macro wants to access an item from `core` or `std` (depending `#![no_std]`), it generates `::core::path::to::item` or `::std::path::to::item` respectively (c.f. `fn std_path()` in `libsyntax/ext/base.rs`). This PR refactors the builtin macros to instead always emit `$crate::path::to::item` here. That is, the def site of builtin macros is taken to be in `extern crate core;` or `extern crate std;`. Since builtin macros are macros 1.0 (i.e. mostly unhygienic), changing the def site can only effect the resolution of `$crate`. r? @nrc
This commit is contained in:
commit
3dfbc88a62
|
@ -175,7 +175,7 @@ pub fn lower_crate(sess: &Session,
|
|||
let _ignore = dep_graph.in_ignore();
|
||||
|
||||
LoweringContext {
|
||||
crate_root: std_inject::injected_crate_name(krate),
|
||||
crate_root: std_inject::injected_crate_name(),
|
||||
sess,
|
||||
cstore,
|
||||
parent_def: None,
|
||||
|
|
|
@ -40,6 +40,7 @@ use syntax::ext::base::Determinacy::Undetermined;
|
|||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::ext::tt::macro_rules;
|
||||
use syntax::parse::token::{self, Token};
|
||||
use syntax::std_inject::injected_crate_name;
|
||||
use syntax::symbol::keywords;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax::visit::{self, Visitor};
|
||||
|
@ -262,6 +263,10 @@ impl<'a> Resolver<'a> {
|
|||
let module =
|
||||
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
|
||||
self.populate_module_if_necessary(module);
|
||||
if injected_crate_name().map_or(false, |name| item.ident.name == name) {
|
||||
self.injected_crate = Some(module);
|
||||
}
|
||||
|
||||
let used = self.process_legacy_macro_imports(item, module, expansion);
|
||||
let binding =
|
||||
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
|
||||
|
@ -558,8 +563,7 @@ impl<'a> Resolver<'a> {
|
|||
if let Some(id) = self.definitions.as_local_node_id(def_id) {
|
||||
self.local_macro_def_scopes[&id]
|
||||
} else if def_id.krate == BUILTIN_MACROS_CRATE {
|
||||
// FIXME(jseyfried): This happens when `include!()`ing a `$crate::` path, c.f, #40469.
|
||||
self.graph_root
|
||||
self.injected_crate.unwrap_or(self.graph_root)
|
||||
} else {
|
||||
let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
|
||||
self.get_module(module_def_id)
|
||||
|
|
|
@ -1338,6 +1338,8 @@ pub struct Resolver<'a> {
|
|||
|
||||
// Only used for better errors on `fn(): fn()`
|
||||
current_type_ascription: Vec<Span>,
|
||||
|
||||
injected_crate: Option<Module<'a>>,
|
||||
}
|
||||
|
||||
pub struct ResolverArenas<'a> {
|
||||
|
@ -1537,6 +1539,7 @@ impl<'a> Resolver<'a> {
|
|||
found_unresolved_macro: false,
|
||||
unused_macros: FxHashSet(),
|
||||
current_type_ascription: Vec::new(),
|
||||
injected_crate: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ use syntax::errors::DiagnosticBuilder;
|
|||
use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
|
||||
use syntax::ext::expand::{Expansion, ExpansionKind, Invocation, InvocationKind, find_attr_invoc};
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::ext::hygiene::{Mark, MarkKind};
|
||||
use syntax::ext::placeholders::placeholder;
|
||||
use syntax::ext::tt::macro_rules;
|
||||
use syntax::feature_gate::{self, emit_feature_err, GateIssue};
|
||||
|
@ -297,16 +297,19 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
InvocationKind::Attr { attr: None, .. } => return Ok(None),
|
||||
_ => self.resolve_invoc_to_def(invoc, scope, force)?,
|
||||
};
|
||||
let def_id = def.def_id();
|
||||
|
||||
self.macro_defs.insert(invoc.expansion_data.mark, def.def_id());
|
||||
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
|
||||
let normal_module_def_id =
|
||||
self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
|
||||
self.definitions.add_macro_def_scope(invoc.expansion_data.mark, normal_module_def_id);
|
||||
|
||||
self.unused_macros.remove(&def.def_id());
|
||||
self.unused_macros.remove(&def_id);
|
||||
let ext = self.get_macro(def);
|
||||
if ext.is_modern() {
|
||||
invoc.expansion_data.mark.set_modern();
|
||||
invoc.expansion_data.mark.set_kind(MarkKind::Modern);
|
||||
} else if def_id.krate == BUILTIN_MACROS_CRATE {
|
||||
invoc.expansion_data.mark.set_kind(MarkKind::Builtin);
|
||||
}
|
||||
Ok(Some(ext))
|
||||
}
|
||||
|
|
|
@ -21,10 +21,11 @@ use fold::{self, Folder};
|
|||
use parse::{self, parser, DirectoryOwnership};
|
||||
use parse::token;
|
||||
use ptr::P;
|
||||
use symbol::Symbol;
|
||||
use symbol::{keywords, Ident, Symbol};
|
||||
use util::small_vector::SmallVector;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::iter;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::default::Default;
|
||||
|
@ -664,7 +665,6 @@ pub struct ExpansionData {
|
|||
pub struct ExtCtxt<'a> {
|
||||
pub parse_sess: &'a parse::ParseSess,
|
||||
pub ecfg: expand::ExpansionConfig<'a>,
|
||||
pub crate_root: Option<&'static str>,
|
||||
pub root_path: PathBuf,
|
||||
pub resolver: &'a mut Resolver,
|
||||
pub resolve_err_count: usize,
|
||||
|
@ -680,7 +680,6 @@ impl<'a> ExtCtxt<'a> {
|
|||
ExtCtxt {
|
||||
parse_sess,
|
||||
ecfg,
|
||||
crate_root: None,
|
||||
root_path: PathBuf::new(),
|
||||
resolver,
|
||||
resolve_err_count: 0,
|
||||
|
@ -822,12 +821,10 @@ impl<'a> ExtCtxt<'a> {
|
|||
ast::Ident::from_str(st)
|
||||
}
|
||||
pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
|
||||
let mut v = Vec::new();
|
||||
if let Some(s) = self.crate_root {
|
||||
v.push(self.ident_of(s));
|
||||
}
|
||||
v.extend(components.iter().map(|s| self.ident_of(s)));
|
||||
v
|
||||
let def_site = SyntaxContext::empty().apply_mark(self.current_expansion.mark);
|
||||
iter::once(Ident { ctxt: def_site, ..keywords::DollarCrate.ident() })
|
||||
.chain(components.iter().map(|s| self.ident_of(s)))
|
||||
.collect()
|
||||
}
|
||||
pub fn name_of(&self, st: &str) -> ast::Name {
|
||||
Symbol::intern(st)
|
||||
|
|
|
@ -319,9 +319,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
types: Vec<P<ast::Ty>>,
|
||||
bindings: Vec<ast::TypeBinding> )
|
||||
-> ast::Path {
|
||||
use syntax::parse::token;
|
||||
|
||||
let last_identifier = idents.pop().unwrap();
|
||||
let mut segments: Vec<ast::PathSegment> = Vec::new();
|
||||
if global {
|
||||
if global &&
|
||||
!idents.first().map_or(false, |&ident| token::Ident(ident).is_path_segment_keyword()) {
|
||||
segments.push(ast::PathSegment::crate_root(span));
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ use parse::{DirectoryOwnership, PResult};
|
|||
use parse::token::{self, Token};
|
||||
use parse::parser::Parser;
|
||||
use ptr::P;
|
||||
use std_inject;
|
||||
use symbol::Symbol;
|
||||
use symbol::keywords;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
@ -219,7 +218,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
|
||||
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
|
||||
self.cx.crate_root = std_inject::injected_crate_name(&krate);
|
||||
let mut module = ModuleData {
|
||||
mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
|
||||
directory: self.cx.codemap().span_to_unmapped_path(krate.span),
|
||||
|
|
|
@ -18,6 +18,7 @@ use util::parser::{self, AssocOp, Fixity};
|
|||
use attr;
|
||||
use codemap::{self, CodeMap};
|
||||
use syntax_pos::{self, BytePos};
|
||||
use syntax_pos::hygiene::{Mark, MarkKind, SyntaxContext};
|
||||
use parse::token::{self, BinOpToken, Token};
|
||||
use parse::lexer::comments;
|
||||
use parse::{self, ParseSess};
|
||||
|
@ -93,7 +94,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
|
|||
is_expanded: bool) -> io::Result<()> {
|
||||
let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded);
|
||||
|
||||
if is_expanded && !std_inject::injected_crate_name(krate).is_none() {
|
||||
if is_expanded && !std_inject::injected_crate_name().is_none() {
|
||||
// We need to print `#![no_std]` (and its feature gate) so that
|
||||
// compiling pretty-printed source won't inject libstd again.
|
||||
// However we don't want these attributes in the AST because
|
||||
|
@ -734,6 +735,8 @@ pub trait PrintState<'a> {
|
|||
if segment.identifier.name != keywords::CrateRoot.name() &&
|
||||
segment.identifier.name != keywords::DollarCrate.name() {
|
||||
self.writer().word(&segment.identifier.name.as_str())?;
|
||||
} else if segment.identifier.name == keywords::DollarCrate.name() {
|
||||
self.print_dollar_crate(segment.identifier.ctxt)?;
|
||||
}
|
||||
}
|
||||
self.writer().space()?;
|
||||
|
@ -822,6 +825,19 @@ pub trait PrintState<'a> {
|
|||
}
|
||||
|
||||
fn nbsp(&mut self) -> io::Result<()> { self.writer().word(" ") }
|
||||
|
||||
fn print_dollar_crate(&mut self, mut ctxt: SyntaxContext) -> io::Result<()> {
|
||||
if let Some(mark) = ctxt.adjust(Mark::root()) {
|
||||
// Make a best effort to print something that complies
|
||||
if mark.kind() == MarkKind::Builtin {
|
||||
if let Some(name) = std_inject::injected_crate_name() {
|
||||
self.writer().word("::")?;
|
||||
self.writer().word(name)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PrintState<'a> for State<'a> {
|
||||
|
@ -2411,6 +2427,8 @@ impl<'a> State<'a> {
|
|||
if let Some(ref parameters) = segment.parameters {
|
||||
self.print_path_parameters(parameters, colons_before_params)?;
|
||||
}
|
||||
} else if segment.identifier.name == keywords::DollarCrate.name() {
|
||||
self.print_dollar_crate(segment.identifier.ctxt)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
use ast;
|
||||
use attr;
|
||||
use std::cell::Cell;
|
||||
use ext::hygiene::{Mark, SyntaxContext};
|
||||
use symbol::{Symbol, keywords};
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
|
@ -34,22 +35,25 @@ fn ignored_span(sp: Span) -> Span {
|
|||
sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
|
||||
}
|
||||
|
||||
pub fn injected_crate_name(krate: &ast::Crate) -> Option<&'static str> {
|
||||
if attr::contains_name(&krate.attrs, "no_core") {
|
||||
None
|
||||
} else if attr::contains_name(&krate.attrs, "no_std") {
|
||||
Some("core")
|
||||
} else {
|
||||
Some("std")
|
||||
}
|
||||
pub fn injected_crate_name() -> Option<&'static str> {
|
||||
INJECTED_CRATE_NAME.with(|name| name.get())
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static INJECTED_CRATE_NAME: Cell<Option<&'static str>> = Cell::new(None);
|
||||
}
|
||||
|
||||
pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<String>) -> ast::Crate {
|
||||
let name = match injected_crate_name(&krate) {
|
||||
Some(name) => name,
|
||||
None => return krate,
|
||||
let name = if attr::contains_name(&krate.attrs, "no_core") {
|
||||
return krate;
|
||||
} else if attr::contains_name(&krate.attrs, "no_std") {
|
||||
"core"
|
||||
} else {
|
||||
"std"
|
||||
};
|
||||
|
||||
INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));
|
||||
|
||||
let crate_name = Symbol::intern(&alt_std_name.unwrap_or_else(|| name.to_string()));
|
||||
|
||||
krate.module.items.insert(0, P(ast::Item {
|
||||
|
|
|
@ -272,7 +272,7 @@ fn generate_test_harness(sess: &ParseSess,
|
|||
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
|
||||
let mut cx: TestCtxt = TestCtxt {
|
||||
let cx = TestCtxt {
|
||||
span_diagnostic: sd,
|
||||
ext_cx: ExtCtxt::new(sess, ExpansionConfig::default("test".to_string()), resolver),
|
||||
path: Vec::new(),
|
||||
|
@ -283,7 +283,6 @@ fn generate_test_harness(sess: &ParseSess,
|
|||
toplevel_reexport: None,
|
||||
ctxt: SyntaxContext::empty().apply_mark(mark),
|
||||
};
|
||||
cx.ext_cx.crate_root = Some("std");
|
||||
|
||||
mark.set_expn_info(ExpnInfo {
|
||||
call_site: DUMMY_SP,
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use deriving::path_std;
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
|
||||
use syntax::ast::MetaItem;
|
||||
use syntax::ext::base::{Annotatable, ExtCtxt};
|
||||
use syntax_pos::Span;
|
||||
|
@ -28,15 +28,10 @@ pub fn expand_deriving_copy(cx: &mut ExtCtxt,
|
|||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut FnMut(Annotatable)) {
|
||||
let mut v = cx.crate_root.map(|s| vec![s]).unwrap_or(Vec::new());
|
||||
v.push("marker");
|
||||
v.push("Copy");
|
||||
let path = Path::new(v);
|
||||
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path,
|
||||
path: path_std!(cx, marker::Copy),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use deriving::path_std;
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
|
||||
|
@ -55,7 +56,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
|
|||
}));
|
||||
}
|
||||
ItemKind::Union(..) => {
|
||||
bounds = vec![Literal(path_std!(cx, core::marker::Copy))];
|
||||
bounds = vec![Literal(path_std!(cx, marker::Copy))];
|
||||
is_shallow = true;
|
||||
substructure = combine_substructure(Box::new(|c, s, sub| {
|
||||
cs_clone_shallow("Clone", c, s, sub, true)
|
||||
|
@ -79,7 +80,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
|
|||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path: path_std!(cx, core::clone::Clone),
|
||||
path: path_std!(cx, clone::Clone),
|
||||
additional_bounds: bounds,
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use deriving::path_std;
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
|
||||
|
@ -30,7 +31,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
|
|||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path: path_std!(cx, core::cmp::Eq),
|
||||
path: path_std!(cx, cmp::Eq),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use deriving::path_std;
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
|
||||
|
@ -28,7 +29,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
|||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path: path_std!(cx, core::cmp::Ord),
|
||||
path: path_std!(cx, cmp::Ord),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
@ -38,7 +39,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
|||
generics: LifetimeBounds::empty(),
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec![borrowed_self()],
|
||||
ret_ty: Literal(path_std!(cx, core::cmp::Ordering)),
|
||||
ret_ty: Literal(path_std!(cx, cmp::Ordering)),
|
||||
attributes: attrs,
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: true,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use deriving::{path_local, path_std};
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
|
||||
|
@ -93,7 +94,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
|
|||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path: path_std!(cx, core::cmp::PartialEq),
|
||||
path: path_std!(cx, cmp::PartialEq),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
pub use self::OrderingOp::*;
|
||||
|
||||
use deriving::{path_local, pathvec_std, path_std};
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
|
||||
|
@ -45,11 +46,11 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
|
|||
} }
|
||||
}
|
||||
|
||||
let ordering_ty = Literal(path_std!(cx, core::cmp::Ordering));
|
||||
let ret_ty = Literal(Path::new_(pathvec_std!(cx, core::option::Option),
|
||||
let ordering_ty = Literal(path_std!(cx, cmp::Ordering));
|
||||
let ret_ty = Literal(Path::new_(pathvec_std!(cx, option::Option),
|
||||
None,
|
||||
vec![Box::new(ordering_ty)],
|
||||
true));
|
||||
PathKind::Std));
|
||||
|
||||
let inline = cx.meta_word(span, Symbol::intern("inline"));
|
||||
let attrs = vec![cx.attribute(span, inline)];
|
||||
|
@ -84,7 +85,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
|
|||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: vec![],
|
||||
path: path_std!(cx, core::cmp::PartialOrd),
|
||||
path: path_std!(cx, cmp::PartialOrd),
|
||||
additional_bounds: vec![],
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use deriving::path_std;
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
|
||||
|
@ -24,13 +25,13 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt,
|
|||
item: &Annotatable,
|
||||
push: &mut FnMut(Annotatable)) {
|
||||
// &mut ::std::fmt::Formatter
|
||||
let fmtr = Ptr(Box::new(Literal(path_std!(cx, core::fmt::Formatter))),
|
||||
let fmtr = Ptr(Box::new(Literal(path_std!(cx, fmt::Formatter))),
|
||||
Borrowed(None, ast::Mutability::Mutable));
|
||||
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path: path_std!(cx, core::fmt::Debug),
|
||||
path: path_std!(cx, fmt::Debug),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
@ -40,7 +41,7 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt,
|
|||
generics: LifetimeBounds::empty(),
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec![fmtr],
|
||||
ret_ty: Literal(path_std!(cx, core::fmt::Result)),
|
||||
ret_ty: Literal(path_std!(cx, fmt::Result)),
|
||||
attributes: Vec::new(),
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: false,
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
//! The compiler code necessary for `#[derive(Decodable)]`. See encodable.rs for more.
|
||||
|
||||
use deriving;
|
||||
use deriving::{self, pathvec_std};
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
use deriving::warn_if_deprecated;
|
||||
|
@ -46,20 +46,12 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
|
|||
item: &Annotatable,
|
||||
push: &mut FnMut(Annotatable),
|
||||
krate: &'static str) {
|
||||
if cx.crate_root != Some("std") {
|
||||
// FIXME(#21880): lift this requirement.
|
||||
cx.span_err(span,
|
||||
"this trait cannot be derived with #![no_std] \
|
||||
or #![no_core]");
|
||||
return;
|
||||
}
|
||||
|
||||
let typaram = &*deriving::hygienic_type_parameter(item, "__D");
|
||||
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path: Path::new_(vec![krate, "Decodable"], None, vec![], true),
|
||||
path: Path::new_(vec![krate, "Decodable"], None, vec![], PathKind::Global),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
@ -72,18 +64,18 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
|
|||
vec![Path::new_(vec![krate, "Decoder"],
|
||||
None,
|
||||
vec![],
|
||||
true)])],
|
||||
PathKind::Global)])],
|
||||
},
|
||||
explicit_self: None,
|
||||
args: vec![Ptr(Box::new(Literal(Path::new_local(typaram))),
|
||||
Borrowed(None, Mutability::Mutable))],
|
||||
ret_ty:
|
||||
Literal(Path::new_(pathvec_std!(cx, core::result::Result),
|
||||
Literal(Path::new_(pathvec_std!(cx, result::Result),
|
||||
None,
|
||||
vec![Box::new(Self_), Box::new(Literal(Path::new_(
|
||||
vec![typaram, "Error"], None, vec![], false
|
||||
vec![typaram, "Error"], None, vec![], PathKind::Local
|
||||
)))],
|
||||
true)),
|
||||
PathKind::Std)),
|
||||
attributes: Vec::new(),
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: false,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use deriving::path_std;
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
|
||||
|
@ -28,7 +29,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
|
|||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path: path_std!(cx, core::default::Default),
|
||||
path: path_std!(cx, default::Default),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
//! }
|
||||
//! ```
|
||||
|
||||
use deriving;
|
||||
use deriving::{self, pathvec_std};
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
use deriving::warn_if_deprecated;
|
||||
|
@ -127,20 +127,12 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
|
|||
item: &Annotatable,
|
||||
push: &mut FnMut(Annotatable),
|
||||
krate: &'static str) {
|
||||
if cx.crate_root != Some("std") {
|
||||
// FIXME(#21880): lift this requirement.
|
||||
cx.span_err(span,
|
||||
"this trait cannot be derived with #![no_std] \
|
||||
or #![no_core]");
|
||||
return;
|
||||
}
|
||||
|
||||
let typaram = &*deriving::hygienic_type_parameter(item, "__S");
|
||||
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path: Path::new_(vec![krate, "Encodable"], None, vec![], true),
|
||||
path: Path::new_(vec![krate, "Encodable"], None, vec![], PathKind::Global),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
@ -150,19 +142,21 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
|
|||
name: "encode",
|
||||
generics: LifetimeBounds {
|
||||
lifetimes: Vec::new(),
|
||||
bounds: vec![(typaram,
|
||||
vec![Path::new_(vec![krate, "Encoder"], None, vec![], true)])]
|
||||
bounds: vec![
|
||||
(typaram,
|
||||
vec![Path::new_(vec![krate, "Encoder"], None, vec![], PathKind::Global)])
|
||||
],
|
||||
},
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec![Ptr(Box::new(Literal(Path::new_local(typaram))),
|
||||
Borrowed(None, Mutability::Mutable))],
|
||||
ret_ty: Literal(Path::new_(
|
||||
pathvec_std!(cx, core::result::Result),
|
||||
pathvec_std!(cx, result::Result),
|
||||
None,
|
||||
vec![Box::new(Tuple(Vec::new())), Box::new(Literal(Path::new_(
|
||||
vec![typaram, "Error"], None, vec![], false
|
||||
vec![typaram, "Error"], None, vec![], PathKind::Local
|
||||
)))],
|
||||
true
|
||||
PathKind::Std
|
||||
)),
|
||||
attributes: Vec::new(),
|
||||
is_unsafe: false,
|
||||
|
|
|
@ -21,6 +21,8 @@ use syntax::ext::build::AstBuilder;
|
|||
use syntax::codemap::respan;
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::Span;
|
||||
use syntax_pos::hygiene::SyntaxContext;
|
||||
use syntax_pos::symbol::keywords;
|
||||
|
||||
/// The types of pointers
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
|
@ -36,29 +38,36 @@ pub enum PtrTy<'a> {
|
|||
/// for type parameters and a lifetime.
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct Path<'a> {
|
||||
pub path: Vec<&'a str>,
|
||||
pub lifetime: Option<&'a str>,
|
||||
pub params: Vec<Box<Ty<'a>>>,
|
||||
pub global: bool,
|
||||
path: Vec<&'a str>,
|
||||
lifetime: Option<&'a str>,
|
||||
params: Vec<Box<Ty<'a>>>,
|
||||
kind: PathKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub enum PathKind {
|
||||
Local,
|
||||
Global,
|
||||
Std,
|
||||
}
|
||||
|
||||
impl<'a> Path<'a> {
|
||||
pub fn new<'r>(path: Vec<&'r str>) -> Path<'r> {
|
||||
Path::new_(path, None, Vec::new(), true)
|
||||
Path::new_(path, None, Vec::new(), PathKind::Std)
|
||||
}
|
||||
pub fn new_local<'r>(path: &'r str) -> Path<'r> {
|
||||
Path::new_(vec![path], None, Vec::new(), false)
|
||||
Path::new_(vec![path], None, Vec::new(), PathKind::Local)
|
||||
}
|
||||
pub fn new_<'r>(path: Vec<&'r str>,
|
||||
lifetime: Option<&'r str>,
|
||||
params: Vec<Box<Ty<'r>>>,
|
||||
global: bool)
|
||||
kind: PathKind)
|
||||
-> Path<'r> {
|
||||
Path {
|
||||
path,
|
||||
lifetime,
|
||||
params,
|
||||
global,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,11 +85,20 @@ impl<'a> Path<'a> {
|
|||
self_ty: Ident,
|
||||
self_generics: &Generics)
|
||||
-> ast::Path {
|
||||
let idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
|
||||
let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
|
||||
let lt = mk_lifetimes(cx, span, &self.lifetime);
|
||||
let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
|
||||
|
||||
cx.path_all(span, self.global, idents, lt, tys, Vec::new())
|
||||
match self.kind {
|
||||
PathKind::Global => cx.path_all(span, true, idents, lt, tys, Vec::new()),
|
||||
PathKind::Local => cx.path_all(span, false, idents, lt, tys, Vec::new()),
|
||||
PathKind::Std => {
|
||||
let def_site = SyntaxContext::empty().apply_mark(cx.current_expansion.mark);
|
||||
idents.insert(0, Ident { ctxt: def_site, ..keywords::DollarCrate.ident() });
|
||||
cx.path_all(span, false, idents, lt, tys, Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use deriving;
|
||||
use deriving::{self, pathvec_std, path_std};
|
||||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
|
||||
|
@ -24,7 +24,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
|
|||
item: &Annotatable,
|
||||
push: &mut FnMut(Annotatable)) {
|
||||
|
||||
let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None, vec![], true);
|
||||
let path = Path::new_(pathvec_std!(cx, hash::Hash), None, vec![], PathKind::Std);
|
||||
|
||||
let typaram = &*deriving::hygienic_type_parameter(item, "__H");
|
||||
|
||||
|
@ -41,7 +41,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
|
|||
name: "hash",
|
||||
generics: LifetimeBounds {
|
||||
lifetimes: Vec::new(),
|
||||
bounds: vec![(typaram, vec![path_std!(cx, core::hash::Hasher)])],
|
||||
bounds: vec![(typaram, vec![path_std!(cx, hash::Hasher)])],
|
||||
},
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec![Ptr(Box::new(Literal(arg)),
|
||||
|
|
|
@ -19,32 +19,16 @@ use syntax::ptr::P;
|
|||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
|
||||
macro_rules! pathvec {
|
||||
($($x:ident)::+) => (
|
||||
vec![ $( stringify!($x) ),+ ]
|
||||
)
|
||||
macro path_local($x:ident) {
|
||||
generic::ty::Path::new_local(stringify!($x))
|
||||
}
|
||||
|
||||
macro_rules! path_local {
|
||||
($x:ident) => (
|
||||
::deriving::generic::ty::Path::new_local(stringify!($x))
|
||||
)
|
||||
}
|
||||
macro pathvec_std($cx:expr, $($rest:ident)::+) {{
|
||||
vec![ $( stringify!($rest) ),+ ]
|
||||
}}
|
||||
|
||||
macro_rules! pathvec_std {
|
||||
($cx:expr, $first:ident :: $($rest:ident)::+) => ({
|
||||
let mut v = pathvec![$($rest)::+];
|
||||
if let Some(s) = $cx.crate_root {
|
||||
v.insert(0, s);
|
||||
}
|
||||
v
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! path_std {
|
||||
($($x:tt)*) => (
|
||||
::deriving::generic::ty::Path::new( pathvec_std!( $($x)* ) )
|
||||
)
|
||||
macro path_std($($x:tt)*) {
|
||||
generic::ty::Path::new( pathvec_std!( $($x)* ) )
|
||||
}
|
||||
|
||||
pub mod bounds;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#![deny(warnings)]
|
||||
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(decl_macro)]
|
||||
|
||||
extern crate fmt_macros;
|
||||
#[macro_use]
|
||||
|
|
|
@ -27,7 +27,7 @@ use std::fmt;
|
|||
#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
|
||||
pub struct SyntaxContext(pub(super) u32);
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SyntaxContextData {
|
||||
pub outer_mark: Mark,
|
||||
pub prev_ctxt: SyntaxContext,
|
||||
|
@ -35,20 +35,26 @@ pub struct SyntaxContextData {
|
|||
}
|
||||
|
||||
/// A mark is a unique id associated with a macro expansion.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct Mark(u32);
|
||||
|
||||
#[derive(Default)]
|
||||
struct MarkData {
|
||||
parent: Mark,
|
||||
modern: bool,
|
||||
kind: MarkKind,
|
||||
expn_info: Option<ExpnInfo>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum MarkKind {
|
||||
Modern,
|
||||
Builtin,
|
||||
Legacy,
|
||||
}
|
||||
|
||||
impl Mark {
|
||||
pub fn fresh(parent: Mark) -> Self {
|
||||
HygieneData::with(|data| {
|
||||
data.marks.push(MarkData { parent: parent, modern: false, expn_info: None });
|
||||
data.marks.push(MarkData { parent: parent, kind: MarkKind::Legacy, expn_info: None });
|
||||
Mark(data.marks.len() as u32 - 1)
|
||||
})
|
||||
}
|
||||
|
@ -77,7 +83,7 @@ impl Mark {
|
|||
pub fn modern(mut self) -> Mark {
|
||||
HygieneData::with(|data| {
|
||||
loop {
|
||||
if self == Mark::root() || data.marks[self.0 as usize].modern {
|
||||
if self == Mark::root() || data.marks[self.0 as usize].kind == MarkKind::Modern {
|
||||
return self;
|
||||
}
|
||||
self = data.marks[self.0 as usize].parent;
|
||||
|
@ -85,12 +91,12 @@ impl Mark {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn is_modern(self) -> bool {
|
||||
HygieneData::with(|data| data.marks[self.0 as usize].modern)
|
||||
pub fn kind(self) -> MarkKind {
|
||||
HygieneData::with(|data| data.marks[self.0 as usize].kind)
|
||||
}
|
||||
|
||||
pub fn set_modern(self) {
|
||||
HygieneData::with(|data| data.marks[self.0 as usize].modern = true)
|
||||
pub fn set_kind(self, kind: MarkKind) {
|
||||
HygieneData::with(|data| data.marks[self.0 as usize].kind = kind)
|
||||
}
|
||||
|
||||
pub fn is_descendant_of(mut self, ancestor: Mark) -> bool {
|
||||
|
@ -116,8 +122,16 @@ struct HygieneData {
|
|||
impl HygieneData {
|
||||
fn new() -> Self {
|
||||
HygieneData {
|
||||
marks: vec![MarkData::default()],
|
||||
syntax_contexts: vec![SyntaxContextData::default()],
|
||||
marks: vec![MarkData {
|
||||
parent: Mark::root(),
|
||||
kind: MarkKind::Builtin,
|
||||
expn_info: None,
|
||||
}],
|
||||
syntax_contexts: vec![SyntaxContextData {
|
||||
outer_mark: Mark::root(),
|
||||
prev_ctxt: SyntaxContext(0),
|
||||
modern: SyntaxContext(0),
|
||||
}],
|
||||
markings: HashMap::new(),
|
||||
gensym_to_ctxt: HashMap::new(),
|
||||
}
|
||||
|
@ -150,7 +164,7 @@ impl SyntaxContext {
|
|||
HygieneData::with(|data| {
|
||||
data.marks.push(MarkData {
|
||||
parent: Mark::root(),
|
||||
modern: false,
|
||||
kind: MarkKind::Legacy,
|
||||
expn_info: Some(expansion_info)
|
||||
});
|
||||
|
||||
|
@ -170,7 +184,7 @@ impl SyntaxContext {
|
|||
HygieneData::with(|data| {
|
||||
let syntax_contexts = &mut data.syntax_contexts;
|
||||
let mut modern = syntax_contexts[self.0 as usize].modern;
|
||||
if data.marks[mark.0 as usize].modern {
|
||||
if data.marks[mark.0 as usize].kind == MarkKind::Modern {
|
||||
modern = *data.markings.entry((modern, mark)).or_insert_with(|| {
|
||||
let len = syntax_contexts.len() as u32;
|
||||
syntax_contexts.push(SyntaxContextData {
|
||||
|
|
|
@ -40,7 +40,7 @@ pub fn bar() ({
|
|||
|
||||
|
||||
((::fmt::format as
|
||||
for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((<::std::fmt::Arguments>::new_v1
|
||||
for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((<::fmt::Arguments>::new_v1
|
||||
as
|
||||
fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})((&([("test"
|
||||
as
|
||||
|
|
|
@ -69,7 +69,7 @@ fn expand_deriving_partial_eq(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, it
|
|||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
attributes: Vec::new(),
|
||||
path: deriving::generic::ty::Path::new(vec!["std", "cmp", "PartialEq"]),
|
||||
path: deriving::generic::ty::Path::new(vec!["cmp", "PartialEq"]),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
is_unsafe: false,
|
||||
|
|
|
@ -50,7 +50,7 @@ fn expand(cx: &mut ExtCtxt,
|
|||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
attributes: vec![],
|
||||
path: Path::new(vec!["TotalSum"]),
|
||||
path: Path::new_local("TotalSum"),
|
||||
additional_bounds: vec![],
|
||||
generics: LifetimeBounds::empty(),
|
||||
associated_types: vec![],
|
||||
|
|
|
@ -46,7 +46,7 @@ fn expand(cx: &mut ExtCtxt,
|
|||
let trait_def = TraitDef {
|
||||
span: span,
|
||||
attributes: vec![],
|
||||
path: Path::new(vec!["TotalSum"]),
|
||||
path: Path::new_local("TotalSum"),
|
||||
additional_bounds: vec![],
|
||||
generics: LifetimeBounds::empty(),
|
||||
associated_types: vec![],
|
||||
|
|
|
@ -8,22 +8,22 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![no_std]
|
||||
|
||||
extern crate serialize as rustc_serialize;
|
||||
|
||||
#[derive(RustcEncodable)] //~ ERROR this trait cannot be derived
|
||||
#[derive(RustcEncodable)]
|
||||
struct Bar {
|
||||
x: u32,
|
||||
}
|
||||
|
||||
#[derive(RustcDecodable)] //~ ERROR this trait cannot be derived
|
||||
#[derive(RustcDecodable)]
|
||||
struct Baz {
|
||||
x: u32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
Foo { x: 0 };
|
||||
Bar { x: 0 };
|
||||
Baz { x: 0 };
|
||||
}
|
Loading…
Reference in New Issue