diff options
Diffstat (limited to 'compiler')
51 files changed, 541 insertions, 594 deletions
diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs index d4718339ffe..95f969d7691 100644 --- a/compiler/rustc_ast_pretty/src/pp.rs +++ b/compiler/rustc_ast_pretty/src/pp.rs @@ -485,12 +485,9 @@ impl Printer { } fn get_top(&mut self) -> PrintStackElem { - match self.print_stack.last() { - Some(el) => *el, - None => { - PrintStackElem { offset: 0, pbreak: PrintStackBreak::Broken(Breaks::Inconsistent) } - } - } + *self.print_stack.last().unwrap_or({ + &PrintStackElem { offset: 0, pbreak: PrintStackBreak::Broken(Breaks::Inconsistent) } + }) } fn print_begin(&mut self, b: BeginToken, l: isize) { diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index ff81b5eca13..b69b00d65f2 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -385,7 +385,7 @@ pub mod printf { if let Start = state { match c { '1'..='9' => { - let end = at_next_cp_while(next, is_digit); + let end = at_next_cp_while(next, char::is_ascii_digit); match end.next_cp() { // Yes, this *is* the parameter. Some(('$', end2)) => { @@ -427,7 +427,7 @@ pub mod printf { move_to!(next); } '1'..='9' => { - let end = at_next_cp_while(next, is_digit); + let end = at_next_cp_while(next, char::is_ascii_digit); state = Prec; width = Some(Num::from_str(at.slice_between(end).unwrap(), None)); move_to!(end); @@ -441,7 +441,7 @@ pub mod printf { } if let WidthArg = state { - let end = at_next_cp_while(at, is_digit); + let end = at_next_cp_while(at, char::is_ascii_digit); match end.next_cp() { Some(('$', end2)) => { state = Prec; @@ -473,7 +473,7 @@ pub mod printf { if let PrecInner = state { match c { '*' => { - let end = at_next_cp_while(next, is_digit); + let end = at_next_cp_while(next, char::is_ascii_digit); match end.next_cp() { Some(('$', end2)) => { state = Length; @@ -488,7 +488,7 @@ pub mod printf { } } '0'..='9' => { - let end = at_next_cp_while(next, is_digit); + let end = at_next_cp_while(next, char::is_ascii_digit); state = Length; precision = Some(Num::from_str(at.slice_between(end).unwrap(), None)); move_to!(end); @@ -563,12 +563,12 @@ pub mod printf { fn at_next_cp_while<F>(mut cur: Cur<'_>, mut pred: F) -> Cur<'_> where - F: FnMut(char) -> bool, + F: FnMut(&char) -> bool, { loop { match cur.next_cp() { Some((c, next)) => { - if pred(c) { + if pred(&c) { cur = next; } else { return cur; @@ -579,14 +579,7 @@ pub mod printf { } } - fn is_digit(c: char) -> bool { - match c { - '0'..='9' => true, - _ => false, - } - } - - fn is_flag(c: char) -> bool { + fn is_flag(c: &char) -> bool { match c { '0' | '-' | '+' | ' ' | '#' | '\'' => true, _ => false, @@ -723,17 +716,11 @@ pub mod shell { } fn is_ident_head(c: char) -> bool { - match c { - 'a'..='z' | 'A'..='Z' | '_' => true, - _ => false, - } + c.is_ascii_alphabetic() || c == '_' } fn is_ident_tail(c: char) -> bool { - match c { - '0'..='9' => true, - c => is_ident_head(c), - } + c.is_ascii_alphanumeric() || c == '_' } #[cfg(test)] diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index f02c30c3ee3..8d131fa294b 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -194,6 +194,18 @@ pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { ); } +pub fn apply_tune_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { + if let Some(tune) = llvm_util::tune_cpu(cx.tcx.sess) { + let tune_cpu = SmallCStr::new(tune); + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + const_cstr!("tune-cpu"), + tune_cpu.as_c_str(), + ); + } +} + /// Sets the `NonLazyBind` LLVM attribute on a given function, /// assuming the codegen options allow skipping the PLT. pub fn non_lazy_bind(sess: &Session, llfn: &'ll Value) { @@ -303,6 +315,9 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: // Without this, ThinLTO won't inline Rust functions into Clang generated // functions (because Clang annotates functions this way too). apply_target_cpu_attr(cx, llfn); + // tune-cpu is only conveyed through the attribute for our purpose. + // The target doesn't care; the subtarget reads our attribute. + apply_tune_cpu_attr(cx, llfn); let features = llvm_target_features(cx.tcx.sess) .map(|s| s.to_string()) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1696f35563d..d3c71ff501b 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -417,7 +417,8 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn apply_target_cpu_attr(&self, llfn: &'ll Value) { - attributes::apply_target_cpu_attr(self, llfn) + attributes::apply_target_cpu_attr(self, llfn); + attributes::apply_tune_cpu_attr(self, llfn); } fn create_used_variable(&self) { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 1237b39b300..b5f83118d0c 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -116,6 +116,9 @@ impl ExtraBackendMethods for LlvmCodegenBackend { fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str { llvm_util::target_cpu(sess) } + fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str> { + llvm_util::tune_cpu(sess) + } } impl WriteBackendMethods for LlvmCodegenBackend { diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index d42020047fd..a4605f46309 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -202,11 +202,7 @@ pub(crate) fn print(req: PrintRequest, sess: &Session) { } } -pub fn target_cpu(sess: &Session) -> &str { - let name = match sess.opts.cg.target_cpu { - Some(ref s) => &**s, - None => &*sess.target.target.options.cpu, - }; +fn handle_native(name: &str) -> &str { if name != "native" { return name; } @@ -217,3 +213,19 @@ pub fn target_cpu(sess: &Session) -> &str { str::from_utf8(slice::from_raw_parts(ptr as *const u8, len)).unwrap() } } + +pub fn target_cpu(sess: &Session) -> &str { + let name = match sess.opts.cg.target_cpu { + Some(ref s) => &**s, + None => &*sess.target.target.options.cpu, + }; + + handle_native(name) +} + +pub fn tune_cpu(sess: &Session) -> Option<&str> { + match sess.opts.debugging_opts.tune_cpu { + Some(ref s) => Some(handle_native(&**s)), + None => None, + } +} diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 703a17b200a..353189ae1f0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -12,9 +12,9 @@ use crate::MemFlags; use rustc_ast as ast; use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; -use rustc_middle::mir; use rustc_middle::mir::interpret::ConstValue; use rustc_middle::mir::AssertKind; +use rustc_middle::mir::{self, SwitchTargets}; use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; @@ -24,8 +24,6 @@ use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; use rustc_target::abi::{self, LayoutOf}; use rustc_target::spec::abi::Abi; -use std::borrow::Cow; - /// Used by `FunctionCx::codegen_terminator` for emitting common patterns /// e.g., creating a basic block, calling a function, etc. struct TerminatorCodegenHelper<'tcx> { @@ -198,42 +196,37 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mut bx: Bx, discr: &mir::Operand<'tcx>, switch_ty: Ty<'tcx>, - values: &Cow<'tcx, [u128]>, - targets: &Vec<mir::BasicBlock>, + targets: &SwitchTargets, ) { let discr = self.codegen_operand(&mut bx, &discr); // `switch_ty` is redundant, sanity-check that. assert_eq!(discr.layout.ty, switch_ty); - if targets.len() == 2 { - // If there are two targets, emit br instead of switch - let lltrue = helper.llblock(self, targets[0]); - let llfalse = helper.llblock(self, targets[1]); + helper.maybe_sideeffect(self.mir, &mut bx, targets.all_targets()); + + let mut target_iter = targets.iter(); + if target_iter.len() == 1 { + // If there are two targets (one conditional, one fallback), emit br instead of switch + let (test_value, target) = target_iter.next().unwrap(); + let lltrue = helper.llblock(self, target); + let llfalse = helper.llblock(self, targets.otherwise()); if switch_ty == bx.tcx().types.bool { - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); // Don't generate trivial icmps when switching on bool - if let [0] = values[..] { - bx.cond_br(discr.immediate(), llfalse, lltrue); - } else { - assert_eq!(&values[..], &[1]); - bx.cond_br(discr.immediate(), lltrue, llfalse); + match test_value { + 0 => bx.cond_br(discr.immediate(), llfalse, lltrue), + 1 => bx.cond_br(discr.immediate(), lltrue, llfalse), + _ => bug!(), } } else { let switch_llty = bx.immediate_backend_type(bx.layout_of(switch_ty)); - let llval = bx.const_uint_big(switch_llty, values[0]); + let llval = bx.const_uint_big(switch_llty, test_value); let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval); - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); bx.cond_br(cmp, lltrue, llfalse); } } else { - helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); - let (otherwise, targets) = targets.split_last().unwrap(); bx.switch( discr.immediate(), - helper.llblock(self, *otherwise), - values - .iter() - .zip(targets) - .map(|(&value, target)| (value, helper.llblock(self, *target))), + helper.llblock(self, targets.otherwise()), + target_iter.map(|(value, target)| (value, helper.llblock(self, target))), ); } } @@ -975,8 +968,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { helper.funclet_br(self, &mut bx, target); } - mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => { - self.codegen_switchint_terminator(helper, bx, discr, switch_ty, values, targets); + mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref targets } => { + self.codegen_switchint_terminator(helper, bx, discr, switch_ty, targets); } mir::TerminatorKind::Return => { diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 48c07b00894..1f26280b7cc 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -124,4 +124,5 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se opt_level: config::OptLevel, ) -> Arc<dyn Fn() -> Result<Self::TargetMachine, String> + Send + Sync>; fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str; + fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str>; } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 07ce9d0cd94..6553d0ecfdb 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -585,6 +585,7 @@ fn test_debugging_options_tracking_hash() { tracked!(symbol_mangling_version, SymbolManglingVersion::V0); tracked!(teach, true); tracked!(thinlto, Some(true)); + tracked!(tune_cpu, Some(String::from("abc"))); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); tracked!(treat_err_as_bug, Some(1)); tracked!(unleash_the_miri_inside_of_you, true); diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 60705f68681..05b8dad3097 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -94,7 +94,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, adt_def => { cdata.get_adt_def(def_id.index, tcx) } adt_destructor => { let _ = cdata; - tcx.calculate_dtor(def_id, &mut |_,_| Ok(())) + tcx.calculate_dtor(def_id, |_,_| Ok(())) } variances_of => { tcx.arena.alloc_from_iter(cdata.get_item_variances(def_id.index)) } associated_item_def_ids => { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 0878e9313d8..b5cdd7edb8d 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,9 +1,10 @@ //! Values computed by queries that use MIR. -use crate::mir::{Body, Promoted}; +use crate::mir::{abstract_const, Body, Promoted}; use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; +use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::bit_set::BitMatrix; @@ -407,7 +408,12 @@ pub struct CoverageInfo { pub num_expressions: u32, } +/// Shims which make dealing with `WithOptConstParam` easier. +/// +/// For more information on why this is needed, consider looking +/// at the docs for `WithOptConstParam` itself. impl<'tcx> TyCtxt<'tcx> { + #[inline] pub fn mir_borrowck_opt_const_arg( self, def: ty::WithOptConstParam<LocalDefId>, @@ -419,6 +425,7 @@ impl<'tcx> TyCtxt<'tcx> { } } + #[inline] pub fn mir_const_qualif_opt_const_arg( self, def: ty::WithOptConstParam<LocalDefId>, @@ -430,7 +437,8 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn promoted_mir_of_opt_const_arg( + #[inline] + pub fn promoted_mir_opt_const_arg( self, def: ty::WithOptConstParam<DefId>, ) -> &'tcx IndexVec<Promoted, Body<'tcx>> { @@ -440,4 +448,28 @@ impl<'tcx> TyCtxt<'tcx> { self.promoted_mir(def.did) } } + + #[inline] + pub fn optimized_mir_opt_const_arg( + self, + def: ty::WithOptConstParam<DefId>, + ) -> &'tcx Body<'tcx> { + if let Some((did, param_did)) = def.as_const_arg() { + self.optimized_mir_of_const_arg((did, param_did)) + } else { + self.optimized_mir(def.did) + } + } + + #[inline] + pub fn mir_abstract_const_opt_const_arg( + self, + def: ty::WithOptConstParam<DefId>, + ) -> Result<Option<&'tcx [abstract_const::Node<'tcx>]>, ErrorReported> { + if let Some((did, param_did)) = def.as_const_arg() { + self.mir_abstract_const_of_const_arg((did, param_did)) + } else { + self.mir_abstract_const(def.did) + } + } } diff --git a/compiler/rustc_middle/src/mir/terminator/mod.rs b/compiler/rustc_middle/src/mir/terminator/mod.rs index 8909f02270c..e1071454e65 100644 --- a/compiler/rustc_middle/src/mir/terminator/mod.rs +++ b/compiler/rustc_middle/src/mir/terminator/mod.rs @@ -1,6 +1,7 @@ use crate::mir::interpret::Scalar; use crate::ty::{self, Ty, TyCtxt}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use smallvec::{smallvec, SmallVec}; use super::{ AssertMessage, BasicBlock, InlineAsmOperand, Operand, Place, SourceInfo, Successors, @@ -16,6 +17,87 @@ use std::slice; pub use super::query::*; +#[derive(Debug, Clone, TyEncodable, TyDecodable, HashStable, PartialEq)] +pub struct SwitchTargets { + /// Possible values. The locations to branch to in each case + /// are found in the corresponding indices from the `targets` vector. + values: SmallVec<[u128; 1]>, + + /// Possible branch sites. The last element of this vector is used + /// for the otherwise branch, so targets.len() == values.len() + 1 + /// should hold. + // + // This invariant is quite non-obvious and also could be improved. + // One way to make this invariant is to have something like this instead: + // + // branches: Vec<(ConstInt, BasicBlock)>, + // otherwise: Option<BasicBlock> // exhaustive if None + // + // However we’ve decided to keep this as-is until we figure a case + // where some other approach seems to be strictly better than other. + targets: SmallVec<[BasicBlock; 2]>, +} + +impl SwitchTargets { + /// Creates switch targets from an iterator of values and target blocks. + /// + /// The iterator may be empty, in which case the `SwitchInt` instruction is equivalent to + /// `goto otherwise;`. + pub fn new(targets: impl Iterator<Item = (u128, BasicBlock)>, otherwise: BasicBlock) -> Self { + let (values, mut targets): (SmallVec<_>, SmallVec<_>) = targets.unzip(); + targets.push(otherwise); + Self { values: values.into(), targets } + } + + /// Builds a switch targets definition that jumps to `then` if the tested value equals `value`, + /// and to `else_` if not. + pub fn static_if(value: u128, then: BasicBlock, else_: BasicBlock) -> Self { + Self { values: smallvec![value], targets: smallvec![then, else_] } + } + + /// Returns the fallback target that is jumped to when none of the values match the operand. + pub fn otherwise(&self) -> BasicBlock { + *self.targets.last().unwrap() + } + + /// Returns an iterator over the switch targets. + /// + /// The iterator will yield tuples containing the value and corresponding target to jump to, not + /// including the `otherwise` fallback target. + /// + /// Note that this may yield 0 elements. Only the `otherwise` branch is mandatory. + pub fn iter(&self) -> SwitchTargetsIter<'_> { + SwitchTargetsIter { inner: self.values.iter().zip(self.targets.iter()) } + } + + /// Returns a slice with all possible jump targets (including the fallback target). + pub fn all_targets(&self) -> &[BasicBlock] { + &self.targets + } + + pub fn all_targets_mut(&mut self) -> &mut [BasicBlock] { + &mut self.targets + } +} + +pub struct SwitchTargetsIter<'a> { + inner: iter::Zip<slice::Iter<'a, u128>, slice::Iter<'a, BasicBlock>>, +} + +impl<'a> Iterator for SwitchTargetsIter<'a> { + type Item = (u128, BasicBlock); + + fn next(&mut self) -> Option<Self::Item> { + self.inner.next().map(|(val, bb)| (*val, *bb)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.inner.size_hint() + } +} + +impl<'a> ExactSizeIterator for SwitchTargetsIter<'a> {} + #[derive(Clone, TyEncodable, TyDecodable, HashStable, PartialEq)] pub enum TerminatorKind<'tcx> { /// Block should have one successor in the graph; we jump there. @@ -32,23 +114,7 @@ pub enum TerminatorKind<'tcx> { /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing. switch_ty: Ty<'tcx>, - /// Possible values. The locations to branch to in each case - /// are found in the corresponding indices from the `targets` vector. - values: Cow<'tcx, [u128]>, - - /// Possible branch sites. The last element of this vector is used - /// for the otherwise branch, so targets.len() == values.len() + 1 - /// should hold. - // - // This invariant is quite non-obvious and also could be improved. - // One way to make this invariant is to have something like this instead: - // - // branches: Vec<(ConstInt, BasicBlock)>, - // otherwise: Option<BasicBlock> // exhaustive if None - // - // However we’ve decided to keep this as-is until we figure a case - // where some other approach seems to be strictly better than other. - targets: Vec<BasicBlock>, + targets: SwitchTargets, }, /// Indicates that the landing pad is finished and unwinding should @@ -227,12 +293,10 @@ impl<'tcx> TerminatorKind<'tcx> { t: BasicBlock, f: BasicBlock, ) -> TerminatorKind<'tcx> { - static BOOL_SWITCH_FALSE: &[u128] = &[0]; TerminatorKind::SwitchInt { discr: cond, switch_ty: tcx.types.bool, - values: From::from(BOOL_SWITCH_FALSE), - targets: vec![f, t], + targets: SwitchTargets::static_if(0, f, t), } } @@ -263,7 +327,7 @@ impl<'tcx> TerminatorKind<'tcx> { | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => { Some(t).into_iter().chain(slice::from_ref(u)) } - SwitchInt { ref targets, .. } => None.into_iter().chain(&targets[..]), + SwitchInt { ref targets, .. } => None.into_iter().chain(&targets.targets[..]), FalseEdge { ref real_target, ref imaginary_target } => { Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)) } @@ -297,7 +361,7 @@ impl<'tcx> TerminatorKind<'tcx> { | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { Some(t).into_iter().chain(slice::from_mut(u)) } - SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets[..]), + SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets[..]), FalseEdge { ref mut real_target, ref mut imaginary_target } => { Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) } @@ -469,11 +533,12 @@ impl<'tcx> TerminatorKind<'tcx> { match *self { Return | Resume | Abort | Unreachable | GeneratorDrop => vec![], Goto { .. } => vec!["".into()], - SwitchInt { ref values, switch_ty, .. } => ty::tls::with(|tcx| { + SwitchInt { ref targets, switch_ty, .. } => ty::tls::with(|tcx| { let param_env = ty::ParamEnv::empty(); let switch_ty = tcx.lift(&switch_ty).unwrap(); let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size; - values + targets + .values .iter() .map(|&u| { ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty) diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index ad2eae0298c..9297aed66a4 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -21,10 +21,9 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { let kind = match self.kind { Goto { target } => Goto { target }, - SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt { + SwitchInt { ref discr, switch_ty, ref targets } => SwitchInt { discr: discr.fold_with(folder), switch_ty: switch_ty.fold_with(folder), - values: values.clone(), targets: targets.clone(), }, Drop { ref place, target, unwind } => { diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 9a6bfa10189..1adebe30b5e 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -453,7 +453,6 @@ macro_rules! make_mir_visitor { TerminatorKind::SwitchInt { discr, switch_ty, - values: _, targets: _ } => { self.visit_operand(discr, location); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f069faed9e2..cccfc5eced9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2953,13 +2953,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair. pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { match instance { - ty::InstanceDef::Item(def) => { - if let Some((did, param_did)) = def.as_const_arg() { - self.optimized_mir_of_const_arg((did, param_did)) - } else { - self.optimized_mir(def.did) - } - } + ty::InstanceDef::Item(def) => self.optimized_mir_opt_const_arg(def), ty::InstanceDef::VtableShim(..) | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::Intrinsic(..) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index d8ea2f67393..5ac12dfa993 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -341,7 +341,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn calculate_dtor( self, adt_did: DefId, - validate: &mut dyn FnMut(Self, DefId) -> Result<(), ErrorReported>, + validate: impl Fn(Self, DefId) -> Result<(), ErrorReported>, ) -> Option<ty::Destructor> { let drop_trait = self.lang_items().drop_trait()?; self.ensure().coherent_trait(drop_trait); diff --git a/compiler/rustc_mir/src/borrow_check/invalidation.rs b/compiler/rustc_mir/src/borrow_check/invalidation.rs index c84ccafaff5..8c05e6fd5d0 100644 --- a/compiler/rustc_mir/src/borrow_check/invalidation.rs +++ b/compiler/rustc_mir/src/borrow_check/invalidation.rs @@ -117,7 +117,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { self.check_activations(location); match &terminator.kind { - TerminatorKind::SwitchInt { ref discr, switch_ty: _, values: _, targets: _ } => { + TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => { self.consume_operand(location, discr); } TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => { diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 9b34db1de40..4b7af271bae 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -671,7 +671,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc self.check_activations(loc, span, flow_state); match term.kind { - TerminatorKind::SwitchInt { ref discr, switch_ty: _, values: _, targets: _ } => { + TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => { self.consume_operand(loc, (discr, span), flow_state); } TerminatorKind::Drop { place: ref drop_place, target: _, unwind: _ } => { diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index f8a8801595a..4fc1c570e46 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -1777,7 +1777,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.assert_iscleanup(body, block_data, target, is_cleanup) } TerminatorKind::SwitchInt { ref targets, .. } => { - for target in targets { + for target in targets.all_targets() { self.assert_iscleanup(body, block_data, *target, is_cleanup); } } diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index 57aa216850a..6ef73b04238 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -343,7 +343,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( // deny-by-default lint _ => { if let Some(p) = cid.promoted { - let span = tcx.promoted_mir_of_opt_const_arg(def.to_global())[p].span; + let span = tcx.promoted_mir_opt_const_arg(def.to_global())[p].span; if let err_inval!(ReferencedConstant) = err.error { Err(err.report_as_error( tcx.at(span), diff --git a/compiler/rustc_mir/src/dataflow/framework/direction.rs b/compiler/rustc_mir/src/dataflow/framework/direction.rs index ca2bb6e0bf7..8a9ced91eb3 100644 --- a/compiler/rustc_mir/src/dataflow/framework/direction.rs +++ b/compiler/rustc_mir/src/dataflow/framework/direction.rs @@ -1,5 +1,5 @@ use rustc_index::bit_set::BitSet; -use rustc_middle::mir::{self, BasicBlock, Location}; +use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets}; use rustc_middle::ty::TyCtxt; use std::ops::RangeInclusive; @@ -488,11 +488,10 @@ impl Direction for Forward { } } - SwitchInt { ref targets, ref values, ref discr, switch_ty: _ } => { + SwitchInt { ref targets, ref discr, switch_ty: _ } => { let mut applier = SwitchIntEdgeEffectApplier { exit_state, - targets: targets.as_ref(), - values: values.as_ref(), + targets, propagate, effects_applied: false, }; @@ -504,8 +503,8 @@ impl Direction for Forward { } = applier; if !effects_applied { - for &target in targets.iter() { - propagate(target, exit_state); + for target in targets.all_targets() { + propagate(*target, exit_state); } } } @@ -515,8 +514,7 @@ impl Direction for Forward { struct SwitchIntEdgeEffectApplier<'a, D, F> { exit_state: &'a mut D, - values: &'a [u128], - targets: &'a [BasicBlock], + targets: &'a SwitchTargets, propagate: F, effects_applied: bool, @@ -531,7 +529,7 @@ where assert!(!self.effects_applied); let mut tmp = None; - for (&value, &target) in self.values.iter().zip(self.targets.iter()) { + for (value, target) in self.targets.iter() { let tmp = opt_clone_from_or_clone(&mut tmp, self.exit_state); apply_edge_effect(tmp, SwitchIntTarget { value: Some(value), target }); (self.propagate)(target, tmp); @@ -539,7 +537,7 @@ where // Once we get to the final, "otherwise" branch, there is no need to preserve `exit_state`, // so pass it directly to `apply_edge_effect` to save a clone of the dataflow state. - let otherwise = self.targets.last().copied().unwrap(); + let otherwise = self.targets.otherwise(); apply_edge_effect(self.exit_state, SwitchIntTarget { value: None, target: otherwise }); (self.propagate)(otherwise, self.exit_state); diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 93da6e3d38a..ec1195d3703 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -477,16 +477,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } trace!("load mir(instance={:?}, promoted={:?})", instance, promoted); if let Some(promoted) = promoted { - return Ok(&self.tcx.promoted_mir_of_opt_const_arg(def)[promoted]); + return Ok(&self.tcx.promoted_mir_opt_const_arg(def)[promoted]); } match instance { ty::InstanceDef::Item(def) => { if self.tcx.is_mir_available(def.did) { - if let Some((did, param_did)) = def.as_const_arg() { - Ok(self.tcx.optimized_mir_of_const_arg((did, param_did))) - } else { - Ok(self.tcx.optimized_mir(def.did)) - } + Ok(self.tcx.optimized_mir_opt_const_arg(def)) } else { throw_unsup!(NoMirFor(def.did)) } diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_mir/src/interpret/terminator.rs index 9f200ca62b8..bb11c2a23bd 100644 --- a/compiler/rustc_mir/src/interpret/terminator.rs +++ b/compiler/rustc_mir/src/interpret/terminator.rs @@ -24,16 +24,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Goto { target } => self.go_to_block(target), - SwitchInt { ref discr, ref values, ref targets, switch_ty } => { + SwitchInt { ref discr, ref targets, switch_ty } => { let discr = self.read_immediate(self.eval_operand(discr, None)?)?; trace!("SwitchInt({:?})", *discr); assert_eq!(discr.layout.ty, switch_ty); // Branch to the `otherwise` case by default, if no match is found. - assert!(!targets.is_empty()); - let mut target_block = targets[targets.len() - 1]; + assert!(!targets.iter().is_empty()); + let mut target_block = targets.otherwise(); - for (index, &const_int) in values.iter().enumerate() { + for (const_int, target) in targets.iter() { // Compare using binary_op, to also support pointer values let res = self .overflowing_binary_op( @@ -43,7 +43,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )? .0; if res.to_bool()? { - target_block = targets[index]; + target_block = target; break; } } diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 7e12cc9176e..417176564b9 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -197,6 +197,7 @@ use rustc_session::config::EntryFnType; use rustc_span::source_map::{dummy_spanned, respan, Span, Spanned, DUMMY_SP}; use smallvec::SmallVec; use std::iter; +use std::ops::Range; use std::path::PathBuf; #[derive(PartialEq)] @@ -210,9 +211,8 @@ pub enum MonoItemCollectionMode { pub struct InliningMap<'tcx> { // Maps a source mono item to the range of mono items // accessed by it. - // The two numbers in the tuple are the start (inclusive) and - // end index (exclusive) within the `targets` vecs. - index: FxHashMap<MonoItem<'tcx>, (usize, usize)>, + // The range selects elements within the `targets` vecs. + index: FxHashMap<MonoItem<'tcx>, Range<usize>>, targets: Vec<MonoItem<'tcx>>, // Contains one bit per mono item in the `targets` field. That bit @@ -245,7 +245,7 @@ impl<'tcx> InliningMap<'tcx> { } let end_index = self.targets.len(); - assert!(self.index.insert(source, (start_index, end_index)).is_none()); + assert!(self.index.insert(source, start_index..end_index).is_none()); } // Internally iterate over all items referenced by `source` which will be @@ -254,9 +254,9 @@ impl<'tcx> InliningMap<'tcx> { where F: FnMut(MonoItem<'tcx>), { - if let Some(&(start_index, end_index)) = self.index.get(&source) { - for (i, candidate) in self.targets[start_index..end_index].iter().enumerate() { - if self.inlines.contains(start_index + i) { + if let Some(range) = self.index.get(&source) { + for (i, candidate) in self.targets[range.clone()].iter().enumerate() { + if self.inlines.contains(range.start + i) { f(*candidate); } } @@ -268,8 +268,8 @@ impl<'tcx> InliningMap<'tcx> { where F: FnMut(MonoItem<'tcx>, &[MonoItem<'tcx>]), { - for (&accessor, &(start_index, end_index)) in &self.index { - f(accessor, &self.targets[start_index..end_index]) + for (&accessor, range) in &self.index { + f(accessor, &self.targets[range.clone()]) } } } diff --git a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs b/compiler/rustc_mir/src/transform/check_const_item_mutation.rs index 26993a6b941..fb89b36060a 100644 --- a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs +++ b/compiler/rustc_mir/src/transform/check_const_item_mutation.rs @@ -53,7 +53,7 @@ impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> { // // #[const_mutation_allowed] // pub const LOG: Log = Log { msg: "" }; - match self.tcx.calculate_dtor(def_id, &mut |_, _| Ok(())) { + match self.tcx.calculate_dtor(def_id, |_, _| Ok(())) { Some(_) => None, None => Some(def_id), } diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs index 237a5c7864b..f97dcf4852d 100644 --- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs +++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs @@ -1,7 +1,7 @@ use crate::{transform::MirPass, util::patch::MirPatch}; use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; -use std::{borrow::Cow, fmt::Debug}; +use std::fmt::Debug; use super::simplify::simplify_cfg; @@ -95,15 +95,17 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { StatementKind::Assign(box (Place::from(not_equal_temp), not_equal_rvalue)), ); - let (mut targets_to_jump_to, values_to_jump_to): (Vec<_>, Vec<_>) = opt_to_apply + let new_targets = opt_to_apply .infos .iter() .flat_map(|x| x.second_switch_info.targets_with_values.iter()) - .cloned() - .unzip(); + .cloned(); + + let targets = SwitchTargets::new( + new_targets, + opt_to_apply.infos[0].first_switch_info.otherwise_bb, + ); - // add otherwise case in the end - targets_to_jump_to.push(opt_to_apply.infos[0].first_switch_info.otherwise_bb); // new block that jumps to the correct discriminant case. This block is switched to if the discriminants are equal let new_switch_data = BasicBlockData::new(Some(Terminator { source_info: opt_to_apply.infos[0].second_switch_info.discr_source_info, @@ -111,8 +113,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { // the first and second discriminants are equal, so just pick one discr: Operand::Copy(first_descriminant_place), switch_ty: discr_type, - values: Cow::from(values_to_jump_to), - targets: targets_to_jump_to, + targets, }, })); @@ -176,7 +177,7 @@ struct SwitchDiscriminantInfo<'tcx> { /// The basic block that the otherwise branch points to otherwise_bb: BasicBlock, /// Target along with the value being branched from. Otherwise is not included - targets_with_values: Vec<(BasicBlock, u128)>, + targets_with_values: Vec<(u128, BasicBlock)>, discr_source_info: SourceInfo, /// The place of the discriminant used in the switch discr_used_in_switch: Place<'tcx>, @@ -211,7 +212,7 @@ impl<'a, 'tcx> Helper<'a, 'tcx> { let discr = self.find_switch_discriminant_info(bb, switch)?; // go through each target, finding a discriminant read, and a switch - let results = discr.targets_with_values.iter().map(|(target, value)| { + let results = discr.targets_with_values.iter().map(|(value, target)| { self.find_discriminant_switch_pairing(&discr, target.clone(), value.clone()) }); @@ -253,7 +254,7 @@ impl<'a, 'tcx> Helper<'a, 'tcx> { } // check that the value being matched on is the same. The - if this_bb_discr_info.targets_with_values.iter().find(|x| x.1 == value).is_none() { + if this_bb_discr_info.targets_with_values.iter().find(|x| x.0 == value).is_none() { trace!("NO: values being matched on are not the same"); return None; } @@ -270,7 +271,7 @@ impl<'a, 'tcx> Helper<'a, 'tcx> { // ``` // We check this by seeing that the value of the first discriminant is the only other discriminant value being used as a target in the second switch if !(this_bb_discr_info.targets_with_values.len() == 1 - && this_bb_discr_info.targets_with_values[0].1 == value) + && this_bb_discr_info.targets_with_values[0].0 == value) { trace!( "NO: The second switch did not have only 1 target (besides otherwise) that had the same value as the value from the first switch that got us here" @@ -296,18 +297,14 @@ impl<'a, 'tcx> Helper<'a, 'tcx> { switch: &Terminator<'tcx>, ) -> Option<SwitchDiscriminantInfo<'tcx>> { match &switch.kind { - TerminatorKind::SwitchInt { discr, targets, values, .. } => { + TerminatorKind::SwitchInt { discr, targets, .. } => { let discr_local = discr.place()?.as_local()?; // the declaration of the discriminant read. Place of this read is being used in the switch let discr_decl = &self.body.local_decls()[discr_local]; let discr_ty = discr_decl.ty; // the otherwise target lies as the last element - let otherwise_bb = targets.get(values.len())?.clone(); - let targets_with_values = targets - .iter() - .zip(values.iter()) - .map(|(t, v)| (t.clone(), v.clone())) - .collect(); + let otherwise_bb = targets.otherwise(); + let targets_with_values = targets.iter().collect(); // find the place of the adt where the discriminant is being read from // assume this is the last statement of the block diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir/src/transform/generator.rs index 924bb4996fc..039d4753a8c 100644 --- a/compiler/rustc_mir/src/transform/generator.rs +++ b/compiler/rustc_mir/src/transform/generator.rs @@ -71,7 +71,6 @@ use rustc_middle::ty::GeneratorSubsts; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt}; use rustc_target::abi::VariantIdx; use rustc_target::spec::PanicStrategy; -use std::borrow::Cow; use std::{iter, ops}; pub struct StateTransform; @@ -839,11 +838,12 @@ fn insert_switch<'tcx>( ) { let default_block = insert_term_block(body, default); let (assign, discr) = transform.get_discr(body); + let switch_targets = + SwitchTargets::new(cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), default_block); let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), switch_ty: transform.discr_ty, - values: Cow::from(cases.iter().map(|&(i, _)| i as u128).collect::<Vec<_>>()), - targets: cases.iter().map(|&(_, d)| d).chain(iter::once(default_block)).collect(), + targets: switch_targets, }; let source_info = SourceInfo::outermost(body.span); diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index bec1eb79047..34aaefdcbea 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -771,7 +771,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { *target = self.update_target(*target); } TerminatorKind::SwitchInt { ref mut targets, .. } => { - for tgt in targets { + for tgt in targets.all_targets_mut() { *tgt = self.update_target(*tgt); } } diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs index dad3812c5cd..8b2d6b09aa8 100644 --- a/compiler/rustc_mir/src/transform/match_branches.rs +++ b/compiler/rustc_mir/src/transform/match_branches.rs @@ -46,10 +46,13 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { discr: Operand::Copy(ref place) | Operand::Move(ref place), switch_ty, ref targets, - ref values, .. - } if targets.len() == 2 && values.len() == 1 && targets[0] != targets[1] => { - (place, values[0], switch_ty, targets[0], targets[1]) + } if targets.iter().len() == 1 => { + let (value, target) = targets.iter().next().unwrap(); + if target == targets.otherwise() { + continue; + } + (place, value, switch_ty, target, targets.otherwise()) } // Only optimize switch int statements _ => continue, diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index b4f5947f5a3..4bafcb2535f 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -287,11 +287,7 @@ fn mir_promoted( // this point, before we steal the mir-const result. // Also this means promotion can rely on all const checks having been done. let _ = tcx.mir_const_qualif_opt_const_arg(def); - let _ = if let Some(param_did) = def.const_param_did { - tcx.mir_abstract_const_of_const_arg((def.did, param_did)) - } else { - tcx.mir_abstract_const(def.did.to_def_id()) - }; + let _ = tcx.mir_abstract_const_opt_const_arg(def.to_global()); let mut body = tcx.mir_const(def).steal(); let mut required_consts = Vec::new(); diff --git a/compiler/rustc_mir/src/transform/simplify_branches.rs b/compiler/rustc_mir/src/transform/simplify_branches.rs index 161856a38ee..5f63c03993d 100644 --- a/compiler/rustc_mir/src/transform/simplify_branches.rs +++ b/compiler/rustc_mir/src/transform/simplify_branches.rs @@ -29,17 +29,16 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { TerminatorKind::SwitchInt { discr: Operand::Constant(ref c), switch_ty, - ref values, ref targets, .. } => { let constant = c.literal.try_eval_bits(tcx, param_env, switch_ty); if let Some(constant) = constant { - let (otherwise, targets) = targets.split_last().unwrap(); - let mut ret = TerminatorKind::Goto { target: *otherwise }; - for (&v, t) in values.iter().zip(targets.iter()) { + let otherwise = targets.otherwise(); + let mut ret = TerminatorKind::Goto { target: otherwise }; + for (v, t) in targets.iter() { if v == constant { - ret = TerminatorKind::Goto { target: *t }; + ret = TerminatorKind::Goto { target: t }; break; } } diff --git a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs index 9f837cf78a6..6372f8960dd 100644 --- a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs +++ b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs @@ -1,8 +1,10 @@ +use std::iter; + use super::MirPass; use rustc_middle::{ mir::{ interpret::Scalar, BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement, - StatementKind, TerminatorKind, + StatementKind, SwitchTargets, TerminatorKind, }, ty::{Ty, TyCtxt}, }; @@ -43,19 +45,21 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { Scalar::Ptr(_) => continue, }; const FALSE: u128 = 0; - let mut new_targets = opt.targets.clone(); - let first_is_false_target = opt.values[0] == FALSE; + + let mut new_targets = opt.targets; + let first_value = new_targets.iter().next().unwrap().0; + let first_is_false_target = first_value == FALSE; match opt.op { BinOp::Eq => { // if the assignment was Eq we want the true case to be first if first_is_false_target { - new_targets.swap(0, 1); + new_targets.all_targets_mut().swap(0, 1); } } BinOp::Ne => { // if the assignment was Ne we want the false case to be first if !first_is_false_target { - new_targets.swap(0, 1); + new_targets.all_targets_mut().swap(0, 1); } } _ => unreachable!(), @@ -96,7 +100,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { } storage_deads_to_remove.push((stmt_idx, opt.bb_idx)); // if we have StorageDeads to remove then make sure to insert them at the top of each target - for bb_idx in new_targets.iter() { + for bb_idx in new_targets.all_targets() { storage_deads_to_insert.push(( *bb_idx, Statement { @@ -107,13 +111,18 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { } } - let terminator = bb.terminator_mut(); + let [bb_cond, bb_otherwise] = match new_targets.all_targets() { + [a, b] => [*a, *b], + e => bug!("expected 2 switch targets, got: {:?}", e), + }; + + let targets = SwitchTargets::new(iter::once((new_value, bb_cond)), bb_otherwise); + let terminator = bb.terminator_mut(); terminator.kind = TerminatorKind::SwitchInt { discr: Operand::Move(opt.to_switch_on), switch_ty: opt.branch_value_ty, - values: vec![new_value].into(), - targets: new_targets, + targets, }; } @@ -138,15 +147,13 @@ impl<'a, 'tcx> OptimizationFinder<'a, 'tcx> { .iter_enumerated() .filter_map(|(bb_idx, bb)| { // find switch - let (place_switched_on, values, targets, place_switched_on_moved) = match &bb - .terminator() - .kind - { - rustc_middle::mir::TerminatorKind::SwitchInt { - discr, values, targets, .. - } => Some((discr.place()?, values, targets, discr.is_move())), - _ => None, - }?; + let (place_switched_on, targets, place_switched_on_moved) = + match &bb.terminator().kind { + rustc_middle::mir::TerminatorKind::SwitchInt { discr, targets, .. } => { + Some((discr.place()?, targets, discr.is_move())) + } + _ => None, + }?; // find the statement that assigns the place being switched on bb.statements.iter().enumerate().rev().find_map(|(stmt_idx, stmt)| { @@ -167,7 +174,6 @@ impl<'a, 'tcx> OptimizationFinder<'a, 'tcx> { branch_value_scalar, branch_value_ty, op: *op, - values: values.clone().into_owned(), targets: targets.clone(), }) } @@ -220,8 +226,6 @@ struct OptimizationInfo<'tcx> { branch_value_ty: Ty<'tcx>, /// Either Eq or Ne op: BinOp, - /// Current values used in the switch target. This needs to be replaced with the branch_value - values: Vec<u128>, /// Current targets used in the switch - targets: Vec<BasicBlock>, + targets: SwitchTargets, } diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir/src/transform/simplify_try.rs index a4e7a5a9453..27bb1def726 100644 --- a/compiler/rustc_mir/src/transform/simplify_try.rs +++ b/compiler/rustc_mir/src/transform/simplify_try.rs @@ -576,15 +576,13 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> { .iter_enumerated() .filter_map(|(bb_idx, bb)| { let (discr_switched_on, targets_and_values) = match &bb.terminator().kind { - TerminatorKind::SwitchInt { targets, discr, values, .. } => { - // if values.len() == targets.len() - 1, we need to include None where no value is present - // such that the zip does not throw away targets. If no `otherwise` case is in targets, the zip will simply throw away the added None - let values_extended = values.iter().map(|x|Some(*x)).chain(once(None)); - let targets_and_values:Vec<_> = targets.iter().zip(values_extended) - .map(|(target, value)| SwitchTargetAndValue{target:*target, value}) + TerminatorKind::SwitchInt { targets, discr, .. } => { + let targets_and_values: Vec<_> = targets.iter() + .map(|(val, target)| SwitchTargetAndValue { target, value: Some(val) }) + .chain(once(SwitchTargetAndValue { target: targets.otherwise(), value: None })) .collect(); - assert_eq!(targets.len(), targets_and_values.len()); - (discr, targets_and_values)}, + (discr, targets_and_values) + }, _ => return None, }; diff --git a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs b/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs index 87906e83ed5..465832c89fd 100644 --- a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs @@ -3,7 +3,8 @@ use crate::transform::MirPass; use rustc_data_structures::stable_set::FxHashSet; use rustc_middle::mir::{ - BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind, + BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets, + TerminatorKind, }; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{Ty, TyCtxt}; @@ -101,21 +102,15 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { trace!("allowed_variants = {:?}", allowed_variants); - if let TerminatorKind::SwitchInt { values, targets, .. } = + if let TerminatorKind::SwitchInt { targets, .. } = &mut body.basic_blocks_mut()[bb].terminator_mut().kind { - // take otherwise out early - let otherwise = targets.pop().unwrap(); - assert_eq!(targets.len(), values.len()); - let mut i = 0; - targets.retain(|_| { - let keep = allowed_variants.contains(&values[i]); - i += 1; - keep - }); - targets.push(otherwise); - - values.to_mut().retain(|var| allowed_variants.contains(var)); + let new_targets = SwitchTargets::new( + targets.iter().filter(|(val, _)| allowed_variants.contains(val)), + targets.otherwise(), + ); + + *targets = new_targets; } else { unreachable!() } diff --git a/compiler/rustc_mir/src/transform/unreachable_prop.rs b/compiler/rustc_mir/src/transform/unreachable_prop.rs index c6426a06ea1..f6d39dae342 100644 --- a/compiler/rustc_mir/src/transform/unreachable_prop.rs +++ b/compiler/rustc_mir/src/transform/unreachable_prop.rs @@ -7,7 +7,6 @@ use crate::transform::MirPass; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use std::borrow::Cow; pub struct UnreachablePropagation; @@ -69,14 +68,15 @@ where { let terminator = match *terminator_kind { TerminatorKind::Goto { target } if predicate(target) => TerminatorKind::Unreachable, - TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => { - let original_targets_len = targets.len(); - let (otherwise, targets) = targets.split_last().unwrap(); + TerminatorKind::SwitchInt { ref discr, switch_ty, ref targets } => { + let otherwise = targets.otherwise(); + + let original_targets_len = targets.iter().len() + 1; let (mut values, mut targets): (Vec<_>, Vec<_>) = - values.iter().zip(targets.iter()).filter(|(_, &t)| !predicate(t)).unzip(); + targets.iter().filter(|(_, bb)| !predicate(*bb)).unzip(); - if !predicate(*otherwise) { - targets.push(*otherwise); + if !predicate(otherwise) { + targets.push(otherwise); } else { values.pop(); } @@ -91,8 +91,10 @@ where TerminatorKind::SwitchInt { discr: discr.clone(), switch_ty, - values: Cow::from(values), - targets, + targets: SwitchTargets::new( + values.iter().copied().zip(targets.iter().copied()), + *targets.last().unwrap(), + ), } } else { return None; diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs index cf51e86c5bc..48477f60ef7 100644 --- a/compiler/rustc_mir/src/transform/validate.rs +++ b/compiler/rustc_mir/src/transform/validate.rs @@ -334,7 +334,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { TerminatorKind::Goto { target } => { self.check_edge(location, *target, EdgeKind::Normal); } - TerminatorKind::SwitchInt { targets, values, switch_ty, discr } => { + TerminatorKind::SwitchInt { targets, switch_ty, discr } => { let ty = discr.ty(&self.body.local_decls, self.tcx); if ty != *switch_ty { self.fail( @@ -345,19 +345,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ), ); } - if targets.len() != values.len() + 1 { - self.fail( - location, - format!( - "encountered `SwitchInt` terminator with {} values, but {} targets (should be values+1)", - values.len(), - targets.len(), - ), - ); - } - for target in targets { - self.check_edge(location, *target, EdgeKind::Normal); + for (_, target) in targets.iter() { + self.check_edge(location, target, EdgeKind::Normal); } + self.check_edge(location, targets.otherwise(), EdgeKind::Normal); } TerminatorKind::Drop { target, unwind, .. } => { self.check_edge(location, *target, EdgeKind::Normal); diff --git a/compiler/rustc_mir/src/util/elaborate_drops.rs b/compiler/rustc_mir/src/util/elaborate_drops.rs index 43fa15d7e49..0e2d8e5495b 100644 --- a/compiler/rustc_mir/src/util/elaborate_drops.rs +++ b/compiler/rustc_mir/src/util/elaborate_drops.rs @@ -588,8 +588,10 @@ where kind: TerminatorKind::SwitchInt { discr: Operand::Move(discr), switch_ty: discr_ty, - values: From::from(values.to_owned()), - targets: blocks, + targets: SwitchTargets::new( + values.iter().copied().zip(blocks.iter().copied()), + *blocks.last().unwrap(), + ), }, }), is_cleanup: unwind.is_cleanup(), @@ -758,8 +760,6 @@ where let elem_size = Place::from(self.new_temp(tcx.types.usize)); let len = Place::from(self.new_temp(tcx.types.usize)); - static USIZE_SWITCH_ZERO: &[u128] = &[0]; - let base_block = BasicBlockData { statements: vec![ self.assign(elem_size, Rvalue::NullaryOp(NullOp::SizeOf, ety)), @@ -771,11 +771,11 @@ where kind: TerminatorKind::SwitchInt { discr: move_(elem_size), switch_ty: tcx.types.usize, - values: From::from(USIZE_SWITCH_ZERO), - targets: vec![ + targets: SwitchTargets::static_if( + 0, self.drop_loop_pair(ety, false, len), self.drop_loop_pair(ety, true, len), - ], + ), }, }), }; diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 02dcf0394f6..c4191900147 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -167,48 +167,42 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let target_blocks = make_target_blocks(self); // Variants is a BitVec of indexes into adt_def.variants. let num_enum_variants = adt_def.variants.len(); - let used_variants = variants.count(); debug_assert_eq!(target_blocks.len(), num_enum_variants + 1); let otherwise_block = *target_blocks.last().unwrap(); - let mut targets = Vec::with_capacity(used_variants + 1); - let mut values = Vec::with_capacity(used_variants); let tcx = self.hir.tcx(); - for (idx, discr) in adt_def.discriminants(tcx) { - if variants.contains(idx) { - debug_assert_ne!( - target_blocks[idx.index()], - otherwise_block, - "no canididates for tested discriminant: {:?}", - discr, - ); - values.push(discr.val); - targets.push(target_blocks[idx.index()]); - } else { - debug_assert_eq!( - target_blocks[idx.index()], - otherwise_block, - "found canididates for untested discriminant: {:?}", - discr, - ); - } - } - targets.push(otherwise_block); - debug!( - "num_enum_variants: {}, tested variants: {:?}, variants: {:?}", - num_enum_variants, values, variants + let switch_targets = SwitchTargets::new( + adt_def.discriminants(tcx).filter_map(|(idx, discr)| { + if variants.contains(idx) { + debug_assert_ne!( + target_blocks[idx.index()], + otherwise_block, + "no canididates for tested discriminant: {:?}", + discr, + ); + Some((discr.val, target_blocks[idx.index()])) + } else { + debug_assert_eq!( + target_blocks[idx.index()], + otherwise_block, + "found canididates for untested discriminant: {:?}", + discr, + ); + None + } + }), + otherwise_block, ); + debug!("num_enum_variants: {}, variants: {:?}", num_enum_variants, variants); let discr_ty = adt_def.repr.discr_type().to_ty(tcx); let discr = self.temp(discr_ty, test.span); self.cfg.push_assign(block, source_info, discr, Rvalue::Discriminant(place)); - assert_eq!(values.len() + 1, targets.len()); self.cfg.terminate( block, source_info, TerminatorKind::SwitchInt { discr: Operand::Move(discr), switch_ty: discr_ty, - values: From::from(values), - targets, + targets: switch_targets, }, ); } @@ -230,11 +224,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } else { // The switch may be inexhaustive so we have a catch all block debug_assert_eq!(options.len() + 1, target_blocks.len()); + let otherwise_block = *target_blocks.last().unwrap(); + let switch_targets = SwitchTargets::new( + options.values().copied().zip(target_blocks), + otherwise_block, + ); TerminatorKind::SwitchInt { discr: Operand::Copy(place), switch_ty, - values: options.values().copied().collect(), - targets: target_blocks, + targets: switch_targets, } }; self.cfg.terminate(block, source_info, terminator); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index e3cf6d12bd5..774a147c114 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -469,24 +469,17 @@ impl<'a> Resolver<'a> { ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => { let mut err = self.session.struct_span_err( span, - "generic parameters must not be used inside of non-trivial constant values", - ); - err.span_label( - span, - &format!( - "non-trivial anonymous constants must not depend on the parameter `{}`", - name - ), + "generic parameters may not be used in const operations", ); + err.span_label(span, &format!("cannot perform const operation using `{}`", name)); if is_type { - err.note("type parameters are currently not permitted in anonymous constants"); + err.note("type parameters may not be used in const expressions"); } else { - err.help( - &format!("it is currently only allowed to use either `{0}` or `{{ {0} }}` as generic constants", - name - ) - ); + err.help(&format!( + "const parameters may only be used as standalone arguments, i.e. `{}`", + name + )); } err diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index fe8f5926385..6677a5ffe28 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -218,7 +218,7 @@ enum ResolutionError<'a> { ParamInTyOfConstParam(Symbol), /// constant values inside of type parameter defaults must not depend on generic parameters. ParamInAnonConstInTyDefault(Symbol), - /// generic parameters must not be used inside of non-trivial constant values. + /// generic parameters must not be used inside const evaluations. /// /// This error is only emitted when using `min_const_generics`. ParamInNonTrivialAnonConst { name: Symbol, is_type: bool }, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index a106007c274..627adcceb3f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1078,6 +1078,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "show extended diagnostic help (default: no)"), terminal_width: Option<usize> = (None, parse_opt_uint, [UNTRACKED], "set the current terminal width"), + tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED], + "select processor to schedule for (`rustc --print target-cpus` for details)"), thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED], "enable ThinLTO when possible"), // We default to 1 here since we want to behave like diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs index 0234ff55f01..98e42f6c37c 100644 --- a/compiler/rustc_target/src/spec/windows_gnu_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs @@ -11,6 +11,10 @@ pub fn opts() -> TargetOptions { "-fno-use-linker-plugin".to_string(), // Always enable DEP (NX bit) when it is available "-Wl,--nxcompat".to_string(), + // Enable ASLR + "-Wl,--dynamicbase".to_string(), + // ASLR will rebase it anyway so leaving that option enabled only leads to confusion + "-Wl,--disable-auto-image-base".to_string(), ], ); diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs index e93755d1aa4..c901102ed6c 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs @@ -3,7 +3,10 @@ use crate::spec::{LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_gnu_base::opts(); base.cpu = "x86-64".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + let gcc_pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + gcc_pre_link_args.push("-m64".to_string()); + // Use high-entropy 64 bit address space for ASLR + gcc_pre_link_args.push("-Wl,--high-entropy-va".to_string()); base.pre_link_args .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pep".to_string()]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs index b288271406c..a775cfc4f79 100644 --- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs @@ -3,7 +3,10 @@ use crate::spec::{LinkerFlavor, LldFlavor, Target}; pub fn target() -> Target { let mut base = super::windows_uwp_gnu_base::opts(); base.cpu = "x86-64".to_string(); - base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + let gcc_pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); + gcc_pre_link_args.push("-m64".to_string()); + // Use high-entropy 64 bit address space for ASLR + gcc_pre_link_args.push("-Wl,--high-entropy-va".to_string()); base.pre_link_args .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pep".to_string()]); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 3828cf4d302..1e1eb16faf4 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -147,11 +147,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( if concrete.is_ok() && substs.has_param_types_or_consts() { match infcx.tcx.def_kind(def.did) { DefKind::AnonConst => { - let mir_body = if let Some(def) = def.as_const_arg() { - infcx.tcx.optimized_mir_of_const_arg(def) - } else { - infcx.tcx.optimized_mir(def.did) - }; + let mir_body = infcx.tcx.optimized_mir_opt_const_arg(def); if mir_body.is_polymorphic { future_compat_lint(); @@ -212,13 +208,7 @@ impl AbstractConst<'tcx> { def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>, ) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> { - let inner = match (def.did.as_local(), def.const_param_did) { - (Some(did), Some(param_did)) => { - tcx.mir_abstract_const_of_const_arg((did, param_did))? - } - _ => tcx.mir_abstract_const(def.did)?, - }; - + let inner = tcx.mir_abstract_const_opt_const_arg(def)?; Ok(inner.map(|inner| AbstractConst { inner, substs })) } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 27751eb554d..97dd180b27b 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -120,7 +120,8 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { &mut self, selcx: &mut SelectionContext<'a, 'tcx>, ) -> Result<(), Vec<FulfillmentError<'tcx>>> { - debug!("select(obligation-forest-size={})", self.predicates.len()); + let span = debug_span!("select", obligation_forest_size = ?self.predicates.len()); + let _enter = span.enter(); let mut errors = Vec::new(); @@ -173,7 +174,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { projection_ty: ty::ProjectionTy<'tcx>, cause: ObligationCause<'tcx>, ) -> Ty<'tcx> { - debug!("normalize_projection_type(projection_ty={:?})", projection_ty); + debug!(?projection_ty, "normalize_projection_type"); debug_assert!(!projection_ty.has_escaping_bound_vars()); @@ -191,7 +192,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { ); self.register_predicate_obligations(infcx, obligations); - debug!("normalize_projection_type: result={:?}", normalized_ty); + debug!(?normalized_ty); normalized_ty } @@ -205,7 +206,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { // debug output much nicer to read and so on. let obligation = infcx.resolve_vars_if_possible(&obligation); - debug!("register_predicate_obligation(obligation={:?})", obligation); + debug!(?obligation, "register_predicate_obligation"); assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot); @@ -342,7 +343,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate); } - debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause); + debug!(?obligation, ?obligation.cause, "process_obligation"); let infcx = self.selcx.infcx(); @@ -509,7 +510,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { } ty::PredicateAtom::ConstEquate(c1, c2) => { - debug!("equating consts: c1={:?} c2={:?}", c1, c2); + debug!(?c1, ?c2, "equating consts"); if self.selcx.tcx().features().const_evaluatable_checked { // FIXME: we probably should only try to unify abstract constants // if the constants depend on generic parameters. @@ -601,6 +602,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { } } + #[instrument(level = "debug", skip(self, obligation, stalled_on))] fn process_trait_obligation( &mut self, obligation: &PredicateObligation<'tcx>, @@ -613,8 +615,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { // FIXME: consider caching errors too. if infcx.predicate_must_hold_considering_regions(obligation) { debug!( - "selecting trait `{:?}` at depth {} evaluated to holds", - obligation.predicate, obligation.recursion_depth + "selecting trait at depth {} evaluated to holds", + obligation.recursion_depth ); return ProcessResult::Changed(vec![]); } @@ -622,17 +624,11 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { match self.selcx.select(&trait_obligation) { Ok(Some(impl_source)) => { - debug!( - "selecting trait `{:?}` at depth {} yielded Ok(Some)", - trait_obligation.predicate, obligation.recursion_depth - ); + debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth); ProcessResult::Changed(mk_pending(impl_source.nested_obligations())) } Ok(None) => { - debug!( - "selecting trait `{:?}` at depth {} yielded Ok(None)", - trait_obligation.predicate, obligation.recursion_depth - ); + debug!("selecting trait at depth {} yielded Ok(None)", obligation.recursion_depth); // This is a bit subtle: for the most part, the // only reason we can fail to make progress on @@ -652,10 +648,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { ProcessResult::Unchanged } Err(selection_err) => { - info!( - "selecting trait `{:?}` at depth {} yielded Err", - trait_obligation.predicate, obligation.recursion_depth - ); + info!("selecting trait at depth {} yielded Err", obligation.recursion_depth); ProcessResult::Error(CodeSelectionError(selection_err)) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index de42aa0e6b7..8dbf7ec51c6 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -157,6 +157,7 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> { /// the given obligations. If the projection cannot be normalized because /// the required trait bound doesn't hold this returned with `obligations` /// being a predicate that cannot be proven. +#[instrument(level = "debug", skip(selcx))] pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &PolyProjectionObligation<'tcx>, @@ -164,8 +165,6 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>, MismatchedProjectionTypes<'tcx>, > { - debug!("poly_project_and_unify_type(obligation={:?})", obligation); - let infcx = selcx.infcx(); infcx.commit_if_ok(|_snapshot| { let placeholder_predicate = @@ -191,7 +190,7 @@ fn project_and_unify_type<'cx, 'tcx>( Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>, MismatchedProjectionTypes<'tcx>, > { - debug!("project_and_unify_type(obligation={:?})", obligation); + debug!(?obligation, "project_and_unify_type"); let mut obligations = vec![]; let normalized_ty = match opt_normalize_projection_type( @@ -207,10 +206,7 @@ fn project_and_unify_type<'cx, 'tcx>( Err(InProgress) => return Ok(Err(InProgress)), }; - debug!( - "project_and_unify_type: normalized_ty={:?} obligations={:?}", - normalized_ty, obligations - ); + debug!(?normalized_ty, ?obligations, "project_and_unify_type result"); let infcx = selcx.infcx(); match infcx @@ -275,6 +271,7 @@ where Normalized { value, obligations } } +#[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -286,16 +283,10 @@ pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>( where T: TypeFoldable<'tcx>, { - debug!("normalize_with_depth(depth={}, value={:?})", depth, value); let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations); let result = ensure_sufficient_stack(|| normalizer.fold(value)); - debug!( - "normalize_with_depth: depth={} result={:?} with {} obligations", - depth, - result, - normalizer.obligations.len() - ); - debug!("normalize_with_depth: depth={} obligations={:?}", depth, normalizer.obligations); + debug!(?result, obligations.len = normalizer.obligations.len()); + debug!(?normalizer.obligations,); result } @@ -396,12 +387,11 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { &mut self.obligations, ); debug!( - "AssocTypeNormalizer: depth={} normalized {:?} to {:?}, \ - now with {} obligations", - self.depth, - ty, - normalized_ty, - self.obligations.len() + ?self.depth, + ?ty, + ?normalized_ty, + obligations.len = ?self.obligations.len(), + "AssocTypeNormalizer: normalized type" ); normalized_ty } @@ -473,6 +463,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( /// often immediately appended to another obligations vector. So now this /// function takes an obligations vector and appends to it directly, which is /// slightly uglier but avoids the need for an extra short-lived allocation. +#[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] fn opt_normalize_projection_type<'a, 'b, 'tcx>( selcx: &'a mut SelectionContext<'b, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -486,13 +477,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( let projection_ty = infcx.resolve_vars_if_possible(&projection_ty); let cache_key = ProjectionCacheKey::new(projection_ty); - debug!( - "opt_normalize_projection_type(\ - projection_ty={:?}, \ - depth={})", - projection_ty, depth - ); - // FIXME(#20304) For now, I am caching here, which is good, but it // means we don't capture the type variables that are created in // the case of ambiguity. Which means we may create a large stream @@ -508,10 +492,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // If we found ambiguity the last time, that means we will continue // to do so until some type in the key changes (and we know it // hasn't, because we just fully resolved it). - debug!( - "opt_normalize_projection_type: \ - found cache entry: ambiguous" - ); + debug!("found cache entry: ambiguous"); return Ok(None); } Err(ProjectionCacheEntry::InProgress) => { @@ -529,10 +510,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // with `A::B`, which can trigger a recursive // normalization. - debug!( - "opt_normalize_projection_type: \ - found cache entry: in-progress" - ); + debug!("found cache entry: in-progress"); return Err(InProgress); } @@ -548,11 +526,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // discarded as duplicated). But when doing trait // evaluation this is not the case, and dropping the trait // evaluations can causes ICEs (e.g., #43132). - debug!( - "opt_normalize_projection_type: \ - found normalized ty `{:?}`", - ty - ); + debug!(?ty, "found normalized ty"); // Once we have inferred everything we need to know, we // can ignore the `obligations` from that point on. @@ -565,10 +539,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( return Ok(Some(ty.value)); } Err(ProjectionCacheEntry::Error) => { - debug!( - "opt_normalize_projection_type: \ - found error" - ); + debug!("opt_normalize_projection_type: found error"); let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth); obligations.extend(result.obligations); return Ok(Some(result.value)); @@ -586,13 +557,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( // an impl, where-clause etc) and hence we must // re-normalize it - debug!( - "opt_normalize_projection_type: \ - projected_ty={:?} \ - depth={} \ - projected_obligations={:?}", - projected_ty, depth, projected_obligations - ); + debug!(?projected_ty, ?depth, ?projected_obligations); let result = if projected_ty.has_projections() { let mut normalizer = AssocTypeNormalizer::new( @@ -604,11 +569,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( ); let normalized_ty = normalizer.fold(&projected_ty); - debug!( - "opt_normalize_projection_type: \ - normalized_ty={:?} depth={}", - normalized_ty, depth - ); + debug!(?normalized_ty, ?depth); Normalized { value: normalized_ty, obligations: projected_obligations } } else { @@ -621,21 +582,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( Ok(Some(result.value)) } Ok(ProjectedTy::NoProgress(projected_ty)) => { - debug!( - "opt_normalize_projection_type: \ - projected_ty={:?} no progress", - projected_ty - ); + debug!(?projected_ty, "opt_normalize_projection_type: no progress"); let result = Normalized { value: projected_ty, obligations: vec![] }; infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone()); // No need to extend `obligations`. Ok(Some(result.value)) } Err(ProjectionTyError::TooManyCandidates) => { - debug!( - "opt_normalize_projection_type: \ - too many candidates" - ); + debug!("opt_normalize_projection_type: too many candidates"); infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key); Ok(None) } @@ -755,15 +709,12 @@ impl<'tcx> Progress<'tcx> { fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self { debug!( - "with_addl_obligations: self.obligations.len={} obligations.len={}", - self.obligations.len(), - obligations.len() + self.obligations.len = ?self.obligations.len(), + obligations.len = obligations.len(), + "with_addl_obligations" ); - debug!( - "with_addl_obligations: self.obligations={:?} obligations={:?}", - self.obligations, obligations - ); + debug!(?self.obligations, ?obligations, "with_addl_obligations"); self.obligations.append(&mut obligations); self @@ -778,7 +729,7 @@ fn project_type<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, ) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> { - debug!("project(obligation={:?})", obligation); + debug!(?obligation, "project_type"); if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) { debug!("project: overflow!"); @@ -787,7 +738,7 @@ fn project_type<'cx, 'tcx>( let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx()); - debug!("project: obligation_trait_ref={:?}", obligation_trait_ref); + debug!(?obligation_trait_ref); if obligation_trait_ref.references_error() { return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx()))); @@ -951,10 +902,11 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>, potentially_unnormalized_candidates: bool, ) { - debug!("assemble_candidates_from_predicates(obligation={:?})", obligation); + debug!(?obligation, "assemble_candidates_from_predicates"); + let infcx = selcx.infcx(); for predicate in env_predicates { - debug!("assemble_candidates_from_predicates: predicate={:?}", predicate); + debug!(?predicate); if let ty::PredicateAtom::Projection(data) = predicate.skip_binders() { let data = ty::Binder::bind(data); let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id; @@ -969,11 +921,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( ) }); - debug!( - "assemble_candidates_from_predicates: candidate={:?} \ - is_match={} same_def_id={}", - data, is_match, same_def_id - ); + debug!(?data, ?is_match, ?same_def_id); if is_match { candidate_set.push_candidate(ctor(data)); @@ -997,6 +945,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( obligation_trait_ref: &ty::TraitRef<'tcx>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>, ) { + debug!("assemble_candidates_from_impls"); + // If we are resolving `<T as TraitRef<...>>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); @@ -1009,7 +959,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( return Err(()); } Err(e) => { - debug!("assemble_candidates_from_impls: selection error {:?}", e); + debug!(error = ?e, "selection error"); candidate_set.mark_error(e); return Err(()); } @@ -1020,7 +970,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | super::ImplSource::Generator(_) | super::ImplSource::FnPointer(_) | super::ImplSource::TraitAlias(_) => { - debug!("assemble_candidates_from_impls: impl_source={:?}", impl_source); + debug!(?impl_source); true } super::ImplSource::UserDefined(impl_data) => { @@ -1066,10 +1016,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( !poly_trait_ref.still_further_specializable() } else { debug!( - "assemble_candidates_from_impls: not eligible due to default: \ - assoc_ty={} predicate={}", - selcx.tcx().def_path_str(node_item.item.def_id), - obligation.predicate, + assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id), + ?obligation.predicate, + "assemble_candidates_from_impls: not eligible due to default", ); false } @@ -1176,8 +1125,7 @@ fn confirm_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, candidate: ProjectionTyCandidate<'tcx>, ) -> Progress<'tcx> { - debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation); - + debug!(?obligation, ?candidate, "confirm_candidate"); let mut progress = match candidate { ProjectionTyCandidate::ParamEnv(poly_projection) | ProjectionTyCandidate::Object(poly_projection) => { @@ -1220,9 +1168,8 @@ fn confirm_select_candidate<'cx, 'tcx>( | super::ImplSource::AutoImpl(..) | super::ImplSource::Param(..) | super::ImplSource::Builtin(..) - | super::ImplSource::TraitAlias(..) => - // we don't create Select candidates with this kind of resolution - { + | super::ImplSource::TraitAlias(..) => { + // we don't create Select candidates with this kind of resolution span_bug!( obligation.cause.span, "Cannot project an associated type from `{:?}`", @@ -1246,10 +1193,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( &gen_sig, ); - debug!( - "confirm_generator_candidate: obligation={:?},gen_sig={:?},obligations={:?}", - obligation, gen_sig, obligations - ); + debug!(?obligation, ?gen_sig, ?obligations, "confirm_generator_candidate"); let tcx = selcx.tcx(); @@ -1339,10 +1283,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( &closure_sig, ); - debug!( - "confirm_closure_candidate: obligation={:?},closure_sig={:?},obligations={:?}", - obligation, closure_sig, obligations - ); + debug!(?obligation, ?closure_sig, ?obligations, "confirm_closure_candidate"); confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No) .with_addl_obligations(impl_source.nested) @@ -1357,7 +1298,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { let tcx = selcx.tcx(); - debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig); + debug!(?obligation, ?fn_sig, "confirm_callable_candidate"); let fn_once_def_id = tcx.require_lang_item(LangItem::FnOnce, None); let fn_once_output_def_id = tcx.require_lang_item(LangItem::FnOnceOutput, None); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 038ba431c47..fdf1641c986 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -22,6 +22,7 @@ use super::SelectionCandidate::{self, *}; use super::{EvaluatedCandidate, SelectionCandidateSet, SelectionContext, TraitObligationStack}; impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { + #[instrument(level = "debug", skip(self))] pub(super) fn candidate_from_obligation<'o>( &mut self, stack: &TraitObligationStack<'o, 'tcx>, @@ -35,16 +36,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // this is because we want the unbound variables to be // replaced with fresh types starting from index 0. let cache_fresh_trait_pred = self.infcx.freshen(stack.obligation.predicate); - debug!( - "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})", - cache_fresh_trait_pred, stack - ); + debug!(?cache_fresh_trait_pred); debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars()); if let Some(c) = self.check_candidate_cache(stack.obligation.param_env, cache_fresh_trait_pred) { - debug!("CACHE HIT: SELECT({:?})={:?}", cache_fresh_trait_pred, c); + debug!(candidate = ?c, "CACHE HIT"); return c; } @@ -57,7 +55,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let (candidate, dep_node) = self.in_task(|this| this.candidate_from_obligation_no_cache(stack)); - debug!("CACHE MISS: SELECT({:?})={:?}", cache_fresh_trait_pred, candidate); + debug!(?candidate, "CACHE MISS"); self.insert_candidate_cache( stack.obligation.param_env, cache_fresh_trait_pred, @@ -103,7 +101,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else { IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } }; - debug!("evaluate_stack: pushing cause = {:?}", cause); + debug!(?cause, "evaluate_stack: pushing cause"); self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); } } @@ -120,7 +118,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut candidates = candidate_set.vec; - debug!("assembled {} candidates for {:?}: {:?}", candidates.len(), stack, candidates); + debug!(?stack, ?candidates, "assembled {} candidates", candidates.len()); // At this point, we know that each of the entries in the // candidate set is *individually* applicable. Now we have to @@ -163,7 +161,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .flat_map(Result::transpose) .collect::<Result<Vec<_>, _>>()?; - debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates); + debug!(?stack, ?candidates, "winnowed to {} candidates", candidates.len()); let needs_infer = stack.obligation.predicate.has_infer_types_or_consts(); @@ -181,10 +179,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) }); if is_dup { - debug!("Dropping candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]); + debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len()); candidates.swap_remove(i); } else { - debug!("Retaining candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]); + debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len()); i += 1; // If there are *STILL* multiple candidates, give up @@ -257,7 +255,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let lang_items = self.tcx().lang_items(); if lang_items.copy_trait() == Some(def_id) { - debug!("obligation self ty is {:?}", obligation.predicate.skip_binder().self_ty()); + debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty()); // User-defined copy impls are permitted, but only for // structs and enums. @@ -308,7 +306,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { - debug!("assemble_candidates_for_projected_tys({:?})", obligation); + debug!(?obligation, "assemble_candidates_from_projected_tys"); // Before we go into the whole placeholder thing, just // quickly check if the self-type is a projection at all. @@ -341,7 +339,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack: &TraitObligationStack<'o, 'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { - debug!("assemble_candidates_from_caller_bounds({:?})", stack.obligation); + debug!(?stack.obligation, "assemble_candidates_from_caller_bounds"); let all_bounds = stack .obligation @@ -383,10 +381,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = obligation.self_ty().skip_binder(); match self_ty.kind() { ty::Generator(..) => { - debug!( - "assemble_generator_candidates: self_ty={:?} obligation={:?}", - self_ty, obligation - ); + debug!(?self_ty, ?obligation, "assemble_generator_candidates",); candidates.vec.push(GeneratorCandidate); } @@ -423,10 +418,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // type/region parameters match *obligation.self_ty().skip_binder().kind() { ty::Closure(_, closure_substs) => { - debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}", kind, obligation); + debug!(?kind, ?obligation, "assemble_unboxed_candidates"); match self.infcx.closure_kind(closure_substs) { Some(closure_kind) => { - debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind); + debug!(?closure_kind, "assemble_unboxed_candidates"); if closure_kind.extends(kind) { candidates.vec.push(ClosureCandidate); } @@ -503,7 +498,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) -> Result<(), SelectionError<'tcx>> { - debug!("assemble_candidates_from_impls(obligation={:?})", obligation); + debug!(?obligation, "assemble_candidates_from_impls"); // Essentially any user-written impl will match with an error type, // so creating `ImplCandidates` isn't useful. However, we might @@ -537,7 +532,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result<(), SelectionError<'tcx>> { // Okay to skip binder here because the tests we do below do not involve bound regions. let self_ty = obligation.self_ty().skip_binder(); - debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty); + debug!(?self_ty, "assemble_candidates_from_auto_impls"); let def_id = obligation.predicate.def_id(); @@ -604,8 +599,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates: &mut SelectionCandidateSet<'tcx>, ) { debug!( - "assemble_candidates_from_object_ty(self_ty={:?})", - obligation.self_ty().skip_binder() + self_ty = ?obligation.self_ty().skip_binder(), + "assemble_candidates_from_object_ty", ); self.infcx.probe(|_snapshot| { @@ -645,7 +640,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => return, }; - debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}", poly_trait_ref); + debug!(?poly_trait_ref, "assemble_candidates_from_object_ty"); // Count only those upcast versions that match the trait-ref // we are looking for. Specifically, do not only check for the @@ -697,7 +692,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1); - debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})", source, target); + debug!(?source, ?target, "assemble_candidates_for_unsizing"); let may_apply = match (source.kind(), target.kind()) { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). @@ -758,7 +753,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result<(), SelectionError<'tcx>> { // Okay to skip binder here because the tests we do below do not involve bound regions. let self_ty = obligation.self_ty().skip_binder(); - debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty); + debug!(?self_ty, "assemble_candidates_for_trait_alias"); let def_id = obligation.predicate.def_id(); @@ -778,7 +773,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result<(), SelectionError<'tcx>> { match conditions { BuiltinImplConditions::Where(nested) => { - debug!("builtin_bound: nested={:?}", nested); + debug!(?nested, "builtin_bound"); candidates .vec .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() }); diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 96f0bedf6f1..37d619d5942 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -42,13 +42,12 @@ use super::SelectionContext; use std::iter; impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { + #[instrument(level = "debug", skip(self))] pub(super) fn confirm_candidate( &mut self, obligation: &TraitObligation<'tcx>, candidate: SelectionCandidate<'tcx>, ) -> Result<Selection<'tcx>, SelectionError<'tcx>> { - debug!("confirm_candidate({:?}, {:?})", obligation, candidate); - match candidate { BuiltinCandidate { has_nested } => { let data = self.confirm_builtin_candidate(obligation, has_nested); @@ -191,7 +190,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, param: ty::PolyTraitRef<'tcx>, ) -> Vec<PredicateObligation<'tcx>> { - debug!("confirm_param_candidate({:?},{:?})", obligation, param); + debug!(?obligation, ?param, "confirm_param_candidate"); // During evaluation, we already checked that this // where-clause trait-ref could be unified with the obligation @@ -214,7 +213,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, has_nested: bool, ) -> ImplSourceBuiltinData<PredicateObligation<'tcx>> { - debug!("confirm_builtin_candidate({:?}, {:?})", obligation, has_nested); + debug!(?obligation, ?has_nested, "confirm_builtin_candidate"); let lang_items = self.tcx().lang_items(); let obligations = if has_nested { @@ -247,7 +246,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { vec![] }; - debug!("confirm_builtin_candidate: obligations={:?}", obligations); + debug!(?obligations); ImplSourceBuiltinData { nested: obligations } } @@ -262,7 +261,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_def_id: DefId, ) -> ImplSourceAutoImplData<PredicateObligation<'tcx>> { - debug!("confirm_auto_impl_candidate({:?}, {:?})", obligation, trait_def_id); + debug!(?obligation, ?trait_def_id, "confirm_auto_impl_candidate"); let types = obligation.predicate.map_bound(|inner| { let self_ty = self.infcx.shallow_resolve(inner.self_ty()); @@ -278,7 +277,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { trait_def_id: DefId, nested: ty::Binder<Vec<Ty<'tcx>>>, ) -> ImplSourceAutoImplData<PredicateObligation<'tcx>> { - debug!("vtable_auto_impl: nested={:?}", nested); + debug!(?nested, "vtable_auto_impl"); ensure_sufficient_stack(|| { let cause = obligation.derived_cause(BuiltinDerivedObligation); let mut obligations = self.collect_predicates_for_types( @@ -308,7 +307,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // predicate as usual. It won't have any effect since auto traits are coinductive. obligations.extend(trait_obligations); - debug!("vtable_auto_impl: obligations={:?}", obligations); + debug!(?obligations, "vtable_auto_impl"); ImplSourceAutoImplData { trait_def_id, nested: obligations } }) @@ -319,13 +318,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, impl_def_id: DefId, ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> { - debug!("confirm_impl_candidate({:?},{:?})", obligation, impl_def_id); + debug!(?obligation, ?impl_def_id, "confirm_impl_candidate"); // First, create the substitutions by matching the impl again, // this time not in a probe. self.infcx.commit_unconditionally(|_| { let substs = self.rematch_impl(impl_def_id, obligation); - debug!("confirm_impl_candidate: substs={:?}", substs); + debug!(?substs, "impl substs"); let cause = obligation.derived_cause(ImplDerivedObligation); ensure_sufficient_stack(|| { self.vtable_impl( @@ -347,10 +346,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, ) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> { - debug!( - "vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={})", - impl_def_id, substs, recursion_depth, - ); + debug!(?impl_def_id, ?substs, ?recursion_depth, "vtable_impl"); let mut impl_obligations = self.impl_or_trait_obligations( cause, @@ -360,10 +356,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &substs.value, ); - debug!( - "vtable_impl: impl_def_id={:?} impl_obligations={:?}", - impl_def_id, impl_obligations - ); + debug!(?impl_obligations, "vtable_impl"); // Because of RFC447, the impl-trait-ref and obligations // are sufficient to determine the impl substs, without @@ -379,8 +372,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, ) -> ImplSourceObjectData<'tcx, PredicateObligation<'tcx>> { + debug!(?obligation, "confirm_object_candidate"); let tcx = self.tcx(); - debug!("confirm_object_candidate({:?})", obligation); let trait_predicate = self.infcx.replace_bound_vars_with_placeholders(&obligation.predicate); @@ -507,7 +500,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - debug!("confirm_object_candidate: nested: {:?}", nested); + debug!(?nested, "object nested obligations"); ImplSourceObjectData { upcast_trait_ref, vtable_base, nested } } @@ -516,7 +509,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, ) -> Result<ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> { - debug!("confirm_fn_pointer_candidate({:?})", obligation); + debug!(?obligation, "confirm_fn_pointer_candidate"); // Okay to skip binder; it is reintroduced below. let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); @@ -554,7 +547,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, alias_def_id: DefId, ) -> ImplSourceTraitAliasData<'tcx, PredicateObligation<'tcx>> { - debug!("confirm_trait_alias_candidate({:?}, {:?})", obligation, alias_def_id); + debug!(?obligation, ?alias_def_id, "confirm_trait_alias_candidate"); self.infcx.commit_unconditionally(|_| { let predicate = @@ -571,10 +564,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &substs, ); - debug!( - "confirm_trait_alias_candidate: trait_def_id={:?} trait_obligations={:?}", - trait_def_id, trait_obligations - ); + debug!(?trait_def_id, ?trait_obligations, "trait alias obligations"); ImplSourceTraitAliasData { alias_def_id, substs, nested: trait_obligations } }) @@ -594,7 +584,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("closure candidate for non-closure {:?}", obligation), }; - debug!("confirm_generator_candidate({:?},{:?},{:?})", obligation, generator_def_id, substs); + debug!(?obligation, ?generator_def_id, ?substs, "confirm_generator_candidate"); let trait_ref = self.generator_trait_ref_unnormalized(obligation, substs); let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| { @@ -607,11 +597,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) }); - debug!( - "confirm_generator_candidate(generator_def_id={:?}, \ - trait_ref={:?}, obligations={:?})", - generator_def_id, trait_ref, obligations - ); + debug!(?trait_ref, ?obligations, "generator candidate obligations"); obligations.extend(self.confirm_poly_trait_refs( obligation.cause.clone(), @@ -627,7 +613,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, ) -> Result<ImplSourceClosureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> { - debug!("confirm_closure_candidate({:?})", obligation); + debug!(?obligation, "confirm_closure_candidate"); let kind = self .tcx() @@ -654,10 +640,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) }); - debug!( - "confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})", - closure_def_id, trait_ref, obligations - ); + debug!(?closure_def_id, ?trait_ref, ?obligations, "confirm closure candidate obligations"); obligations.extend(self.confirm_poly_trait_refs( obligation.cause.clone(), @@ -731,7 +714,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1); let target = self.infcx.shallow_resolve(target); - debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})", source, target); + debug!(?source, ?target, "confirm_builtin_unsize_candidate"); let mut nested = vec![]; match (source.kind(), target.kind()) { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a142ba58a69..57b680b0e53 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -236,7 +236,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, allow_negative_impls: bool, ) -> SelectionContext<'cx, 'tcx> { - debug!("with_negative({:?})", allow_negative_impls); + debug!(?allow_negative_impls, "with_negative"); SelectionContext { infcx, freshener: infcx.freshener(), @@ -251,7 +251,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, query_mode: TraitQueryMode, ) -> SelectionContext<'cx, 'tcx> { - debug!("with_query_mode({:?})", query_mode); + debug!(?query_mode, "with_query_mode"); SelectionContext { infcx, freshener: infcx.freshener(), @@ -311,11 +311,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Attempts to satisfy the obligation. If successful, this will affect the surrounding /// type environment by performing unification. + #[instrument(level = "debug", skip(self))] pub fn select( &mut self, obligation: &TraitObligation<'tcx>, ) -> SelectionResult<'tcx, Selection<'tcx>> { - debug!("select({:?})", obligation); debug_assert!(!obligation.predicate.has_escaping_bound_vars()); let pec = &ProvisionalEvaluationCache::default(); @@ -344,7 +344,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } Err(e) => Err(e), Ok(candidate) => { - debug!("select: candidate = {:?}", candidate); + debug!(?candidate); Ok(Some(candidate)) } } @@ -362,7 +362,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Evaluates whether the obligation `obligation` can be satisfied (by any means). pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool { - debug!("predicate_may_hold_fatal({:?})", obligation); + debug!(?obligation, "predicate_may_hold_fatal"); // This fatal query is a stopgap that should only be used in standard mode, // where we do not expect overflow to be propagated. @@ -419,10 +419,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug, { let mut result = EvaluatedToOk; - debug!("evaluate_predicates_recursively({:?})", predicates); + debug!(?predicates, "evaluate_predicates_recursively"); for obligation in predicates { let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?; - debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval); if let EvaluatedToErr = eval { // fast-path - EvaluatedToErr is the top of the lattice, // so we don't need to look on the other predicates. @@ -434,17 +433,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(result) } + #[instrument( + level = "debug", + skip(self, previous_stack), + fields(previous_stack = ?previous_stack.head()) + )] fn evaluate_predicate_recursively<'o>( &mut self, previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: PredicateObligation<'tcx>, ) -> Result<EvaluationResult, OverflowError> { - debug!( - "evaluate_predicate_recursively(obligation={:?}, previous_stack={:?})", - obligation, - previous_stack.head() - ); - // `previous_stack` stores a `TraitObligation`, while `obligation` is // a `PredicateObligation`. These are distinct types, so we can't // use any `Option` combinator method that would force them to be @@ -454,7 +452,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { None => self.check_recursion_limit(&obligation, &obligation)?, } - ensure_sufficient_stack(|| { + let result = ensure_sufficient_stack(|| { match obligation.predicate.skip_binders() { ty::PredicateAtom::Trait(t, _) => { let t = ty::Binder::bind(t); @@ -561,10 +559,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::PredicateAtom::ConstEquate(c1, c2) => { - debug!( - "evaluate_predicate_recursively: equating consts c1={:?} c2={:?}", - c1, c2 - ); + debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts"); let evaluate = |c: &'tcx ty::Const<'tcx>| { if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val { @@ -610,7 +605,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { bug!("TypeWellFormedFromEnv is only used for chalk") } } - }) + }); + + debug!(?result); + + result } fn evaluate_trait_predicate_recursively<'o>( @@ -618,7 +617,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, mut obligation: TraitObligation<'tcx>, ) -> Result<EvaluationResult, OverflowError> { - debug!("evaluate_trait_predicate_recursively({:?})", obligation); + debug!(?obligation, "evaluate_trait_predicate_recursively"); if !self.intercrate && obligation.is_global() @@ -627,19 +626,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // If a param env has no global bounds, global obligations do not // depend on its particular value in order to work, so we can clear // out the param env and get better caching. - debug!("evaluate_trait_predicate_recursively({:?}) - in global", obligation); + debug!("evaluate_trait_predicate_recursively - in global"); obligation.param_env = obligation.param_env.without_caller_bounds(); } let stack = self.push_stack(previous_stack, &obligation); let fresh_trait_ref = stack.fresh_trait_ref; + + debug!(?fresh_trait_ref); + if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_ref) { - debug!("CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result); + debug!(?result, "CACHE HIT"); return Ok(result); } if let Some(result) = stack.cache().get_provisional(fresh_trait_ref) { - debug!("PROVISIONAL CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result); + debug!(?result, "PROVISIONAL CACHE HIT"); stack.update_reached_depth(stack.cache().current_reached_depth()); return Ok(result); } @@ -662,7 +664,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let reached_depth = stack.reached_depth.get(); if reached_depth >= stack.depth { - debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result); + debug!(?result, "CACHE MISS"); self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result); stack.cache().on_completion(stack.depth, |fresh_trait_ref, provisional_result| { @@ -674,7 +676,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); }); } else { - debug!("PROVISIONAL: {:?}={:?}", fresh_trait_ref, result); + debug!(?result, "PROVISIONAL"); debug!( "evaluate_trait_predicate_recursively: caching provisionally because {:?} \ is a cycle participant (at depth {}, reached depth {})", @@ -719,10 +721,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) .map(|stack| stack.depth) { - debug!( - "evaluate_stack({:?}) --> recursive at depth {}", - stack.fresh_trait_ref, cycle_depth, - ); + debug!("evaluate_stack --> recursive at depth {}", cycle_depth); // If we have a stack like `A B C D E A`, where the top of // the stack is the final `A`, then this will iterate over @@ -742,10 +741,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cycle = cycle.map(|stack| stack.obligation.predicate.without_const().to_predicate(tcx)); if self.coinductive_match(cycle) { - debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref); + debug!("evaluate_stack --> recursive, coinductive"); Some(EvaluatedToOk) } else { - debug!("evaluate_stack({:?}) --> recursive, inductive", stack.fresh_trait_ref); + debug!("evaluate_stack --> recursive, inductive"); Some(EvaluatedToRecur) } } else { @@ -786,10 +785,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This check was an imperfect workaround for a bug in the old // intercrate mode; it should be removed when that goes away. if unbound_input_types && self.intercrate { - debug!( - "evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous", - stack.fresh_trait_ref - ); + debug!("evaluate_stack --> unbound argument, intercrate --> ambiguous",); // Heuristics: show the diagnostics when there are no candidates in crate. if self.intercrate_ambiguity_causes.is_some() { debug!("evaluate_stack: intercrate_ambiguity_causes is some"); @@ -807,7 +803,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }, }); - debug!("evaluate_stack: pushing cause = {:?}", cause); + debug!(?cause, "evaluate_stack: pushing cause"); self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); } } @@ -824,10 +820,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) }) { - debug!( - "evaluate_stack({:?}) --> unbound argument, recursive --> giving up", - stack.fresh_trait_ref - ); + debug!("evaluate_stack --> unbound argument, recursive --> giving up",); return Ok(EvaluatedToUnknown); } @@ -860,27 +853,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateAtom::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()), _ => false, }; - debug!("coinductive_predicate({:?}) = {:?}", predicate, result); + debug!(?predicate, ?result, "coinductive_predicate"); result } /// Further evaluates `candidate` to decide whether all type parameters match and whether nested /// obligations are met. Returns whether `candidate` remains viable after this further /// scrutiny. + #[instrument( + level = "debug", + skip(self, stack), + fields(depth = stack.obligation.recursion_depth) + )] fn evaluate_candidate<'o>( &mut self, stack: &TraitObligationStack<'o, 'tcx>, candidate: &SelectionCandidate<'tcx>, ) -> Result<EvaluationResult, OverflowError> { - debug!( - "evaluate_candidate: depth={} candidate={:?}", - stack.obligation.recursion_depth, candidate - ); let result = self.evaluation_probe(|this| { let candidate = (*candidate).clone(); match this.confirm_candidate(stack.obligation, candidate) { Ok(selection) => { - debug!("evaluate_candidate: selection = {:?}", selection); + debug!(?selection); this.evaluate_predicates_recursively( stack.list(), selection.nested_obligations().into_iter(), @@ -889,10 +883,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(..) => Ok(EvaluatedToErr), } })?; - debug!( - "evaluate_candidate: depth={} result={:?}", - stack.obligation.recursion_depth, result - ); + debug!(?result); Ok(result) } @@ -925,10 +916,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.can_use_global_caches(param_env) { if !trait_ref.needs_infer() { - debug!( - "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global", - trait_ref, result, - ); + debug!(?trait_ref, ?result, "insert_evaluation_cache global"); // This may overwrite the cache with the same value // FIXME: Due to #50507 this overwrites the different values // This should be changed to use HashMapExt::insert_same @@ -938,7 +926,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - debug!("insert_evaluation_cache(trait_ref={:?}, candidate={:?})", trait_ref, result,); + debug!(?trait_ref, ?result, "insert_evaluation_cache"); self.infcx.evaluation_cache.insert(param_env.and(trait_ref), dep_node, result); } @@ -1127,11 +1115,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref; if !self.can_cache_candidate(&candidate) { - debug!( - "insert_candidate_cache(trait_ref={:?}, candidate={:?} -\ - candidate is not cacheable", - trait_ref, candidate - ); + debug!(?trait_ref, ?candidate, "insert_candidate_cache - candidate is not cacheable"); return; } @@ -1140,10 +1124,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Don't cache overflow globally; we only produce this in certain modes. } else if !trait_ref.needs_infer() { if !candidate.needs_infer() { - debug!( - "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global", - trait_ref, candidate, - ); + debug!(?trait_ref, ?candidate, "insert_candidate_cache global"); // This may overwrite the cache with the same value. tcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate); return; @@ -1151,10 +1132,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - debug!( - "insert_candidate_cache(trait_ref={:?}, candidate={:?}) local", - trait_ref, candidate, - ); + debug!(?trait_ref, ?candidate, "insert_candidate_cache local"); self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate); } @@ -1172,9 +1150,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let placeholder_trait_predicate = self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate); debug!( - "match_projection_obligation_against_definition_bounds: \ - placeholder_trait_predicate={:?}", - placeholder_trait_predicate, + ?placeholder_trait_predicate, + "match_projection_obligation_against_definition_bounds" ); let tcx = self.infcx.tcx; @@ -1225,11 +1202,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) .collect(); - debug!( - "match_projection_obligation_against_definition_bounds: \ - matching_bounds={:?}", - matching_bounds - ); + debug!(?matching_bounds, "match_projection_obligation_against_definition_bounds"); matching_bounds } @@ -1816,6 +1789,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { impl_def_id: DefId, obligation: &TraitObligation<'tcx>, ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> { + debug!(?impl_def_id, ?obligation, "match_impl"); let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); // Before we create the substitutions and everything, first @@ -1844,11 +1818,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) }); - debug!( - "match_impl(impl_def_id={:?}, obligation={:?}, \ - impl_trait_ref={:?}, placeholder_obligation_trait_ref={:?})", - impl_def_id, obligation, impl_trait_ref, placeholder_obligation_trait_ref - ); + debug!(?impl_trait_ref, ?placeholder_obligation_trait_ref); let InferOk { obligations, .. } = self .infcx @@ -1864,7 +1834,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - debug!("match_impl: success impl_substs={:?}", impl_substs); + debug!(?impl_substs, "match_impl: success"); Ok(Normalized { value: impl_substs, obligations: nested_obligations }) } @@ -1926,10 +1896,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result<Vec<PredicateObligation<'tcx>>, ()> { - debug!( - "match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}", - obligation, poly_trait_ref - ); + debug!(?obligation, ?poly_trait_ref, "match_poly_trait_ref"); self.infcx .at(&obligation.cause, obligation.param_env) @@ -1976,10 +1943,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, substs: SubstsRef<'tcx>, ) -> ty::PolyTraitRef<'tcx> { - debug!("closure_trait_ref_unnormalized(obligation={:?}, substs={:?})", obligation, substs); + debug!(?obligation, ?substs, "closure_trait_ref_unnormalized"); let closure_sig = substs.as_closure().sig(); - debug!("closure_trait_ref_unnormalized: closure_sig = {:?}", closure_sig); + debug!(?closure_sig); // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an unboxed closure type and hence is @@ -2030,7 +1997,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { def_id: DefId, // of impl or trait substs: SubstsRef<'tcx>, // for impl or trait ) -> Vec<PredicateObligation<'tcx>> { - debug!("impl_or_trait_obligations(def_id={:?})", def_id); + debug!(?def_id, "impl_or_trait_obligations"); let tcx = self.tcx(); // To allow for one-pass evaluation of the nested obligation, @@ -2152,10 +2119,10 @@ impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> { self.depth, reached_depth, ); - debug!("update_reached_depth(reached_depth={})", reached_depth); + debug!(reached_depth, "update_reached_depth"); let mut p = self; while reached_depth < p.depth { - debug!("update_reached_depth: marking {:?} as cycle participant", p.fresh_trait_ref); + debug!(?p.fresh_trait_ref, "update_reached_depth: marking as cycle participant"); p.reached_depth.set(p.reached_depth.get().min(reached_depth)); p = p.previous.head.unwrap(); } @@ -2282,10 +2249,10 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { /// `self.current_reached_depth()` and above. fn get_provisional(&self, fresh_trait_ref: ty::PolyTraitRef<'tcx>) -> Option<EvaluationResult> { debug!( - "get_provisional(fresh_trait_ref={:?}) = {:#?} with reached-depth {}", - fresh_trait_ref, + ?fresh_trait_ref, + reached_depth = ?self.reached_depth.get(), + "get_provisional = {:#?}", self.map.borrow().get(&fresh_trait_ref), - self.reached_depth.get(), ); Some(self.map.borrow().get(&fresh_trait_ref)?.result) } @@ -2308,14 +2275,11 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { fresh_trait_ref: ty::PolyTraitRef<'tcx>, result: EvaluationResult, ) { - debug!( - "insert_provisional(from_dfn={}, reached_depth={}, fresh_trait_ref={:?}, result={:?})", - from_dfn, reached_depth, fresh_trait_ref, result, - ); + debug!(?from_dfn, ?reached_depth, ?fresh_trait_ref, ?result, "insert_provisional"); let r_d = self.reached_depth.get(); self.reached_depth.set(r_d.min(reached_depth)); - debug!("insert_provisional: reached_depth={:?}", self.reached_depth.get()); + debug!(reached_depth = self.reached_depth.get()); self.map.borrow_mut().insert(fresh_trait_ref, ProvisionalEvaluation { from_dfn, result }); } @@ -2329,7 +2293,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { /// these provisional entries must either depend on it or some /// ancestor of it. fn on_failure(&self, dfn: usize) { - debug!("on_failure(dfn={:?})", dfn,); + debug!(?dfn, "on_failure"); self.map.borrow_mut().retain(|key, eval| { if !eval.from_dfn >= dfn { debug!("on_failure: removing {:?}", key); @@ -2350,7 +2314,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { depth: usize, mut op: impl FnMut(ty::PolyTraitRef<'tcx>, EvaluationResult), ) { - debug!("on_completion(depth={}, reached_depth={})", depth, self.reached_depth.get(),); + debug!(?depth, reached_depth = ?self.reached_depth.get(), "on_completion"); if self.reached_depth.get() < depth { debug!("on_completion: did not yet reach depth to complete"); @@ -2358,7 +2322,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { } for (fresh_trait_ref, eval) in self.map.borrow_mut().drain() { - debug!("on_completion: fresh_trait_ref={:?} eval={:?}", fresh_trait_ref, eval,); + debug!(?fresh_trait_ref, ?eval, "on_completion"); op(fresh_trait_ref, eval.result); } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 97172d391ba..1cb6ae21a47 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -264,7 +264,7 @@ pub fn provide(providers: &mut Providers) { } fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> { - tcx.calculate_dtor(def_id, &mut dropck::check_drop_impl) + tcx.calculate_dtor(def_id, dropck::check_drop_impl) } /// If this `DefId` is a "primary tables entry", returns |
