From 4837fb45ff41ad8ff4c6dfc9bd3f8056959f3d4e Mon Sep 17 00:00:00 2001 From: Adrian Friedli Date: Sat, 16 Feb 2019 22:34:28 +0100 Subject: [PATCH 1/9] implement nth_back for Box --- src/liballoc/boxed.rs | 3 +++ src/liballoc/lib.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 51549f92d4dbf..1e3ccf90eb87f 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -662,6 +662,9 @@ impl DoubleEndedIterator for Box { fn next_back(&mut self) -> Option { (**self).next_back() } + fn nth_back(&mut self, n: usize) -> Option { + (**self).nth_back(n) + } } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Box { diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 95b9dacf8565a..da1afc2ff8aa3 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -115,6 +115,7 @@ #![feature(maybe_uninit)] #![feature(alloc_layout_extra)] #![feature(try_trait)] +#![feature(iter_nth_back)] // Allow testing this library From 739ba0417ae6477ffc9c5e8298b5075725d52420 Mon Sep 17 00:00:00 2001 From: Adrian Friedli Date: Sun, 24 Feb 2019 00:22:41 +0100 Subject: [PATCH 2/9] implement nth_back for Windows --- src/libcore/slice/mod.rs | 13 +++++++++++++ src/libcore/tests/slice.rs | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index acca9748372ca..b048a12e402a5 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3835,6 +3835,19 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> { ret } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.v.len().overflowing_sub(n); + if end < self.size || overflow { + self.v = &[]; + None + } else { + let ret = &self.v[end-self.size..end]; + self.v = &self.v[..end-1]; + Some(ret) + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 04d646ea01d03..1e92b6f787870 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -578,6 +578,19 @@ fn test_windows_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_windows_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.windows(2); + assert_eq!(c.nth_back(2).unwrap()[0], 2); + assert_eq!(c.next_back().unwrap()[1], 2); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.windows(4); + assert_eq!(c2.nth_back(1).unwrap()[1], 1); + assert_eq!(c2.next_back(), None); +} + #[test] fn test_windows_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; From fbc4326f4b249413fd71fe11a93ecf11f7533116 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 15 Mar 2019 15:04:34 +0000 Subject: [PATCH 3/9] Track changes to robots.txt --- src/doc/robots.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/doc/robots.txt diff --git a/src/doc/robots.txt b/src/doc/robots.txt new file mode 100644 index 0000000000000..a54ec508c1bef --- /dev/null +++ b/src/doc/robots.txt @@ -0,0 +1,19 @@ +# NB: This file is not automatically deployed. After changes, it needs to be uploaded manually to doc.rust-lang.org +User-agent: * +Disallow: /0.3/ +Disallow: /0.4/ +Disallow: /0.5/ +Disallow: /0.6/ +Disallow: /0.7/ +Disallow: /0.8/ +Disallow: /0.9/ +Disallow: /0.10/ +Disallow: /0.11.0/ +Disallow: /0.12.0/ +Disallow: /1.0.0-alpha/ +Disallow: /1.0.0-alpha.2/ +Disallow: /1.0.0-beta/ +Disallow: /1.0.0-beta.2/ +Disallow: /1.0.0-beta.3/ +Disallow: /1.0.0-beta.4/ +Disallow: /1.0.0-beta.5/ From 64303189f0b3a111c3b1e59d77cdaad91ca90efe Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 17 Mar 2019 10:36:10 +0000 Subject: [PATCH 4/9] Use a valid name for graphviz graphs --- src/librustc_driver/pretty.rs | 12 +++++++++- src/librustc_mir/borrow_check/mod.rs | 8 +++---- src/librustc_mir/dataflow/graphviz.rs | 17 +++++++------- src/librustc_mir/dataflow/mod.rs | 12 +++++----- src/librustc_mir/transform/elaborate_drops.rs | 12 +++++----- src/librustc_mir/transform/generator.rs | 6 ++--- src/librustc_mir/transform/rustc_peek.rs | 19 ++++++++------- src/librustc_mir/util/graphviz.rs | 14 ++++++++++- src/librustc_mir/util/mod.rs | 2 +- src/test/mir-opt/graphviz.rs | 23 +++++++++++++++++++ 10 files changed, 85 insertions(+), 40 deletions(-) create mode 100644 src/test/mir-opt/graphviz.rs diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index dde88a212408d..ace5198deaf2e 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -633,10 +633,20 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, let body = tcx.hir().body(body_id); let cfg = cfg::CFG::new(tcx, &body); let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges; + let hir_id = code.id(); + // We have to disassemble the hir_id because name must be ASCII + // alphanumeric. This does not appear in the rendered graph, so it does not + // have to be user friendly. + let name = format!( + "hir_id_{}_{}_{}", + hir_id.owner.address_space().index(), + hir_id.owner.as_array_index(), + hir_id.local_id.index(), + ); let lcfg = LabelledCFG { tcx, cfg: &cfg, - name: format!("node_{}", code.id()), + name, labelled_edges, }; diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c4e371d5afedb..551f18b95fe52 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -156,7 +156,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let mut flow_inits = FlowAtLocation::new(do_dataflow( tcx, mir, - id, + def_id, &attributes, &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &mdpe), @@ -191,7 +191,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let flow_borrows = FlowAtLocation::new(do_dataflow( tcx, mir, - id, + def_id, &attributes, &dead_unwinds, Borrows::new(tcx, mir, regioncx.clone(), &borrow_set), @@ -200,7 +200,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let flow_uninits = FlowAtLocation::new(do_dataflow( tcx, mir, - id, + def_id, &attributes, &dead_unwinds, MaybeUninitializedPlaces::new(tcx, mir, &mdpe), @@ -209,7 +209,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let flow_ever_inits = FlowAtLocation::new(do_dataflow( tcx, mir, - id, + def_id, &attributes, &dead_unwinds, EverInitializedPlaces::new(tcx, mir, &mdpe), diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index da9cc118f5521..d68377681f1ca 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -1,6 +1,6 @@ //! Hook into libgraphviz for rendering dataflow graphs for MIR. -use rustc::hir::HirId; +use rustc::hir::def_id::DefId; use rustc::mir::{BasicBlock, Mir}; use std::fs; @@ -8,13 +8,15 @@ use std::io; use std::marker::PhantomData; use std::path::Path; +use crate::util::graphviz_safe_def_name; + use super::{BitDenotation, DataflowState}; use super::DataflowBuilder; use super::DebugFormatted; pub trait MirWithFlowState<'tcx> { type BD: BitDenotation<'tcx>; - fn hir_id(&self) -> HirId; + fn def_id(&self) -> DefId; fn mir(&self) -> &Mir<'tcx>; fn flow_state(&self) -> &DataflowState<'tcx, Self::BD>; } @@ -23,7 +25,7 @@ impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation<'tcx> { type BD = BD; - fn hir_id(&self) -> HirId { self.hir_id } + fn def_id(&self) -> DefId { self.def_id } fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() } fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> { &self.flow_state.flow_state } } @@ -47,8 +49,8 @@ pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>( let g = Graph { mbcx, phantom: PhantomData, render_idx }; let mut v = Vec::new(); dot::render(&g, &mut v)?; - debug!("print_borrowck_graph_to path: {} hir_id: {}", - path.display(), mbcx.hir_id); + debug!("print_borrowck_graph_to path: {} def_id: {:?}", + path.display(), mbcx.def_id); fs::write(path, v) } @@ -69,9 +71,8 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> type Node = Node; type Edge = Edge; fn graph_id(&self) -> dot::Id<'_> { - dot::Id::new(format!("graph_for_node_{}", - self.mbcx.hir_id())) - .unwrap() + let name = graphviz_safe_def_name(self.mbcx.def_id()); + dot::Id::new(format!("graph_for_def_id_{}", name)).unwrap() } fn node_id(&self, n: &Node) -> dot::Id<'_> { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 03f8ac6743617..d0035bf7d3bc2 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -4,7 +4,7 @@ use rustc_data_structures::bit_set::{BitSet, BitSetOperator, HybridBitSet}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::work_queue::WorkQueue; -use rustc::hir::HirId; +use rustc::hir::def_id::DefId; use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator}; use rustc::mir::traversal; @@ -39,7 +39,7 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation<'tcx> { - hir_id: HirId, + def_id: DefId, flow_state: DataflowAnalysis<'a, 'tcx, BD>, print_preflow_to: Option, print_postflow_to: Option, @@ -117,7 +117,7 @@ pub struct MoveDataParamEnv<'gcx, 'tcx> { pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, - hir_id: HirId, + def_id: DefId, attributes: &[ast::Attribute], dead_unwinds: &BitSet, bd: BD, @@ -127,14 +127,14 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>, P: Fn(&BD, BD::Idx) -> DebugFormatted { let flow_state = DataflowAnalysis::new(mir, dead_unwinds, bd); - flow_state.run(tcx, hir_id, attributes, p) + flow_state.run(tcx, def_id, attributes, p) } impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation<'tcx> { pub(crate) fn run

(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - hir_id: HirId, + def_id: DefId, attributes: &[ast::Attribute], p: P) -> DataflowResults<'tcx, BD> where P: Fn(&BD, BD::Idx) -> DebugFormatted @@ -159,7 +159,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitD name_found(tcx.sess, attributes, "borrowck_graphviz_postflow"); let mut mbcx = DataflowBuilder { - hir_id, + def_id, print_preflow_to, print_postflow_to, flow_state: self, }; diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 32c027d90a0ce..3b0db48a94f18 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -28,7 +28,7 @@ impl MirPass for ElaborateDrops { { debug!("elaborate_drops({:?} @ {:?})", src, mir.span); - let id = tcx.hir().as_local_hir_id(src.def_id()).unwrap(); + let def_id = src.def_id(); let param_env = tcx.param_env(src.def_id()).with_reveal_all(); let move_data = match MoveData::gather_moves(mir, tcx) { Ok(move_data) => move_data, @@ -50,13 +50,13 @@ impl MirPass for ElaborateDrops { move_data, param_env, }; - let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env); + let dead_unwinds = find_dead_unwinds(tcx, mir, def_id, &env); let flow_inits = - do_dataflow(tcx, mir, id, &[], &dead_unwinds, + do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); let flow_uninits = - do_dataflow(tcx, mir, id, &[], &dead_unwinds, + do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, MaybeUninitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); @@ -80,7 +80,7 @@ impl MirPass for ElaborateDrops { fn find_dead_unwinds<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, - id: hir::HirId, + def_id: hir::def_id::DefId, env: &MoveDataParamEnv<'tcx, 'tcx>) -> BitSet { @@ -89,7 +89,7 @@ fn find_dead_unwinds<'a, 'tcx>( // reach cleanup blocks, which can't have unwind edges themselves. let mut dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); let flow_inits = - do_dataflow(tcx, mir, id, &[], &dead_unwinds, + do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 1f59802f8c6c0..98dcc3a16f209 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -383,13 +383,13 @@ fn locals_live_across_suspend_points( FxHashMap, ) { let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); - let hir_id = tcx.hir().as_local_hir_id(source.def_id()).unwrap(); + let def_id = source.def_id(); // Calculate when MIR locals have live storage. This gives us an upper bound of their // lifetimes. let storage_live_analysis = MaybeStorageLive::new(mir); let storage_live = - do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, storage_live_analysis, + do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, storage_live_analysis, |bd, p| DebugFormatted::new(&bd.mir().local_decls[p])); // Find the MIR locals which do not use StorageLive/StorageDead statements. @@ -403,7 +403,7 @@ fn locals_live_across_suspend_points( let borrowed_locals = if !movable { let analysis = HaveBeenBorrowedLocals::new(mir); let result = - do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, analysis, + do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, analysis, |bd, p| DebugFormatted::new(&bd.mir().local_decls[p])); Some((analysis, result)) } else { diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index f9f8abbe6c065..246f876235d71 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -3,7 +3,7 @@ use syntax::ast; use syntax_pos::Span; use rustc::ty::{self, TyCtxt}; -use rustc::hir; +use rustc::hir::def_id::DefId; use rustc::mir::{self, Mir, Location}; use rustc_data_structures::bit_set::BitSet; use crate::transform::{MirPass, MirSource}; @@ -27,7 +27,6 @@ impl MirPass for SanityCheck { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource<'tcx>, mir: &mut Mir<'tcx>) { let def_id = src.def_id(); - let id = tcx.hir().as_local_hir_id(def_id).unwrap(); if !tcx.has_attr(def_id, "rustc_mir") { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); return; @@ -41,26 +40,26 @@ impl MirPass for SanityCheck { let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); let flow_inits = - do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_uninits = - do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds, MaybeUninitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_def_inits = - do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds, DefinitelyInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() { - sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits); + sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_inits); } if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() { - sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits); + sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_uninits); } if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() { - sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits); + sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_def_inits); } if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() { tcx.sess.fatal("stop_after_dataflow ended compilation"); @@ -86,12 +85,12 @@ impl MirPass for SanityCheck { /// errors are not intended to be used for unit tests.) pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, - id: hir::HirId, + def_id: DefId, _attributes: &[ast::Attribute], results: &DataflowResults<'tcx, O>) where O: BitDenotation<'tcx, Idx=MovePathIndex> + HasMoveData<'tcx> { - debug!("sanity_check_via_rustc_peek id: {:?}", id); + debug!("sanity_check_via_rustc_peek def_id: {:?}", def_id); // FIXME: this is not DRY. Figure out way to abstract this and // `dataflow::build_sets`. (But note it is doing non-standard // stuff, so such generalization may not be realistic.) diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index 69a2adcfce026..f87714b58c442 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -1,6 +1,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::*; use rustc::ty::TyCtxt; +use rustc_data_structures::indexed_vec::Idx; use std::fmt::Debug; use std::io::{self, Write}; @@ -20,6 +21,17 @@ pub fn write_mir_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, Ok(()) } +// Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so +// it does not have to be user friendly. +pub fn graphviz_safe_def_name(def_id: DefId) -> String { + format!( + "{}_{}_{}", + def_id.krate.index(), + def_id.index.address_space().index(), + def_id.index.as_array_index(), + ) +} + /// Write a graphviz DOT graph of the MIR. pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, def_id: DefId, @@ -27,7 +39,7 @@ pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, w: &mut W) -> io::Result<()> where W: Write { - writeln!(w, "digraph Mir_{} {{", tcx.hir().as_local_hir_id(def_id).unwrap())?; + writeln!(w, "digraph Mir_{} {{", graphviz_safe_def_name(def_id))?; // Global graph properties writeln!(w, r#" graph [fontname="monospace"];"#)?; diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs index 29614a33f8e27..1a5a2a92247dd 100644 --- a/src/librustc_mir/util/mod.rs +++ b/src/librustc_mir/util/mod.rs @@ -15,7 +15,7 @@ pub mod collect_writes; pub use self::alignment::is_disaligned; pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere}; -pub use self::graphviz::{write_mir_graphviz}; +pub use self::graphviz::{graphviz_safe_def_name, write_mir_graphviz}; pub use self::graphviz::write_node_label as write_graphviz_node_label; /// If possible, suggest replacing `ref` with `ref mut`. diff --git a/src/test/mir-opt/graphviz.rs b/src/test/mir-opt/graphviz.rs new file mode 100644 index 0000000000000..660576996e5d4 --- /dev/null +++ b/src/test/mir-opt/graphviz.rs @@ -0,0 +1,23 @@ +// Test graphviz output +// compile-flags: -Z dump-mir-graphviz + +// ignore-tidy-linelength + +fn main() {} + +// END RUST SOURCE +// START rustc.main.mir_map.0.dot +// digraph Mir_0_0_3 { // The name here MUST be an ASCII identifier. +// graph [fontname="monospace"]; +// node [fontname="monospace"]; +// edge [fontname="monospace"]; +// label=>; +// bb0 [shape="none", label=<
0
_0 = ()
goto
+// >]; +// bb1 [shape="none", label=<
1
resume
+// >]; +// bb2 [shape="none", label=<
2
return
+// >]; +// bb0 -> bb2 [label=""]; +// } +// END rustc.main.mir_map.0.dot From 30d5dc9a0ac48b7fae1e5ca79987fa004b00eec1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 19 Mar 2019 21:32:17 +0300 Subject: [PATCH 5/9] Do not encode gensymed imports in metadata --- src/librustc_resolve/build_reduced_graph.rs | 4 ++-- src/librustc_resolve/resolve_imports.rs | 6 ++++-- src/libsyntax_pos/symbol.rs | 4 ++++ src/test/ui/imports/auxiliary/gensymed.rs | 3 +++ src/test/ui/imports/gensymed.rs | 7 +++++++ 5 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/imports/auxiliary/gensymed.rs create mode 100644 src/test/ui/imports/gensymed.rs diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 6fad4b2db9713..f312ef216822d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -303,7 +303,7 @@ impl<'a> Resolver<'a> { } // Empty groups `a::b::{}` are turned into synthetic `self` imports - // `a::b::c::{self as _}`, so that their prefixes are correctly + // `a::b::c::{self as __dummy}`, so that their prefixes are correctly // resolved and checked for privacy/stability/etc. if items.is_empty() && !empty_for_self(&prefix) { let new_span = prefix[prefix.len() - 1].ident.span; @@ -312,7 +312,7 @@ impl<'a> Resolver<'a> { Ident::new(keywords::SelfLower.name(), new_span) ), kind: ast::UseTreeKind::Simple( - Some(Ident::new(keywords::Underscore.name().gensymed(), new_span)), + Some(Ident::new(Name::gensym("__dummy"), new_span)), ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID, ), diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 9daffd522bf2c..bda59c6c46c8b 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1295,9 +1295,11 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { None => continue, }; - // Filter away "empty import canaries" and ambiguous imports. + // Filter away ambiguous and gensymed imports. Gensymed imports + // (e.g. implicitly injected `std`) cannot be properly encoded in metadata, + // so they can cause name conflict errors downstream. let is_good_import = binding.is_import() && !binding.is_ambiguity() && - binding.vis != ty::Visibility::Invisible; + !(ident.name.is_gensymed() && ident.name != "_"); if is_good_import || binding.is_macro_def() { let def = binding.def(); if def != Def::Err { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index e8d215a562e2c..f61aa4284d29b 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -179,6 +179,10 @@ impl Symbol { with_interner(|interner| interner.gensymed(self)) } + pub fn is_gensymed(self) -> bool { + with_interner(|interner| interner.is_gensymed(self)) + } + pub fn as_str(self) -> LocalInternedString { with_interner(|interner| unsafe { LocalInternedString { diff --git a/src/test/ui/imports/auxiliary/gensymed.rs b/src/test/ui/imports/auxiliary/gensymed.rs new file mode 100644 index 0000000000000..bbb19f5ec6519 --- /dev/null +++ b/src/test/ui/imports/auxiliary/gensymed.rs @@ -0,0 +1,3 @@ +// edition:2018 + +mod std {} diff --git a/src/test/ui/imports/gensymed.rs b/src/test/ui/imports/gensymed.rs new file mode 100644 index 0000000000000..317441079ff87 --- /dev/null +++ b/src/test/ui/imports/gensymed.rs @@ -0,0 +1,7 @@ +// compile-pass +// edition:2018 +// aux-build:gensymed.rs + +extern crate gensymed; + +fn main() {} From 830c98d7fa4da9381d3ee9c8b918bc5dff11c378 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 16 Mar 2019 18:07:58 +0100 Subject: [PATCH 6/9] Fix undefined behavior in hint::spin_loop for x86 targets without SSE2 The pause instruction requires SSE2 but was being unconditionally used on targets without it, resulting in undefined behavior. This PR fixes that by only using the pause intrinsic if SSE2 is available. It also removes the inline assembly which was not required since these instructions are available in core::arch, and extends support of the spin_loop hint to arm targets with the v6 feature which also support the yield instruction. Closes #59237 . --- src/libcore/hint.rs | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 89de5c1bc8af8..b2f82ef0d175c 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -62,13 +62,32 @@ pub unsafe fn unreachable_unchecked() -> ! { #[inline] #[unstable(feature = "renamed_spin_loop", issue = "55002")] pub fn spin_loop() { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - unsafe { - asm!("pause" ::: "memory" : "volatile"); + #[cfg( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse2" + ) + )] { + #[cfg(target_arch = "x86")] { + unsafe { crate::arch::x86::_mm_pause() }; + } + + #[cfg(target_arch = "x86_64")] { + unsafe { crate::arch::x86_64::_mm_pause() }; + } } - #[cfg(target_arch = "aarch64")] - unsafe { - asm!("yield" ::: "memory" : "volatile"); + #[cfg( + any( + target_arch = "aarch64", + all(target_arch = "arm", target_feature = "v6") + ) + )] { + #[cfg(target_arch = "aarch64")] { + unsafe { crate::arch::aarch64::__yield() }; + } + #[cfg(target_arch = "arm")] { + unsafe { crate::arch::arm::__yield() }; + } } } From f94f85bebde816d78d8a7e6d8ebb75b2a254593c Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 22 Mar 2019 01:49:42 +0000 Subject: [PATCH 7/9] Fix ICE with const generic param in struct --- src/librustc_resolve/lib.rs | 44 ++++++++++++------- .../struct-with-invalid-const-param.rs | 6 +++ .../struct-with-invalid-const-param.stderr | 15 +++++++ 3 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/const-generics/struct-with-invalid-const-param.rs create mode 100644 src/test/ui/const-generics/struct-with-invalid-const-param.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ac149be4b2a89..c9b9898fb4132 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -814,7 +814,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { debug!("(resolving function) entering function"); let (rib_kind, asyncness) = match function_kind { FnKind::ItemFn(_, ref header, ..) => - (ItemRibKind, header.asyncness.node), + (FnItemRibKind, header.asyncness.node), FnKind::Method(_, ref sig, _, _) => (TraitOrImplItemRibKind, sig.header.asyncness.node), FnKind::Closure(_) => @@ -950,6 +950,10 @@ enum RibKind<'a> { /// upvars). TraitOrImplItemRibKind, + /// We passed through a function definition. Disallow upvars. + /// Permit only those const parameters specified in the function's generics. + FnItemRibKind, + /// We passed through an item scope. Disallow upvars. ItemRibKind, @@ -3863,7 +3867,7 @@ impl<'a> Resolver<'a> { seen.insert(node_id, depth); } } - ItemRibKind | TraitOrImplItemRibKind => { + ItemRibKind | FnItemRibKind | TraitOrImplItemRibKind => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. @@ -3897,7 +3901,7 @@ impl<'a> Resolver<'a> { ConstantItemRibKind => { // Nothing to do. Continue. } - ItemRibKind => { + ItemRibKind | FnItemRibKind => { // This was an attempt to use a type parameter outside its scope. if record_used { resolve_error( @@ -3912,21 +3916,27 @@ impl<'a> Resolver<'a> { } } Def::ConstParam(..) => { - // A const param is always declared in a signature, which is always followed by - // some kind of function rib kind (specifically, ItemRibKind in the case of a - // normal function), so we can skip the first rib as it will be guaranteed to - // (spuriously) conflict with the const param. - for rib in &ribs[1..] { - if let ItemRibKind = rib.kind { - // This was an attempt to use a const parameter outside its scope. - if record_used { - resolve_error( - self, - span, - ResolutionError::GenericParamsFromOuterFunction(def), - ); + let mut ribs = ribs.iter().peekable(); + if let Some(Rib { kind: FnItemRibKind, .. }) = ribs.peek() { + // When declaring const parameters inside function signatures, the first rib + // is always a `FnItemRibKind`. In this case, we can skip it, to avoid it + // (spuriously) conflicting with the const param. + ribs.next(); + } + for rib in ribs { + match rib.kind { + ItemRibKind | FnItemRibKind => { + // This was an attempt to use a const parameter outside its scope. + if record_used { + resolve_error( + self, + span, + ResolutionError::GenericParamsFromOuterFunction(def), + ); + } + return Def::Err; } - return Def::Err; + _ => {} } } } diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.rs b/src/test/ui/const-generics/struct-with-invalid-const-param.rs new file mode 100644 index 0000000000000..207b07bf69514 --- /dev/null +++ b/src/test/ui/const-generics/struct-with-invalid-const-param.rs @@ -0,0 +1,6 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct S(C); //~ ERROR expected type, found const parameter + +fn main() {} diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr new file mode 100644 index 0000000000000..561464b21cc8f --- /dev/null +++ b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr @@ -0,0 +1,15 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/struct-with-invalid-const-param.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + +error[E0573]: expected type, found const parameter `C` + --> $DIR/struct-with-invalid-const-param.rs:4:23 + | +LL | struct S(C); + | ^ help: a struct with a similar name exists: `S` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0573`. From 8d3dd39d885f427faf3898521e7e1e9319d76b91 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 22 Mar 2019 17:08:06 -0500 Subject: [PATCH 8/9] Correct minimum system LLVM version in tests Since commit 9452a8dfa3ba, the new debug info format is only generated for LLVM 8 and newer versions. However, the tests still assume that LLVM 7 will use the new debug info format. Fix the tests (and a comment in the code) to match the actual version check. --- src/librustc_codegen_llvm/debuginfo/metadata.rs | 8 +++++--- src/test/codegen/enum-debug-clike.rs | 2 +- src/test/codegen/enum-debug-niche-2.rs | 2 +- src/test/codegen/enum-debug-niche.rs | 2 +- src/test/codegen/enum-debug-tagged.rs | 2 +- src/test/debuginfo/borrowed-enum.rs | 2 +- .../debuginfo/generic-enum-with-different-disr-sizes.rs | 2 +- src/test/debuginfo/generic-struct-style-enum.rs | 2 +- src/test/debuginfo/generic-tuple-style-enum.rs | 2 +- src/test/debuginfo/recursive-struct.rs | 2 +- src/test/debuginfo/struct-style-enum.rs | 2 +- src/test/debuginfo/tuple-style-enum.rs | 2 +- src/test/debuginfo/unique-enum.rs | 2 +- 13 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index ddcbf29da832b..8efa025e3dd9d 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1156,12 +1156,14 @@ fn prepare_union_metadata( // Enums //=----------------------------------------------------------------------------- -// DWARF variant support is only available starting in LLVM 7. +// DWARF variant support is only available starting in LLVM 8. // Although the earlier enum debug info output did not work properly // in all situations, it is better for the time being to continue to // sometimes emit the old style rather than emit something completely -// useless when rust is compiled against LLVM 6 or older. This -// function decides which representation will be emitted. +// useless when rust is compiled against LLVM 6 or older. LLVM 7 +// contains an early version of the DWARF variant support, and will +// crash when handling the new debug info format. This function +// decides which representation will be emitted. fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool { // On MSVC we have to use the fallback mode, because LLVM doesn't // lower variant parts to PDB. diff --git a/src/test/codegen/enum-debug-clike.rs b/src/test/codegen/enum-debug-clike.rs index 62cfef5a845e9..f268c8bcbccdb 100644 --- a/src/test/codegen/enum-debug-clike.rs +++ b/src/test/codegen/enum-debug-clike.rs @@ -4,7 +4,7 @@ // ignore-tidy-linelength // ignore-windows -// min-system-llvm-version 7.0 +// min-system-llvm-version 8.0 // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/codegen/enum-debug-niche-2.rs b/src/test/codegen/enum-debug-niche-2.rs index 369fa1fcfda7b..aa6cbf66b4aa3 100644 --- a/src/test/codegen/enum-debug-niche-2.rs +++ b/src/test/codegen/enum-debug-niche-2.rs @@ -4,7 +4,7 @@ // ignore-tidy-linelength // ignore-windows -// min-system-llvm-version 7.0 +// min-system-llvm-version 8.0 // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/codegen/enum-debug-niche.rs b/src/test/codegen/enum-debug-niche.rs index 1273a785ba42f..93eebde7b8f42 100644 --- a/src/test/codegen/enum-debug-niche.rs +++ b/src/test/codegen/enum-debug-niche.rs @@ -4,7 +4,7 @@ // ignore-tidy-linelength // ignore-windows -// min-system-llvm-version 7.0 +// min-system-llvm-version 8.0 // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/codegen/enum-debug-tagged.rs b/src/test/codegen/enum-debug-tagged.rs index 5c37e40c27032..84976ce97af4b 100644 --- a/src/test/codegen/enum-debug-tagged.rs +++ b/src/test/codegen/enum-debug-tagged.rs @@ -4,7 +4,7 @@ // ignore-tidy-linelength // ignore-windows -// min-system-llvm-version 7.0 +// min-system-llvm-version 8.0 // compile-flags: -g -C no-prepopulate-passes diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs index e27a31dd0e585..63c11f59c157d 100644 --- a/src/test/debuginfo/borrowed-enum.rs +++ b/src/test/debuginfo/borrowed-enum.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength // Require LLVM with DW_TAG_variant_part and a gdb or lldb that can read it. -// min-system-llvm-version: 7.0 +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs index 9392aa7097147..e26294cb730a0 100644 --- a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs +++ b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs @@ -3,7 +3,7 @@ // min-lldb-version: 310 // Require LLVM with DW_TAG_variant_part and a gdb that can read it. -// min-system-llvm-version: 7.0 +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // compile-flags:-g diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs index 3e593470303ea..3dc5cb807b452 100644 --- a/src/test/debuginfo/generic-struct-style-enum.rs +++ b/src/test/debuginfo/generic-struct-style-enum.rs @@ -2,7 +2,7 @@ // min-lldb-version: 310 // Require LLVM with DW_TAG_variant_part and a gdb that can read it. -// min-system-llvm-version: 7.0 +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // compile-flags:-g diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs index 3c136add07915..b16634ee6d7f9 100644 --- a/src/test/debuginfo/generic-tuple-style-enum.rs +++ b/src/test/debuginfo/generic-tuple-style-enum.rs @@ -2,7 +2,7 @@ // Require LLVM with DW_TAG_variant_part and a gdb and lldb that can // read it. -// min-system-llvm-version: 7.0 +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs index c3d2bea9139c0..8fb83b7956be3 100644 --- a/src/test/debuginfo/recursive-struct.rs +++ b/src/test/debuginfo/recursive-struct.rs @@ -2,7 +2,7 @@ // ignore-lldb // Require LLVM with DW_TAG_variant_part and a gdb that can read it. -// min-system-llvm-version: 7.0 +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // compile-flags:-g diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs index 1654c9320912f..5843b076b1f46 100644 --- a/src/test/debuginfo/struct-style-enum.rs +++ b/src/test/debuginfo/struct-style-enum.rs @@ -2,7 +2,7 @@ // Require LLVM with DW_TAG_variant_part and a gdb and lldb that can // read it. -// min-system-llvm-version: 7.0 +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs index fd76bcb0afc32..4d9727a388b8e 100644 --- a/src/test/debuginfo/tuple-style-enum.rs +++ b/src/test/debuginfo/tuple-style-enum.rs @@ -2,7 +2,7 @@ // Require LLVM with DW_TAG_variant_part and a gdb and lldb that can // read it. -// min-system-llvm-version: 7.0 +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // rust-lldb diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs index da0d06213e0ab..32bd93f1ed2ce 100644 --- a/src/test/debuginfo/unique-enum.rs +++ b/src/test/debuginfo/unique-enum.rs @@ -2,7 +2,7 @@ // Require LLVM with DW_TAG_variant_part and a gdb and lldb that can // read it. -// min-system-llvm-version: 7.0 +// min-system-llvm-version: 8.0 // min-gdb-version: 8.2 // rust-lldb From 5032643538da3e121a940438623adf820f95ae64 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 23 Mar 2019 13:05:36 +0000 Subject: [PATCH 9/9] Use `if let` instead of `match` --- src/librustc_resolve/lib.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c9b9898fb4132..6929d920219a2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -951,7 +951,7 @@ enum RibKind<'a> { TraitOrImplItemRibKind, /// We passed through a function definition. Disallow upvars. - /// Permit only those const parameters specified in the function's generics. + /// Permit only those const parameters that are specified in the function's generics. FnItemRibKind, /// We passed through an item scope. Disallow upvars. @@ -3924,19 +3924,16 @@ impl<'a> Resolver<'a> { ribs.next(); } for rib in ribs { - match rib.kind { - ItemRibKind | FnItemRibKind => { - // This was an attempt to use a const parameter outside its scope. - if record_used { - resolve_error( - self, - span, - ResolutionError::GenericParamsFromOuterFunction(def), - ); - } - return Def::Err; + if let ItemRibKind | FnItemRibKind = rib.kind { + // This was an attempt to use a const parameter outside its scope. + if record_used { + resolve_error( + self, + span, + ResolutionError::GenericParamsFromOuterFunction(def), + ); } - _ => {} + return Def::Err; } } }