From 23ca66ecd2e10d0c6de2e3a657f58f6db35d0a9a Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Tue, 20 May 2014 21:25:42 -0700 Subject: [PATCH] Change std inject attributes to outer attributes The #[phase(syntax,link)] attribute on `extern crate std` needs to be an outer attribute so it can pretty-print properly. Also add `#![no_std]` and `#[feature(phase)]` so compiling the pretty-printed source will work. --- src/librustc/front/std_inject.rs | 52 +++++++++++++++++-------------- src/librustc/front/test.rs | 2 +- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/trans/base.rs | 2 +- src/libsyntax/attr.rs | 18 +++++++++-- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs index f6e6875f0e7..92bd81a40f2 100644 --- a/src/librustc/front/std_inject.rs +++ b/src/librustc/front/std_inject.rs @@ -22,6 +22,8 @@ use syntax::parse::token::InternedString; use syntax::parse::token; use syntax::util::small_vector::SmallVector; +use std::mem; + pub static VERSION: &'static str = "0.11.0-pre"; pub fn maybe_inject_crates_ref(sess: &Session, krate: ast::Crate) @@ -70,13 +72,13 @@ pub fn with_version(krate: &str) -> Option<(InternedString, ast::StrStyle)> { } impl<'a> fold::Folder for StandardLibraryInjector<'a> { - fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate { + fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { let mut vis = vec!(ast::ViewItem { node: ast::ViewItemExternCrate(token::str_to_ident("std"), with_version("std"), ast::DUMMY_NODE_ID), attrs: vec!( - attr::mk_attr(attr::mk_list_item( + attr::mk_attr_outer(attr::mk_list_item( InternedString::new("phase"), vec!( attr::mk_word_item(InternedString::new("syntax")), @@ -101,16 +103,20 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> { } // `extern crate` must be precede `use` items - vis.push_all_move(krate.module.view_items.clone()); - let new_module = ast::Mod { - view_items: vis, - ..krate.module.clone() - }; + mem::swap(&mut vis, &mut krate.module.view_items); + krate.module.view_items.push_all_move(vis); - ast::Crate { - module: new_module, - ..krate - } + // don't add #![no_std] here, that will block the prelude injection later. + // Add it during the prelude injection instead. + + // Add #![feature(phase)] here, because we use #[phase] on extern crate std. + let feat_phase_attr = attr::mk_attr_inner(attr::mk_list_item( + InternedString::new("feature"), + vec![attr::mk_word_item(InternedString::new("phase"))], + )); + krate.attrs.push(feat_phase_attr); + + krate } } @@ -127,29 +133,29 @@ struct PreludeInjector<'a> { impl<'a> fold::Folder for PreludeInjector<'a> { - fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate { + fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { + // Add #![no_std] here, so we don't re-inject when compiling pretty-printed source. + // This must happen here and not in StandardLibraryInjector because this + // fold happens second. + + let no_std_attr = attr::mk_attr_inner(attr::mk_word_item(InternedString::new("no_std"))); + krate.attrs.push(no_std_attr); + if !no_prelude(krate.attrs.as_slice()) { // only add `use std::prelude::*;` if there wasn't a // `#![no_implicit_prelude]` at the crate level. - let mut attrs = krate.attrs.clone(); - // fold_mod() will insert glob path. - let globs_attr = attr::mk_attr(attr::mk_list_item( + let globs_attr = attr::mk_attr_inner(attr::mk_list_item( InternedString::new("feature"), vec!( attr::mk_word_item(InternedString::new("globs")), ))); - attrs.push(globs_attr); + krate.attrs.push(globs_attr); - ast::Crate { - module: self.fold_mod(&krate.module), - attrs: attrs, - ..krate - } - } else { - krate + krate.module = self.fold_mod(&krate.module); } + krate } fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> { diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 0d532d7cec1..0ebd392e582 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -341,7 +341,7 @@ fn mk_test_module(cx: &TestCtxt) -> @ast::Item { // This attribute tells resolve to let us call unexported functions let resolve_unexported_str = InternedString::new("!resolve_unexported"); let resolve_unexported_attr = - attr::mk_attr(attr::mk_word_item(resolve_unexported_str)); + attr::mk_attr_inner(attr::mk_word_item(resolve_unexported_str)); let item = ast::Item { ident: token::str_to_ident("__test"), diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index a7ba8300aed..e3ded05e17b 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1436,7 +1436,7 @@ fn synthesize_crate_attrs(ecx: &EncodeContext, fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute { assert!(!ecx.link_meta.crateid.name.is_empty()); - attr::mk_attr( + attr::mk_attr_inner( attr::mk_name_value_item_str( InternedString::new("crate_id"), token::intern_and_get_ident(ecx.link_meta.crateid.to_str()))) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 92e3b95abad..0eabebc9226 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -231,7 +231,7 @@ fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, let f = decl_rust_fn(ccx, false, inputs, output, name); csearch::get_item_attrs(&ccx.sess().cstore, did, |meta_items| { - set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr(x)) + set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr_outer(x)) .collect::>().as_slice(), f) }); diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index cf5163af717..5a57c2d6cc6 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -126,7 +126,11 @@ impl AttributeMethods for Attribute { InternedString::new("doc"), token::intern_and_get_ident(strip_doc_comment_decoration( comment.get()).as_slice())); - mk_attr(meta) + if self.node.style == ast::AttrOuter { + mk_attr_outer(meta) + } else { + mk_attr_inner(meta) + } } else { *self } @@ -154,7 +158,8 @@ pub fn mk_word_item(name: InternedString) -> @MetaItem { @dummy_spanned(MetaWord(name)) } -pub fn mk_attr(item: @MetaItem) -> Attribute { +/// Returns an inner attribute with the given value. +pub fn mk_attr_inner(item: @MetaItem) -> Attribute { dummy_spanned(Attribute_ { style: ast::AttrInner, value: item, @@ -162,6 +167,15 @@ pub fn mk_attr(item: @MetaItem) -> Attribute { }) } +/// Returns an outer attribute with the given value. +pub fn mk_attr_outer(item: @MetaItem) -> Attribute { + dummy_spanned(Attribute_ { + style: ast::AttrOuter, + value: item, + is_sugared_doc: false, + }) +} + pub fn mk_sugared_doc_attr(text: InternedString, lo: BytePos, hi: BytePos) -> Attribute { let style = doc_comment_style(text.get());