From 1ae1a19ba6156479969f493c8e05871539e69b52 Mon Sep 17 00:00:00 2001 From: Adam Ransom Date: Tue, 21 Mar 2017 21:35:57 +0900 Subject: [PATCH 01/11] Refactor checking if a `Lifetime` is static Simply move the test for `keywords::StaticLifetime` into the `Lifetime` impl, to match how elision is checked. --- src/librustc/hir/mod.rs | 4 ++++ src/librustc/middle/resolve_lifetime.rs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index edcfcffaa03a4..8239fd7d13c11 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -100,6 +100,10 @@ impl Lifetime { pub fn is_elided(&self) -> bool { self.name == keywords::Invalid.name() } + + pub fn is_static(&self) -> bool { + self.name == keywords::StaticLifetime.name() + } } /// A lifetime definition, eg `'a: 'b+'c+'d` diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 37749816eb153..10ee760a6a615 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -434,7 +434,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.resolve_elided_lifetimes(slice::ref_slice(lifetime_ref)); return; } - if lifetime_ref.name == keywords::StaticLifetime.name() { + if lifetime_ref.is_static() { self.insert_lifetime(lifetime_ref, Region::Static); return; } @@ -1434,7 +1434,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let lifetime_i = &lifetimes[i]; for lifetime in lifetimes { - if lifetime.lifetime.name == keywords::StaticLifetime.name() { + if lifetime.lifetime.is_static() { let lifetime = lifetime.lifetime; let mut err = struct_span_err!(self.sess, lifetime.span, E0262, "invalid lifetime parameter name: `{}`", lifetime.name); From c5a9f1f3f6d36d6e48586d16fdc3a69e9c75781a Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Wed, 22 Mar 2017 13:39:17 -0400 Subject: [PATCH 02/11] Basic documentation for inclusive range syntax --- src/doc/unstable-book/src/inclusive-range-syntax.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/doc/unstable-book/src/inclusive-range-syntax.md b/src/doc/unstable-book/src/inclusive-range-syntax.md index 74d85536399d7..255445c318dca 100644 --- a/src/doc/unstable-book/src/inclusive-range-syntax.md +++ b/src/doc/unstable-book/src/inclusive-range-syntax.md @@ -6,5 +6,15 @@ The tracking issue for this feature is: [#28237] ------------------------ +To get a range that goes from 0 to 10 and includes the value 10, you +can write `0...10`: +```rust +#![feature(inclusive_range_syntax)] +fn main() { + for i in 0...10 { + println!("{}", i); + } +} +``` From a3a5ff98eba2f81ec76b18cce50f113f59181cce Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 23 Mar 2017 14:18:25 -0400 Subject: [PATCH 03/11] move `export_map` into the tcx --- src/librustc/middle/cstore.rs | 12 ++++++------ src/librustc/ty/context.rs | 6 +++++- src/librustc/ty/mod.rs | 2 +- src/librustc_driver/driver.rs | 6 +++--- src/librustc_metadata/cstore_impl.rs | 6 +++--- src/librustc_metadata/encoder.rs | 6 +----- src/librustc_privacy/lib.rs | 10 +++------- src/librustc_trans/base.rs | 4 +--- src/librustc_trans/context.rs | 12 ------------ src/librustdoc/core.rs | 6 ++---- src/librustdoc/visit_ast.rs | 2 +- 11 files changed, 26 insertions(+), 46 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 225d6fc9bb2b2..56bbc0480c30a 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -255,8 +255,8 @@ pub trait CrateStore { fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>; fn used_crate_source(&self, cnum: CrateNum) -> CrateSource; fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option; - fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - reexports: &def::ExportMap, + fn encode_metadata<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &LinkMeta, reachable: &NodeSet) -> Vec; fn metadata_encoding_version(&self) -> &[u8]; @@ -412,10 +412,10 @@ impl CrateStore for DummyCrateStore { { vec![] } fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") } fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { None } - fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - reexports: &def::ExportMap, - link_meta: &LinkMeta, - reachable: &NodeSet) -> Vec { vec![] } + fn encode_metadata<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + link_meta: &LinkMeta, + reachable: &NodeSet) -> Vec { vec![] } fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 5543223105b44..da56514ea82fb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -15,7 +15,7 @@ use session::Session; use lint; use middle; use hir::TraitMap; -use hir::def::Def; +use hir::def::{Def, ExportMap}; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::map as hir_map; use hir::map::DisambiguatedDefPathData; @@ -416,6 +416,9 @@ pub struct GlobalCtxt<'tcx> { /// is relevant; generated by resolve. pub trait_map: TraitMap, + /// Export map produced by name resolution. + pub export_map: ExportMap, + pub named_region_map: resolve_lifetime::NamedRegionMap, pub region_maps: RegionMaps, @@ -698,6 +701,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { region_maps: region_maps, variance_computed: Cell::new(false), trait_map: resolutions.trait_map, + export_map: resolutions.export_map, fulfilled_predicates: RefCell::new(fulfilled_predicates), hir: hir, maps: maps::Maps::new(dep_graph, providers), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 36d1ae74e9114..0bcfae1e54a69 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -110,7 +110,6 @@ mod sty; /// produced by the driver and fed to trans and later passes. #[derive(Clone)] pub struct CrateAnalysis { - pub export_map: ExportMap, pub access_levels: middle::privacy::AccessLevels, pub reachable: NodeSet, pub name: String, @@ -122,6 +121,7 @@ pub struct Resolutions { pub freevars: FreevarMap, pub trait_map: TraitMap, pub maybe_unused_trait_imports: NodeSet, + pub export_map: ExportMap, } #[derive(Clone, Copy, PartialEq, Eq, Debug)] diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index d37553d7d660e..4947cafb52b3d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -807,7 +807,6 @@ pub fn phase_2_configure_and_expand(sess: &Session, expanded_crate: krate, defs: resolver.definitions, analysis: ty::CrateAnalysis { - export_map: resolver.export_map, access_levels: AccessLevels::default(), reachable: NodeSet(), name: crate_name.to_string(), @@ -815,10 +814,11 @@ pub fn phase_2_configure_and_expand(sess: &Session, }, resolutions: Resolutions { freevars: resolver.freevars, + export_map: resolver.export_map, trait_map: resolver.trait_map, maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, }, - hir_forest: hir_forest + hir_forest: hir_forest, }) } @@ -932,7 +932,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, analysis.access_levels = time(time_passes, "privacy checking", || { - rustc_privacy::check_crate(tcx, &analysis.export_map) + rustc_privacy::check_crate(tcx) }); time(time_passes, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 2a67b79eaa52e..17484138ad3a0 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -496,12 +496,12 @@ impl CrateStore for cstore::CStore { self.do_extern_mod_stmt_cnum(emod_id) } - fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - reexports: &def::ExportMap, + fn encode_metadata<'a, 'tcx>(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &LinkMeta, reachable: &NodeSet) -> Vec { - encoder::encode_metadata(tcx, self, reexports, link_meta, reachable) + encoder::encode_metadata(tcx, self, link_meta, reachable) } fn metadata_encoding_version(&self) -> &[u8] diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 044ed529ef74c..a324c166e738d 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -13,7 +13,6 @@ use index::Index; use schema::*; use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary}; -use rustc::hir::def; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId}; use rustc::hir::map::definitions::DefPathTable; use rustc::middle::dependency_format::Linkage; @@ -48,7 +47,6 @@ use super::index_builder::{FromId, IndexBuilder, Untracked}; pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder<'a>, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - reexports: &'a def::ExportMap, link_meta: &'a LinkMeta, cstore: &'a cstore::CStore, exported_symbols: &'a NodeSet, @@ -306,7 +304,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_id = tcx.hir.local_def_id(id); let data = ModData { - reexports: match self.reexports.get(&id) { + reexports: match tcx.export_map.get(&id) { Some(exports) if *vis == hir::Public => self.lazy_seq_ref(exports), _ => LazySeq::empty(), }, @@ -1423,7 +1421,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cstore: &cstore::CStore, - reexports: &def::ExportMap, link_meta: &LinkMeta, exported_symbols: &NodeSet) -> Vec { @@ -1437,7 +1434,6 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut ecx = EncodeContext { opaque: opaque::Encoder::new(&mut cursor), tcx: tcx, - reexports: reexports, link_meta: link_meta, cstore: cstore, exported_symbols: exported_symbols, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index e32ec25a7e8f7..6b33c7b7816f0 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -27,7 +27,7 @@ extern crate syntax_pos; use rustc::dep_graph::DepNode; use rustc::hir::{self, PatKind}; -use rustc::hir::def::{self, Def}; +use rustc::hir::def::Def; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::DeepVisitor; @@ -71,7 +71,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> { struct EmbargoVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - export_map: &'a def::ExportMap, // Accessibility levels for reachable nodes access_levels: AccessLevels, @@ -324,7 +323,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // This code is here instead of in visit_item so that the // crate module gets processed as well. if self.prev_level.is_some() { - if let Some(exports) = self.export_map.get(&id) { + if let Some(exports) = self.tcx.export_map.get(&id) { for export in exports { if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) { self.update(node_id, Some(AccessLevel::Exported)); @@ -1204,9 +1203,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> fn visit_pat(&mut self, _: &'tcx hir::Pat) {} } -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - export_map: &def::ExportMap) - -> AccessLevels { +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> AccessLevels { let _task = tcx.dep_graph.in_task(DepNode::Privacy); let krate = tcx.hir.krate(); @@ -1226,7 +1223,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // items which are reachable from external crates based on visibility. let mut visitor = EmbargoVisitor { tcx: tcx, - export_map: export_map, access_levels: Default::default(), prev_level: Some(AccessLevel::Public), changed: false, diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 80b563729f5ce..f7ca468fddaef 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -755,7 +755,6 @@ fn write_metadata(cx: &SharedCrateContext, let cstore = &cx.tcx().sess.cstore; let metadata = cstore.encode_metadata(cx.tcx(), - cx.export_map(), cx.link_meta(), exported_symbols); if kind == MetadataKind::Uncompressed { @@ -1056,7 +1055,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // particular items that will be processed. let krate = tcx.hir.krate(); - let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis; + let ty::CrateAnalysis { reachable, name, .. } = analysis; let exported_symbols = find_exported_symbols(tcx, reachable); let check_overflow = tcx.sess.overflow_checks(); @@ -1064,7 +1063,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let link_meta = link::build_link_meta(incremental_hashes_map, &name); let shared_ccx = SharedCrateContext::new(tcx, - export_map, link_meta.clone(), exported_symbols, check_overflow); diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 1c1395f1b7762..73602dc420b3f 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -14,7 +14,6 @@ use rustc::dep_graph::{DepGraph, DepGraphSafe, DepNode, DepTrackingMap, DepTrackingMapConfig, WorkProduct}; use middle::cstore::LinkMeta; use rustc::hir; -use rustc::hir::def::ExportMap; use rustc::hir::def_id::DefId; use rustc::traits; use debuginfo; @@ -68,7 +67,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { metadata_llmod: ModuleRef, metadata_llcx: ContextRef, - export_map: ExportMap, exported_symbols: NodeSet, link_meta: LinkMeta, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -402,7 +400,6 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>, - export_map: ExportMap, link_meta: LinkMeta, exported_symbols: NodeSet, check_overflow: bool) @@ -459,7 +456,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { SharedCrateContext { metadata_llmod: metadata_llmod, metadata_llcx: metadata_llcx, - export_map: export_map, exported_symbols: exported_symbols, link_meta: link_meta, empty_param_env: tcx.empty_parameter_environment(), @@ -499,10 +495,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { self.metadata_llcx } - pub fn export_map<'a>(&'a self) -> &'a ExportMap { - &self.export_map - } - pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet { &self.exported_symbols } @@ -702,10 +694,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) } } - pub fn export_map<'a>(&'a self) -> &'a ExportMap { - &self.shared.export_map - } - pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet { &self.shared.exported_symbols } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 0a9db2c26464c..92aba1fc61de3 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -13,7 +13,7 @@ use rustc_driver::{driver, target_features, abort_on_err}; use rustc::dep_graph::DepGraph; use rustc::session::{self, config}; use rustc::hir::def_id::DefId; -use rustc::hir::def::{Def, ExportMap}; +use rustc::hir::def::Def; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, TyCtxt, GlobalArenas}; use rustc::hir::map as hir_map; @@ -64,7 +64,6 @@ pub struct DocContext<'a, 'tcx: 'a> { pub ty_substs: RefCell>, /// Table node id of lifetime parameter definition -> substituted lifetime pub lt_substs: RefCell>, - pub export_map: ExportMap, } impl<'a, 'tcx> DocContext<'a, 'tcx> { @@ -180,7 +179,7 @@ pub fn run_core(search_paths: SearchPaths, sess.fatal("Compilation failed, aborting rustdoc"); } - let ty::CrateAnalysis { access_levels, export_map, .. } = 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 @@ -198,7 +197,6 @@ pub fn run_core(search_paths: SearchPaths, renderinfo: Default::default(), ty_substs: Default::default(), lt_substs: Default::default(), - export_map: export_map, }; debug!("crate: {:?}", tcx.hir.krate()); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 4a909f8e2a972..2793307697852 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -198,7 +198,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.visit_item(item, None, &mut om); } self.inside_public_path = orig_inside_public_path; - if let Some(exports) = self.cx.export_map.get(&id) { + if let Some(exports) = self.cx.tcx.export_map.get(&id) { for export in exports { if let Def::Macro(def_id, ..) = export.def { if def_id.krate == LOCAL_CRATE { From 69c9d9b3b806148846459cd0e4e30f300686dd97 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 23 Mar 2017 16:45:21 -0400 Subject: [PATCH 04/11] ignore reads of tracked state when there is no current task I realized that, even in the current system, such reads can't really do any harm. Because they are not part of a task, they will occur no matter what (only tasks can be skipped). If you leak the data you read into a task, that is bad, but that is equally bad if you are in a task. *Writes* to tracked state, on the other hand, should never occur except from within a task (and the task then records what things you read to compute it). Once we complete the shift to on-demand, these properties will hold by construction (because the on-demand struct enforces stateless tasks where leaks are impossible -- except by having shared mutable state in the tcx). --- src/librustc/dep_graph/edges.rs | 12 ++++++++---- src/librustc/dep_graph/shadow.rs | 10 ++++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs index 8657a3e5a5878..5dbabcc923048 100644 --- a/src/librustc/dep_graph/edges.rs +++ b/src/librustc/dep_graph/edges.rs @@ -101,11 +101,15 @@ impl DepGraphEdges { } /// Indicates that the current task `C` reads `v` by adding an - /// edge from `v` to `C`. If there is no current task, panics. If - /// you want to suppress this edge, use `ignore`. + /// edge from `v` to `C`. If there is no current task, has no + /// effect. Note that *reading* from tracked state is harmless if + /// you are not in a task; what is bad is *writing* to tracked + /// state (and leaking data that you read into a tracked task). pub fn read(&mut self, v: DepNode) { - let source = self.make_node(v); - self.add_edge_from_current_node(|current| (source, current)) + if self.current_node().is_some() { + let source = self.make_node(v); + self.add_edge_from_current_node(|current| (source, current)) + } } /// Indicates that the current task `C` writes `v` by adding an diff --git a/src/librustc/dep_graph/shadow.rs b/src/librustc/dep_graph/shadow.rs index 5d4190a8ae1a3..bedb6ff2771f0 100644 --- a/src/librustc/dep_graph/shadow.rs +++ b/src/librustc/dep_graph/shadow.rs @@ -80,7 +80,13 @@ impl ShadowGraph { let mut stack = self.stack.borrow_mut(); match *message { - DepMessage::Read(ref n) => self.check_edge(Some(Some(n)), top(&stack)), + // It is ok to READ shared state outside of a + // task. That can't do any harm (at least, the only + // way it can do harm is by leaking that data into a + // query or task, which would be a problem + // anyway). What would be bad is WRITING to that + // state. + DepMessage::Read(_) => { } DepMessage::Write(ref n) => self.check_edge(top(&stack), Some(Some(n))), DepMessage::PushTask(ref n) => stack.push(Some(n.clone())), DepMessage::PushIgnore => stack.push(None), @@ -116,7 +122,7 @@ impl ShadowGraph { (None, None) => unreachable!(), // nothing on top of the stack - (None, Some(n)) | (Some(n), None) => bug!("read/write of {:?} but no current task", n), + (None, Some(n)) | (Some(n), None) => bug!("write of {:?} but no current task", n), // this corresponds to an Ignore being top of the stack (Some(None), _) | (_, Some(None)) => (), From a9f6babcda1479f4e5566d1aadbf9a0d99aa3182 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 23 Mar 2017 15:13:29 -0400 Subject: [PATCH 05/11] convert privacy access levels into a query --- src/librustc/dep_graph/dep_node.rs | 5 +++-- src/librustc/lint/context.rs | 8 +++++--- src/librustc/middle/dead.rs | 7 ++++--- src/librustc/middle/reachable.rs | 8 +++++--- src/librustc/middle/stability.rs | 5 +++-- src/librustc/ty/maps.rs | 10 ++++++++++ src/librustc/ty/mod.rs | 7 +++++-- src/librustc_driver/driver.rs | 20 ++++++++------------ src/librustc_privacy/lib.rs | 29 +++++++++++++++++++++++------ src/librustdoc/core.rs | 4 ++-- 10 files changed, 68 insertions(+), 35 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 399af258e9251..5ee9258852b0b 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir::def_id::CrateNum; use std::fmt::Debug; use std::sync::Arc; @@ -81,7 +82,7 @@ pub enum DepNode { TypeckItemType(D), UnusedTraitCheck, CheckConst(D), - Privacy, + PrivacyAccessLevels(CrateNum), IntrinsicCheck(D), MatchCheck(D), @@ -230,7 +231,7 @@ impl DepNode { CheckEntryFn => Some(CheckEntryFn), Variance => Some(Variance), UnusedTraitCheck => Some(UnusedTraitCheck), - Privacy => Some(Privacy), + PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)), Reachability => Some(Reachability), DeadCheck => Some(DeadCheck), LateLintCheck => Some(LateLintCheck), diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 843f3a53f33e5..d35f965e2ffd7 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -44,9 +44,10 @@ use std::ops::Deref; use syntax::attr; use syntax::ast; use syntax::symbol::Symbol; -use syntax_pos::{MultiSpan, Span}; +use syntax_pos::{DUMMY_SP, MultiSpan, Span}; use errors::{self, Diagnostic, DiagnosticBuilder}; use hir; +use hir::def_id::LOCAL_CRATE; use hir::intravisit as hir_visit; use syntax::visit as ast_visit; @@ -1231,10 +1232,11 @@ fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore, /// Perform lint checking on a crate. /// /// Consumes the `lint_store` field of the `Session`. -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - access_levels: &AccessLevels) { +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck); + let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE); + let krate = tcx.hir.krate(); // We want to own the lint store, so move it out of the session. diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index cc6d6e88dee4e..8926ff5c1fbbb 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -21,12 +21,13 @@ use hir::itemlikevisit::ItemLikeVisitor; use middle::privacy; use ty::{self, TyCtxt}; use hir::def::Def; -use hir::def_id::{DefId}; +use hir::def_id::{DefId, LOCAL_CRATE}; use lint; use util::nodemap::FxHashSet; use syntax::{ast, codemap}; use syntax::attr; +use syntax::codemap::DUMMY_SP; use syntax_pos; // Any local node that may call something in its body block should be @@ -592,9 +593,9 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { } } -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - access_levels: &privacy::AccessLevels) { +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let _task = tcx.dep_graph.in_task(DepNode::DeadCheck); + let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE); let krate = tcx.hir.krate(); let live_symbols = find_live(tcx, access_levels, krate); let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols }; diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 4ec43e368a60d..b0e39442af98c 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -27,7 +27,9 @@ use util::nodemap::{NodeSet, FxHashSet}; use syntax::abi::Abi; use syntax::ast; use syntax::attr; +use syntax::codemap::DUMMY_SP; use hir; +use hir::def_id::LOCAL_CRATE; use hir::intravisit::{Visitor, NestedVisitorMap}; use hir::itemlikevisit::ItemLikeVisitor; use hir::intravisit; @@ -359,11 +361,11 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, } } -pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - access_levels: &privacy::AccessLevels) - -> NodeSet { +pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet { let _task = tcx.dep_graph.in_task(DepNode::Reachability); + let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE); + let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib || *ty == config::CrateTypeProcMacro diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 1fb5371402574..4115b4669f4b2 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -656,10 +656,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Given the list of enabled features that were not language features (i.e. that /// were expected to be library features), and the list of features used from /// libraries, identify activated features that don't exist and error about them. -pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - access_levels: &AccessLevels) { +pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let sess = &tcx.sess; + let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE); + if tcx.stability.borrow().staged_api[&LOCAL_CRATE] && tcx.sess.features.borrow().staged_api { let _task = tcx.dep_graph.in_task(DepNode::StabilityIndex); let krate = tcx.hir.krate(); diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index ac8c38c7d5856..da4e58addd71b 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -11,6 +11,7 @@ use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig}; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use middle::const_val::ConstVal; +use middle::privacy::AccessLevels; use mir; use ty::{self, Ty, TyCtxt}; @@ -189,6 +190,12 @@ impl<'tcx> QueryDescription for queries::mir_shims<'tcx> { } } +impl<'tcx> QueryDescription for queries::privacy_access_levels<'tcx> { + fn describe(_: TyCtxt, _: CrateNum) -> String { + format!("privacy access levels") + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* @@ -406,6 +413,9 @@ define_maps! { <'tcx> /// other items, such as enum variant explicit discriminants. pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result, ()>, + /// Performs the privacy check and computes "access levels". + pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc, + pub mir_shims: mir_shim(ty::InstanceDef<'tcx>) -> &'tcx RefCell> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 0bcfae1e54a69..4283b10ec624f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -17,11 +17,11 @@ pub use self::fold::TypeFoldable; use dep_graph::{self, DepNode}; use hir::{map as hir_map, FreevarMap, TraitMap}; -use middle; use hir::def::{Def, CtorKind, ExportMap}; use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use middle::const_val::ConstVal; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; +use middle::privacy::AccessLevels; use middle::region::{CodeExtent, ROOT_CODE_EXTENT}; use middle::resolve_lifetime::ObjectLifetimeDefault; use mir::Mir; @@ -108,9 +108,12 @@ mod sty; /// The complete set of all analyses described in this module. This is /// produced by the driver and fed to trans and later passes. +/// +/// NB: These contents are being migrated into queries using the +/// *on-demand* infrastructure. #[derive(Clone)] pub struct CrateAnalysis { - pub access_levels: middle::privacy::AccessLevels, + pub access_levels: Rc, pub reachable: NodeSet, pub name: String, pub glob_map: Option, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 4947cafb52b3d..e8b9be4a903c3 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -48,6 +48,7 @@ use std::fs; use std::io::{self, Write}; use std::iter; use std::path::{Path, PathBuf}; +use std::rc::Rc; use syntax::{ast, diagnostics, visit}; use syntax::attr; use syntax::ext::base::ExtCtxt; @@ -807,7 +808,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, expanded_crate: krate, defs: resolver.definitions, analysis: ty::CrateAnalysis { - access_levels: AccessLevels::default(), + access_levels: Rc::new(AccessLevels::default()), reachable: NodeSet(), name: crate_name.to_string(), glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None }, @@ -888,6 +889,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut local_providers = ty::maps::Providers::default(); mir::provide(&mut local_providers); + rustc_privacy::provide(&mut local_providers); typeck::provide(&mut local_providers); ty::provide(&mut local_providers); @@ -931,9 +933,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, || consts::check_crate(tcx)); analysis.access_levels = - time(time_passes, "privacy checking", || { - rustc_privacy::check_crate(tcx) - }); + time(time_passes, "privacy checking", || rustc_privacy::check_crate(tcx)); time(time_passes, "intrinsic checking", @@ -1000,19 +1000,15 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, analysis.reachable = time(time_passes, "reachability checking", - || reachable::find_reachable(tcx, &analysis.access_levels)); + || reachable::find_reachable(tcx)); - time(time_passes, "death checking", || { - middle::dead::check_crate(tcx, &analysis.access_levels); - }); + time(time_passes, "death checking", || middle::dead::check_crate(tcx)); time(time_passes, "unused lib feature checking", || { - stability::check_unused_or_stable_features(tcx, &analysis.access_levels) + stability::check_unused_or_stable_features(tcx) }); - time(time_passes, - "lint checking", - || lint::check_crate(tcx, &analysis.access_levels)); + time(time_passes, "lint checking", || lint::check_crate(tcx)); // The above three passes generate errors w/o aborting if sess.err_count() > 0 { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 6b33c7b7816f0..64821f5d44bf4 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -17,6 +17,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![deny(warnings)] +#![cfg_attr(stage0, feature(field_init_shorthand))] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(staged_api)] @@ -25,10 +26,9 @@ extern crate rustc; #[macro_use] extern crate syntax; extern crate syntax_pos; -use rustc::dep_graph::DepNode; use rustc::hir::{self, PatKind}; use rustc::hir::def::Def; -use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::DeepVisitor; use rustc::hir::pat_util::EnumerateAndAdjustIterator; @@ -36,12 +36,14 @@ use rustc::lint; use rustc::middle::privacy::{AccessLevel, AccessLevels}; use rustc::ty::{self, TyCtxt, Ty, TypeFoldable}; use rustc::ty::fold::TypeVisitor; +use rustc::ty::maps::Providers; use rustc::util::nodemap::NodeSet; use syntax::ast; -use syntax_pos::Span; +use syntax_pos::{DUMMY_SP, Span}; use std::cmp; use std::mem::replace; +use std::rc::Rc; pub mod diagnostics; @@ -1203,8 +1205,23 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> fn visit_pat(&mut self, _: &'tcx hir::Pat) {} } -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> AccessLevels { - let _task = tcx.dep_graph.in_task(DepNode::Privacy); +pub fn provide(providers: &mut Providers) { + *providers = Providers { + privacy_access_levels, + ..*providers + }; +} + +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Rc { + tcx.dep_graph.with_ignore(|| { // FIXME + ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE) + }) +} + +fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + krate: CrateNum) + -> Rc { + assert_eq!(krate, LOCAL_CRATE); let krate = tcx.hir.krate(); @@ -1266,7 +1283,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> AccessLevels { krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); } - visitor.access_levels + Rc::new(visitor.access_levels) } __build_diagnostic_array! { librustc_privacy, DIAGNOSTICS } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 92aba1fc61de3..a47d5f9937a02 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -184,8 +184,8 @@ pub fn run_core(search_paths: SearchPaths, // Convert from a NodeId set to a DefId set since we don't always have easy access // to the map from defid -> nodeid let access_levels = AccessLevels { - map: access_levels.map.into_iter() - .map(|(k, v)| (tcx.hir.local_def_id(k), v)) + map: access_levels.map.iter() + .map(|(&k, &v)| (tcx.hir.local_def_id(k), v)) .collect() }; From 8fba638b08eb85cda1bd2a4e855f7f76727dfc52 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 18 Mar 2017 10:37:52 -0400 Subject: [PATCH 06/11] Rewrite `io::BufRead` doc examples to better demonstrate behaviors. Prior to this commit, most of the `BufRead` examples used `StdinLock` to demonstrate how certain `BufRead` methods worked. Using `StdinLock` is not ideal since: * Relying on run-time data means we can't show concrete examples of how these methods work up-front. The user is required to run them in order to see how they behave. * If the user tries to run an example in the playpen, it won't work because the playpen doesn't support user input to stdin. --- src/libstd/io/mod.rs | 137 ++++++++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 53 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 850885a8c0f3a..5b628d51d1513 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1290,28 +1290,42 @@ pub trait BufRead: Read { /// If an I/O error is encountered then all bytes read so far will be /// present in `buf` and its length will have been adjusted appropriately. /// - /// # Examples - /// - /// A locked standard input implements `BufRead`. In this example, we'll - /// read from standard input until we see an `a` byte. - /// /// [`fill_buf`]: #tymethod.fill_buf /// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted /// - /// ``` - /// use std::io; - /// use std::io::prelude::*; + /// # Examples /// - /// fn foo() -> io::Result<()> { - /// let stdin = io::stdin(); - /// let mut stdin = stdin.lock(); - /// let mut buffer = Vec::new(); + /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In + /// this example, we use [`Cursor`] to read all the bytes in a byte slice + /// in hyphen delimited segments: /// - /// stdin.read_until(b'a', &mut buffer)?; + /// [`Cursor`]: struct.Cursor.html /// - /// println!("{:?}", buffer); - /// # Ok(()) - /// # } + /// ``` + /// use std::io::{self, BufRead}; + /// + /// let mut cursor = io::Cursor::new(b"lorem-ipsum"); + /// let mut buf = vec![]; + /// + /// // cursor is at 'l' + /// let num_bytes = cursor.read_until(b'-', &mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 6); + /// assert_eq!(buf, b"lorem-"); + /// buf.clear(); + /// + /// // cursor is at 'i' + /// let num_bytes = cursor.read_until(b'-', &mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 5); + /// assert_eq!(buf, b"ipsum"); + /// buf.clear(); + /// + /// // cursor is at EOF + /// let num_bytes = cursor.read_until(b'-', &mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 0); + /// assert_eq!(buf, b""); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read_until(&mut self, byte: u8, buf: &mut Vec) -> Result { @@ -1337,28 +1351,36 @@ pub trait BufRead: Read { /// /// # Examples /// - /// A locked standard input implements `BufRead`. In this example, we'll - /// read all of the lines from standard input. If we were to do this in - /// an actual project, the [`lines`] method would be easier, of - /// course. + /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In + /// this example, we use [`Cursor`] to read all the lines in a byte slice: /// - /// [`lines`]: #method.lines - /// [`read_until`]: #method.read_until + /// [`Cursor`]: struct.Cursor.html /// /// ``` - /// use std::io; - /// use std::io::prelude::*; - /// - /// let stdin = io::stdin(); - /// let mut stdin = stdin.lock(); - /// let mut buffer = String::new(); - /// - /// while stdin.read_line(&mut buffer).unwrap() > 0 { - /// // work with buffer - /// println!("{:?}", buffer); - /// - /// buffer.clear(); - /// } + /// use std::io::{self, BufRead}; + /// + /// let mut cursor = io::Cursor::new(b"foo\nbar"); + /// let mut buf = String::new(); + /// + /// // cursor is at 'f' + /// let num_bytes = cursor.read_line(&mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 4); + /// assert_eq!(buf, "foo\n"); + /// buf.clear(); + /// + /// // cursor is at 'b' + /// let num_bytes = cursor.read_line(&mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 3); + /// assert_eq!(buf, "bar"); + /// buf.clear(); + /// + /// // cursor is at EOF + /// let num_bytes = cursor.read_line(&mut buf) + /// .expect("reading from cursor won't fail"); + /// assert_eq!(num_bytes, 0); + /// assert_eq!(buf, ""); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn read_line(&mut self, buf: &mut String) -> Result { @@ -1378,24 +1400,28 @@ pub trait BufRead: Read { /// This function will yield errors whenever [`read_until`] would have /// also yielded an error. /// - /// # Examples - /// - /// A locked standard input implements `BufRead`. In this example, we'll - /// read some input from standard input, splitting on commas. - /// /// [`io::Result`]: type.Result.html /// [`Vec`]: ../vec/struct.Vec.html /// [`read_until`]: #method.read_until /// + /// # Examples + /// + /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In + /// this example, we use [`Cursor`] to iterate over all hyphen delimited + /// segments in a byte slice + /// + /// [`Cursor`]: struct.Cursor.html + /// /// ``` - /// use std::io; - /// use std::io::prelude::*; + /// use std::io::{self, BufRead}; /// - /// let stdin = io::stdin(); + /// let cursor = io::Cursor::new(b"lorem-ipsum-dolor"); /// - /// for content in stdin.lock().split(b',') { - /// println!("{:?}", content.unwrap()); - /// } + /// let mut split_iter = cursor.split(b'-').map(|l| l.unwrap()); + /// assert_eq!(split_iter.next(), Some(b"lorem".to_vec())); + /// assert_eq!(split_iter.next(), Some(b"ipsum".to_vec())); + /// assert_eq!(split_iter.next(), Some(b"dolor".to_vec())); + /// assert_eq!(split_iter.next(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn split(self, byte: u8) -> Split where Self: Sized { @@ -1413,17 +1439,22 @@ pub trait BufRead: Read { /// /// # Examples /// - /// A locked standard input implements `BufRead`: + /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In + /// this example, we use [`Cursor`] to iterate over all the lines in a byte + /// slice. + /// + /// [`Cursor`]: struct.Cursor.html /// /// ``` - /// use std::io; - /// use std::io::prelude::*; + /// use std::io::{self, BufRead}; /// - /// let stdin = io::stdin(); + /// let cursor = io::Cursor::new(b"lorem\nipsum\r\ndolor"); /// - /// for line in stdin.lock().lines() { - /// println!("{}", line.unwrap()); - /// } + /// let mut lines_iter = cursor.lines().map(|l| l.unwrap()); + /// assert_eq!(lines_iter.next(), Some(String::from("lorem"))); + /// assert_eq!(lines_iter.next(), Some(String::from("ipsum"))); + /// assert_eq!(lines_iter.next(), Some(String::from("dolor"))); + /// assert_eq!(lines_iter.next(), None); /// ``` /// /// # Errors From 2c816f7fb6772fe0b77af04da9355aab6c2d3fb2 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Sat, 25 Mar 2017 00:27:47 +0100 Subject: [PATCH 07/11] Optimize insertion sort This change slightly changes the main iteration loop so that LLVM can optimize it more efficiently. Benchmark: name before ns/iter after ns/iter diff ns/iter diff % slice::sort_unstable_small_ascending 39 (2051 MB/s) 38 (2105 MB/s) -1 -2.56% slice::sort_unstable_small_big_random 579 (2210 MB/s) 575 (2226 MB/s) -4 -0.69% slice::sort_unstable_small_descending 80 (1000 MB/s) 70 (1142 MB/s) -10 -12.50% slice::sort_unstable_small_random 396 (202 MB/s) 386 -10 -2.53% --- src/libcore/slice/sort.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index d13d537d99301..307e4974d9769 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -152,8 +152,8 @@ fn partial_insertion_sort(v: &mut [T], is_less: &mut F) -> bool fn insertion_sort(v: &mut [T], is_less: &mut F) where F: FnMut(&T, &T) -> bool { - for i in 2..v.len()+1 { - shift_tail(&mut v[..i], is_less); + for i in 1..v.len() { + shift_tail(&mut v[..i+1], is_less); } } From e7949d0013bb8b45c884b173ca22c20e6899d612 Mon Sep 17 00:00:00 2001 From: Adam Ransom Date: Tue, 21 Mar 2017 21:38:32 +0900 Subject: [PATCH 08/11] Warn when using a `'static` lifetime bound Previously a `'static` lifetime bound would result in an `undeclared lifetime` error when compiling, even though it could be considered valid. However, it is unnecessary to use it as a lifetime bound so we present the user with a warning instead and suggest using the `'static` lifetime directly, in place of the lifetime parameter. --- src/librustc/middle/resolve_lifetime.rs | 14 ++++++++++++-- src/test/compile-fail/static-lifetime-bound.rs | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/static-lifetime-bound.rs diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 10ee760a6a615..5094e28475b26 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -29,7 +29,7 @@ use syntax::ast; use syntax::attr; use syntax::ptr::P; use syntax::symbol::keywords; -use syntax_pos::Span; +use syntax_pos::{mk_sp, Span}; use errors::DiagnosticBuilder; use util::nodemap::{NodeMap, NodeSet, FxHashSet, FxHashMap, DefIdMap}; use rustc_back::slice; @@ -1464,7 +1464,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime); for bound in &lifetime_i.bounds { - self.resolve_lifetime_ref(bound); + if !bound.is_static() { + self.resolve_lifetime_ref(bound); + } else { + self.insert_lifetime(bound, Region::Static); + let full_span = mk_sp(lifetime_i.lifetime.span.lo, bound.span.hi); + self.sess.struct_span_warn(full_span, + &format!("unnecessary lifetime parameter `{}`", lifetime_i.lifetime.name)) + .help(&format!("you can use the `'static` lifetime directly, in place \ + of `{}`", lifetime_i.lifetime.name)) + .emit(); + } } } } diff --git a/src/test/compile-fail/static-lifetime-bound.rs b/src/test/compile-fail/static-lifetime-bound.rs new file mode 100644 index 0000000000000..38534ab0a3687 --- /dev/null +++ b/src/test/compile-fail/static-lifetime-bound.rs @@ -0,0 +1,16 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f<'a: 'static>(_: &'a i32) {} //~WARN unnecessary lifetime parameter `'a` + +fn main() { + let x = 0; + f(&x); //~ERROR does not live long enough +} From 5d9d652e0f746d7db9542f95115d5820fefeedaa Mon Sep 17 00:00:00 2001 From: Irfan Hudda Date: Sat, 25 Mar 2017 16:21:08 +0530 Subject: [PATCH 09/11] Fix typo in dec2flt/algorithm.rs --- src/libcore/num/dec2flt/algorithm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs index 604bc7c10dea0..60dab943a3acf 100644 --- a/src/libcore/num/dec2flt/algorithm.rs +++ b/src/libcore/num/dec2flt/algorithm.rs @@ -141,7 +141,7 @@ pub fn fast_path(integral: &[u8], fractional: &[u8], e: i64) -> Opt /// /// It rounds ``f`` to a float with 64 bit significand and multiplies it by the best approximation /// of `10^e` (in the same floating point format). This is often enough to get the correct result. -/// However, when the result is close to halfway between two adjecent (ordinary) floats, the +/// However, when the result is close to halfway between two adjacent (ordinary) floats, the /// compound rounding error from multiplying two approximation means the result may be off by a /// few bits. When this happens, the iterative Algorithm R fixes things up. /// @@ -392,7 +392,7 @@ fn underflow(x: Big, v: Big, rem: Big) -> T { // // Therefore, when the rounded-off bits are != 0.5 ULP, they decide the rounding // on their own. When they are equal and the remainder is non-zero, the value still - // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainer + // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainder // is zero, we have a half-to-even situation. let bits = x.bit_length(); let lsb = bits - T::sig_bits() as usize; From ca85c400dae365c9ade87bbd100ddfe3ecd3822a Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 25 Mar 2017 15:01:25 +0300 Subject: [PATCH 10/11] travis: try to fix the build on emscripten The emsdk-portable .tar.gz now extracts to emsdk-portable instead of emsdk_portable. Handle that. --- src/ci/docker/emscripten/build-emscripten.sh | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/emscripten/build-emscripten.sh b/src/ci/docker/emscripten/build-emscripten.sh index 88bf583007ce5..b9aa197f85e0d 100755 --- a/src/ci/docker/emscripten/build-emscripten.sh +++ b/src/ci/docker/emscripten/build-emscripten.sh @@ -29,7 +29,20 @@ exit 1 } curl https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \ - tar xzf - + tar xzf - + +# Some versions of the EMSDK archive have their contents in .emsdk-portable +# and others in emsdk_portable. Make sure the EMSDK ends up in a fixed path. +if [ -d emsdk-portable ]; then + mv emsdk-portable emsdk_portable +fi + +if [ ! -d emsdk_portable ]; then + echo "ERROR: Invalid emsdk archive. Dumping working directory." >&2 + ls -l + exit 1 +fi + source emsdk_portable/emsdk_env.sh hide_output emsdk update hide_output emsdk install --build=Release sdk-tag-1.37.1-32bit From 935d84a272a8b637e13c54b18a1571994e962e5c Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sat, 25 Mar 2017 17:22:07 +0100 Subject: [PATCH 11/11] fix permissions of emsdk_portable --- src/ci/docker/emscripten/build-emscripten.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ci/docker/emscripten/build-emscripten.sh b/src/ci/docker/emscripten/build-emscripten.sh index b9aa197f85e0d..e39767357ad63 100755 --- a/src/ci/docker/emscripten/build-emscripten.sh +++ b/src/ci/docker/emscripten/build-emscripten.sh @@ -43,6 +43,10 @@ if [ ! -d emsdk_portable ]; then exit 1 fi +# Some versions of the EMSDK set the permissions of the root directory to +# 0700. Ensure the directory is readable by all users. +chmod 755 emsdk_portable + source emsdk_portable/emsdk_env.sh hide_output emsdk update hide_output emsdk install --build=Release sdk-tag-1.37.1-32bit