From a0df4204c49975d3a5fb9c3a6562d49faf130b01 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 17 Oct 2018 15:51:10 +0200 Subject: [PATCH 01/16] Implement FromStr for PathBuf Initially landed in https://github.com/rust-lang/rust/pull/48292 and reverted in https://github.com/rust-lang/rust/pull/50401. This time, use `std::string::ParseError` as suggested in https://github.com/rust-lang/rust/issues/44431#issuecomment-428112632 --- src/libstd/path.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index ca8be75fab5be..a153456370c6f 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -87,6 +87,8 @@ use io; use iter::{self, FusedIterator}; use ops::{self, Deref}; use rc::Rc; +use str::FromStr; +use string::ParseError; use sync::Arc; use ffi::{OsStr, OsString}; @@ -1443,6 +1445,15 @@ impl From for PathBuf { } } +#[stable(feature = "path_from_str", since = "1.26.0")] +impl FromStr for PathBuf { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + Ok(PathBuf::from(s)) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl> iter::FromIterator

for PathBuf { fn from_iter>(iter: I) -> PathBuf { From ac186354354e6032c34ad95ce22d526371729cb6 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 21 Oct 2018 23:54:35 +0200 Subject: [PATCH 02/16] Add MaybeUninit::new Sometimes it *is* initialized! --- src/libcore/lib.rs | 1 + src/libcore/mem.rs | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 59cc312bee5fc..1eded42683073 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -82,6 +82,7 @@ #![feature(const_fn)] #![feature(const_int_ops)] #![feature(const_fn_union)] +#![feature(const_manually_drop_new)] #![feature(custom_attribute)] #![feature(doc_cfg)] #![feature(doc_spotlight)] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 27ee9556bd089..a955e0e662a6c 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1021,6 +1021,15 @@ pub union MaybeUninit { } impl MaybeUninit { + /// Create a new `MaybeUninit` initialized with the given value. + /// + /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. + /// It is your responsibility to make sure `T` gets dropped if it got initialized. + #[unstable(feature = "maybe_uninit", issue = "53491")] + pub const fn new(val: T) -> MaybeUninit { + MaybeUninit { value: ManuallyDrop::new(val) } + } + /// Create a new `MaybeUninit` in an uninitialized state. /// /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. From 412ad9bf3746bd0682db136c36a433f3205715f1 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Sun, 21 Oct 2018 20:09:42 -0700 Subject: [PATCH 03/16] Allow extern statics with an extern type Fixes #55239 --- src/librustc_typeck/check/wfcheck.rs | 42 +++++++++++++++--------- src/test/ui/static/static-extern-type.rs | 37 +++++++++++++++++++++ 2 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/static/static-extern-type.rs diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ec773e384af38..ec6ca242fa36b 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -13,7 +13,7 @@ use constrained_type_params::{identify_constrained_type_params, Parameter}; use hir::def_id::DefId; use rustc::traits::{self, ObligationCauseCode}; -use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; +use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable}; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::util::ExplicitSelf; use rustc::util::nodemap::{FxHashSet, FxHashMap}; @@ -119,14 +119,14 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def check_item_fn(tcx, item); } hir::ItemKind::Static(ref ty, ..) => { - check_item_type(tcx, item.id, ty.span); + check_item_type(tcx, item.id, ty.span, false); } hir::ItemKind::Const(ref ty, ..) => { - check_item_type(tcx, item.id, ty.span); + check_item_type(tcx, item.id, ty.span, false); } hir::ItemKind::ForeignMod(ref module) => for it in module.items.iter() { if let hir::ForeignItemKind::Static(ref ty, ..) = it.node { - check_item_type(tcx, it.id, ty.span); + check_item_type(tcx, it.id, ty.span, true); } }, hir::ItemKind::Struct(ref struct_def, ref ast_generics) => { @@ -340,23 +340,35 @@ fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { }) } -fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId, ty_span: Span) { +fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + ty_span: Span, + allow_foreign_ty: bool) { debug!("check_item_type: {:?}", item_id); for_id(tcx, item_id, ty_span).with_fcx(|fcx, _this| { let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item_id)); let item_ty = fcx.normalize_associated_types_in(ty_span, &ty); - fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); - fcx.register_bound( - item_ty, - fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new( - ty_span, - fcx.body_id, - traits::MiscObligation, - ), - ); + let mut allow_unsized = false; + if allow_foreign_ty { + if let TyKind::Foreign(_) = tcx.struct_tail(item_ty).sty { + allow_unsized = true; + } + } + + if !allow_unsized { + fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); + fcx.register_bound( + item_ty, + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), + traits::ObligationCause::new( + ty_span, + fcx.body_id, + traits::MiscObligation, + ), + ); + } vec![] // no implied bounds in a const etc }); diff --git a/src/test/ui/static/static-extern-type.rs b/src/test/ui/static/static-extern-type.rs new file mode 100644 index 0000000000000..72e2853b9f038 --- /dev/null +++ b/src/test/ui/static/static-extern-type.rs @@ -0,0 +1,37 @@ +// Copyright 2018 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. + +// compile-pass +#![feature(extern_types)] + +pub mod a { + extern "C" { + pub type StartFn; + pub static start: StartFn; + } +} + +pub mod b { + #[repr(transparent)] + pub struct TransparentType(::a::StartFn); + extern "C" { + pub static start: TransparentType; + } +} + +pub mod c { + #[repr(C)] + pub struct CType(u32, ::b::TransparentType); + extern "C" { + pub static start: CType; + } +} + +fn main() {} From 5b84550d7c39821704a48b53c8cbe3916ab100b7 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Mon, 22 Oct 2018 07:03:53 -0700 Subject: [PATCH 04/16] Keep an obligation for both sized and unsized types --- src/librustc_typeck/check/wfcheck.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ec6ca242fa36b..f21296a2a0772 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -340,33 +340,31 @@ fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) { }) } -fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item_id: ast::NodeId, - ty_span: Span, - allow_foreign_ty: bool) { +fn check_item_type<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + ty_span: Span, + allow_foreign_ty: bool, +) { debug!("check_item_type: {:?}", item_id); for_id(tcx, item_id, ty_span).with_fcx(|fcx, _this| { let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item_id)); let item_ty = fcx.normalize_associated_types_in(ty_span, &ty); - let mut allow_unsized = false; + let mut forbid_unsized = true; if allow_foreign_ty { if let TyKind::Foreign(_) = tcx.struct_tail(item_ty).sty { - allow_unsized = true; + forbid_unsized = false; } } - if !allow_unsized { - fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); + fcx.register_wf_obligation(item_ty, ty_span, ObligationCauseCode::MiscObligation); + if forbid_unsized { fcx.register_bound( item_ty, fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), - traits::ObligationCause::new( - ty_span, - fcx.body_id, - traits::MiscObligation, - ), + traits::ObligationCause::new(ty_span, fcx.body_id, traits::MiscObligation), ); } From 37e1d2975e1002f0718552554055647392e46f0d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 20 Oct 2018 16:18:17 -0400 Subject: [PATCH 05/16] Don't rerun Mir passes when inlining When inlining a function using the Mir inliner, we shouldn't rerun the various Mir passes on it because the Mir has already been lowered and that wil break various early Mir passes. The issue in #50411 is that we've inlined a function with promotions whose Mir has already been lowered. The promotions are then copied into the local function and we begin to run passes on their lowered Mir which causes the ICE. Fixes #50411 --- src/librustc/mir/mod.rs | 29 +++++++++++++++++++++++++++++ src/librustc_mir/transform/mod.rs | 25 ++++++++++++++++++++----- src/test/ui/issues/issue-50411.rs | 11 +++++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/issues/issue-50411.rs diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 34fc81a495e24..797836f166173 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -69,6 +69,17 @@ impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> { } } +/// The various "big phases" that MIR goes through. +/// +/// Warning: ordering of variants is significant +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum MirPhase { + Build, + Const, + Validated, + Optimized, +} + /// Lowered representation of a single function. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Mir<'tcx> { @@ -76,6 +87,13 @@ pub struct Mir<'tcx> { /// that indexes into this vector. basic_blocks: IndexVec>, + /// Records how far through the "desugaring and optimization" process this particular + /// MIR has traversed. This is particularly useful when inlining, since in that context + /// we instantiate the promoted constants and add them to our promoted vector -- but those + /// promoted items have already been optimized, whereas ours have not. This field allows + /// us to see the difference and forego optimization on the inlined promoted items. + pub phase: MirPhase, + /// List of source scopes; these are referenced by statements /// and used for debuginfo. Indexed by a `SourceScope`. pub source_scopes: IndexVec, @@ -151,6 +169,7 @@ impl<'tcx> Mir<'tcx> { ); Mir { + phase: MirPhase::Build, basic_blocks, source_scopes, source_scope_local_data, @@ -368,6 +387,7 @@ pub enum Safety { } impl_stable_hash_for!(struct Mir<'tcx> { + phase, basic_blocks, source_scopes, source_scope_local_data, @@ -616,6 +636,13 @@ impl_stable_hash_for!(enum self::ImplicitSelfKind { None }); +impl_stable_hash_for!(enum self::MirPhase { + Build, + Const, + Validated, + Optimized, +}); + mod binding_form_impl { use ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; @@ -2777,6 +2804,7 @@ pub enum ClosureOutlivesSubject<'tcx> { CloneTypeFoldableAndLiftImpls! { BlockTailInfo, + MirPhase, Mutability, SourceInfo, UpvarDecl, @@ -2789,6 +2817,7 @@ CloneTypeFoldableAndLiftImpls! { BraceStructTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> { + phase, basic_blocks, source_scopes, source_scope_local_data, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index d18836999dccf..61e150ea12a22 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -11,7 +11,7 @@ use borrow_check::nll::type_check; use build; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc::mir::{Mir, Promoted}; +use rustc::mir::{Mir, MirPhase, Promoted}; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; use rustc::ty::steal::Steal; @@ -155,9 +155,22 @@ pub trait MirPass { mir: &mut Mir<'tcx>); } -pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $($pass:expr,)*) {{ +pub macro run_passes( + $tcx:ident, + $mir:ident, + $def_id:ident, + $suite_index:expr, + $mir_phase:expr; + $($pass:expr,)* +) {{ let suite_index: usize = $suite_index; let run_passes = |mir: &mut _, promoted| { + let mir: &mut Mir<'_> = mir; + + if mir.phase >= $mir_phase { + return; + } + let source = MirSource { def_id: $def_id, promoted @@ -175,6 +188,8 @@ pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $ index += 1; }; $(run_pass(&$pass);)* + + mir.phase = $mir_phase; }; run_passes(&mut $mir, None); @@ -192,7 +207,7 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea let _ = tcx.unsafety_check_result(def_id); let mut mir = tcx.mir_built(def_id).steal(); - run_passes![tcx, mir, def_id, 0; + run_passes![tcx, mir, def_id, 0, MirPhase::Const; // Remove all `EndRegion` statements that are not involved in borrows. cleanup_post_borrowck::CleanEndRegions, @@ -214,7 +229,7 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } let mut mir = tcx.mir_const(def_id).steal(); - run_passes![tcx, mir, def_id, 1; + run_passes![tcx, mir, def_id, 1, MirPhase::Validated; // What we need to run borrowck etc. qualify_consts::QualifyAndPromoteConstants, simplify::SimplifyCfg::new("qualify-consts"), @@ -232,7 +247,7 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } let mut mir = tcx.mir_validated(def_id).steal(); - run_passes![tcx, mir, def_id, 2; + run_passes![tcx, mir, def_id, 2, MirPhase::Optimized; // Remove all things not needed by analysis no_landing_pads::NoLandingPads, simplify_branches::SimplifyBranches::new("initial"), diff --git a/src/test/ui/issues/issue-50411.rs b/src/test/ui/issues/issue-50411.rs new file mode 100644 index 0000000000000..1ba47d3b932ef --- /dev/null +++ b/src/test/ui/issues/issue-50411.rs @@ -0,0 +1,11 @@ +// Regression test for #50411: the MIR inliner was causing problems +// here because it would inline promoted code (which had already had +// elaborate-drops invoked on it) and then try to elaboate drops a +// second time. Uncool. + +// compile-flags:-Zmir-opt-level=3 +// compile-pass + +fn main() { + let _ = (0 .. 1).filter(|_| [1].iter().all(|_| true)).count(); +} From 895a4b2d45e6d5c274bcd561391b2cc6a73dd2c5 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 21 Oct 2018 10:47:01 -0400 Subject: [PATCH 06/16] Remove the `suite_index` parameter of the `run_passes!()` macro This can be obtained via the `$mir_phase` value. --- src/librustc/mir/mod.rs | 12 ++++++++++++ src/librustc_mir/transform/mod.rs | 12 ++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 797836f166173..e53def65886de 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -80,6 +80,18 @@ pub enum MirPhase { Optimized, } +impl MirPhase { + /// Gets the index of the current MirPhase within the set of all MirPhases. + pub fn phase_index(&self) -> usize { + match self { + MirPhase::Build => 0, + MirPhase::Const => 1, + MirPhase::Validated => 2, + MirPhase::Optimized => 3, + } + } +} + /// Lowered representation of a single function. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Mir<'tcx> { diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 61e150ea12a22..ff85d780a4ce3 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -159,11 +159,11 @@ pub macro run_passes( $tcx:ident, $mir:ident, $def_id:ident, - $suite_index:expr, $mir_phase:expr; $($pass:expr,)* ) {{ - let suite_index: usize = $suite_index; + let phase_index = $mir_phase.phase_index(); + let run_passes = |mir: &mut _, promoted| { let mir: &mut Mir<'_> = mir; @@ -178,7 +178,7 @@ pub macro run_passes( let mut index = 0; let mut run_pass = |pass: &dyn MirPass| { let run_hooks = |mir: &_, index, is_after| { - dump_mir::on_mir_pass($tcx, &format_args!("{:03}-{:03}", suite_index, index), + dump_mir::on_mir_pass($tcx, &format_args!("{:03}-{:03}", phase_index, index), &pass.name(), source, mir, is_after); }; run_hooks(mir, index, false); @@ -207,7 +207,7 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea let _ = tcx.unsafety_check_result(def_id); let mut mir = tcx.mir_built(def_id).steal(); - run_passes![tcx, mir, def_id, 0, MirPhase::Const; + run_passes![tcx, mir, def_id, MirPhase::Const; // Remove all `EndRegion` statements that are not involved in borrows. cleanup_post_borrowck::CleanEndRegions, @@ -229,7 +229,7 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } let mut mir = tcx.mir_const(def_id).steal(); - run_passes![tcx, mir, def_id, 1, MirPhase::Validated; + run_passes![tcx, mir, def_id, MirPhase::Validated; // What we need to run borrowck etc. qualify_consts::QualifyAndPromoteConstants, simplify::SimplifyCfg::new("qualify-consts"), @@ -247,7 +247,7 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } let mut mir = tcx.mir_validated(def_id).steal(); - run_passes![tcx, mir, def_id, 2, MirPhase::Optimized; + run_passes![tcx, mir, def_id, MirPhase::Optimized; // Remove all things not needed by analysis no_landing_pads::NoLandingPads, simplify_branches::SimplifyBranches::new("initial"), From c535147f291fee0c79553eabcd520156707cd0d4 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 22 Oct 2018 22:41:21 -0400 Subject: [PATCH 07/16] Replace the `run_passes!` macro with a regular function As suggested in the feedback for #55244. When I replaced the macro with a function, rustc started complaining that there were two unused functions so I also removed those. --- src/librustc_mir/dataflow/impls/borrows.rs | 1 - src/librustc_mir/dataflow/mod.rs | 14 --- src/librustc_mir/transform/mod.rs | 134 ++++++++++----------- 3 files changed, 67 insertions(+), 82 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index f7043487c51a6..cfccb950e8276 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -184,7 +184,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { } crate fn borrows(&self) -> &IndexVec> { &self.borrow_set.borrows } - pub fn scope_tree(&self) -> &Lrc { &self.scope_tree } pub fn location(&self, idx: BorrowIndex) -> &Location { &self.borrow_set.borrows[idx].reserve_location diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index da4bd780eb4fa..c19145636e6da 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -724,20 +724,6 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation } } } - - pub fn new_from_sets(mir: &'a Mir<'tcx>, - dead_unwinds: &'a BitSet, - sets: AllSets, - denotation: D) -> Self { - DataflowAnalysis { - mir, - dead_unwinds, - flow_state: DataflowState { - sets: sets, - operator: denotation, - } - } - } } impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index ff85d780a4ce3..28b7d517da6c9 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -155,68 +155,68 @@ pub trait MirPass { mir: &mut Mir<'tcx>); } -pub macro run_passes( - $tcx:ident, - $mir:ident, - $def_id:ident, - $mir_phase:expr; - $($pass:expr,)* -) {{ - let phase_index = $mir_phase.phase_index(); - - let run_passes = |mir: &mut _, promoted| { - let mir: &mut Mir<'_> = mir; - - if mir.phase >= $mir_phase { +pub fn run_passes( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &mut Mir<'tcx>, + def_id: DefId, + mir_phase: MirPhase, + passes: &[&dyn MirPass]) { + let phase_index = mir_phase.phase_index(); + + let run_passes = |mir: &mut Mir<'tcx>, promoted| { + if mir.phase >= mir_phase { return; } let source = MirSource { - def_id: $def_id, - promoted + def_id, + promoted, }; let mut index = 0; let mut run_pass = |pass: &dyn MirPass| { let run_hooks = |mir: &_, index, is_after| { - dump_mir::on_mir_pass($tcx, &format_args!("{:03}-{:03}", phase_index, index), + dump_mir::on_mir_pass(tcx, &format_args!("{:03}-{:03}", phase_index, index), &pass.name(), source, mir, is_after); }; run_hooks(mir, index, false); - pass.run_pass($tcx, source, mir); + pass.run_pass(tcx, source, mir); run_hooks(mir, index, true); index += 1; }; - $(run_pass(&$pass);)* - mir.phase = $mir_phase; + for pass in passes { + run_pass(*pass); + } + + mir.phase = mir_phase; }; - run_passes(&mut $mir, None); + run_passes(mir, None); - for (index, promoted_mir) in $mir.promoted.iter_enumerated_mut() { + for (index, promoted_mir) in mir.promoted.iter_enumerated_mut() { run_passes(promoted_mir, Some(index)); - // Let's make sure we don't miss any nested instances - assert!(promoted_mir.promoted.is_empty()); + //Let's make sure we don't miss any nested instances + assert!(promoted_mir.promoted.is_empty()) } -}} +} fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal> { // Unsafety check uses the raw mir, so make sure it is run let _ = tcx.unsafety_check_result(def_id); let mut mir = tcx.mir_built(def_id).steal(); - run_passes![tcx, mir, def_id, MirPhase::Const; + run_passes(tcx, &mut mir, def_id, MirPhase::Const, &[ // Remove all `EndRegion` statements that are not involved in borrows. - cleanup_post_borrowck::CleanEndRegions, + &cleanup_post_borrowck::CleanEndRegions, // What we need to do constant evaluation. - simplify::SimplifyCfg::new("initial"), - type_check::TypeckMir, - rustc_peek::SanityCheck, - uniform_array_move_out::UniformArrayMoveOut, - ]; + &simplify::SimplifyCfg::new("initial"), + &type_check::TypeckMir, + &rustc_peek::SanityCheck, + &uniform_array_move_out::UniformArrayMoveOut, + ]); tcx.alloc_steal_mir(mir) } @@ -229,11 +229,11 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } let mut mir = tcx.mir_const(def_id).steal(); - run_passes![tcx, mir, def_id, MirPhase::Validated; + run_passes(tcx, &mut mir, def_id, MirPhase::Validated, &[ // What we need to run borrowck etc. - qualify_consts::QualifyAndPromoteConstants, - simplify::SimplifyCfg::new("qualify-consts"), - ]; + &qualify_consts::QualifyAndPromoteConstants, + &simplify::SimplifyCfg::new("qualify-consts"), + ]); tcx.alloc_steal_mir(mir) } @@ -247,59 +247,59 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } let mut mir = tcx.mir_validated(def_id).steal(); - run_passes![tcx, mir, def_id, MirPhase::Optimized; + run_passes(tcx, &mut mir, def_id, MirPhase::Optimized, &[ // Remove all things not needed by analysis - no_landing_pads::NoLandingPads, - simplify_branches::SimplifyBranches::new("initial"), - remove_noop_landing_pads::RemoveNoopLandingPads, + &no_landing_pads::NoLandingPads, + &simplify_branches::SimplifyBranches::new("initial"), + &remove_noop_landing_pads::RemoveNoopLandingPads, // Remove all `AscribeUserType` statements. - cleanup_post_borrowck::CleanAscribeUserType, + &cleanup_post_borrowck::CleanAscribeUserType, // Remove all `FakeRead` statements and the borrows that are only // used for checking matches - cleanup_post_borrowck::CleanFakeReadsAndBorrows, - simplify::SimplifyCfg::new("early-opt"), + &cleanup_post_borrowck::CleanFakeReadsAndBorrows, + &simplify::SimplifyCfg::new("early-opt"), // These next passes must be executed together - add_call_guards::CriticalCallEdges, - elaborate_drops::ElaborateDrops, - no_landing_pads::NoLandingPads, + &add_call_guards::CriticalCallEdges, + &elaborate_drops::ElaborateDrops, + &no_landing_pads::NoLandingPads, // AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs // an AllCallEdges pass right before it. - add_call_guards::AllCallEdges, - add_validation::AddValidation, + &add_call_guards::AllCallEdges, + &add_validation::AddValidation, // AddMovesForPackedDrops needs to run after drop // elaboration. - add_moves_for_packed_drops::AddMovesForPackedDrops, + &add_moves_for_packed_drops::AddMovesForPackedDrops, - simplify::SimplifyCfg::new("elaborate-drops"), + &simplify::SimplifyCfg::new("elaborate-drops"), // No lifetime analysis based on borrowing can be done from here on out. // From here on out, regions are gone. - erase_regions::EraseRegions, + &erase_regions::EraseRegions, - lower_128bit::Lower128Bit, + &lower_128bit::Lower128Bit, // Optimizations begin. - uniform_array_move_out::RestoreSubsliceArrayMoveOut, - inline::Inline, + &uniform_array_move_out::RestoreSubsliceArrayMoveOut, + &inline::Inline, // Lowering generator control-flow and variables // has to happen before we do anything else to them. - generator::StateTransform, - - instcombine::InstCombine, - const_prop::ConstProp, - simplify_branches::SimplifyBranches::new("after-const-prop"), - deaggregator::Deaggregator, - copy_prop::CopyPropagation, - remove_noop_landing_pads::RemoveNoopLandingPads, - simplify::SimplifyCfg::new("final"), - simplify::SimplifyLocals, - - add_call_guards::CriticalCallEdges, - dump_mir::Marker("PreCodegen"), - ]; + &generator::StateTransform, + + &instcombine::InstCombine, + &const_prop::ConstProp, + &simplify_branches::SimplifyBranches::new("after-const-prop"), + &deaggregator::Deaggregator, + ©_prop::CopyPropagation, + &remove_noop_landing_pads::RemoveNoopLandingPads, + &simplify::SimplifyCfg::new("final"), + &simplify::SimplifyLocals, + + &add_call_guards::CriticalCallEdges, + &dump_mir::Marker("PreCodegen"), + ]); tcx.alloc_mir(mir) } From 4655866a11ddb345c84781cf4e292e99e26ee9fe Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 25 Oct 2018 08:35:53 -0400 Subject: [PATCH 08/16] Fix CR feedback --- src/librustc/mir/mod.rs | 15 +++++---------- src/librustc_mir/transform/mod.rs | 3 ++- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index e53def65886de..f9da40b583899 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -74,21 +74,16 @@ impl<'tcx> HasLocalDecls<'tcx> for Mir<'tcx> { /// Warning: ordering of variants is significant #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum MirPhase { - Build, - Const, - Validated, - Optimized, + Build = 0, + Const = 1, + Validated = 2, + Optimized = 3, } impl MirPhase { /// Gets the index of the current MirPhase within the set of all MirPhases. pub fn phase_index(&self) -> usize { - match self { - MirPhase::Build => 0, - MirPhase::Const => 1, - MirPhase::Validated => 2, - MirPhase::Optimized => 3, - } + *self as usize } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 28b7d517da6c9..46c73c27fe10d 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -160,7 +160,8 @@ pub fn run_passes( mir: &mut Mir<'tcx>, def_id: DefId, mir_phase: MirPhase, - passes: &[&dyn MirPass]) { + passes: &[&dyn MirPass], +) { let phase_index = mir_phase.phase_index(); let run_passes = |mir: &mut Mir<'tcx>, promoted| { From c674802aac1a8d8cc3e78938a192067617aa286e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9ven=20Car?= Date: Tue, 23 Oct 2018 19:59:18 +0200 Subject: [PATCH 09/16] Remove unnecessary mut in iterator.find_map documentation example, Relates to #49098 --- src/libcore/iter/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 5b6d9e2033caa..2903c370df898 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1857,7 +1857,7 @@ pub trait Iterator { /// ``` /// let a = ["lol", "NaN", "2", "5"]; /// - /// let mut first_number = a.iter().find_map(|s| s.parse().ok()); + /// let first_number = a.iter().find_map(|s| s.parse().ok()); /// /// assert_eq!(first_number, Some(2)); /// ``` From b9bd2a60085acfc046365bab4cfa009cb6b9b773 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 19 Oct 2018 12:46:16 +0200 Subject: [PATCH 10/16] Impl items have generics --- src/librustc/util/ppaux.rs | 14 +++----------- src/librustc_mir/const_eval.rs | 7 +++++++ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 709b844526529..abdd7fd8d40bf 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -251,25 +251,17 @@ impl PrintContext { fn parameterized(&mut self, f: &mut F, substs: &subst::Substs<'_>, - mut did: DefId, + did: DefId, projections: &[ty::ProjectionPredicate<'_>]) -> fmt::Result { let key = ty::tls::with(|tcx| tcx.def_key(did)); - let mut item_name = if let Some(name) = key.disambiguated_data.data.get_opt_name() { - Some(name) - } else { - did.index = key.parent.unwrap_or_else( - || bug!("finding type for {:?}, encountered def-id {:?} with no parent", - did, did)); - self.parameterized(f, substs, did, projections)?; - return write!(f, "::{}", key.disambiguated_data.data.as_interned_str()); - }; let verbose = self.is_verbose; let mut num_supplied_defaults = 0; let mut has_self = false; let mut own_counts: GenericParamCount = Default::default(); let mut is_value_path = false; + let mut item_name = Some(key.disambiguated_data.data.as_interned_str()); let fn_trait_kind = ty::tls::with(|tcx| { // Unfortunately, some kinds of items (e.g., closures) don't have // generics. So walk back up the find the closest parent that DOES @@ -282,6 +274,7 @@ impl PrintContext { DefPathData::AssocTypeInImpl(_) | DefPathData::AssocExistentialInImpl(_) | DefPathData::Trait(_) | + DefPathData::Impl | DefPathData::TypeNs(_) => { break; } @@ -292,7 +285,6 @@ impl PrintContext { } DefPathData::CrateRoot | DefPathData::Misc | - DefPathData::Impl | DefPathData::Module(_) | DefPathData::MacroDef(_) | DefPathData::ClosureExpr | diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 362fbc4b1355b..d92001704285a 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -612,6 +612,13 @@ pub fn const_eval_raw_provider<'a, 'tcx>( other => return other, } } + // the first trace is for replicating an ice + // There's no tracking issue, but the next two lines concatenated link to the discussion on + // zulip. It's not really possible to test this, because it doesn't show up in diagnostics + // or MIR. + // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/ + // subject/anon_const_instance_printing/near/135980032 + trace!("const eval: {}", key.value.instance); trace!("const eval: {:?}", key); let cid = key.value; From 5a48f20bd9eacbca5f0e87022605791cd651935c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 19 Oct 2018 14:24:29 +0200 Subject: [PATCH 11/16] Update tests --- src/test/mir-opt/end_region_4.rs | 2 +- src/test/mir-opt/end_region_5.rs | 2 +- src/test/mir-opt/end_region_6.rs | 2 +- src/test/mir-opt/end_region_7.rs | 2 +- src/test/mir-opt/end_region_8.rs | 2 +- src/test/mir-opt/end_region_destruction_extents_1.rs | 8 ++++---- src/test/mir-opt/packed-struct-drop-aligned.rs | 2 +- src/test/ui/issues/issue-21554.stderr | 2 +- src/test/ui/issues/issue-35241.stderr | 2 +- src/test/ui/namespace/namespace-mix.stderr | 8 ++++---- src/test/ui/privacy/private-inferred-type-3.rs | 4 ++-- src/test/ui/privacy/private-inferred-type-3.stderr | 4 ++-- src/test/ui/privacy/private-inferred-type.rs | 4 ++-- src/test/ui/privacy/private-inferred-type.stderr | 4 ++-- 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs index 359ed07a9c095..3d15f20bd05f3 100644 --- a/src/test/mir-opt/end_region_4.rs +++ b/src/test/mir-opt/end_region_4.rs @@ -44,7 +44,7 @@ fn foo(i: i32) { // let mut _5: i32; // bb0: { // StorageLive(_1); -// _1 = D::{{constructor}}(const 0i32,); +// _1 = D(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_2); // _2 = const 0i32; diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs index 3b632e198cd66..06d1fbabe1616 100644 --- a/src/test/mir-opt/end_region_5.rs +++ b/src/test/mir-opt/end_region_5.rs @@ -37,7 +37,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let mut _4: &'18s D; // bb0: { // StorageLive(_1); -// _1 = D::{{constructor}}(const 0i32,); +// _1 = D(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_3); // StorageLive(_4); diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs index 03c7de02ec111..d0db23e6de0ee 100644 --- a/src/test/mir-opt/end_region_6.rs +++ b/src/test/mir-opt/end_region_6.rs @@ -37,7 +37,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let mut _4: &'24s D; // bb0: { // StorageLive(_1); -// _1 = D::{{constructor}}(const 0i32,); +// _1 = D(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_3); // StorageLive(_4); diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs index 56e3e0aa6f7a9..c7df440ebe2f3 100644 --- a/src/test/mir-opt/end_region_7.rs +++ b/src/test/mir-opt/end_region_7.rs @@ -36,7 +36,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let mut _3: [closure@NodeId(33) d:D]; // bb0: { // StorageLive(_1); -// _1 = D::{{constructor}}(const 0i32,); +// _1 = D(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_3); // _3 = [closure@NodeId(33)] { d: move _1 }; diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs index 0a54dcaa0d33f..9f2a9c3b72e8b 100644 --- a/src/test/mir-opt/end_region_8.rs +++ b/src/test/mir-opt/end_region_8.rs @@ -39,7 +39,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let mut _4: [closure@NodeId(33) r:&'24s D]; // bb0: { // StorageLive(_1); -// _1 = D::{{constructor}}(const 0i32,); +// _1 = D(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_2); // _2 = &'26_1rs _1; diff --git a/src/test/mir-opt/end_region_destruction_extents_1.rs b/src/test/mir-opt/end_region_destruction_extents_1.rs index a5107d304386f..eb381dfc5521f 100644 --- a/src/test/mir-opt/end_region_destruction_extents_1.rs +++ b/src/test/mir-opt/end_region_destruction_extents_1.rs @@ -79,16 +79,16 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // StorageLive(_3); // StorageLive(_4); // StorageLive(_5); -// _5 = S1::{{constructor}}(const "ex1",); +// _5 = S1(const "ex1",); // _4 = &'15ds _5; // _3 = &'15ds (*_4); // StorageLive(_6); // StorageLive(_7); // StorageLive(_8); -// _8 = S1::{{constructor}}(const "dang1",); +// _8 = S1(const "dang1",); // _7 = &'13s _8; // _6 = &'13s (*_7); -// _2 = D1<'15ds, '13s>::{{constructor}}(move _3, move _6); +// _2 = D1<'15ds, '13s>(move _3, move _6); // EndRegion('13s); // StorageDead(_6); // StorageDead(_3); @@ -132,7 +132,7 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // StorageLive(_7); // _7 = &'13s (promoted[0]: S1); // _6 = &'13s (*_7); -// _2 = D1<'15ds, '13s>::{{constructor}}(move _3, move _6); +// _2 = D1<'15ds, '13s>(move _3, move _6); // EndRegion('13s); // StorageDead(_6); // StorageDead(_3); diff --git a/src/test/mir-opt/packed-struct-drop-aligned.rs b/src/test/mir-opt/packed-struct-drop-aligned.rs index 9441c6f4085a2..1fe29a29e2318 100644 --- a/src/test/mir-opt/packed-struct-drop-aligned.rs +++ b/src/test/mir-opt/packed-struct-drop-aligned.rs @@ -42,7 +42,7 @@ impl Drop for Droppy { // bb0: { // StorageLive(_1); // ... -// _1 = Packed::{{constructor}}(move _2,); +// _1 = Packed(move _2,); // ... // StorageLive(_6); // _6 = move (_1.0: Aligned); diff --git a/src/test/ui/issues/issue-21554.stderr b/src/test/ui/issues/issue-21554.stderr index be7762f1aa245..104970ea448aa 100644 --- a/src/test/ui/issues/issue-21554.stderr +++ b/src/test/ui/issues/issue-21554.stderr @@ -1,4 +1,4 @@ -error[E0606]: casting `fn(i32) -> Inches {Inches::{{constructor}}}` as `f32` is invalid +error[E0606]: casting `fn(i32) -> Inches {Inches}` as `f32` is invalid --> $DIR/issue-21554.rs:14:5 | LL | Inches as f32; diff --git a/src/test/ui/issues/issue-35241.stderr b/src/test/ui/issues/issue-35241.stderr index 42bf0aae5b12c..4404f88de311b 100644 --- a/src/test/ui/issues/issue-35241.stderr +++ b/src/test/ui/issues/issue-35241.stderr @@ -9,7 +9,7 @@ LL | fn test() -> Foo { Foo } //~ ERROR mismatched types | expected `Foo` because of return type | = note: expected type `Foo` - found type `fn(u32) -> Foo {Foo::{{constructor}}}` + found type `fn(u32) -> Foo {Foo}` error: aborting due to previous error diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index 6d72b6044aebe..0a297e58574f7 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -144,11 +144,11 @@ note: required by `check` LL | fn check(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `fn() -> c::TS {c::TS::{{constructor}}}: Impossible` is not satisfied +error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfied --> $DIR/namespace-mix.rs:66:5 | LL | check(m3::TS); //~ ERROR c::TS - | ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS::{{constructor}}}` + | ^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}` | note: required by `check` --> $DIR/namespace-mix.rs:31:1 @@ -192,11 +192,11 @@ note: required by `check` LL | fn check(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::TS::{{constructor}}}: Impossible` is not satisfied +error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}: Impossible` is not satisfied --> $DIR/namespace-mix.rs:72:5 | LL | check(xm3::TS); //~ ERROR c::TS - | ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS::{{constructor}}}` + | ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}` | note: required by `check` --> $DIR/namespace-mix.rs:31:1 diff --git a/src/test/ui/privacy/private-inferred-type-3.rs b/src/test/ui/privacy/private-inferred-type-3.rs index 0c393f02323ec..5151f624b8d98 100644 --- a/src/test/ui/privacy/private-inferred-type-3.rs +++ b/src/test/ui/privacy/private-inferred-type-3.rs @@ -14,8 +14,8 @@ // error-pattern:static `PRIV_STATIC` is private // error-pattern:type `ext::PrivEnum` is private // error-pattern:type `fn() {::method}` is private -// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct::{{constructor}}}` is pr -// error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv +// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private +// error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct}` is private // error-pattern:type `for<'r> fn(&'r ext::Pub) {>::priv_method}` is private #![feature(decl_macro)] diff --git a/src/test/ui/privacy/private-inferred-type-3.stderr b/src/test/ui/privacy/private-inferred-type-3.stderr index 3c37a7ee1e8d2..590ff76b375f2 100644 --- a/src/test/ui/privacy/private-inferred-type-3.stderr +++ b/src/test/ui/privacy/private-inferred-type-3.stderr @@ -30,7 +30,7 @@ LL | ext::m!(); | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct::{{constructor}}}` is private +error: type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private --> $DIR/private-inferred-type-3.rs:26:5 | LL | ext::m!(); @@ -38,7 +38,7 @@ LL | ext::m!(); | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is private +error: type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct}` is private --> $DIR/private-inferred-type-3.rs:26:5 | LL | ext::m!(); diff --git a/src/test/ui/privacy/private-inferred-type.rs b/src/test/ui/privacy/private-inferred-type.rs index 3ca8b1eb2ed3a..58e17b24394a1 100644 --- a/src/test/ui/privacy/private-inferred-type.rs +++ b/src/test/ui/privacy/private-inferred-type.rs @@ -53,9 +53,9 @@ mod m { ::method; //~ ERROR type `fn() {::method}` is private ::method; // OK PrivTupleStruct; - //~^ ERROR type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct::{{constructor}}}` is priv + //~^ ERROR type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct}` is private PubTupleStruct; - //~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct::{{constructor}}}` is privat + //~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct}` is private Pub(0u8).priv_method(); //~^ ERROR type `for<'r> fn(&'r m::Pub) {>::priv_method}` is private } diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr index abbe43fe384cb..1ab281cfc2515 100644 --- a/src/test/ui/privacy/private-inferred-type.stderr +++ b/src/test/ui/privacy/private-inferred-type.stderr @@ -115,7 +115,7 @@ LL | ::method; //~ ERROR type `fn() { m::PrivTupleStruct {m::PrivTupleStruct::{{constructor}}}` is private +error: type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct}` is private --> $DIR/private-inferred-type.rs:55:9 | LL | PrivTupleStruct; @@ -124,7 +124,7 @@ LL | PrivTupleStruct; LL | m::m!(); | -------- in this macro invocation -error: type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct::{{constructor}}}` is private +error: type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct}` is private --> $DIR/private-inferred-type.rs:57:9 | LL | PubTupleStruct; From 4cb611f3d1287526b99e9de93f7f034ab60947cd Mon Sep 17 00:00:00 2001 From: Hsiang-Cheng Yang Date: Sat, 27 Oct 2018 14:33:07 +0800 Subject: [PATCH 12/16] Update string.rs remove unused variable i in example String::with_capacity() --- src/liballoc/string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index ab3f8fc270720..ff3587d5d8730 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -413,7 +413,7 @@ impl String { /// /// // These are all done without reallocating... /// let cap = s.capacity(); - /// for i in 0..10 { + /// for _ in 0..10 { /// s.push('a'); /// } /// From c04893afbb1bccc2ceeccdd7b7f46e5cb5dc126d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 27 Oct 2018 13:34:35 +0200 Subject: [PATCH 13/16] Fix an ICE in the min_const_fn analysis --- .../transform/qualify_min_const_fn.rs | 5 +++-- src/test/ui/consts/single_variant_match_ice.rs | 15 +++++++++++++++ .../ui/consts/single_variant_match_ice.stderr | 8 ++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/consts/single_variant_match_ice.rs create mode 100644 src/test/ui/consts/single_variant_match_ice.stderr diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 52c557b83d591..6ab68789c027b 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -317,7 +317,8 @@ fn check_terminator( check_place(tcx, mir, location, span, PlaceMode::Read)?; check_operand(tcx, mir, value, span) }, - TerminatorKind::SwitchInt { .. } => Err(( + + TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err(( span, "`if`, `match`, `&&` and `||` are not stable in const fn".into(), )), @@ -363,7 +364,7 @@ fn check_terminator( cleanup: _, } => check_operand(tcx, mir, cond, span), - | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => span_bug!( + | TerminatorKind::FalseUnwind { .. } => span_bug!( terminator.source_info.span, "min_const_fn encountered `{:#?}`", terminator diff --git a/src/test/ui/consts/single_variant_match_ice.rs b/src/test/ui/consts/single_variant_match_ice.rs new file mode 100644 index 0000000000000..67a41bc5dc4ad --- /dev/null +++ b/src/test/ui/consts/single_variant_match_ice.rs @@ -0,0 +1,15 @@ +enum Foo { + Prob, +} + +impl Foo { + pub const fn as_val(&self) -> u8 { + use self::Foo::*; + + match *self { + Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn + } + } +} + +fn main() {} diff --git a/src/test/ui/consts/single_variant_match_ice.stderr b/src/test/ui/consts/single_variant_match_ice.stderr new file mode 100644 index 0000000000000..a0222b0d489a4 --- /dev/null +++ b/src/test/ui/consts/single_variant_match_ice.stderr @@ -0,0 +1,8 @@ +error: `if`, `match`, `&&` and `||` are not stable in const fn + --> $DIR/single_variant_match_ice.rs:10:13 + | +LL | Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn + | ^^^^ + +error: aborting due to previous error + From 2fd378b82b14f2746462018e8510e15a079818a0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 19 Oct 2018 01:34:46 +0200 Subject: [PATCH 14/16] Fix sub-variant doc display --- src/librustdoc/html/render.rs | 17 ++++++++--------- src/librustdoc/html/static/main.js | 17 ++++++++++------- src/librustdoc/html/static/rustdoc.css | 22 +++++++++++++++++++++- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 8b35ede4a02c0..0fc2473725a16 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3379,10 +3379,10 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, let variant_id = cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.as_ref().unwrap())); - write!(w, "", + write!(w, "", id = variant_id)?; - write!(w, "

Fields of {name}

\n - ", name = variant.name.as_ref().unwrap())?; + write!(w, "

Fields of {name}

", + name = variant.name.as_ref().unwrap())?; for field in &s.fields { use clean::StructFieldItem; if let StructFieldItem(ref ty) = field.inner { @@ -3394,19 +3394,18 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, ItemType::Variant.name_space(), field.name.as_ref().unwrap(), ItemType::StructField.name_space())); - write!(w, "
")?; } } - write!(w, "
\ - ", + write!(w, "\ + \ + ", id = id, ns_id = ns_id, f = field.name.as_ref().unwrap(), t = *ty)?; document(w, cx, field)?; - write!(w, "
")?; + write!(w, "")?; } render_stability_since(w, variant, it)?; } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 9d1a5c3837830..02229b82b8ac3 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1886,7 +1886,7 @@ if (hasClass(relatedDoc, "stability")) { relatedDoc = relatedDoc.nextElementSibling; } - if (hasClass(relatedDoc, "docblock")) { + if (hasClass(relatedDoc, "docblock") || hasClass(relatedDoc, "sub-variant")) { var action = mode; if (action === "toggle") { if (hasClass(relatedDoc, "hidden-by-usual-hider")) { @@ -2094,15 +2094,13 @@ } var hideItemDeclarations = getCurrentValue('rustdoc-item-declarations') === "false"; - onEach(document.getElementsByClassName('docblock'), function(e) { + function buildToggleWrapper(e) { if (hasClass(e, 'autohide')) { var wrap = e.previousElementSibling; if (wrap && hasClass(wrap, 'toggle-wrapper')) { var toggle = wrap.childNodes[0]; - var extra = false; - if (e.childNodes[0].tagName === 'H3') { - extra = true; - } + var extra = e.childNodes[0].tagName === 'H3'; + e.style.display = 'none'; addClass(wrap, 'collapsed'); onEach(toggle.getElementsByClassName('inner'), function(e) { @@ -2127,6 +2125,8 @@ if (hideItemDeclarations === false) { extraClass = 'collapsed'; } + } else if (hasClass(e, "sub-variant")) { + otherMessage = ' Show fields'; } else if (hasClass(e, "non-exhaustive")) { otherMessage = ' This '; if (hasClass(e, "non-exhaustive-struct")) { @@ -2150,7 +2150,10 @@ collapseDocs(e.previousSibling.childNodes[0], "toggle"); } } - }); + } + + onEach(document.getElementsByClassName('docblock'), buildToggleWrapper); + onEach(document.getElementsByClassName('sub-variant'), buildToggleWrapper); function createToggleWrapper(tog) { var span = document.createElement('span'); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index c0951d9f8401e..8bcb828a5ade1 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -517,6 +517,10 @@ h4 > code, h3 > code, .invisible > code { margin-top: -13px; } +.sub-variant > div > .stability { + margin-top: initial; +} + .content .stability::before { content: '˪'; font-size: 30px; @@ -866,7 +870,23 @@ span.since { } .sub-variant, .sub-variant > h3 { - margin-top: 0 !important; + margin-top: 1px !important; +} + +#main > .sub-variant > h3 { + font-size: 15px; + margin-left: 25px; + margin-bottom: 5px; +} + +.sub-variant > div { + margin-left: 20px; + margin-bottom: 10px; +} + +.sub-variant > div > span { + display: block; + position: relative; } .toggle-label { From 0d06b8c8e59b0641e4487a720de933ffb1316196 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 18 Oct 2018 19:09:49 +0200 Subject: [PATCH 15/16] Add note linking to Rust 2018 path semantics docs. This commit extends existing path suggestions to link to documentation on the changed semantics of `use` in Rust 2018. --- src/librustc_resolve/error_reporting.rs | 25 ++++--- src/librustc_resolve/resolve_imports.rs | 65 +++++++++++++------ .../local-path-suggestions-2018.stderr | 2 + 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index def67923322aa..50ab8ef9c7be7 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -26,7 +26,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { span: Span, path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option> { + ) -> Option<(Vec, Option)> { debug!("make_path_suggestion: span={:?} path={:?}", span, path); // If we don't have a path to suggest changes to, then return. if path.is_empty() { @@ -65,13 +65,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { span: Span, mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option> { + ) -> Option<(Vec, Option)> { // Replace first ident with `self` and check if that is valid. path[0].ident.name = keywords::SelfValue.name(); let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some(path) + Some((path, None)) } else { None } @@ -89,13 +89,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { span: Span, mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option> { + ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = keywords::Crate.name(); let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some(path) + Some(( + path, + Some( + "`use` statements changed in Rust 2018; read more at \ + ".to_string() + ), + )) } else { None } @@ -113,13 +120,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { span: Span, mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option> { + ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = keywords::Super.name(); let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some(path) + Some((path, None)) } else { None } @@ -140,7 +147,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { span: Span, mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option> { + ) -> Option<(Vec, Option)> { // Need to clone else we can't call `resolve_path` without a borrow error. We also store // into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic) // each time. @@ -162,7 +169,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}", name, path, result); if let PathResult::Module(..) = result { - return Some(path) + return Some((path, None)); } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 3ca0a9f7f1b97..359640ccda2b1 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -707,7 +707,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } } }); - } else if let Some((span, err)) = error { + } else if let Some((span, err, note)) = error { errors = true; if let SingleImport { source, ref result, .. } = import.subclass { @@ -737,7 +737,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &import.subclass, span, ); - error_vec.push((span, path, err)); + error_vec.push((span, path, err, note)); seen_spans.insert(span); prev_root_id = import.root_id; } @@ -829,27 +829,45 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } } - fn throw_unresolved_import_error(&self, error_vec: Vec<(Span, String, String)>, - span: Option) { + fn throw_unresolved_import_error( + &self, + error_vec: Vec<(Span, String, String, Option)>, + span: Option, + ) { let max_span_label_msg_count = 10; // upper limit on number of span_label message. - let (span, msg) = if error_vec.is_empty() { - (span.unwrap(), "unresolved import".to_string()) + let (span, msg, note) = if error_vec.is_empty() { + (span.unwrap(), "unresolved import".to_string(), None) } else { - let span = MultiSpan::from_spans(error_vec.clone().into_iter() - .map(|elem: (Span, String, String)| { elem.0 }) - .collect()); + let span = MultiSpan::from_spans( + error_vec.clone().into_iter() + .map(|elem: (Span, String, String, Option)| elem.0) + .collect() + ); + + let note: Option = error_vec.clone().into_iter() + .filter_map(|elem: (Span, String, String, Option)| elem.3) + .last(); + let path_vec: Vec = error_vec.clone().into_iter() - .map(|elem: (Span, String, String)| { format!("`{}`", elem.1) }) + .map(|elem: (Span, String, String, Option)| format!("`{}`", elem.1)) .collect(); let path = path_vec.join(", "); - let msg = format!("unresolved import{} {}", - if path_vec.len() > 1 { "s" } else { "" }, path); - (span, msg) + let msg = format!( + "unresolved import{} {}", + if path_vec.len() > 1 { "s" } else { "" }, + path + ); + + (span, msg, note) }; + let mut err = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg); for span_error in error_vec.into_iter().take(max_span_label_msg_count) { err.span_label(span_error.0, span_error.2); } + if let Some(note) = note { + err.note(¬e); + } err.emit(); } @@ -945,7 +963,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } // If appropriate, returns an error to report. - fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> { + fn finalize_import( + &mut self, + directive: &'b ImportDirective<'b> + ) -> Option<(Span, String, Option)> { self.current_module = directive.parent_scope.module; let ImportDirective { ref module_path, span, .. } = *directive; @@ -969,15 +990,16 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { return None; } PathResult::Failed(span, msg, true) => { - return if let Some(suggested_path) = self.make_path_suggestion( + return if let Some((suggested_path, note)) = self.make_path_suggestion( span, module_path.clone(), &directive.parent_scope ) { Some(( span, - format!("Did you mean `{}`?", Segment::names_to_string(&suggested_path)) + format!("Did you mean `{}`?", Segment::names_to_string(&suggested_path)), + note, )) } else { - Some((span, msg)) + Some((span, msg, None)) }; }, _ => return None, @@ -1002,8 +1024,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { if let ModuleOrUniformRoot::Module(module) = module { if module.def_id() == directive.parent_scope.module.def_id() { // Importing a module into itself is not allowed. - return Some((directive.span, - "Cannot glob-import a module into itself.".to_string())); + return Some(( + directive.span, + "Cannot glob-import a module into itself.".to_string(), + None, + )); } } if !is_prelude && @@ -1101,7 +1126,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } } }; - Some((span, msg)) + Some((span, msg, None)) } else { // `resolve_ident_in_module` reported a privacy error. self.import_dummy_binding(directive); diff --git a/src/test/ui/rust-2018/local-path-suggestions-2018.stderr b/src/test/ui/rust-2018/local-path-suggestions-2018.stderr index 97bf748881f29..2293f4b001749 100644 --- a/src/test/ui/rust-2018/local-path-suggestions-2018.stderr +++ b/src/test/ui/rust-2018/local-path-suggestions-2018.stderr @@ -3,6 +3,8 @@ error[E0432]: unresolved import `foo` | LL | use foo::Bar; | ^^^ Did you mean `crate::foo`? + | + = note: `use` statements changed in Rust 2018; read more at error[E0432]: unresolved import `foo` --> $DIR/local-path-suggestions-2018.rs:27:5 From 0757c0fa7f37e1984492f4dce14b46dd686c67a9 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Sat, 27 Oct 2018 15:05:13 -0400 Subject: [PATCH 16/16] Add ManuallyDrop::take https://internals.rust-lang.org/t/mini-rfc-manuallydrop-take/8679 --- src/libcore/mem.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 27ee9556bd089..8e218fa5a4605 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -973,6 +973,26 @@ impl ManuallyDrop { pub fn into_inner(slot: ManuallyDrop) -> T { slot.value } + + /// Takes the contained value out. + /// + /// This method is primarily intended for moving out values in drop. + /// Instead of using [`ManuallyDrop::drop`] to manually drop the value, + /// you can use this method to take the value and use it however desired. + /// `Drop` will be invoked on the returned value following normal end-of-scope rules. + /// + /// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead. + /// + /// # Safety + /// + /// This function semantically moves out the contained value without preventing further usage. + /// It is up to the user of this method to ensure that this container is not used again. + #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] + #[unstable(feature = "manually_drop_take", issue = "55422")] + #[inline] + pub unsafe fn take(slot: &mut ManuallyDrop) -> T { + ManuallyDrop::into_inner(ptr::read(slot)) + } } impl ManuallyDrop {