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 51549f92d4db..1e3ccf90eb87 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 95b9dacf8565..da1afc2ff8aa 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 acca9748372c..b048a12e402a 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 04d646ea01d0..1e92b6f78787 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 000000000000..a54ec508c1be --- /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 dde88a212408..ace5198deaf2 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 c4e371d5afed..551f18b95fe5 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 da9cc118f552..d68377681f1c 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 03f8ac674361..d0035bf7d3bc 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 32c027d90a0c..3b0db48a94f1 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 1f59802f8c6c..98dcc3a16f20 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 f9f8abbe6c06..246f876235d7 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 69a2adcfce02..f87714b58c44 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 29614a33f8e2..1a5a2a92247d 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 000000000000..660576996e5d --- /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 6fad4b2db971..f312ef216822 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 9daffd522bf2..bda59c6c46c8 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 e8d215a562e2..f61aa4284d29 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 000000000000..bbb19f5ec651 --- /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 000000000000..317441079ff8 --- /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 89de5c1bc8af..b2f82ef0d175 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 ac149be4b2a8..c9b9898fb413 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 000000000000..207b07bf6951 --- /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 000000000000..561464b21cc8 --- /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 ddcbf29da832..8efa025e3dd9 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 62cfef5a845e..f268c8bcbccd 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 369fa1fcfda7..aa6cbf66b4aa 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 1273a785ba42..93eebde7b8f4 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 5c37e40c2703..84976ce97af4 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 e27a31dd0e58..63c11f59c157 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 9392aa709714..e26294cb730a 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 3e593470303e..3dc5cb807b45 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 3c136add0791..b16634ee6d7f 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 c3d2bea9139c..8fb83b7956be 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 1654c9320912..5843b076b1f4 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 fd76bcb0afc3..4d9727a388b8 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 da0d06213e0a..32bd93f1ed2c 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 c9b9898fb413..6929d920219a 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; } } }