From aab345794f4a657937881de75934a7c31064efeb Mon Sep 17 00:00:00 2001 From: Luca Gladiator Date: Sun, 3 May 2020 14:02:30 +0200 Subject: [PATCH 01/13] Make BTreeMap::new and BTreeSet::new const --- src/liballoc/collections/btree/map.rs | 3 ++- src/liballoc/collections/btree/set.rs | 3 ++- src/liballoc/lib.rs | 1 + src/test/ui/collections-const-new.rs | 9 +++++++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index c0b976565e41d..bc3411e57c513 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -556,7 +556,8 @@ impl BTreeMap { /// map.insert(1, "a"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> BTreeMap { + #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + pub const fn new() -> BTreeMap { BTreeMap { root: None, length: 0 } } diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index 9bf483f269f6e..dee5fb878ff2a 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -309,7 +309,8 @@ impl BTreeSet { /// let mut set: BTreeSet = BTreeSet::new(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> BTreeSet { + #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] + pub const fn new() -> BTreeSet { BTreeSet { map: BTreeMap::new() } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index ecec1fb039b33..5365c9d01684a 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -82,6 +82,7 @@ #![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] +#![feature(const_btree_new)] #![feature(const_generic_impls_guard)] #![feature(const_generics)] #![feature(const_in_array_repeat_expressions)] diff --git a/src/test/ui/collections-const-new.rs b/src/test/ui/collections-const-new.rs index a93f9a136db23..df980706087ae 100644 --- a/src/test/ui/collections-const-new.rs +++ b/src/test/ui/collections-const-new.rs @@ -3,9 +3,18 @@ // Test several functions can be used for constants // 1. Vec::new() // 2. String::new() +// 3. BTreeMap::new() +// 3. BTreeSet::new() + +#![feature(const_btree_new)] const MY_VEC: Vec = Vec::new(); const MY_STRING: String = String::new(); +use std::collections::{BTreeMap, BTreeSet}; +const MY_BTREEMAP: BTreeMap = BTreeMap::new(); + +const MY_BTREESET: BTreeSet = BTreeSet::new(); + fn main() {} From 1a439d286530a020bbf7683011f07227e236bd7f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 4 May 2020 11:52:15 -0700 Subject: [PATCH 02/13] Simplify the error Registry methods a little --- src/librustc_errors/registry.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/librustc_errors/registry.rs b/src/librustc_errors/registry.rs index 32700c6500bc8..b1d770d5bd523 100644 --- a/src/librustc_errors/registry.rs +++ b/src/librustc_errors/registry.rs @@ -10,12 +10,12 @@ pub struct Registry { impl Registry { pub fn new(long_descriptions: &[(&'static str, Option<&'static str>)]) -> Registry { - Registry { long_descriptions: long_descriptions.iter().cloned().collect() } + Registry { long_descriptions: long_descriptions.iter().copied().collect() } } /// This will panic if an invalid error code is passed in pub fn find_description(&self, code: &str) -> Option<&'static str> { - self.try_find_description(code).unwrap() + self.long_descriptions[code] } /// Returns `InvalidErrorCode` if the code requested does not exist in the /// registry. Otherwise, returns an `Option` where `None` means the error @@ -24,9 +24,6 @@ impl Registry { &self, code: &str, ) -> Result, InvalidErrorCode> { - if !self.long_descriptions.contains_key(code) { - return Err(InvalidErrorCode); - } - Ok(*self.long_descriptions.get(code).unwrap()) + self.long_descriptions.get(code).copied().ok_or(InvalidErrorCode) } } From 707cfd167236cf6bffb7bb60e98cd5eb44f678c7 Mon Sep 17 00:00:00 2001 From: LG3696 Date: Tue, 5 May 2020 10:08:02 +0200 Subject: [PATCH 03/13] Fix the numbering of the tests --- src/test/ui/collections-const-new.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/collections-const-new.rs b/src/test/ui/collections-const-new.rs index df980706087ae..978f25f9a9344 100644 --- a/src/test/ui/collections-const-new.rs +++ b/src/test/ui/collections-const-new.rs @@ -4,7 +4,7 @@ // 1. Vec::new() // 2. String::new() // 3. BTreeMap::new() -// 3. BTreeSet::new() +// 4. BTreeSet::new() #![feature(const_btree_new)] From a17234ca542f45028d846c7ec95c0a19d96df743 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 6 May 2020 10:30:11 +1000 Subject: [PATCH 04/13] Add `SourceInfo::outermost`. --- src/librustc_middle/mir/mod.rs | 16 ++++++++----- src/librustc_middle/mir/visit.rs | 16 ++++++------- src/librustc_mir/dataflow/framework/tests.rs | 2 +- src/librustc_mir/shim.rs | 11 ++++----- src/librustc_mir/transform/add_retag.rs | 8 +++---- src/librustc_mir/transform/check_unsafety.rs | 2 +- src/librustc_mir/transform/generator.rs | 24 ++++++++------------ src/librustc_mir/transform/promote_consts.rs | 4 ++-- src/librustc_mir/util/patch.rs | 2 +- src/librustc_mir_build/build/mod.rs | 11 +++------ src/librustc_mir_build/build/scope.rs | 2 +- 11 files changed, 45 insertions(+), 53 deletions(-) diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 8d416536155ac..e5f70d7ef9984 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -474,6 +474,13 @@ pub struct SourceInfo { pub scope: SourceScope, } +impl SourceInfo { + #[inline] + pub fn outermost(span: Span) -> Self { + SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE } + } +} + /////////////////////////////////////////////////////////////////////////// // Borrow kinds @@ -944,7 +951,7 @@ impl<'tcx> LocalDecl<'tcx> { mutability, ty, user_ty: UserTypeProjections::none(), - source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }, + source_info: SourceInfo::outermost(span), internal, local_info: LocalInfo::Other, is_block_tail: None, @@ -960,7 +967,7 @@ impl<'tcx> LocalDecl<'tcx> { mutability: Mutability::Mut, ty: return_ty, user_ty: UserTypeProjections::none(), - source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }, + source_info: SourceInfo::outermost(span), internal: false, is_block_tail: None, local_info: LocalInfo::Other, @@ -1406,10 +1413,7 @@ impl<'tcx> BasicBlockData<'tcx> { let mut gap = self.statements.len()..self.statements.len() + extra_stmts; self.statements.resize( gap.end, - Statement { - source_info: SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE }, - kind: StatementKind::Nop, - }, + Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop }, ); for (splice_start, new_stmts) in splices.into_iter().rev() { let splice_end = splice_start + new_stmts.size_hint().0; diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs index 97f7cccdb600b..2b6d44984bf53 100644 --- a/src/librustc_middle/mir/visit.rs +++ b/src/librustc_middle/mir/visit.rs @@ -242,10 +242,10 @@ macro_rules! make_mir_visitor { ) { let span = body.span; if let Some(yield_ty) = &$($mutability)? body.yield_ty { - self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo { - span, - scope: OUTERMOST_SOURCE_SCOPE, - })); + self.visit_ty( + yield_ty, + TyContext::YieldTy(SourceInfo::outermost(span)) + ); } // for best performance, we want to use an iterator rather @@ -263,10 +263,10 @@ macro_rules! make_mir_visitor { self.visit_source_scope_data(scope); } - self.visit_ty(&$($mutability)? body.return_ty(), TyContext::ReturnTy(SourceInfo { - span: body.span, - scope: OUTERMOST_SOURCE_SCOPE, - })); + self.visit_ty( + &$($mutability)? body.return_ty(), + TyContext::ReturnTy(SourceInfo::outermost(body.span)) + ); for local in body.local_decls.indices() { self.visit_local_decl(local, & $($mutability)? body.local_decls[local]); diff --git a/src/librustc_mir/dataflow/framework/tests.rs b/src/librustc_mir/dataflow/framework/tests.rs index a8dce7079b7a8..3ed0a9594e7d5 100644 --- a/src/librustc_mir/dataflow/framework/tests.rs +++ b/src/librustc_mir/dataflow/framework/tests.rs @@ -16,7 +16,7 @@ use crate::dataflow::BottomValue; /// This is the `Body` that will be used by the `MockAnalysis` below. The shape of its CFG is not /// important. fn mock_body() -> mir::Body<'static> { - let source_info = mir::SourceInfo { scope: mir::OUTERMOST_SOURCE_SCOPE, span: DUMMY_SP }; + let source_info = mir::SourceInfo::outermost(DUMMY_SP); let mut blocks = IndexVec::new(); let mut block = |n, kind| { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index dfa1bb764e47a..a58ac7cfe18af 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -146,12 +146,11 @@ enum CallKind { } fn temp_decl(mutability: Mutability, ty: Ty<'_>, span: Span) -> LocalDecl<'_> { - let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span }; LocalDecl { mutability, ty, user_ty: UserTypeProjections::none(), - source_info, + source_info: SourceInfo::outermost(span), internal: false, local_info: LocalInfo::Other, is_block_tail: None, @@ -185,7 +184,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) let sig = tcx.erase_late_bound_regions(&sig); let span = tcx.def_span(def_id); - let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; + let source_info = SourceInfo::outermost(span); let return_block = BasicBlock::new(1); let mut blocks = IndexVec::with_capacity(2); @@ -374,7 +373,7 @@ impl CloneShimBuilder<'tcx> { } fn source_info(&self) -> SourceInfo { - SourceInfo { span: self.span, scope: OUTERMOST_SOURCE_SCOPE } + SourceInfo::outermost(self.span) } fn block( @@ -687,7 +686,7 @@ fn build_call_shim<'tcx>( debug!("build_call_shim: sig={:?}", sig); let mut local_decls = local_decls_for_sig(&sig, span); - let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; + let source_info = SourceInfo::outermost(span); let rcvr_place = || { assert!(rcvr_adjustment.is_some()); @@ -849,7 +848,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { let local_decls = local_decls_for_sig(&sig, span); - let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; + let source_info = SourceInfo::outermost(span); let variant_index = if adt_def.is_enum() { adt_def.variant_index_with_ctor_id(ctor_id) diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index 6d5853def1e9c..baa3e5e1581c5 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -77,11 +77,9 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // PART 1 // Retag arguments at the beginning of the start block. { - let source_info = SourceInfo { - scope: OUTERMOST_SOURCE_SCOPE, - span, // FIXME: Consider using just the span covering the function - // argument declaration. - }; + // FIXME: Consider using just the span covering the function + // argument declaration. + let source_info = SourceInfo::outermost(span); // Gather all arguments, skip return value. let places = local_decls .iter_enumerated() diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index a8487be77def3..35726dde602da 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -50,7 +50,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { const_context, min_const_fn, violations: vec![], - source_info: SourceInfo { span: body.span, scope: OUTERMOST_SOURCE_SCOPE }, + source_info: SourceInfo::outermost(body.span), tcx, param_env, used_unsafe: Default::default(), diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 25804c2a62cfe..a9d566c92e935 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -261,7 +261,7 @@ impl TransformVisitor<'tcx> { let self_place = Place::from(SELF_ARG); let assign = Statement { - source_info: source_info(body), + source_info: SourceInfo::outermost(body.span), kind: StatementKind::Assign(box (temp, Rvalue::Discriminant(self_place))), }; (assign, temp) @@ -395,7 +395,7 @@ fn replace_local<'tcx>( body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>, ) -> Local { - let source_info = source_info(body); + let source_info = SourceInfo::outermost(body.span); let new_decl = LocalDecl { mutability: Mutability::Mut, ty, @@ -784,7 +784,7 @@ fn insert_switch<'tcx>( targets: cases.iter().map(|&(_, d)| d).chain(iter::once(default_block)).collect(), }; - let source_info = source_info(body); + let source_info = SourceInfo::outermost(body.span); body.basic_blocks_mut().raw.insert( 0, BasicBlockData { @@ -858,7 +858,7 @@ fn create_generator_drop_shim<'tcx>( let mut body = body.clone(); body.arg_count = 1; // make sure the resume argument is not included here - let source_info = source_info(&body); + let source_info = SourceInfo::outermost(body.span); let mut cases = create_cases(&mut body, transform, Operation::Drop); @@ -922,7 +922,7 @@ fn create_generator_drop_shim<'tcx>( } fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock { - let source_info = source_info(body); + let source_info = SourceInfo::outermost(body.span); body.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, kind }), @@ -948,7 +948,7 @@ fn insert_panic_block<'tcx>( cleanup: None, }; - let source_info = source_info(body); + let source_info = SourceInfo::outermost(body.span); body.basic_blocks_mut().push(BasicBlockData { statements: Vec::new(), terminator: Some(Terminator { source_info, kind: term }), @@ -1025,7 +1025,7 @@ fn create_generator_resume_function<'tcx>( // Poison the generator when it unwinds if can_unwind { - let source_info = source_info(body); + let source_info = SourceInfo::outermost(body.span); let poison_block = body.basic_blocks_mut().push(BasicBlockData { statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)], terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }), @@ -1092,10 +1092,6 @@ fn create_generator_resume_function<'tcx>( dump_mir(tcx, None, "generator_resume", &0, source, body, |_, _| Ok(())); } -fn source_info(body: &Body<'_>) -> SourceInfo { - SourceInfo { span: body.span, scope: OUTERMOST_SOURCE_SCOPE } -} - fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock { let return_block = insert_term_block(body, TerminatorKind::Return); @@ -1104,7 +1100,7 @@ fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock { target: return_block, unwind: None, }; - let source_info = source_info(body); + let source_info = SourceInfo::outermost(body.span); // Create a block to destroy an unresumed generators. This can only destroy upvars. body.basic_blocks_mut().push(BasicBlockData { @@ -1135,7 +1131,7 @@ fn create_cases<'tcx>( transform: &TransformVisitor<'tcx>, operation: Operation, ) -> Vec<(usize, BasicBlock)> { - let source_info = source_info(body); + let source_info = SourceInfo::outermost(body.span); transform .suspension_points @@ -1241,7 +1237,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { replace_local(resume_local, body.local_decls[resume_local].ty, body, tcx); // When first entering the generator, move the resume argument into its new local. - let source_info = source_info(body); + let source_info = SourceInfo::outermost(body.span); let stmts = &mut body.basic_blocks_mut()[BasicBlock::new(0)].statements; stmts.insert( 0, diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index ad98920eb63b9..8559e0a20eafb 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -775,7 +775,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.promoted.basic_blocks_mut().push(BasicBlockData { statements: vec![], terminator: Some(Terminator { - source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }, + source_info: SourceInfo::outermost(span), kind: TerminatorKind::Return, }), is_cleanup: false, @@ -786,7 +786,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let last = self.promoted.basic_blocks().last().unwrap(); let data = &mut self.promoted[last]; data.statements.push(Statement { - source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }, + source_info: SourceInfo::outermost(span), kind: StatementKind::Assign(box (Place::from(dest), rvalue)), }); } diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index 9153f82588b9e..c1c97909b3c4f 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -50,7 +50,7 @@ impl<'tcx> MirPatch<'tcx> { result.new_block(BasicBlockData { statements: vec![], terminator: Some(Terminator { - source_info: SourceInfo { span: body.span, scope: OUTERMOST_SOURCE_SCOPE }, + source_info: SourceInfo::outermost(body.span), kind: TerminatorKind::Resume, }), is_cleanup: true, diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index 2ce2627987a01..9a02b92145cd3 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -804,10 +804,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> BlockAnd<()> { // Allocate locals for the function arguments for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() { - let source_info = SourceInfo { - scope: OUTERMOST_SOURCE_SCOPE, - span: arg_opt.map_or(self.fn_span, |arg| arg.pat.span), - }; + let source_info = + SourceInfo::outermost(arg_opt.map_or(self.fn_span, |arg| arg.pat.span)); let arg_local = self.local_decls.push(LocalDecl { mutability: Mutability::Mut, ty, @@ -885,10 +883,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.var_debug_info.push(VarDebugInfo { name, - source_info: SourceInfo { - scope: OUTERMOST_SOURCE_SCOPE, - span: tcx_hir.span(var_id), - }, + source_info: SourceInfo::outermost(tcx_hir.span(var_id)), place: Place { local: closure_env_arg, projection: tcx.intern_place_elems(&projs), diff --git a/src/librustc_mir_build/build/scope.rs b/src/librustc_mir_build/build/scope.rs index d88cbf9451305..4daf567d7d451 100644 --- a/src/librustc_mir_build/build/scope.rs +++ b/src/librustc_mir_build/build/scope.rs @@ -989,7 +989,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let resumeblk = self.cfg.start_new_cleanup_block(); self.cfg.terminate( resumeblk, - SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span: self.fn_span }, + SourceInfo::outermost(self.fn_span), TerminatorKind::Resume, ); self.cached_resume_block = Some(resumeblk); From afd8a4e7ec4c5b6d8296d6d9109389b27e074980 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 6 May 2020 10:17:38 +1000 Subject: [PATCH 05/13] Improve `LocalDecl` creation. This commit adds some new `LocalDecl` methods: - `with_source_info`, a most general constructor. - `new`, a variant of `with_source_info` which represents the most common use case. - `internal` a modifying method (like the already present `immutable`). It removes some old `LocalDecl` methods: - `new_internal` and `new_local`, because they're subsumed by the new methods. - `new_return_place`, because it was identical to `new_temp`. Finally, it cleans up all the use sites. --- src/librustc_middle/mir/mod.rs | 62 +++++++------------ src/librustc_mir/shim.rs | 44 ++++++------- src/librustc_mir/transform/generator.rs | 34 ++-------- src/librustc_mir/transform/inline.rs | 4 +- src/librustc_mir/transform/promote_consts.rs | 9 ++- src/librustc_mir/util/patch.rs | 4 +- src/librustc_mir_build/build/expr/as_place.rs | 2 +- .../build/expr/as_rvalue.rs | 4 +- src/librustc_mir_build/build/expr/as_temp.rs | 2 +- src/librustc_mir_build/build/expr/into.rs | 13 ++-- src/librustc_mir_build/build/matches/mod.rs | 2 +- src/librustc_mir_build/build/misc.rs | 2 +- src/librustc_mir_build/build/mod.rs | 25 +------- 13 files changed, 70 insertions(+), 137 deletions(-) diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index e5f70d7ef9984..adcbaba5a6908 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -918,10 +918,31 @@ impl<'tcx> LocalDecl<'tcx> { self.source_info.span.desugaring_kind().is_some() } - /// Creates a new `LocalDecl` for a temporary. + /// Creates a new `LocalDecl` for a temporary: mutable, non-internal. #[inline] - pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self { - Self::new_local(ty, Mutability::Mut, false, span) + pub fn new(ty: Ty<'tcx>, span: Span) -> Self { + Self::with_source_info(ty, SourceInfo::outermost(span)) + } + + /// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`. + #[inline] + pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self { + LocalDecl { + mutability: Mutability::Mut, + local_info: LocalInfo::Other, + internal: false, + is_block_tail: None, + ty, + user_ty: UserTypeProjections::none(), + source_info, + } + } + + /// Converts `self` into same `LocalDecl` except tagged as internal. + #[inline] + pub fn internal(mut self) -> Self { + self.internal = true; + self } /// Converts `self` into same `LocalDecl` except tagged as immutable. @@ -938,41 +959,6 @@ impl<'tcx> LocalDecl<'tcx> { self.is_block_tail = Some(info); self } - - /// Creates a new `LocalDecl` for a internal temporary. - #[inline] - pub fn new_internal(ty: Ty<'tcx>, span: Span) -> Self { - Self::new_local(ty, Mutability::Mut, true, span) - } - - #[inline] - fn new_local(ty: Ty<'tcx>, mutability: Mutability, internal: bool, span: Span) -> Self { - LocalDecl { - mutability, - ty, - user_ty: UserTypeProjections::none(), - source_info: SourceInfo::outermost(span), - internal, - local_info: LocalInfo::Other, - is_block_tail: None, - } - } - - /// Builds a `LocalDecl` for the return place. - /// - /// This must be inserted into the `local_decls` list as the first local. - #[inline] - pub fn new_return_place(return_ty: Ty<'_>, span: Span) -> LocalDecl<'_> { - LocalDecl { - mutability: Mutability::Mut, - ty: return_ty, - user_ty: UserTypeProjections::none(), - source_info: SourceInfo::outermost(span), - internal: false, - is_block_tail: None, - local_info: LocalInfo::Other, - } - } } /// Debug information pertaining to a user variable. diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index a58ac7cfe18af..847f59b95e959 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -145,24 +145,12 @@ enum CallKind { Direct(DefId), } -fn temp_decl(mutability: Mutability, ty: Ty<'_>, span: Span) -> LocalDecl<'_> { - LocalDecl { - mutability, - ty, - user_ty: UserTypeProjections::none(), - source_info: SourceInfo::outermost(span), - internal: false, - local_info: LocalInfo::Other, - is_block_tail: None, - } -} - fn local_decls_for_sig<'tcx>( sig: &ty::FnSig<'tcx>, span: Span, ) -> IndexVec> { - iter::once(temp_decl(Mutability::Mut, sig.output(), span)) - .chain(sig.inputs().iter().map(|ity| temp_decl(Mutability::Not, ity, span))) + iter::once(LocalDecl::new(sig.output(), span)) + .chain(sig.inputs().iter().map(|ity| LocalDecl::new(ity, span).immutable())) .collect() } @@ -413,7 +401,11 @@ impl CloneShimBuilder<'tcx> { fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> { let span = self.span; - Place::from(self.local_decls.push(temp_decl(mutability, ty, span))) + let mut local = LocalDecl::new(ty, span); + if mutability == Mutability::Not { + local = local.immutable(); + } + Place::from(self.local_decls.push(local)) } fn make_clone_call( @@ -497,7 +489,7 @@ impl CloneShimBuilder<'tcx> { let tcx = self.tcx; let span = self.span; - let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span)); + let beg = self.local_decls.push(LocalDecl::new(tcx.types.usize, span)); let end = self.make_place(Mutability::Not, tcx.types.usize); // BB #0 @@ -552,7 +544,7 @@ impl CloneShimBuilder<'tcx> { // `let mut beg = 0;` // goto #6; let end = beg; - let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span)); + let beg = self.local_decls.push(LocalDecl::new(tcx.types.usize, span)); let init = self.make_statement(StatementKind::Assign(box ( Place::from(beg), Rvalue::Use(Operand::Constant(self.make_usize(0))), @@ -700,14 +692,16 @@ fn build_call_shim<'tcx>( Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_place())), Adjustment::RefMut => { // let rcvr = &mut rcvr; - let ref_rcvr = local_decls.push(temp_decl( - Mutability::Not, - tcx.mk_ref( - tcx.lifetimes.re_erased, - ty::TypeAndMut { ty: sig.inputs()[0], mutbl: hir::Mutability::Mut }, - ), - span, - )); + let ref_rcvr = local_decls.push( + LocalDecl::new( + tcx.mk_ref( + tcx.lifetimes.re_erased, + ty::TypeAndMut { ty: sig.inputs()[0], mutbl: hir::Mutability::Mut }, + ), + span, + ) + .immutable(), + ); let borrow_kind = BorrowKind::Mut { allow_two_phase_borrow: false }; statements.push(Statement { source_info, diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a9d566c92e935..91f0297710e0c 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -255,7 +255,7 @@ impl TransformVisitor<'tcx> { // Create a statement which reads the discriminant into a temporary fn get_discr(&self, body: &mut Body<'tcx>) -> (Statement<'tcx>, Place<'tcx>) { - let temp_decl = LocalDecl::new_internal(self.tcx.types.isize, body.span); + let temp_decl = LocalDecl::new(self.tcx.types.isize, body.span).internal(); let local_decls_len = body.local_decls.push(temp_decl); let temp = Place::from(local_decls_len); @@ -395,16 +395,7 @@ fn replace_local<'tcx>( body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>, ) -> Local { - let source_info = SourceInfo::outermost(body.span); - let new_decl = LocalDecl { - mutability: Mutability::Mut, - ty, - user_ty: UserTypeProjections::none(), - source_info, - internal: false, - is_block_tail: None, - local_info: LocalInfo::Other, - }; + let new_decl = LocalDecl::new(ty, body.span); let new_local = body.local_decls.push(new_decl); body.local_decls.swap(local, new_local); @@ -877,28 +868,15 @@ fn create_generator_drop_shim<'tcx>( } // Replace the return variable - body.local_decls[RETURN_PLACE] = LocalDecl { - mutability: Mutability::Mut, - ty: tcx.mk_unit(), - user_ty: UserTypeProjections::none(), - source_info, - internal: false, - is_block_tail: None, - local_info: LocalInfo::Other, - }; + body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(tcx.mk_unit(), source_info); make_generator_state_argument_indirect(tcx, &mut body); // Change the generator argument from &mut to *mut - body.local_decls[SELF_ARG] = LocalDecl { - mutability: Mutability::Mut, - ty: tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }), - user_ty: UserTypeProjections::none(), + body.local_decls[SELF_ARG] = LocalDecl::with_source_info( + tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }), source_info, - internal: false, - is_block_tail: None, - local_info: LocalInfo::Other, - }; + ); if tcx.sess.opts.debugging_opts.mir_emit_retag { // Alias tracking must know we changed the type body.basic_blocks_mut()[START_BLOCK].statements.insert( diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 985bd2b16605f..a8e949ecb3144 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -480,7 +480,7 @@ impl Inliner<'tcx> { let ty = dest.ty(caller_body, self.tcx); - let temp = LocalDecl::new_temp(ty, callsite.location.span); + let temp = LocalDecl::new(ty, callsite.location.span); let tmp = caller_body.local_decls.push(temp); let tmp = Place::from(tmp); @@ -631,7 +631,7 @@ impl Inliner<'tcx> { let ty = arg.ty(caller_body, self.tcx); - let arg_tmp = LocalDecl::new_temp(ty, callsite.location.span); + let arg_tmp = LocalDecl::new(ty, callsite.location.span); let arg_tmp = caller_body.local_decls.push(arg_tmp); let stmt = Statement { diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 8559e0a20eafb..ebb162eca4654 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -815,7 +815,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } let num_stmts = self.source[loc.block].statements.len(); - let new_temp = self.promoted.local_decls.push(LocalDecl::new_temp( + let new_temp = self.promoted.local_decls.push(LocalDecl::new( self.source.local_decls[temp].ty, self.source.local_decls[temp].source_info.span, )); @@ -915,7 +915,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let tcx = self.tcx; let mut promoted_operand = |ty, span| { promoted.span = span; - promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span); + promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span); Operand::Constant(Box::new(Constant { span, @@ -963,7 +963,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { // Create a temp to hold the promoted reference. // This is because `*r` requires `r` to be a local, // otherwise we would use the `promoted` directly. - let mut promoted_ref = LocalDecl::new_temp(ref_ty, span); + let mut promoted_ref = LocalDecl::new(ref_ty, span); promoted_ref.source_info = statement.source_info; let promoted_ref = local_decls.push(promoted_ref); assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref); @@ -1081,8 +1081,7 @@ pub fn promote_candidates<'tcx>( } // Declare return place local so that `mir::Body::new` doesn't complain. - let initial_locals = - iter::once(LocalDecl::new_return_place(tcx.types.never, body.span)).collect(); + let initial_locals = iter::once(LocalDecl::new(tcx.types.never, body.span)).collect(); let mut promoted = Body::new( IndexVec::new(), diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index c1c97909b3c4f..6566a996fe442 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -83,14 +83,14 @@ impl<'tcx> MirPatch<'tcx> { pub fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local { let index = self.next_local; self.next_local += 1; - self.new_locals.push(LocalDecl::new_temp(ty, span)); + self.new_locals.push(LocalDecl::new(ty, span)); Local::new(index as usize) } pub fn new_internal(&mut self, ty: Ty<'tcx>, span: Span) -> Local { let index = self.next_local; self.next_local += 1; - self.new_locals.push(LocalDecl::new_internal(ty, span)); + self.new_locals.push(LocalDecl::new(ty, span).internal()); Local::new(index as usize) } diff --git a/src/librustc_mir_build/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs index 9f74385b3368b..e08eedc6b6e91 100644 --- a/src/librustc_mir_build/build/expr/as_place.rs +++ b/src/librustc_mir_build/build/expr/as_place.rs @@ -383,7 +383,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let fake_borrow_ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty); let fake_borrow_temp = - self.local_decls.push(LocalDecl::new_temp(fake_borrow_ty, expr_span)); + self.local_decls.push(LocalDecl::new(fake_borrow_ty, expr_span)); let projection = tcx.intern_place_elems(&base_place.projection[..idx]); self.cfg.push_assign( block, diff --git a/src/librustc_mir_build/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs index 38f71135c7d92..d934ba1dc841e 100644 --- a/src/librustc_mir_build/build/expr/as_rvalue.rs +++ b/src/librustc_mir_build/build/expr/as_rvalue.rs @@ -97,7 +97,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // The `Box` temporary created here is not a part of the HIR, // and therefore is not considered during generator OIBIT // determination. See the comment about `box` at `yield_in_scope`. - let result = this.local_decls.push(LocalDecl::new_internal(expr.ty, expr_span)); + let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span).internal()); this.cfg.push( block, Statement { source_info, kind: StatementKind::StorageLive(result) }, @@ -377,7 +377,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let this = self; let source_info = this.source_info(upvar_span); - let temp = this.local_decls.push(LocalDecl::new_temp(upvar_ty, upvar_span)); + let temp = this.local_decls.push(LocalDecl::new(upvar_ty, upvar_span)); this.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) }); diff --git a/src/librustc_mir_build/build/expr/as_temp.rs b/src/librustc_mir_build/build/expr/as_temp.rs index b4ef536afb740..16ca205758497 100644 --- a/src/librustc_mir_build/build/expr/as_temp.rs +++ b/src/librustc_mir_build/build/expr/as_temp.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr_ty = expr.ty; let temp = { - let mut local_decl = LocalDecl::new_temp(expr_ty, expr_span); + let mut local_decl = LocalDecl::new(expr_ty, expr_span); if mutability == Mutability::Not { local_decl = local_decl.immutable(); } diff --git a/src/librustc_mir_build/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs index 52336b40a48dc..e26fb48a3f997 100644 --- a/src/librustc_mir_build/build/expr/into.rs +++ b/src/librustc_mir_build/build/expr/into.rs @@ -187,15 +187,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let ptr_ty = ptr.ty; // Create an *internal* temp for the pointer, so that unsafety // checking won't complain about the raw pointer assignment. - let ptr_temp = this.local_decls.push(LocalDecl { - mutability: Mutability::Mut, - ty: ptr_ty, - user_ty: UserTypeProjections::none(), + let ptr_temp = this.local_decls.push(LocalDecl::with_source_info( + ptr_ty, source_info, - internal: true, - local_info: LocalInfo::Other, - is_block_tail: None, - }); + ).internal()); let ptr_temp = Place::from(ptr_temp); let block = unpack!(this.into(ptr_temp, block, ptr)); this.into(this.hir.tcx().mk_place_deref(ptr_temp), block, val) @@ -348,7 +343,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // value is Sized. Usually, this is caught in type checking, but // in the case of box expr there is no such check. if !destination.projection.is_empty() { - this.local_decls.push(LocalDecl::new_temp(expr.ty, expr.span)); + this.local_decls.push(LocalDecl::new(expr.ty, expr.span)); } debug_assert!(Category::of(&expr.kind) == Some(Category::Place)); diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs index b9d61458a839b..03fdd2ed8f12e 100644 --- a/src/librustc_mir_build/build/matches/mod.rs +++ b/src/librustc_mir_build/build/matches/mod.rs @@ -1539,7 +1539,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty; let fake_borrow_ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty); let fake_borrow_temp = - self.local_decls.push(LocalDecl::new_temp(fake_borrow_ty, temp_span)); + self.local_decls.push(LocalDecl::new(fake_borrow_ty, temp_span)); (matched_place, fake_borrow_temp) }) diff --git a/src/librustc_mir_build/build/misc.rs b/src/librustc_mir_build/build/misc.rs index 578b862b90543..e8933ff8aa749 100644 --- a/src/librustc_mir_build/build/misc.rs +++ b/src/librustc_mir_build/build/misc.rs @@ -15,7 +15,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// N.B., **No cleanup is scheduled for this temporary.** You should /// call `schedule_drop` once the temporary is initialized. crate fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> { - let temp = self.local_decls.push(LocalDecl::new_temp(ty, span)); + let temp = self.local_decls.push(LocalDecl::new(ty, span)); let place = Place::from(temp); debug!("temp: created temp {:?} with type {:?}", place, self.local_decls[temp].ty); place diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index 9a02b92145cd3..a668cb869106f 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -708,15 +708,7 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t // Some MIR passes will expect the number of parameters to match the // function declaration. for _ in 0..num_params { - builder.local_decls.push(LocalDecl { - mutability: Mutability::Mut, - ty, - user_ty: UserTypeProjections::none(), - source_info, - internal: false, - local_info: LocalInfo::Other, - is_block_tail: None, - }); + builder.local_decls.push(LocalDecl::with_source_info(ty, source_info)); } builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); let mut body = builder.finish(); @@ -750,10 +742,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { guard_context: vec![], push_unsafe_count: 0, unpushed_unsafe: safety, - local_decls: IndexVec::from_elem_n( - LocalDecl::new_return_place(return_ty, return_span), - 1, - ), + local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1), canonical_user_type_annotations: IndexVec::new(), upvar_mutbls: vec![], var_indices: Default::default(), @@ -806,15 +795,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() { let source_info = SourceInfo::outermost(arg_opt.map_or(self.fn_span, |arg| arg.pat.span)); - let arg_local = self.local_decls.push(LocalDecl { - mutability: Mutability::Mut, - ty, - user_ty: UserTypeProjections::none(), - source_info, - internal: false, - local_info: LocalInfo::Other, - is_block_tail: None, - }); + let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info)); // If this is a simple binding pattern, give debuginfo a nice name. if let Some(arg) = arg_opt { From cda162727893f87ce510ab1832254040e6945bd7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 6 May 2020 09:35:11 +1000 Subject: [PATCH 06/13] Add a size assertion for `LocalDecl`. --- src/librustc_middle/mir/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index adcbaba5a6908..599408807e937 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -816,6 +816,10 @@ pub struct LocalDecl<'tcx> { pub source_info: SourceInfo, } +// `LocalDecl` is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(target_arch = "x86_64")] +static_assert_size!(LocalDecl<'_>, 128); + /// Extra information about a local that's used for diagnostics. #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)] pub enum LocalInfo<'tcx> { From 27ae2f0d60d9201133e1f9ec7a04c05c8e55e665 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 6 May 2020 12:29:00 +1000 Subject: [PATCH 07/13] Shrink `LocalDecl` by 56 bytes. By boxing `local_info`. --- src/librustc_middle/mir/mod.rs | 34 +++++++++---------- .../diagnostics/conflict_errors.rs | 8 ++--- .../borrow_check/diagnostics/mod.rs | 2 +- .../borrow_check/diagnostics/move_errors.rs | 8 ++--- .../diagnostics/mutability_errors.rs | 18 +++++----- .../transform/check_consts/validation.rs | 2 +- src/librustc_mir/transform/check_unsafety.rs | 2 +- src/librustc_mir_build/build/expr/as_temp.rs | 2 +- src/librustc_mir_build/build/matches/mod.rs | 10 +++--- src/librustc_mir_build/build/mod.rs | 6 ++-- 10 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 599408807e937..0c1b99d871e24 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -696,7 +696,7 @@ pub struct LocalDecl<'tcx> { pub mutability: Mutability, // FIXME(matthewjasper) Don't store in this in `Body` - pub local_info: LocalInfo<'tcx>, + pub local_info: Option>>, /// `true` if this is an internal local. /// @@ -818,9 +818,11 @@ pub struct LocalDecl<'tcx> { // `LocalDecl` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(LocalDecl<'_>, 128); +static_assert_size!(LocalDecl<'_>, 72); -/// Extra information about a local that's used for diagnostics. +/// Extra information about a some locals that's used for diagnostics. (Not +/// used for non-StaticRef temporaries, the return place, or anonymous function +/// parameters.) #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)] pub enum LocalInfo<'tcx> { /// A user-defined local variable or function parameter @@ -831,8 +833,6 @@ pub enum LocalInfo<'tcx> { User(ClearCrossCrate>), /// A temporary created that references the static with the given `DefId`. StaticRef { def_id: DefId, is_thread_local: bool }, - /// Any other temporary, the return place, or an anonymous function parameter. - Other, } impl<'tcx> LocalDecl<'tcx> { @@ -844,16 +844,16 @@ impl<'tcx> LocalDecl<'tcx> { /// - or `match ... { C(x) => ... }` pub fn can_be_made_mutable(&self) -> bool { match self.local_info { - LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_), opt_ty_info: _, opt_match_place: _, pat_span: _, - }))) => true, + })))) => true, - LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf( + Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf( ImplicitSelfKind::Imm, - ))) => true, + )))) => true, _ => false, } @@ -864,14 +864,14 @@ impl<'tcx> LocalDecl<'tcx> { /// mutable bindings, but the inverse does not necessarily hold). pub fn is_nonref_binding(&self) -> bool { match self.local_info { - LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_), opt_ty_info: _, opt_match_place: _, pat_span: _, - }))) => true, + })))) => true, - LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true, + Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_)))) => true, _ => false, } @@ -882,7 +882,7 @@ impl<'tcx> LocalDecl<'tcx> { #[inline] pub fn is_user_variable(&self) -> bool { match self.local_info { - LocalInfo::User(_) => true, + Some(box LocalInfo::User(_)) => true, _ => false, } } @@ -892,7 +892,7 @@ impl<'tcx> LocalDecl<'tcx> { /// match arm. pub fn is_ref_for_guard(&self) -> bool { match self.local_info { - LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)) => true, + Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))) => true, _ => false, } } @@ -901,7 +901,7 @@ impl<'tcx> LocalDecl<'tcx> { /// access that static pub fn is_ref_to_static(&self) -> bool { match self.local_info { - LocalInfo::StaticRef { .. } => true, + Some(box LocalInfo::StaticRef { .. }) => true, _ => false, } } @@ -910,7 +910,7 @@ impl<'tcx> LocalDecl<'tcx> { /// access that static pub fn is_ref_to_thread_local(&self) -> bool { match self.local_info { - LocalInfo::StaticRef { is_thread_local, .. } => is_thread_local, + Some(box LocalInfo::StaticRef { is_thread_local, .. }) => is_thread_local, _ => false, } } @@ -933,7 +933,7 @@ impl<'tcx> LocalDecl<'tcx> { pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self { LocalDecl { mutability: Mutability::Mut, - local_info: LocalInfo::Other, + local_info: None, internal: false, is_block_tail: None, ty, diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 5bc9f6df889c7..9eb55bca86859 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -1448,15 +1448,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let (place_description, assigned_span) = match local_decl { Some(LocalDecl { local_info: - LocalInfo::User( + Some(box LocalInfo::User( ClearCrossCrate::Clear | ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { opt_match_place: None, .. })), - ) - | LocalInfo::StaticRef { .. } - | LocalInfo::Other, + )) + | Some(box LocalInfo::StaticRef { .. }) + | None, .. }) | None => (self.describe_any_place(place.as_ref()), assigned_span), diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 9e4458e7104ff..c218e3906fff2 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -202,7 +202,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if self.body.local_decls[local].is_ref_to_static() => { let local_info = &self.body.local_decls[local].local_info; - if let LocalInfo::StaticRef { def_id, .. } = *local_info { + if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info { buf.push_str(&self.infcx.tcx.item_name(def_id).as_str()); } else { unreachable!(); diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index 457e263a46611..ddaf78626f2c2 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -103,14 +103,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // // opt_match_place is None for let [mut] x = ... statements, // whether or not the right-hand side is a place expression - if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( + if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( VarBindingForm { opt_match_place: Some((opt_match_place, match_span)), binding_mode: _, opt_ty_info: _, pat_span: _, }, - ))) = local_decl.local_info + )))) = local_decl.local_info { let stmt_source_info = self.body.source_info(location); self.append_binding_error( @@ -482,10 +482,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let mut suggestions: Vec<(Span, &str, String)> = Vec::new(); for local in binds_to { let bind_to = &self.body.local_decls[*local]; - if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { pat_span, .. - }))) = bind_to.local_info + })))) = bind_to.local_info { if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) { diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index 1a4876db0ded3..402eac47c462b 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } else { item_msg = format!("`{}`", access_place_desc.unwrap()); let local_info = &self.body.local_decls[local].local_info; - if let LocalInfo::StaticRef { def_id, .. } = *local_info { + if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info { let static_name = &self.infcx.tcx.item_name(def_id); reason = format!(", as `{}` is an immutable static item", static_name); } else { @@ -216,9 +216,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .local_decls .get(local) .map(|local_decl| { - if let LocalInfo::User(ClearCrossCrate::Set( + if let Some(box LocalInfo::User(ClearCrossCrate::Set( mir::BindingForm::ImplicitSelf(kind), - )) = local_decl.local_info + ))) = local_decl.local_info { // Check if the user variable is a `&mut self` and we can therefore // suggest removing the `&mut`. @@ -340,8 +340,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { match self.local_names[local] { Some(name) if !local_decl.from_compiler_desugaring() => { - let label = match local_decl.local_info { - LocalInfo::User(ClearCrossCrate::Set( + let label = match local_decl.local_info.as_ref().unwrap() { + box LocalInfo::User(ClearCrossCrate::Set( mir::BindingForm::ImplicitSelf(_), )) => { let (span, suggestion) = @@ -349,7 +349,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some((true, span, suggestion)) } - LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( + box LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( mir::VarBindingForm { binding_mode: ty::BindingMode::BindByValue(_), opt_ty_info, @@ -381,14 +381,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { self.infcx.tcx, local_decl, opt_assignment_rhs_span, - opt_ty_info, + *opt_ty_info, ); Some((true, span, suggestion)) } } } - LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( + box LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( mir::VarBindingForm { binding_mode: ty::BindingMode::BindByReference(_), .. @@ -399,7 +399,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .map(|replacement| (true, pattern_span, replacement)) } - LocalInfo::User(ClearCrossCrate::Clear) => { + box LocalInfo::User(ClearCrossCrate::Clear) => { bug!("saw cleared local state") } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 3fd9131d5db76..10cf47d47ffc7 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -456,7 +456,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { if proj_base.is_empty() { if let (local, []) = (place_local, proj_base) { let decl = &self.body.local_decls[local]; - if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { + if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info { let span = decl.source_info.span; self.check_static(def_id, span); return; diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 35726dde602da..0bd9b3e1b2084 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -218,7 +218,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if let [] = proj_base { let decl = &self.body.local_decls[place.local]; if decl.internal { - if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { + if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info { if self.tcx.is_mutable_static(def_id) { self.require_unsafe( "use of mutable static", diff --git a/src/librustc_mir_build/build/expr/as_temp.rs b/src/librustc_mir_build/build/expr/as_temp.rs index 16ca205758497..50bd5a73e2580 100644 --- a/src/librustc_mir_build/build/expr/as_temp.rs +++ b/src/librustc_mir_build/build/expr/as_temp.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let ExprKind::StaticRef { def_id, .. } = expr.kind { let is_thread_local = this.hir.tcx().is_thread_local_static(def_id); local_decl.internal = true; - local_decl.local_info = LocalInfo::StaticRef { def_id, is_thread_local }; + local_decl.local_info = Some(box LocalInfo::StaticRef { def_id, is_thread_local }); } this.local_decls.push(local_decl) }; diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs index 03fdd2ed8f12e..7812848e92666 100644 --- a/src/librustc_mir_build/build/matches/mod.rs +++ b/src/librustc_mir_build/build/matches/mod.rs @@ -470,9 +470,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { for binding in &candidate_ref.bindings { let local = self.var_local_id(binding.var_id, OutsideGuard); - if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( + if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. }, - ))) = self.local_decls[local].local_info + )))) = self.local_decls[local].local_info { *match_place = Some(initializer); } else { @@ -1953,7 +1953,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, internal: false, is_block_tail: None, - local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { binding_mode, // hypothetically, `visit_bindings` could try to unzip // an outermost hir::Ty as we descend, matching up @@ -1962,7 +1962,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { opt_ty_info: None, opt_match_place, pat_span, - }))), + })))), }; let for_arm_body = self.local_decls.push(local); self.var_debug_info.push(VarDebugInfo { @@ -1980,7 +1980,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, internal: false, is_block_tail: None, - local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)), + local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))), }); self.var_debug_info.push(VarDebugInfo { name, diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index a668cb869106f..6c61c27c4ed7f 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -909,17 +909,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.local_decls[local].mutability = mutability; self.local_decls[local].source_info.scope = self.source_scope; self.local_decls[local].local_info = if let Some(kind) = self_binding { - LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind))) + Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind)))) } else { let binding_mode = ty::BindingMode::BindByValue(mutability); - LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( + Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( VarBindingForm { binding_mode, opt_ty_info, opt_match_place: Some((Some(place), span)), pat_span: span, }, - ))) + )))) }; self.var_indices.insert(var, LocalsForNode::One(local)); } From 001496c0ebb27373ace8bd019b78b3f02ce531d1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 6 May 2020 12:41:15 +1000 Subject: [PATCH 08/13] Shrink `LocalDecl` by 16 bytes. By boxing `user_ty`. --- src/librustc_middle/mir/mod.rs | 12 ++-- src/librustc_middle/mir/visit.rs | 6 +- .../borrow_check/diagnostics/move_errors.rs | 7 +-- .../borrow_check/type_check/mod.rs | 57 ++++++++++--------- src/librustc_mir/util/pretty.rs | 6 +- src/librustc_mir_build/build/matches/mod.rs | 4 +- 6 files changed, 51 insertions(+), 41 deletions(-) diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 0c1b99d871e24..1586266051226 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -732,7 +732,7 @@ pub struct LocalDecl<'tcx> { /// borrow checker needs this information since it can affect /// region inference. // FIXME(matthewjasper) Don't store in this in `Body` - pub user_ty: UserTypeProjections, + pub user_ty: Option>, /// The *syntactic* (i.e., not visibility) source scope the local is defined /// in. If the local was defined in a let-statement, this @@ -818,7 +818,7 @@ pub struct LocalDecl<'tcx> { // `LocalDecl` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(LocalDecl<'_>, 72); +static_assert_size!(LocalDecl<'_>, 56); /// Extra information about a some locals that's used for diagnostics. (Not /// used for non-StaticRef temporaries, the return place, or anonymous function @@ -937,7 +937,7 @@ impl<'tcx> LocalDecl<'tcx> { internal: false, is_block_tail: None, ty, - user_ty: UserTypeProjections::none(), + user_ty: None, source_info, } } @@ -2451,7 +2451,7 @@ impl Constant<'tcx> { /// &'static str`. #[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)] pub struct UserTypeProjections { - pub(crate) contents: Vec<(UserTypeProjection, Span)>, + pub contents: Vec<(UserTypeProjection, Span)>, } impl<'tcx> UserTypeProjections { @@ -2459,6 +2459,10 @@ impl<'tcx> UserTypeProjections { UserTypeProjections { contents: vec![] } } + pub fn is_empty(&self) -> bool { + self.contents.is_empty() + } + pub fn from_projections(projs: impl Iterator) -> Self { UserTypeProjections { contents: projs.collect() } } diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs index 2b6d44984bf53..2f3d89dc02980 100644 --- a/src/librustc_middle/mir/visit.rs +++ b/src/librustc_middle/mir/visit.rs @@ -715,8 +715,10 @@ macro_rules! make_mir_visitor { local, source_info: *source_info, }); - for (user_ty, _) in & $($mutability)? user_ty.contents { - self.visit_user_type_projection(user_ty); + if let Some(user_ty) = user_ty { + for (user_ty, _) in & $($mutability)? user_ty.contents { + self.visit_user_type_projection(user_ty); + } } self.visit_source_info(source_info); } diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index ddaf78626f2c2..67254811ec52a 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -482,10 +482,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let mut suggestions: Vec<(Span, &str, String)> = Vec::new(); for local in binds_to { let bind_to = &self.body.local_decls[*local]; - if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { - pat_span, - .. - })))) = bind_to.local_info + if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( + VarBindingForm { pat_span, .. }, + )))) = bind_to.local_info { if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) { diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 7f554742777e2..bd38ad04e7eaa 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -405,35 +405,38 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { self.super_local_decl(local, local_decl); self.sanitize_type(local_decl, local_decl.ty); - for (user_ty, span) in local_decl.user_ty.projections_and_spans() { - let ty = if !local_decl.is_nonref_binding() { - // If we have a binding of the form `let ref x: T = ..` then remove the outermost - // reference so we can check the type annotation for the remaining type. - if let ty::Ref(_, rty, _) = local_decl.ty.kind { - rty + if let Some(user_ty) = &local_decl.user_ty { + for (user_ty, span) in user_ty.projections_and_spans() { + let ty = if !local_decl.is_nonref_binding() { + // If we have a binding of the form `let ref x: T = ..` + // then remove the outermost reference so we can check the + // type annotation for the remaining type. + if let ty::Ref(_, rty, _) = local_decl.ty.kind { + rty + } else { + bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty); + } } else { - bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty); - } - } else { - local_decl.ty - }; + local_decl.ty + }; - if let Err(terr) = self.cx.relate_type_and_user_type( - ty, - ty::Variance::Invariant, - user_ty, - Locations::All(*span), - ConstraintCategory::TypeAnnotation, - ) { - span_mirbug!( - self, - local, - "bad user type on variable {:?}: {:?} != {:?} ({:?})", - local, - local_decl.ty, - local_decl.user_ty, - terr, - ); + if let Err(terr) = self.cx.relate_type_and_user_type( + ty, + ty::Variance::Invariant, + user_ty, + Locations::All(*span), + ConstraintCategory::TypeAnnotation, + ) { + span_mirbug!( + self, + local, + "bad user type on variable {:?}: {:?} != {:?} ({:?})", + local, + local_decl.ty, + local_decl.user_ty, + terr, + ); + } } } } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 098601626db89..090cd41543733 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -472,8 +472,10 @@ fn write_scope_tree( let mut indented_decl = format!("{0:1$}let {2}{3:?}: {4:?}", INDENT, indent, mut_str, local, local_decl.ty); - for user_ty in local_decl.user_ty.projections() { - write!(indented_decl, " as {:?}", user_ty).unwrap(); + if let Some(user_ty) = &local_decl.user_ty { + for user_ty in user_ty.projections() { + write!(indented_decl, " as {:?}", user_ty).unwrap(); + } } indented_decl.push_str(";"); diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs index 7812848e92666..f14de38a3f942 100644 --- a/src/librustc_mir_build/build/matches/mod.rs +++ b/src/librustc_mir_build/build/matches/mod.rs @@ -1949,7 +1949,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local = LocalDecl::<'tcx> { mutability, ty: var_ty, - user_ty, + user_ty: if user_ty.is_empty() { None } else { Some(box user_ty) }, source_info, internal: false, is_block_tail: None, @@ -1976,7 +1976,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // immutable to avoid the unused mut lint. mutability: Mutability::Not, ty: tcx.mk_imm_ref(tcx.lifetimes.re_erased, var_ty), - user_ty: UserTypeProjections::none(), + user_ty: None, source_info, internal: false, is_block_tail: None, From b6d5d1fb7901b4c0fe4c9ffa2854f616fd60e541 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Wed, 6 May 2020 10:01:20 +0200 Subject: [PATCH 09/13] Dead-code pass highlights too much of impl functions --- src/librustc_passes/dead.rs | 14 ++++++-- .../ui/lint/dead-code/lint-dead-code-3.stderr | 4 +-- .../ui/lint/dead-code/lint-dead-code-6.rs | 20 ++++++++++++ .../ui/lint/dead-code/lint-dead-code-6.stderr | 32 +++++++++++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/lint/dead-code/lint-dead-code-6.rs create mode 100644 src/test/ui/lint/dead-code/lint-dead-code-6.stderr diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 1b8c053b16e0b..22ff87efd2ede 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -589,7 +589,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { // FIXME(66095): Because item.span is annotated with things // like expansion data, and ident.span isn't, we use the // def_span method if it's part of a macro invocation - // (and thus has asource_callee set). + // (and thus has a source_callee set). // We should probably annotate ident.span with the macro // context, but that's a larger change. if item.span.source_callee().is_some() { @@ -653,7 +653,17 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { } hir::ImplItemKind::Fn(_, body_id) => { if !self.symbol_is_live(impl_item.hir_id) { - let span = self.tcx.sess.source_map().guess_head_span(impl_item.span); + // FIXME(66095): Because impl_item.span is annotated with things + // like expansion data, and ident.span isn't, we use the + // def_span method if it's part of a macro invocation + // (and thus has a source_callee set). + // We should probably annotate ident.span with the macro + // context, but that's a larger change. + let span = if impl_item.span.source_callee().is_some() { + self.tcx.sess.source_map().guess_head_span(impl_item.span) + } else { + impl_item.ident.span + }; self.warn_dead_code(impl_item.hir_id, span, impl_item.ident.name, "used"); } self.visit_nested_body(body_id) diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr index a2614a0bf74b3..6d174e8d9bc38 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr @@ -11,10 +11,10 @@ LL | #![deny(dead_code)] | ^^^^^^^^^ error: associated function is never used: `foo` - --> $DIR/lint-dead-code-3.rs:15:5 + --> $DIR/lint-dead-code-3.rs:15:8 | LL | fn foo(&self) { - | ^^^^^^^^^^^^^ + | ^^^ error: function is never used: `bar` --> $DIR/lint-dead-code-3.rs:20:4 diff --git a/src/test/ui/lint/dead-code/lint-dead-code-6.rs b/src/test/ui/lint/dead-code/lint-dead-code-6.rs new file mode 100644 index 0000000000000..0a543d5c6228d --- /dev/null +++ b/src/test/ui/lint/dead-code/lint-dead-code-6.rs @@ -0,0 +1,20 @@ +#![deny(dead_code)] + +struct UnusedStruct; //~ ERROR struct is never constructed: `UnusedStruct` +impl UnusedStruct { + fn unused_impl_fn_1() { //~ ERROR associated function is never used: `unused_impl_fn_1` + println!("blah"); + } + + fn unused_impl_fn_2(var: i32) { //~ ERROR associated function is never used: `unused_impl_fn_2` + println!("foo {}", var); + } + + fn unused_impl_fn_3( //~ ERROR associated function is never used: `unused_impl_fn_3` + var: i32, + ) { + println!("bar {}", var); + } +} + +fn main() {} diff --git a/src/test/ui/lint/dead-code/lint-dead-code-6.stderr b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr new file mode 100644 index 0000000000000..7dc60730d6aad --- /dev/null +++ b/src/test/ui/lint/dead-code/lint-dead-code-6.stderr @@ -0,0 +1,32 @@ +error: struct is never constructed: `UnusedStruct` + --> $DIR/lint-dead-code-6.rs:3:8 + | +LL | struct UnusedStruct; + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-6.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: associated function is never used: `unused_impl_fn_1` + --> $DIR/lint-dead-code-6.rs:5:8 + | +LL | fn unused_impl_fn_1() { + | ^^^^^^^^^^^^^^^^ + +error: associated function is never used: `unused_impl_fn_2` + --> $DIR/lint-dead-code-6.rs:9:8 + | +LL | fn unused_impl_fn_2(var: i32) { + | ^^^^^^^^^^^^^^^^ + +error: associated function is never used: `unused_impl_fn_3` + --> $DIR/lint-dead-code-6.rs:13:8 + | +LL | fn unused_impl_fn_3( + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + From 029515d9164bddc0928c159d375aadfc7f256b28 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Mon, 6 Apr 2020 09:24:44 +0200 Subject: [PATCH 10/13] Add core::future::{pending,ready} --- src/libcore/future/mod.rs | 8 +++++ src/libcore/future/pending.rs | 57 +++++++++++++++++++++++++++++++++++ src/libcore/future/ready.rs | 45 +++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 src/libcore/future/pending.rs create mode 100644 src/libcore/future/ready.rs diff --git a/src/libcore/future/mod.rs b/src/libcore/future/mod.rs index 8dfda7a4a3236..d339e18d7c343 100644 --- a/src/libcore/future/mod.rs +++ b/src/libcore/future/mod.rs @@ -11,9 +11,17 @@ use crate::{ }; mod future; +mod pending; +mod ready; + #[stable(feature = "futures_api", since = "1.36.0")] pub use self::future::Future; +#[unstable(feature = "future_readiness_fns", issue = "70921")] +pub use pending::{pending, Pending}; +#[unstable(feature = "future_readiness_fns", issue = "70921")] +pub use ready::{ready, Ready}; + /// This type is needed because: /// /// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass diff --git a/src/libcore/future/pending.rs b/src/libcore/future/pending.rs new file mode 100644 index 0000000000000..74887b68aa0fa --- /dev/null +++ b/src/libcore/future/pending.rs @@ -0,0 +1,57 @@ +use crate::future::Future; +use crate::marker; +use crate::pin::Pin; +use crate::task::{Context, Poll}; + +/// Creates a future which never resolves, representing a computation that never +/// finishes. +/// +/// This `struct` is created by the [`pending`] function. See its +/// documentation for more. +/// +/// [`pending`]: fn.pending.html +#[unstable(feature = "future_readiness_fns", issue = "70921")] +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Pending { + _data: marker::PhantomData, +} + +/// Creates a future which never resolves, representing a computation that never +/// finishes. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(future_readiness_fns)] +/// use core::future; +/// +/// # async fn run() { +/// let future = future::pending(); +/// let () = future.await; +/// unreachable!(); +/// # } +/// ``` +#[unstable(feature = "future_readiness_fns", issue = "70921")] +pub fn pending() -> Pending { + Pending { _data: marker::PhantomData } +} + +#[unstable(feature = "future_readiness_fns", issue = "70921")] +impl Future for Pending { + type Output = T; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +#[unstable(feature = "future_readiness_fns", issue = "70921")] +impl Unpin for Pending {} + +#[unstable(feature = "future_readiness_fns", issue = "70921")] +impl Clone for Pending { + fn clone(&self) -> Self { + pending() + } +} diff --git a/src/libcore/future/ready.rs b/src/libcore/future/ready.rs new file mode 100644 index 0000000000000..31b39d7fb6cd5 --- /dev/null +++ b/src/libcore/future/ready.rs @@ -0,0 +1,45 @@ +use crate::future::Future; +use crate::pin::Pin; +use crate::task::{Context, Poll}; + +/// Creates a future that is immediately ready with a value. +/// +/// This `struct` is created by the [`ready`] function. See its +/// documentation for more. +/// +/// [`ready`]: fn.ready.html +#[unstable(feature = "future_readiness_fns", issue = "70921")] +#[derive(Debug, Clone)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Ready(Option); + +#[unstable(feature = "future_readiness_fns", issue = "70921")] +impl Unpin for Ready {} + +#[unstable(feature = "future_readiness_fns", issue = "70921")] +impl Future for Ready { + type Output = T; + + #[inline] + fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Ready(self.0.take().expect("Ready polled after completion")) + } +} + +/// Creates a future that is immediately ready with a value. +/// +/// # Examples +/// +/// ``` +/// #![feature(future_readiness_fns)] +/// use core::future; +/// +/// # async fn run() { +/// let a = future::ready(1); +/// assert_eq!(a.await, 1); +/// # } +/// ``` +#[unstable(feature = "future_readiness_fns", issue = "70921")] +pub fn ready(t: T) -> Ready { + Ready(Some(t)) +} From 0bf269925bd1d01c7f19a9714f1ce8b18e52b517 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Thu, 7 May 2020 16:22:22 +0300 Subject: [PATCH 11/13] Fix `strip-priv-imports` pass name in the rustdoc documentation --- src/doc/rustdoc/src/passes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustdoc/src/passes.md b/src/doc/rustdoc/src/passes.md index 12d4ea205b31e..081e477de8010 100644 --- a/src/doc/rustdoc/src/passes.md +++ b/src/doc/rustdoc/src/passes.md @@ -17,7 +17,7 @@ By default, rustdoc will run some passes, namely: * `collapse-docs` * `unindent-comments` -However, `strip-private` implies `strip-private-imports`, and so effectively, +However, `strip-private` implies `strip-priv-imports`, and so effectively, all passes are run by default. ## `strip-hidden` From 9dabea1a2928d25dea2c15a948755890d4d1dbd0 Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 8 May 2020 11:06:25 -0500 Subject: [PATCH 12/13] fix canonicalization links --- src/librustc_infer/infer/canonical/canonicalizer.rs | 6 +++--- src/librustc_infer/infer/canonical/mod.rs | 2 +- src/librustc_infer/infer/canonical/query_response.rs | 4 ++-- src/librustc_infer/infer/canonical/substitute.rs | 2 +- src/librustc_middle/infer/canonical.rs | 2 +- src/librustc_trait_selection/traits/query/type_op/mod.rs | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index acb9329afbf9a..42ceae617ba84 100644 --- a/src/librustc_infer/infer/canonical/canonicalizer.rs +++ b/src/librustc_infer/infer/canonical/canonicalizer.rs @@ -3,7 +3,7 @@ //! For an overview of what canonicalization is and how it fits into //! rustc, check out the [chapter in the rustc dev guide][c]. //! -//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html +//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html use crate::infer::canonical::{ Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, Canonicalized, @@ -35,7 +35,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// To get a good understanding of what is happening here, check /// out the [chapter in the rustc dev guide][c]. /// - /// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#canonicalizing-the-query + /// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#canonicalizing-the-query pub fn canonicalize_query( &self, value: &V, @@ -79,7 +79,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// To get a good understanding of what is happening here, check /// out the [chapter in the rustc dev guide][c]. /// - /// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#canonicalizing-the-query-result + /// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#canonicalizing-the-query-result pub fn canonicalize_response(&self, value: &V) -> Canonicalized<'tcx, V> where V: TypeFoldable<'tcx>, diff --git a/src/librustc_infer/infer/canonical/mod.rs b/src/librustc_infer/infer/canonical/mod.rs index b7890cf9e925a..7f58b29a73f36 100644 --- a/src/librustc_infer/infer/canonical/mod.rs +++ b/src/librustc_infer/infer/canonical/mod.rs @@ -19,7 +19,7 @@ //! For a more detailed look at what is happening here, check //! out the [chapter in the rustc dev guide][c]. //! -//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html +//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind}; use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind}; diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs index 9fe7ebf58b343..de93baff79beb 100644 --- a/src/librustc_infer/infer/canonical/query_response.rs +++ b/src/librustc_infer/infer/canonical/query_response.rs @@ -5,7 +5,7 @@ //! For an overview of what canonicaliation is and how it fits into //! rustc, check out the [chapter in the rustc dev guide][c]. //! -//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html +//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html use crate::infer::canonical::substitute::{substitute_value, CanonicalExt}; use crate::infer::canonical::{ @@ -154,7 +154,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// To get a good understanding of what is happening here, check /// out the [chapter in the rustc dev guide][c]. /// - /// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html#processing-the-canonicalized-query-result + /// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#processing-the-canonicalized-query-result pub fn instantiate_query_response_and_region_obligations( &self, cause: &ObligationCause<'tcx>, diff --git a/src/librustc_infer/infer/canonical/substitute.rs b/src/librustc_infer/infer/canonical/substitute.rs index 55609c080acc1..65791f6fc6523 100644 --- a/src/librustc_infer/infer/canonical/substitute.rs +++ b/src/librustc_infer/infer/canonical/substitute.rs @@ -4,7 +4,7 @@ //! For an overview of what canonicalization is and how it fits into //! rustc, check out the [chapter in the rustc dev guide][c]. //! -//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html +//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html use crate::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::ty::fold::TypeFoldable; diff --git a/src/librustc_middle/infer/canonical.rs b/src/librustc_middle/infer/canonical.rs index 5f7e8c849653c..9433d282ad297 100644 --- a/src/librustc_middle/infer/canonical.rs +++ b/src/librustc_middle/infer/canonical.rs @@ -19,7 +19,7 @@ //! For a more detailed look at what is happening here, check //! out the [chapter in the rustc dev guide][c]. //! -//! [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html +//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html use crate::infer::MemberConstraint; use crate::ty::subst::GenericArg; diff --git a/src/librustc_trait_selection/traits/query/type_op/mod.rs b/src/librustc_trait_selection/traits/query/type_op/mod.rs index 763cf12afa66f..ed6c6d0cc0a98 100644 --- a/src/librustc_trait_selection/traits/query/type_op/mod.rs +++ b/src/librustc_trait_selection/traits/query/type_op/mod.rs @@ -44,7 +44,7 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug { /// first canonicalize the key and then invoke the query on the tcx, /// which produces the resulting query region constraints. /// -/// [c]: https://rustc-dev-guide.rust-lang.org/traits/canonicalization.html +/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx { type QueryResponse: TypeFoldable<'tcx>; From 05fc7faacb7c33eaad6614f62a7d560b0d2660a5 Mon Sep 17 00:00:00 2001 From: Elinvynia <59487684+Elinvynia@users.noreply.github.com> Date: Sat, 9 May 2020 01:17:20 +0200 Subject: [PATCH 13/13] Better documentation for io::Read::read() return value --- src/libstd/io/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 36c6aa620d579..ebe6d09023f42 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -517,6 +517,11 @@ pub trait Read { /// reader will *always* no longer be able to produce bytes. /// 2. The buffer specified was 0 bytes in length. /// + /// It is not an error if the returned value `n` is smaller than the buffer size, + /// even when the reader is not at the end of the stream yet. + /// This may happen for example because fewer bytes are actually available right now + /// (e. g. being close to end-of-file) or because read() was interrupted by a signal. + /// /// No guarantees are provided about the contents of `buf` when this /// function is called, implementations cannot rely on any property of the /// contents of `buf` being true. It is recommended that *implementations*