]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #29945 - nrc:save-crate-name, r=alexcrichton
authorbors <bors@rust-lang.org>
Fri, 20 Nov 2015 20:03:16 +0000 (20:03 +0000)
committerbors <bors@rust-lang.org>
Fri, 20 Nov 2015 20:03:16 +0000 (20:03 +0000)
r? @alexcrichton

This prevents outputting csv files with the same name and thus overwriting each other when indexing Cargo projects with a bin crate (and some other cases).

25 files changed:
src/doc/book/compiler-plugins.md
src/librustc/lint/context.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/dead.rs
src/librustc/middle/privacy.rs
src/librustc/middle/reachable.rs
src/librustc/middle/stability.rs
src/librustc/middle/ty/mod.rs
src/librustc/session/config.rs
src/librustc_driver/driver.rs
src/librustc_lint/builtin.rs
src/librustc_llvm/lib.rs
src/librustc_privacy/lib.rs
src/librustc_trans/back/write.rs
src/librustdoc/clean/inline.rs
src/librustdoc/core.rs
src/librustdoc/html/render.rs
src/librustdoc/passes.rs
src/librustdoc/visit_ast.rs
src/libstd/collections/hash/set.rs
src/rustllvm/PassWrapper.cpp
src/test/auxiliary/issue-27362.rs [new file with mode: 0644]
src/test/auxiliary/roman_numerals.rs
src/test/compile-fail/const-call.rs [new file with mode: 0644]
src/test/rustdoc/issue-27362.rs [new file with mode: 0644]

index 42dfaa1a8090aaa214d0702214687ab85d586285..2cb62cdfca555ea3d416207c01eb3d566c9c437a 100644 (file)
@@ -54,14 +54,21 @@ use rustc::plugin::Registry;
 fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
         -> Box<MacResult + 'static> {
 
-    static NUMERALS: &'static [(&'static str, u32)] = &[
+    static NUMERALS: &'static [(&'static str, usize)] = &[
         ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
         ("C",  100), ("XC",  90), ("L",  50), ("XL",  40),
         ("X",   10), ("IX",   9), ("V",   5), ("IV",   4),
         ("I",    1)];
 
-    let text = match args {
-        [TokenTree::Token(_, token::Ident(s, _))] => s.to_string(),
+    if args.len() != 1 {
+        cx.span_err(
+            sp,
+            &format!("argument should be a single identifier, but got {} arguments", args.len()));
+        return DummyResult::any(sp);
+    }
+
+    let text = match args[0] {
+        TokenTree::Token(_, token::Ident(s, _)) => s.to_string(),
         _ => {
             cx.span_err(sp, "argument should be a single identifier");
             return DummyResult::any(sp);
@@ -83,7 +90,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
         }
     }
 
-    MacEager::expr(cx.expr_u32(sp, total))
+    MacEager::expr(cx.expr_usize(sp, total))
 }
 
 #[plugin_registrar]
index 798f4866d346c8edac3b82bff5c3e49f5b38f22e..74a61f700e3b8ac172fcfa3185f72f569c15a8b8 100644 (file)
@@ -25,7 +25,7 @@
 //! for all lint attributes.
 use self::TargetLint::*;
 
-use middle::privacy::ExportedItems;
+use middle::privacy::AccessLevels;
 use middle::ty::{self, Ty};
 use session::{early_error, Session};
 use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass};
@@ -277,8 +277,8 @@ pub struct LateContext<'a, 'tcx: 'a> {
     /// The crate being checked.
     pub krate: &'a hir::Crate,
 
-    /// Items exported from the crate being checked.
-    pub exported_items: &'a ExportedItems,
+    /// Items accessible from the crate being checked.
+    pub access_levels: &'a AccessLevels,
 
     /// The store of registered lints.
     lints: LintStore,
@@ -564,7 +564,7 @@ fn visit_ids<F>(&mut self, f: F)
 impl<'a, 'tcx> LateContext<'a, 'tcx> {
     fn new(tcx: &'a ty::ctxt<'tcx>,
            krate: &'a hir::Crate,
-           exported_items: &'a ExportedItems) -> LateContext<'a, 'tcx> {
+           access_levels: &'a AccessLevels) -> LateContext<'a, 'tcx> {
         // We want to own the lint store, so move it out of the session.
         let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(),
                                       LintStore::new());
@@ -572,7 +572,7 @@ fn new(tcx: &'a ty::ctxt<'tcx>,
         LateContext {
             tcx: tcx,
             krate: krate,
-            exported_items: exported_items,
+            access_levels: access_levels,
             lints: lint_store,
             level_stack: vec![],
             node_levels: RefCell::new(FnvHashMap()),
@@ -1014,10 +1014,9 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
 /// Perform lint checking on a crate.
 ///
 /// Consumes the `lint_store` field of the `Session`.
-pub fn check_crate(tcx: &ty::ctxt,
-                   exported_items: &ExportedItems) {
+pub fn check_crate(tcx: &ty::ctxt, access_levels: &AccessLevels) {
     let krate = tcx.map.krate();
-    let mut cx = LateContext::new(tcx, krate, exported_items);
+    let mut cx = LateContext::new(tcx, krate, access_levels);
 
     // Visit the whole crate.
     cx.with_lint_attrs(&krate.attrs, |cx| {
index 039c62a904c9b59ffca3fe4c9340c4dd3e197fb5..e43d162874363d69d538e1302ae170633e31c3bd 100644 (file)
@@ -1055,8 +1055,6 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
           };
           let (
               decl,
-              unsafety,
-              abi,
               block,
               constness,
           ) = match try!(eval_const_expr_partial(tcx, callee, sub_ty_hint, fn_args)) {
@@ -1065,12 +1063,12 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                       Some(ast_map::NodeItem(it)) => match it.node {
                           hir::ItemFn(
                               ref decl,
-                              unsafety,
+                              hir::Unsafety::Normal,
                               constness,
-                              abi,
+                              abi::Abi::Rust,
                               _, // ducktype generics? types are funky in const_eval
                               ref block,
-                          ) => (decl, unsafety, abi, block, constness),
+                          ) => (decl, block, constness),
                           _ => signal!(e, NonConstPath),
                       },
                       _ => signal!(e, NonConstPath),
@@ -1080,18 +1078,19 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
               },
               _ => signal!(e, NonConstPath),
           };
-          if let ExprTypeChecked = ty_hint {
-              // no need to check for constness... either check_const
-              // already forbids this or we const eval over whatever
-              // we want
-          } else {
-              // we don't know much about the function, so we force it to be a const fn
-              // so compilation will fail later in case the const fn's body is not const
-              assert_eq!(constness, hir::Constness::Const)
+          match (ty_hint, constness) {
+              (ExprTypeChecked, _) => {
+                  // no need to check for constness... either check_const
+                  // already forbids this or we const eval over whatever
+                  // we want
+              },
+              (_, hir::Constness::Const) => {
+                  // we don't know much about the function, so we force it to be a const fn
+                  // so compilation will fail later in case the const fn's body is not const
+              },
+              _ => signal!(e, NonConstPath),
           }
           assert_eq!(decl.inputs.len(), args.len());
-          assert_eq!(unsafety, hir::Unsafety::Normal);
-          assert_eq!(abi, abi::Abi::Rust);
 
           let mut call_args = NodeMap();
           for (arg, arg_expr) in decl.inputs.iter().zip(args.iter()) {
index 6dfddce9bfed89cb4bb5a8fec963c0dab58786f1..acd635874e39266bd0a0a11cdaacf6e4ec8ca27a 100644 (file)
@@ -19,7 +19,6 @@
 use middle::{def, pat_util, privacy, ty};
 use middle::def_id::{DefId};
 use lint;
-use util::nodemap::NodeSet;
 
 use std::collections::HashSet;
 use syntax::{ast, codemap};
@@ -370,25 +369,10 @@ fn visit_item(&mut self, item: &hir::Item) {
 }
 
 fn create_and_seed_worklist(tcx: &ty::ctxt,
-                            exported_items: &privacy::ExportedItems,
-                            reachable_symbols: &NodeSet,
+                            access_levels: &privacy::AccessLevels,
                             krate: &hir::Crate) -> Vec<ast::NodeId> {
     let mut worklist = Vec::new();
-
-    // Preferably, we would only need to seed the worklist with reachable
-    // symbols. However, since the set of reachable symbols differs
-    // depending on whether a crate is built as bin or lib, and we want
-    // the warning to be consistent, we also seed the worklist with
-    // exported symbols.
-    for id in exported_items {
-        worklist.push(*id);
-    }
-    for id in reachable_symbols {
-        // Reachable variants can be dead, because we warn about
-        // variants never constructed, not variants never used.
-        if let Some(ast_map::NodeVariant(..)) = tcx.map.find(*id) {
-            continue;
-        }
+    for (id, _) in &access_levels.map {
         worklist.push(*id);
     }
 
@@ -408,12 +392,10 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
 }
 
 fn find_live(tcx: &ty::ctxt,
-             exported_items: &privacy::ExportedItems,
-             reachable_symbols: &NodeSet,
+             access_levels: &privacy::AccessLevels,
              krate: &hir::Crate)
              -> Box<HashSet<ast::NodeId>> {
-    let worklist = create_and_seed_worklist(tcx, exported_items,
-                                            reachable_symbols, krate);
+    let worklist = create_and_seed_worklist(tcx, access_levels, krate);
     let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist);
     symbol_visitor.mark_live_symbols();
     symbol_visitor.live_symbols
@@ -607,12 +589,9 @@ fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
     }
 }
 
-pub fn check_crate(tcx: &ty::ctxt,
-                   exported_items: &privacy::ExportedItems,
-                   reachable_symbols: &NodeSet) {
+pub fn check_crate(tcx: &ty::ctxt, access_levels: &privacy::AccessLevels) {
     let krate = tcx.map.krate();
-    let live_symbols = find_live(tcx, exported_items,
-                                 reachable_symbols, krate);
+    let live_symbols = find_live(tcx, access_levels, krate);
     let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols };
     intravisit::walk_crate(&mut visitor, krate);
 }
index 4a1be3bba7bc1403479de9ee1dbc2786cdd4914f..f464ea58c2d196f76a103d5e493791b2dc9f6ec7 100644 (file)
 pub use self::LastPrivate::*;
 
 use middle::def_id::DefId;
-use util::nodemap::{DefIdSet, NodeSet};
+use util::nodemap::{DefIdSet, FnvHashMap};
 
-/// A set of AST nodes exported by the crate.
-pub type ExportedItems = NodeSet;
+use std::hash::Hash;
+use syntax::ast::NodeId;
+
+// Accessibility levels, sorted in ascending order
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub enum AccessLevel {
+    // Exported items + items participating in various kinds of public interfaces,
+    // but not directly nameable. For example, if function `fn f() -> T {...}` is
+    // public, then type `T` is exported. Its values can be obtained by other crates
+    // even if the type itseld is not nameable.
+    // FIXME: Mostly unimplemented. Only `type` aliases export items currently.
+    Reachable,
+    // Public items + items accessible to other crates with help of `pub use` reexports
+    Exported,
+    // Items accessible to other crates directly, without help of reexports
+    Public,
+}
+
+// Accessibility levels for reachable HIR nodes
+#[derive(Clone)]
+pub struct AccessLevels<Id = NodeId> {
+    pub map: FnvHashMap<Id, AccessLevel>
+}
+
+impl<Id: Hash + Eq> AccessLevels<Id> {
+    pub fn is_reachable(&self, id: Id) -> bool {
+        self.map.contains_key(&id)
+    }
+    pub fn is_exported(&self, id: Id) -> bool {
+        self.map.get(&id) >= Some(&AccessLevel::Exported)
+    }
+    pub fn is_public(&self, id: Id) -> bool {
+        self.map.get(&id) >= Some(&AccessLevel::Public)
+    }
+}
+
+impl<Id: Hash + Eq> Default for AccessLevels<Id> {
+    fn default() -> Self {
+        AccessLevels { map: Default::default() }
+    }
+}
 
 /// A set containing all exported definitions from external crates.
 /// The set does not contain any entries from local crates.
 pub type ExternalExports = DefIdSet;
 
-/// A set of AST nodes that are fully public in the crate. This map is used for
-/// documentation purposes (reexporting a private struct inlines the doc,
-/// reexporting a public struct doesn't inline the doc).
-pub type PublicItems = NodeSet;
-
 #[derive(Copy, Clone, Debug)]
 pub enum LastPrivate {
     LastMod(PrivateDep),
index 86237a2321a722550b6e6aa9e18c5b9480d7e85f..d146ad2d8003b766d2eabae34cd0e1d0e62c4f25 100644 (file)
@@ -329,7 +329,7 @@ fn propagate_node(&mut self, node: &ast_map::Node,
 // trait items are used from inlinable code through method call syntax or UFCS, or their
 // trait is a lang item.
 struct CollectPrivateImplItemsVisitor<'a> {
-    exported_items: &'a privacy::ExportedItems,
+    access_levels: &'a privacy::AccessLevels,
     worklist: &'a mut Vec<ast::NodeId>,
 }
 
@@ -337,7 +337,7 @@ impl<'a, 'v> Visitor<'v> for CollectPrivateImplItemsVisitor<'a> {
     fn visit_item(&mut self, item: &hir::Item) {
         // We need only trait impls here, not inherent impls, and only non-exported ones
         if let hir::ItemImpl(_, _, _, Some(_), _, ref impl_items) = item.node {
-            if !self.exported_items.contains(&item.id) {
+            if !self.access_levels.is_reachable(item.id) {
                 for impl_item in impl_items {
                     self.worklist.push(impl_item.id);
                 }
@@ -347,7 +347,7 @@ fn visit_item(&mut self, item: &hir::Item) {
 }
 
 pub fn find_reachable(tcx: &ty::ctxt,
-                      exported_items: &privacy::ExportedItems)
+                      access_levels: &privacy::AccessLevels)
                       -> NodeSet {
 
     let mut reachable_context = ReachableContext::new(tcx);
@@ -357,7 +357,7 @@ pub fn find_reachable(tcx: &ty::ctxt,
     //         If other crates link to us, they're going to expect to be able to
     //         use the lang items, so we need to be sure to mark them as
     //         exported.
-    for id in exported_items {
+    for (id, _) in &access_levels.map {
         reachable_context.worklist.push(*id);
     }
     for (_, item) in tcx.lang_items.items() {
@@ -369,7 +369,7 @@ pub fn find_reachable(tcx: &ty::ctxt,
     }
     {
         let mut collect_private_impl_items = CollectPrivateImplItemsVisitor {
-            exported_items: exported_items,
+            access_levels: access_levels,
             worklist: &mut reachable_context.worklist,
         };
         tcx.map.krate().visit_all_items(&mut collect_private_impl_items);
index 2ba66807d4ecc5b7e9079cb883bd59778de83346..0ef2ac723fcec7123ed4a160900ea5099a22ee82 100644 (file)
@@ -19,7 +19,7 @@
 use middle::def;
 use middle::def_id::{CRATE_DEF_INDEX, DefId};
 use middle::ty;
-use middle::privacy::PublicItems;
+use middle::privacy::AccessLevels;
 use metadata::csearch;
 use syntax::parse::token::InternedString;
 use syntax::codemap::{Span, DUMMY_SP};
@@ -73,7 +73,7 @@ struct Annotator<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
     index: &'a mut Index<'tcx>,
     parent: Option<&'tcx Stability>,
-    export_map: &'a PublicItems,
+    access_levels: &'a AccessLevels,
     in_trait_impl: bool,
     in_enum: bool,
 }
@@ -143,7 +143,7 @@ fn annotate<F>(&mut self, id: NodeId, attrs: &Vec<Attribute>,
             } else {
                 debug!("annotate: not found, parent = {:?}", self.parent);
                 let mut is_error = kind == AnnotationKind::Required &&
-                                   self.export_map.contains(&id) &&
+                                   self.access_levels.is_reachable(id) &&
                                    !self.tcx.sess.opts.test;
                 if let Some(stab) = self.parent {
                     if stab.level.is_unstable() {
@@ -266,12 +266,12 @@ fn visit_macro_def(&mut self, md: &'v hir::MacroDef) {
 
 impl<'tcx> Index<'tcx> {
     /// Construct the stability index for a crate being compiled.
-    pub fn build(&mut self, tcx: &ty::ctxt<'tcx>, krate: &'tcx Crate, export_map: &PublicItems) {
+    pub fn build(&mut self, tcx: &ty::ctxt<'tcx>, krate: &Crate, access_levels: &AccessLevels) {
         let mut annotator = Annotator {
             tcx: tcx,
             index: self,
             parent: None,
-            export_map: export_map,
+            access_levels: access_levels,
             in_trait_impl: false,
             in_enum: false,
         };
index 42bba0c8aeff6438d2f965c859db611cd954d759..501781627fbce5a4c90c0da927847ee0f9ee121d 100644 (file)
 /// produced by the driver and fed to trans and later passes.
 pub struct CrateAnalysis<'a> {
     pub export_map: ExportMap,
-    pub exported_items: middle::privacy::ExportedItems,
-    pub public_items: middle::privacy::PublicItems,
+    pub access_levels: middle::privacy::AccessLevels,
     pub reachable: NodeSet,
     pub name: &'a str,
     pub glob_map: Option<GlobMap>,
 }
 
-
 #[derive(Copy, Clone)]
 pub enum DtorKind {
     NoDtor,
index 808a63982c263ad10bc74e926763c78c06ed4e08..4781992b9875d76a215ad67b5af1636ceb9da87f 100644 (file)
@@ -513,6 +513,8 @@ fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
         "optimize with possible levels 0-3"),
     debug_assertions: Option<bool> = (None, parse_opt_bool,
         "explicitly enable the cfg(debug_assertions) directive"),
+    inline_threshold: Option<usize> = (None, parse_opt_uint,
+        "set the inlining threshold for"),
 }
 
 
index f8ac2759e854d4ceb420739a80396e35009b8e5a..cb345ac517e0dd80439248c650d5ea7bd4e6cadf 100644 (file)
@@ -746,7 +746,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                         "const checking",
                                         || middle::check_const::check_crate(tcx));
 
-                                   let (exported_items, public_items) =
+                                   let access_levels =
                                        time(time_passes, "privacy checking", || {
                                            rustc_privacy::check_crate(tcx,
                                                                       &export_map,
@@ -755,7 +755,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
                                    // Do not move this check past lint
                                    time(time_passes, "stability index", || {
-                                       tcx.stability.borrow_mut().build(tcx, krate, &exported_items)
+                                       tcx.stability.borrow_mut().build(tcx, krate, &access_levels)
                                    });
 
                                    time(time_passes,
@@ -807,12 +807,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                    let reachable_map =
                                        time(time_passes,
                                             "reachability checking",
-                                            || reachable::find_reachable(tcx, &exported_items));
+                                            || reachable::find_reachable(tcx, &access_levels));
 
                                    time(time_passes, "death checking", || {
-                                       middle::dead::check_crate(tcx,
-                                                                 &exported_items,
-                                                                 &reachable_map)
+                                       middle::dead::check_crate(tcx, &access_levels);
                                    });
 
                                    let ref lib_features_used =
@@ -827,7 +825,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
                                    time(time_passes,
                                         "lint checking",
-                                        || lint::check_crate(tcx, &exported_items));
+                                        || lint::check_crate(tcx, &access_levels));
 
                                    // The above three passes generate errors w/o aborting
                                    tcx.sess.abort_if_errors();
@@ -836,8 +834,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                      mir_map,
                                      ty::CrateAnalysis {
                                          export_map: export_map,
-                                         exported_items: exported_items,
-                                         public_items: public_items,
+                                         access_levels: access_levels,
                                          reachable: reachable_map,
                                          name: name,
                                          glob_map: glob_map,
index d24c336dd3fbd0a2910abd06c734c71896c4293a..1fd4ee72cec913c7f42fe914f2329a3440108d7b 100644 (file)
@@ -301,8 +301,8 @@ fn check_missing_docs_attrs(&self,
         // Only check publicly-visible items, using the result from the privacy pass.
         // It's an option so the crate root can also use this function (it doesn't
         // have a NodeId).
-        if let Some(ref id) = id {
-            if !cx.exported_items.contains(id) {
+        if let Some(id) = id {
+            if !cx.access_levels.is_exported(id) {
                 return;
             }
         }
@@ -470,7 +470,7 @@ fn get_lints(&self) -> LintArray {
 
 impl LateLintPass for MissingCopyImplementations {
     fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
-        if !cx.exported_items.contains(&item.id) {
+        if !cx.access_levels.is_reachable(item.id) {
             return;
         }
         let (def, ty) = match item.node {
@@ -534,7 +534,7 @@ fn get_lints(&self) -> LintArray {
 
 impl LateLintPass for MissingDebugImplementations {
     fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
-        if !cx.exported_items.contains(&item.id) {
+        if !cx.access_levels.is_reachable(item.id) {
             return;
         }
 
@@ -987,7 +987,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         match it.node {
             hir::ItemFn(..) => {
                 if attr::contains_name(&it.attrs, "no_mangle") &&
-                       !cx.exported_items.contains(&it.id) {
+                       !cx.access_levels.is_reachable(it.id) {
                     let msg = format!("function {} is marked #[no_mangle], but not exported",
                                       it.name);
                     cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg);
@@ -995,7 +995,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
             },
             hir::ItemStatic(..) => {
                 if attr::contains_name(&it.attrs, "no_mangle") &&
-                       !cx.exported_items.contains(&it.id) {
+                       !cx.access_levels.is_reachable(it.id) {
                     let msg = format!("static {} is marked #[no_mangle], but not exported",
                                       it.name);
                     cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg);
index 9cb5012cf0f818b83acd02d1b32e2a6e462c7935..0cb0869db86d77467313814d1651204e3c569b6a 100644 (file)
@@ -2044,7 +2044,6 @@ pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
                                        Model: CodeGenModel,
                                        Reloc: RelocMode,
                                        Level: CodeGenOptLevel,
-                                       EnableSegstk: bool,
                                        UseSoftFP: bool,
                                        PositionIndependentExecutable: bool,
                                        FunctionSections: bool,
index d11880ecca19b0884837fa1141e865012224e9b7..1ca8eeadfe5bb0a58bfc60dad26d807965fb87cb 100644 (file)
@@ -32,6 +32,7 @@
 use self::PrivacyResult::*;
 use self::FieldName::*;
 
+use std::cmp;
 use std::mem::replace;
 
 use rustc_front::hir;
 
 use rustc::middle::def;
 use rustc::middle::def_id::DefId;
+use rustc::middle::privacy::{AccessLevel, AccessLevels};
 use rustc::middle::privacy::ImportUse::*;
 use rustc::middle::privacy::LastPrivate::*;
 use rustc::middle::privacy::PrivateDep::*;
-use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems};
+use rustc::middle::privacy::ExternalExports;
 use rustc::middle::ty::{self, Ty};
-use rustc::util::nodemap::{NodeMap, NodeSet};
+use rustc::util::nodemap::NodeMap;
 use rustc::front::map as ast_map;
 
 use syntax::ast;
@@ -159,64 +161,57 @@ struct EmbargoVisitor<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
     export_map: &'a def::ExportMap,
 
-    // This flag is an indicator of whether the previous item in the
-    // hierarchical chain was exported or not. This is the indicator of whether
-    // children should be exported as well. Note that this can flip from false
-    // to true if a reexported module is entered (or an action similar).
-    prev_exported: bool,
-
-    // This is a list of all exported items in the AST. An exported item is any
-    // function/method/item which is usable by external crates. This essentially
-    // means that the result is "public all the way down", but the "path down"
-    // may jump across private boundaries through reexport statements or type aliases.
-    exported_items: ExportedItems,
-
-    // Items that are directly public without help of reexports or type aliases.
-    // These two fields are closely related to one another in that they are only
-    // used for generation of the `public_items` set, not for privacy checking at
-    // all. Invariant: at any moment public items are a subset of exported items.
-    public_items: PublicItems,
-    prev_public: bool,
+    // Accessibility levels for reachable nodes
+    access_levels: AccessLevels,
+    // Previous accessibility level, None means unreachable
+    prev_level: Option<AccessLevel>,
+    // Have something changed in the level map?
+    changed: bool,
 }
 
 impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
-    // Returns tuple (is_public, is_exported) for a type
-    fn is_public_exported_ty(&self, ty: &hir::Ty) -> (bool, bool) {
+    fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
         if let hir::TyPath(..) = ty.node {
             match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
                 def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {
-                    (true, true)
+                    Some(AccessLevel::Public)
                 }
                 def => {
                     if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) {
-                        (self.public_items.contains(&node_id),
-                         self.exported_items.contains(&node_id))
+                        self.get(node_id)
                     } else {
-                        (true, true)
+                        Some(AccessLevel::Public)
                     }
                 }
             }
         } else {
-            (true, true)
+            Some(AccessLevel::Public)
         }
     }
 
-    // Returns tuple (is_public, is_exported) for a trait
-    fn is_public_exported_trait(&self, trait_ref: &hir::TraitRef) -> (bool, bool) {
+    fn trait_level(&self, trait_ref: &hir::TraitRef) -> Option<AccessLevel> {
         let did = self.tcx.trait_ref_to_def_id(trait_ref);
         if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
-            (self.public_items.contains(&node_id), self.exported_items.contains(&node_id))
+            self.get(node_id)
         } else {
-            (true, true)
+            Some(AccessLevel::Public)
         }
     }
 
-    fn maybe_insert_id(&mut self, id: ast::NodeId) {
-        if self.prev_public {
-            self.public_items.insert(id);
-        }
-        if self.prev_exported {
-            self.exported_items.insert(id);
+    fn get(&self, id: ast::NodeId) -> Option<AccessLevel> {
+        self.access_levels.map.get(&id).cloned()
+    }
+
+    // Updates node level and returns the updated level
+    fn update(&mut self, id: ast::NodeId, level: Option<AccessLevel>) -> Option<AccessLevel> {
+        let old_level = self.get(id);
+        // Accessibility levels can only grow
+        if level > old_level {
+            self.access_levels.map.insert(id, level.unwrap());
+            self.changed = true;
+            level
+        } else {
+            old_level
         }
     }
 }
@@ -227,187 +222,126 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
     fn visit_nested_item(&mut self, item: hir::ItemId) {
         self.visit_item(self.tcx.map.expect_item(item.id))
     }
+
     fn visit_item(&mut self, item: &hir::Item) {
-        let orig_all_public = self.prev_public;
-        let orig_all_exported = self.prev_exported;
-        match item.node {
-            // impls/extern blocks do not break the "public chain" because they
-            // cannot have visibility qualifiers on them anyway. Impls are also not
-            // added to public/exported sets based on inherited publicity.
-            hir::ItemImpl(..) | hir::ItemDefaultImpl(..) => {}
+        let inherited_item_level = match item.node {
+            // Impls inherit level from their types and traits
+            hir::ItemImpl(_, _, _, None, ref ty, _) => {
+                self.ty_level(&ty)
+            }
+            hir::ItemImpl(_, _, _, Some(ref trait_ref), ref ty, _) => {
+                cmp::min(self.ty_level(&ty), self.trait_level(trait_ref))
+            }
+            hir::ItemDefaultImpl(_, ref trait_ref) => {
+                self.trait_level(trait_ref)
+            }
+            // Foreign mods inherit level from parents
             hir::ItemForeignMod(..) => {
-                self.maybe_insert_id(item.id);
+                self.prev_level
             }
-
-            // Private by default, hence we only retain the "public chain" if
-            // `pub` is explicitly listed.
+            // Other `pub` items inherit levels from parents
             _ => {
-                self.prev_public = self.prev_public && item.vis == hir::Public;
-                self.prev_exported = (self.prev_exported && item.vis == hir::Public) ||
-                                     self.exported_items.contains(&item.id);
-
-                self.maybe_insert_id(item.id);
+                if item.vis == hir::Public { self.prev_level } else { None }
             }
-        }
+        };
 
+        // Update id of the item itself
+        let item_level = self.update(item.id, inherited_item_level);
+
+        // Update ids of nested things
         match item.node {
-            // Enum variants inherit from their parent, so if the enum is
-            // public all variants are public
             hir::ItemEnum(ref def, _) => {
                 for variant in &def.variants {
-                    self.maybe_insert_id(variant.node.data.id());
+                    let variant_level = self.update(variant.node.data.id(), item_level);
                     for field in variant.node.data.fields() {
-                        // Variant fields are always public
-                        self.maybe_insert_id(field.node.id);
+                        self.update(field.node.id, variant_level);
                     }
                 }
             }
-
-            // Inherent impls for public/exported types and their public items are public/exported
-            hir::ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
-                let (public_ty, exported_ty) = self.is_public_exported_ty(&ty);
-
-                if public_ty {
-                    self.public_items.insert(item.id);
-                }
-                if exported_ty {
-                    self.exported_items.insert(item.id);
-                }
-
+            hir::ItemImpl(_, _, _, None, _, ref impl_items) => {
                 for impl_item in impl_items {
                     if impl_item.vis == hir::Public {
-                        if public_ty {
-                            self.public_items.insert(impl_item.id);
-                        }
-                        if exported_ty {
-                            self.exported_items.insert(impl_item.id);
-                        }
+                        self.update(impl_item.id, item_level);
                     }
                 }
             }
-
-            // Trait impl and its items are public/exported if both the self type and the trait
-            // of this impl are public/exported
-            hir::ItemImpl(_, _, _, Some(ref trait_ref), ref ty, ref impl_items) => {
-                let (public_ty, exported_ty) = self.is_public_exported_ty(&ty);
-                let (public_trait, exported_trait) = self.is_public_exported_trait(trait_ref);
-
-                if public_ty && public_trait {
-                    self.public_items.insert(item.id);
-                }
-                if exported_ty && exported_trait {
-                    self.exported_items.insert(item.id);
-                }
-
+            hir::ItemImpl(_, _, _, Some(_), _, ref impl_items) => {
                 for impl_item in impl_items {
-                    if public_ty && public_trait {
-                        self.public_items.insert(impl_item.id);
-                    }
-                    if exported_ty && exported_trait {
-                        self.exported_items.insert(impl_item.id);
-                    }
-                }
-            }
-
-            // Default trait impls are public/exported for public/exported traits
-            hir::ItemDefaultImpl(_, ref trait_ref) => {
-                let (public_trait, exported_trait) = self.is_public_exported_trait(trait_ref);
-
-                if public_trait {
-                    self.public_items.insert(item.id);
-                }
-                if exported_trait {
-                    self.exported_items.insert(item.id);
+                    self.update(impl_item.id, item_level);
                 }
             }
-
-            // Default methods on traits are all public/exported so long as the trait
-            // is public/exported
             hir::ItemTrait(_, _, _, ref trait_items) => {
                 for trait_item in trait_items {
-                    self.maybe_insert_id(trait_item.id);
+                    self.update(trait_item.id, item_level);
                 }
             }
-
-            // Struct constructors are public if the struct is all public.
             hir::ItemStruct(ref def, _) => {
                 if !def.is_struct() {
-                    self.maybe_insert_id(def.id());
+                    self.update(def.id(), item_level);
                 }
                 for field in def.fields() {
-                    // Struct fields can be public or private, so lets check
                     if field.node.kind.visibility() == hir::Public {
-                        self.maybe_insert_id(field.node.id);
+                        self.update(field.node.id, item_level);
                     }
                 }
             }
-
-            hir::ItemTy(ref ty, _) if self.prev_exported => {
+            hir::ItemForeignMod(ref foreign_mod) => {
+                for foreign_item in &foreign_mod.items {
+                    if foreign_item.vis == hir::Public {
+                        self.update(foreign_item.id, item_level);
+                    }
+                }
+            }
+            hir::ItemTy(ref ty, _) if item_level.is_some() => {
                 if let hir::TyPath(..) = ty.node {
                     match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
                         def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {},
                         def => {
                             if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) {
-                                self.exported_items.insert(node_id);
+                                self.update(node_id, Some(AccessLevel::Reachable));
                             }
                         }
                     }
                 }
             }
-
-            hir::ItemForeignMod(ref foreign_mod) => {
-                for foreign_item in &foreign_mod.items {
-                    let public = self.prev_public && foreign_item.vis == hir::Public;
-                    let exported = (self.prev_exported && foreign_item.vis == hir::Public) ||
-                                   self.exported_items.contains(&foreign_item.id);
-
-                    if public {
-                        self.public_items.insert(foreign_item.id);
-                    }
-                    if exported {
-                        self.exported_items.insert(foreign_item.id);
-                    }
-                }
-            }
-
             _ => {}
         }
 
+        let orig_level = self.prev_level;
+        self.prev_level = item_level;
+
         intravisit::walk_item(self, item);
 
-        self.prev_public = orig_all_public;
-        self.prev_exported = orig_all_exported;
+        self.prev_level = orig_level;
     }
 
     fn visit_block(&mut self, b: &'v hir::Block) {
-        let orig_all_public = replace(&mut self.prev_public, false);
-        let orig_all_exported = replace(&mut self.prev_exported, false);
+        let orig_level = replace(&mut self.prev_level, None);
 
-        // Blocks can have exported and public items, for example impls, but they always
-        // start as non-public and non-exported regardless of publicity of a function,
+        // Blocks can have public items, for example impls, but they always
+        // start as completely private regardless of publicity of a function,
         // constant, type, field, etc. in which this block resides
         intravisit::walk_block(self, b);
 
-        self.prev_public = orig_all_public;
-        self.prev_exported = orig_all_exported;
+        self.prev_level = orig_level;
     }
 
     fn visit_mod(&mut self, m: &hir::Mod, _sp: Span, id: ast::NodeId) {
         // This code is here instead of in visit_item so that the
         // crate module gets processed as well.
-        if self.prev_exported {
-            assert!(self.export_map.contains_key(&id), "wut {}", id);
-            for export in self.export_map.get(&id).unwrap() {
+        if self.prev_level.is_some() {
+            for export in self.export_map.get(&id).expect("module isn't found in export map") {
                 if let Some(node_id) = self.tcx.map.as_local_node_id(export.def_id) {
-                    self.exported_items.insert(node_id);
+                    self.update(node_id, Some(AccessLevel::Exported));
                 }
             }
         }
-        intravisit::walk_mod(self, m)
+
+        intravisit::walk_mod(self, m);
     }
 
     fn visit_macro_def(&mut self, md: &'v hir::MacroDef) {
-        self.maybe_insert_id(md.id);
+        self.update(md.id, Some(AccessLevel::Public));
     }
 }
 
@@ -1169,8 +1103,7 @@ fn check_all_inherited(&self, item: &hir::Item) {
 
 struct VisiblePrivateTypesVisitor<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
-    exported_items: &'a ExportedItems,
-    public_items: &'a PublicItems,
+    access_levels: &'a AccessLevels,
     in_variant: bool,
 }
 
@@ -1210,7 +1143,7 @@ fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
     fn trait_is_public(&self, trait_id: ast::NodeId) -> bool {
         // FIXME: this would preferably be using `exported_items`, but all
         // traits are exported currently (see `EmbargoVisitor.exported_trait`)
-        self.public_items.contains(&trait_id)
+        self.access_levels.is_public(trait_id)
     }
 
     fn check_ty_param_bound(&self,
@@ -1226,7 +1159,7 @@ fn check_ty_param_bound(&self,
     }
 
     fn item_is_public(&self, id: &ast::NodeId, vis: hir::Visibility) -> bool {
-        self.exported_items.contains(id) || vis == hir::Public
+        self.access_levels.is_reachable(*id) || vis == hir::Public
     }
 }
 
@@ -1332,7 +1265,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                                   match impl_item.node {
                                       hir::ImplItemKind::Const(..) |
                                       hir::ImplItemKind::Method(..) => {
-                                          self.exported_items.contains(&impl_item.id)
+                                          self.access_levels.is_reachable(impl_item.id)
                                       }
                                       hir::ImplItemKind::Type(_) => false,
                                   }
@@ -1461,7 +1394,7 @@ fn visit_generics(&mut self, generics: &hir::Generics) {
     }
 
     fn visit_foreign_item(&mut self, item: &hir::ForeignItem) {
-        if self.exported_items.contains(&item.id) {
+        if self.access_levels.is_reachable(item.id) {
             intravisit::walk_foreign_item(self, item)
         }
     }
@@ -1479,7 +1412,7 @@ fn visit_ty(&mut self, t: &hir::Ty) {
     }
 
     fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics, item_id: ast::NodeId) {
-        if self.exported_items.contains(&v.node.data.id()) {
+        if self.access_levels.is_reachable(v.node.data.id()) {
             self.in_variant = true;
             intravisit::walk_variant(self, v, g, item_id);
             self.in_variant = false;
@@ -1509,7 +1442,7 @@ fn visit_expr(&mut self, _: &hir::Expr) {}
 pub fn check_crate(tcx: &ty::ctxt,
                    export_map: &def::ExportMap,
                    external_exports: ExternalExports)
-                   -> (ExportedItems, PublicItems) {
+                   -> AccessLevels {
     let krate = tcx.map.krate();
 
     // Sanity check to make sure that all privacy usage and controls are
@@ -1544,33 +1477,31 @@ pub fn check_crate(tcx: &ty::ctxt,
     // items which are reachable from external crates based on visibility.
     let mut visitor = EmbargoVisitor {
         tcx: tcx,
-        exported_items: NodeSet(),
-        public_items: NodeSet(),
         export_map: export_map,
-        prev_exported: true,
-        prev_public: true,
+        access_levels: Default::default(),
+        prev_level: Some(AccessLevel::Public),
+        changed: false,
     };
-    visitor.exported_items.insert(ast::CRATE_NODE_ID);
-    visitor.public_items.insert(ast::CRATE_NODE_ID);
     loop {
-        let before = (visitor.exported_items.len(), visitor.public_items.len());
         intravisit::walk_crate(&mut visitor, krate);
-        let after = (visitor.exported_items.len(), visitor.public_items.len());
-        if after == before {
+        if visitor.changed {
+            visitor.changed = false;
+        } else {
             break
         }
     }
+    visitor.update(ast::CRATE_NODE_ID, Some(AccessLevel::Public));
 
-    let EmbargoVisitor { exported_items, public_items, .. } = visitor;
+    let EmbargoVisitor { access_levels, .. } = visitor;
 
     {
         let mut visitor = VisiblePrivateTypesVisitor {
             tcx: tcx,
-            exported_items: &exported_items,
-            public_items: &public_items,
+            access_levels: &access_levels,
             in_variant: false,
         };
         intravisit::walk_crate(&mut visitor, krate);
     }
-    return (exported_items, public_items);
+
+    access_levels
 }
index 17c8d9aa9e1daf1a571e65b2c99cf20860047ff9..5ac27d612279b7af835bcde5a484fbfeb7da301e 100644 (file)
@@ -218,7 +218,6 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
             code_model,
             reloc_model,
             opt_level,
-            true /* EnableSegstk */,
             use_softfp,
             !any_library && reloc_model == llvm::RelocPIC,
             ffunction_sections,
@@ -264,6 +263,7 @@ pub struct ModuleConfig {
     vectorize_loop: bool,
     vectorize_slp: bool,
     merge_functions: bool,
+    inline_threshold: Option<usize>
 }
 
 unsafe impl Send for ModuleConfig { }
@@ -289,6 +289,7 @@ fn new(tm: TargetMachineRef, passes: Vec<String>) -> ModuleConfig {
             vectorize_loop: false,
             vectorize_slp: false,
             merge_functions: false,
+            inline_threshold: None
         }
     }
 
@@ -297,6 +298,7 @@ fn set_flags(&mut self, sess: &Session, trans: &CrateTranslation) {
         self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes;
         self.no_builtins = trans.no_builtins;
         self.time_passes = sess.time_passes();
+        self.inline_threshold = sess.opts.cg.inline_threshold;
 
         // Copy what clang does by turning on loop vectorization at O2 and
         // slp vectorization at O3. Otherwise configure other optimization aspects
@@ -1005,6 +1007,7 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
     // manager.
     let builder = llvm::LLVMPassManagerBuilderCreate();
     let opt = config.opt_level.unwrap_or(llvm::CodeGenLevelNone);
+    let inline_threshold = config.inline_threshold;
 
     llvm::LLVMRustConfigurePassManagerBuilder(builder, opt,
                                               config.merge_functions,
@@ -1017,17 +1020,20 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
     // always-inline functions (but don't add lifetime intrinsics), at O1 we
     // inline with lifetime intrinsics, and O2+ we add an inliner with a
     // thresholds copied from clang.
-    match opt {
-        llvm::CodeGenLevelNone => {
+    match (opt, inline_threshold) {
+        (_, Some(t)) => {
+            llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32);
+        }
+        (llvm::CodeGenLevelNone, _) => {
             llvm::LLVMRustAddAlwaysInlinePass(builder, false);
         }
-        llvm::CodeGenLevelLess => {
+        (llvm::CodeGenLevelLess, _) => {
             llvm::LLVMRustAddAlwaysInlinePass(builder, true);
         }
-        llvm::CodeGenLevelDefault => {
+        (llvm::CodeGenLevelDefault, _) => {
             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
         }
-        llvm::CodeGenLevelAggressive => {
+        (llvm::CodeGenLevelAggressive, _) => {
             llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
         }
     }
index ee772411c4e9af85b8b8ce01b8c385a546d4ee06..d6343abfd15363fede7fdb3e82ab3936da2db5f8 100644 (file)
@@ -170,12 +170,19 @@ fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: DefId) -> clean
         ty::TyBareFn(_, ref f) => ((did, &f.sig).clean(cx), f.unsafety, f.abi),
         _ => panic!("bad function"),
     };
+
+    let constness = if csearch::is_const_fn(&tcx.sess.cstore, did) {
+        hir::Constness::Const
+    } else {
+        hir::Constness::NotConst
+    };
+
     let predicates = tcx.lookup_predicates(did);
     clean::Function {
         decl: decl,
         generics: (&t.generics, &predicates, subst::FnSpace).clean(cx),
         unsafety: style,
-        constness: hir::Constness::NotConst,
+        constness: constness,
         abi: abi,
     }
 }
@@ -345,9 +352,15 @@ pub fn build_impl(cx: &DocContext,
                     clean::TyMethodItem(clean::TyMethod {
                         unsafety, decl, self_, generics, abi
                     }) => {
+                        let constness = if csearch::is_const_fn(&tcx.sess.cstore, did) {
+                            hir::Constness::Const
+                        } else {
+                            hir::Constness::NotConst
+                        };
+
                         clean::MethodItem(clean::Method {
                             unsafety: unsafety,
-                            constness: hir::Constness::NotConst,
+                            constness: constness,
                             decl: decl,
                             self_: self_,
                             generics: generics,
index f9a138f8fd7af603ef9c1f441cc49d87ee1b71a6..f20f5dbbc4e5def07f6c5ee581ff2ff6f4e8eca8 100644 (file)
 use rustc_driver::{driver, target_features};
 use rustc::session::{self, config};
 use rustc::middle::def_id::DefId;
+use rustc::middle::privacy::AccessLevels;
 use rustc::middle::ty;
 use rustc::front::map as hir_map;
 use rustc::lint;
-use rustc::util::nodemap::DefIdSet;
 use rustc_trans::back::link;
 use rustc_resolve as resolve;
 use rustc_front::lowering::{lower_crate, LoweringContext};
@@ -77,8 +77,7 @@ pub fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
 }
 
 pub struct CrateAnalysis {
-    pub exported_items: DefIdSet,
-    pub public_items: DefIdSet,
+    pub access_levels: AccessLevels<DefId>,
     pub external_paths: ExternalPaths,
     pub external_typarams: RefCell<Option<HashMap<DefId, String>>>,
     pub inlined: RefCell<Option<HashSet<DefId>>>,
@@ -147,18 +146,15 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
                                         &name,
                                         resolve::MakeGlobMap::No,
                                         |tcx, _, analysis| {
-        let ty::CrateAnalysis { exported_items, public_items, .. } = analysis;
+        let ty::CrateAnalysis { access_levels, .. } = analysis;
 
         // Convert from a NodeId set to a DefId set since we don't always have easy access
         // to the map from defid -> nodeid
-        let exported_items: DefIdSet =
-            exported_items.into_iter()
-                          .map(|n| tcx.map.local_def_id(n))
-                          .collect();
-        let public_items: DefIdSet =
-            public_items.into_iter()
-                        .map(|n| tcx.map.local_def_id(n))
-                        .collect();
+        let access_levels = AccessLevels {
+            map: access_levels.map.into_iter()
+                                  .map(|(k, v)| (tcx.map.local_def_id(k), v))
+                                  .collect()
+        };
 
         let ctxt = DocContext {
             map: &tcx.map,
@@ -174,8 +170,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
         debug!("crate: {:?}", ctxt.map.krate());
 
         let mut analysis = CrateAnalysis {
-            exported_items: exported_items,
-            public_items: public_items,
+            access_levels: access_levels,
             external_paths: RefCell::new(None),
             external_typarams: RefCell::new(None),
             inlined: RefCell::new(None),
index 49228ac91f6b9082d0d6934e3cf2b0a7be1d1566..1b98f5bae0cc2e6c7f7d1a1879b7b2b8ce30f7fe 100644 (file)
@@ -56,8 +56,8 @@
 use syntax::{abi, ast};
 use rustc::metadata::cstore::LOCAL_CRATE;
 use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability;
-use rustc::util::nodemap::DefIdSet;
 use rustc_front::hir;
 
 use clean::{self, SelfTy};
@@ -244,7 +244,7 @@ pub struct Cache {
     search_index: Vec<IndexItem>,
     privmod: bool,
     remove_priv: bool,
-    public_items: DefIdSet,
+    access_levels: AccessLevels<DefId>,
     deref_trait_did: Option<DefId>,
 
     // In rare case where a structure is defined in one module but implemented
@@ -415,8 +415,8 @@ pub fn run(mut krate: clean::Crate,
     // Crawl the crate to build various caches used for the output
     let analysis = ::ANALYSISKEY.with(|a| a.clone());
     let analysis = analysis.borrow();
-    let public_items = analysis.as_ref().map(|a| a.public_items.clone());
-    let public_items = public_items.unwrap_or(DefIdSet());
+    let access_levels = analysis.as_ref().map(|a| a.access_levels.clone());
+    let access_levels = access_levels.unwrap_or(Default::default());
     let paths: HashMap<DefId, (Vec<String>, ItemType)> =
       analysis.as_ref().map(|a| {
         let paths = a.external_paths.borrow_mut().take().unwrap();
@@ -435,7 +435,7 @@ pub fn run(mut krate: clean::Crate,
         primitive_locations: HashMap::new(),
         remove_priv: cx.passes.contains("strip-private"),
         privmod: false,
-        public_items: public_items,
+        access_levels: access_levels,
         orphan_methods: Vec::new(),
         traits: mem::replace(&mut krate.external_traits, HashMap::new()),
         deref_trait_did: analysis.as_ref().and_then(|a| a.deref_trait_did),
@@ -1053,7 +1053,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 if
                     !self.paths.contains_key(&item.def_id) ||
                     !item.def_id.is_local() ||
-                    self.public_items.contains(&item.def_id)
+                    self.access_levels.is_public(item.def_id)
                 {
                     self.paths.insert(item.def_id,
                                       (self.stack.clone(), shortty(&item)));
@@ -1829,12 +1829,12 @@ fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 
 fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                  f: &clean::Function) -> fmt::Result {
-    try!(write!(w, "<pre class='rust fn'>{vis}{unsafety}{abi}{constness}fn \
+    try!(write!(w, "<pre class='rust fn'>{vis}{constness}{unsafety}{abi}fn \
                     {name}{generics}{decl}{where_clause}</pre>",
            vis = VisSpace(it.visibility),
+           constness = ConstnessSpace(f.constness),
            unsafety = UnsafetySpace(f.unsafety),
            abi = AbiSpace(f.abi),
-           constness = ConstnessSpace(f.constness),
            name = it.name.as_ref().unwrap(),
            generics = f.generics,
            where_clause = WhereClause(&f.generics),
@@ -2055,8 +2055,8 @@ fn method(w: &mut fmt::Formatter,
         };
         write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
-               UnsafetySpace(unsafety),
                ConstnessSpace(constness),
+               UnsafetySpace(unsafety),
                match abi {
                    Abi::Rust => String::new(),
                    a => format!("extern {} ", a.to_string())
index a09ca95dceaa4c364bc30cc1217aa7378b17d2b9..d011ba08a9ccc2199d629ac7bd204b2cf407dbda 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::middle::def_id::DefId;
+use rustc::middle::privacy::AccessLevels;
 use rustc::util::nodemap::DefIdSet;
 use std::cmp;
 use std::string::String;
@@ -96,13 +98,13 @@ pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult {
     let analysis = super::ANALYSISKEY.with(|a| a.clone());
     let analysis = analysis.borrow();
     let analysis = analysis.as_ref().unwrap();
-    let exported_items = analysis.exported_items.clone();
+    let access_levels = analysis.access_levels.clone();
 
     // strip all private items
     {
         let mut stripper = Stripper {
             retained: &mut retained,
-            exported_items: &exported_items,
+            access_levels: &access_levels,
         };
         krate = stripper.fold_crate(krate);
     }
@@ -117,7 +119,7 @@ pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult {
 
 struct Stripper<'a> {
     retained: &'a mut DefIdSet,
-    exported_items: &'a DefIdSet,
+    access_levels: &'a AccessLevels<DefId>,
 }
 
 impl<'a> fold::DocFolder for Stripper<'a> {
@@ -130,18 +132,14 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             clean::VariantItem(..) | clean::MethodItem(..) |
             clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) => {
                 if i.def_id.is_local() {
-                    if !self.exported_items.contains(&i.def_id) {
-                        return None;
-                    }
-                    // Traits are in exported_items even when they're totally private.
-                    if i.is_trait() && i.visibility != Some(hir::Public) {
+                    if !self.access_levels.is_exported(i.def_id) {
                         return None;
                     }
                 }
             }
 
             clean::ConstantItem(..) => {
-                if i.def_id.is_local() && !self.exported_items.contains(&i.def_id) {
+                if i.def_id.is_local() && !self.access_levels.is_exported(i.def_id) {
                     return None;
                 }
             }
@@ -168,7 +166,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             clean::ImplItem(clean::Impl{
                 for_: clean::ResolvedPath{ did, .. }, ..
             }) => {
-                if did.is_local() && !self.exported_items.contains(&did) {
+                if did.is_local() && !self.access_levels.is_exported(did) {
                     return None;
                 }
             }
index 36ef110fba07a6ad975e266e3ca9fc3d02d3bd56..150464404a22f860b88a7e1921f32c37cbf35e0b 100644 (file)
@@ -214,7 +214,7 @@ fn resolve_id(&mut self, id: ast::NodeId, renamed: Option<ast::Name>,
         let analysis = match self.analysis {
             Some(analysis) => analysis, None => return false
         };
-        if !please_inline && analysis.public_items.contains(&def) {
+        if !please_inline && analysis.access_levels.is_public(def) {
             return false
         }
         if !self.view_item_stack.insert(def_node_id) { return false }
index 0021155b00ab7ca0303d7410b3548cc45fca1d6e..daabb0f9fa8bf40e22b3de7bf6dcf8d350e296b3 100644 (file)
@@ -348,8 +348,8 @@ pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, S>)
     ///     println!("{}", x);
     /// }
     ///
-    /// let diff: HashSet<_> = a.intersection(&b).cloned().collect();
-    /// assert_eq!(diff, [2, 3].iter().cloned().collect());
+    /// let intersection: HashSet<_> = a.intersection(&b).cloned().collect();
+    /// assert_eq!(intersection, [2, 3].iter().cloned().collect());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
@@ -373,8 +373,8 @@ pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a,
     ///     println!("{}", x);
     /// }
     ///
-    /// let diff: HashSet<_> = a.union(&b).cloned().collect();
-    /// assert_eq!(diff, [1, 2, 3, 4].iter().cloned().collect());
+    /// let union: HashSet<_> = a.union(&b).cloned().collect();
+    /// assert_eq!(union, [1, 2, 3, 4].iter().cloned().collect());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
index b27a622136f749f90ea50a70e3c459afe7517cf1..30096677aa4ad9939a1fd4f170198e9d379171d7 100644 (file)
@@ -80,7 +80,6 @@ LLVMRustCreateTargetMachine(const char *triple,
                             CodeModel::Model CM,
                             Reloc::Model RM,
                             CodeGenOpt::Level OptLevel,
-                            bool EnableSegmentedStacks,
                             bool UseSoftFloat,
                             bool PositionIndependentExecutable,
                             bool FunctionSections,
diff --git a/src/test/auxiliary/issue-27362.rs b/src/test/auxiliary/issue-27362.rs
new file mode 100644 (file)
index 0000000..e551d62
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 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.
+
+#![feature(const_fn)]
+
+pub const fn foo() {}
+pub const unsafe fn bar() {}
+
+pub struct Foo;
+
+impl Foo {
+    pub const unsafe fn baz() {}
+}
index 3abc6f4a9f5d805f794fb33ab99f00fb7ead1537..c9249fb3357e41843be5f43c6a5547f03f829d98 100644 (file)
@@ -39,8 +39,15 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
         ("X",   10), ("IX",   9), ("V",   5), ("IV",   4),
         ("I",    1)];
 
-    let text = match args {
-        [TokenTree::Token(_, token::Ident(s, _))] => s.to_string(),
+    if args.len() != 1 {
+        cx.span_err(
+            sp,
+            &format!("argument should be a single identifier, but got {} arguments", args.len()));
+        return DummyResult::any(sp);
+    }
+
+    let text = match args[0] {
+        TokenTree::Token(_, token::Ident(s, _)) => s.to_string(),
         _ => {
             cx.span_err(sp, "argument should be a single identifier");
             return DummyResult::any(sp);
diff --git a/src/test/compile-fail/const-call.rs b/src/test/compile-fail/const-call.rs
new file mode 100644 (file)
index 0000000..d49da47
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+#![feature(const_fn)]
+
+const unsafe fn g(x: usize) -> usize {
+    x
+}
+
+fn f(x: usize) -> usize {
+    x
+}
+
+fn main() {
+    let _ = [0; f(2)]; //~ ERROR: non-constant path in constant expression [E0307]
+    let _ = [0; g(2)]; //~ ERROR: non-constant path in constant expression [E0307]
+}
diff --git a/src/test/rustdoc/issue-27362.rs b/src/test/rustdoc/issue-27362.rs
new file mode 100644 (file)
index 0000000..179778f
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 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-27362.rs
+// ignore-cross-compile
+
+extern crate issue_27362;
+pub use issue_27362 as quux;
+
+// @matches issue_27362/quux/fn.foo.html '//pre' "pub const fn foo()"
+// @matches issue_27362/quux/fn.bar.html '//pre' "pub const unsafe fn bar()"
+// @matches issue_27362/quux/struct.Foo.html '//code' "const unsafe fn baz()"