diff options
Diffstat (limited to 'compiler/rustc_middle/src')
20 files changed, 184 insertions, 131 deletions
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs index c5ce6efcb81..9d2f0a45237 100644 --- a/compiler/rustc_middle/src/hooks/mod.rs +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -50,10 +50,10 @@ macro_rules! declare_hooks { declare_hooks! { /// Tries to destructure an `mir::Const` ADT or array into its variant index /// and its field values. This should only be used for pretty printing. - hook try_destructure_mir_constant_for_user_output(val: mir::ConstValue<'tcx>, ty: Ty<'tcx>) -> Option<mir::DestructuredConstant<'tcx>>; + hook try_destructure_mir_constant_for_user_output(val: mir::ConstValue, ty: Ty<'tcx>) -> Option<mir::DestructuredConstant<'tcx>>; /// Getting a &core::panic::Location referring to a span. - hook const_caller_location(file: rustc_span::Symbol, line: u32, col: u32) -> mir::ConstValue<'tcx>; + hook const_caller_location(file: rustc_span::Symbol, line: u32, col: u32) -> mir::ConstValue; /// Returns `true` if this def is a function-like thing that is eligible for /// coverage instrumentation under `-Cinstrument-coverage`. diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 03549091d62..785ddd1ee29 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -182,7 +182,7 @@ impl EffectiveVisibilities { // don't check this condition for them. let is_impl = matches!(tcx.def_kind(def_id), DefKind::Impl { .. }); let is_associated_item_in_trait_impl = tcx - .impl_of_method(def_id.to_def_id()) + .impl_of_assoc(def_id.to_def_id()) .and_then(|impl_id| tcx.trait_id_of_impl(impl_id)) .is_some(); if !is_impl && !is_associated_item_in_trait_impl { diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 0f5b63f5c1d..800c1af660a 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -175,23 +175,22 @@ impl Scope { return DUMMY_SP; }; let span = tcx.hir_span(hir_id); - if let ScopeData::Remainder(first_statement_index) = self.data { - if let Node::Block(blk) = tcx.hir_node(hir_id) { - // Want span for scope starting after the - // indexed statement and ending at end of - // `blk`; reuse span of `blk` and shift `lo` - // forward to end of indexed statement. - // - // (This is the special case alluded to in the - // doc-comment for this method) - - let stmt_span = blk.stmts[first_statement_index.index()].span; - - // To avoid issues with macro-generated spans, the span - // of the statement must be nested in that of the block. - if span.lo() <= stmt_span.lo() && stmt_span.lo() <= span.hi() { - return span.with_lo(stmt_span.lo()); - } + if let ScopeData::Remainder(first_statement_index) = self.data + // Want span for scope starting after the + // indexed statement and ending at end of + // `blk`; reuse span of `blk` and shift `lo` + // forward to end of indexed statement. + // + // (This is the special case alluded to in the + // doc-comment for this method) + && let Node::Block(blk) = tcx.hir_node(hir_id) + { + let stmt_span = blk.stmts[first_statement_index.index()].span; + + // To avoid issues with macro-generated spans, the span + // of the statement must be nested in that of the block. + if span.lo() <= stmt_span.lo() && stmt_span.lo() <= span.hi() { + return span.with_lo(stmt_span.lo()); } } span diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index fb941977528..96131d47a17 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -9,9 +9,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_type_ir::TypeVisitableExt; use super::interpret::ReportedErrorInfo; -use crate::mir::interpret::{ - AllocId, AllocRange, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar, alloc_range, -}; +use crate::mir::interpret::{AllocId, AllocRange, ErrorHandled, GlobalAlloc, Scalar, alloc_range}; use crate::mir::{Promoted, pretty_print_const_value}; use crate::ty::print::{pretty_print_const, with_no_trimmed_paths}; use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt}; @@ -33,8 +31,8 @@ pub struct ConstAlloc<'tcx> { /// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for /// array length computations, enum discriminants and the pattern matching logic. #[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash)] -#[derive(HashStable, Lift)] -pub enum ConstValue<'tcx> { +#[derive(HashStable)] +pub enum ConstValue { /// Used for types with `layout::abi::Scalar` ABI. /// /// Not using the enum `Value` to encode that this must not be `Uninit`. @@ -52,7 +50,7 @@ pub enum ConstValue<'tcx> { Slice { /// The allocation storing the slice contents. /// This always points to the beginning of the allocation. - data: ConstAllocation<'tcx>, + alloc_id: AllocId, /// The metadata field of the reference. /// This is a "target usize", so we use `u64` as in the interpreter. meta: u64, @@ -75,9 +73,9 @@ pub enum ConstValue<'tcx> { } #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(ConstValue<'_>, 24); +rustc_data_structures::static_assert_size!(ConstValue, 24); -impl<'tcx> ConstValue<'tcx> { +impl ConstValue { #[inline] pub fn try_to_scalar(&self) -> Option<Scalar> { match *self { @@ -98,11 +96,11 @@ impl<'tcx> ConstValue<'tcx> { self.try_to_scalar_int()?.try_into().ok() } - pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> { + pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Option<u64> { Some(self.try_to_scalar_int()?.to_target_usize(tcx)) } - pub fn try_to_bits_for_ty( + pub fn try_to_bits_for_ty<'tcx>( &self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, @@ -132,12 +130,15 @@ impl<'tcx> ConstValue<'tcx> { } /// Must only be called on constants of type `&str` or `&[u8]`! - pub fn try_get_slice_bytes_for_diagnostics(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx [u8]> { - let (data, start, end) = match self { + pub fn try_get_slice_bytes_for_diagnostics<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + ) -> Option<&'tcx [u8]> { + let (alloc_id, start, len) = match self { ConstValue::Scalar(_) | ConstValue::ZeroSized => { bug!("`try_get_slice_bytes` on non-slice constant") } - &ConstValue::Slice { data, meta } => (data, 0, meta), + &ConstValue::Slice { alloc_id, meta } => (alloc_id, 0, meta), &ConstValue::Indirect { alloc_id, offset } => { // The reference itself is stored behind an indirection. // Load the reference, and then load the actual slice contents. @@ -170,26 +171,29 @@ impl<'tcx> ConstValue<'tcx> { // Non-empty slice, must have memory. We know this is a relative pointer. let (inner_prov, offset) = ptr.into_pointer_or_addr().ok()?.prov_and_relative_offset(); - let data = tcx.global_alloc(inner_prov.alloc_id()).unwrap_memory(); - (data, offset.bytes(), offset.bytes() + len) + (inner_prov.alloc_id(), offset.bytes(), len) } }; + let data = tcx.global_alloc(alloc_id).unwrap_memory(); + // This is for diagnostics only, so we are okay to use `inspect_with_uninit_and_ptr_outside_interpreter`. let start = start.try_into().unwrap(); - let end = end.try_into().unwrap(); + let end = start + usize::try_from(len).unwrap(); Some(data.inner().inspect_with_uninit_and_ptr_outside_interpreter(start..end)) } /// Check if a constant may contain provenance information. This is used by MIR opts. /// Can return `true` even if there is no provenance. - pub fn may_have_provenance(&self, tcx: TyCtxt<'tcx>, size: Size) -> bool { + pub fn may_have_provenance(&self, tcx: TyCtxt<'_>, size: Size) -> bool { match *self { ConstValue::ZeroSized | ConstValue::Scalar(Scalar::Int(_)) => return false, ConstValue::Scalar(Scalar::Ptr(..)) => return true, // It's hard to find out the part of the allocation we point to; // just conservatively check everything. - ConstValue::Slice { data, meta: _ } => !data.inner().provenance().ptrs().is_empty(), + ConstValue::Slice { alloc_id, meta: _ } => { + !tcx.global_alloc(alloc_id).unwrap_memory().inner().provenance().ptrs().is_empty() + } ConstValue::Indirect { alloc_id, offset } => !tcx .global_alloc(alloc_id) .unwrap_memory() @@ -200,7 +204,7 @@ impl<'tcx> ConstValue<'tcx> { } /// Check if a constant only contains uninitialized bytes. - pub fn all_bytes_uninit(&self, tcx: TyCtxt<'tcx>) -> bool { + pub fn all_bytes_uninit(&self, tcx: TyCtxt<'_>) -> bool { let ConstValue::Indirect { alloc_id, .. } = self else { return false; }; @@ -247,7 +251,7 @@ pub enum Const<'tcx> { /// This constant cannot go back into the type system, as it represents /// something the type system cannot handle (e.g. pointers). - Val(ConstValue<'tcx>, Ty<'tcx>), + Val(ConstValue, Ty<'tcx>), } impl<'tcx> Const<'tcx> { @@ -343,7 +347,7 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, span: Span, - ) -> Result<ConstValue<'tcx>, ErrorHandled> { + ) -> Result<ConstValue, ErrorHandled> { match self { Const::Ty(_, c) => { if c.has_non_region_param() { @@ -440,7 +444,7 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn from_value(val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self { + pub fn from_value(val: ConstValue, ty: Ty<'tcx>) -> Self { Self::Val(val, ty) } @@ -487,9 +491,8 @@ impl<'tcx> Const<'tcx> { /// taking into account even pointer identity tests. pub fn is_deterministic(&self) -> bool { // Some constants may generate fresh allocations for pointers they contain, - // so using the same constant twice can yield two different results: - // - valtrees purposefully generate new allocations - // - ConstValue::Slice also generate new allocations + // so using the same constant twice can yield two different results. + // Notably, valtrees purposefully generate new allocations. match self { Const::Ty(_, c) => match c.kind() { ty::ConstKind::Param(..) => true, @@ -507,11 +510,11 @@ impl<'tcx> Const<'tcx> { | ty::ConstKind::Placeholder(..) => bug!(), }, Const::Unevaluated(..) => false, - // If the same slice appears twice in the MIR, we cannot guarantee that we will - // give the same `AllocId` to the data. - Const::Val(ConstValue::Slice { .. }, _) => false, Const::Val( - ConstValue::ZeroSized | ConstValue::Scalar(_) | ConstValue::Indirect { .. }, + ConstValue::Slice { .. } + | ConstValue::ZeroSized + | ConstValue::Scalar(_) + | ConstValue::Indirect { .. }, _, ) => true, } @@ -574,7 +577,7 @@ impl<'tcx> Display for Const<'tcx> { /// Const-related utilities impl<'tcx> TyCtxt<'tcx> { - pub fn span_as_caller_location(self, span: Span) -> ConstValue<'tcx> { + pub fn span_as_caller_location(self, span: Span) -> ConstValue { let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); let caller = self.sess.source_map().lookup_char_pos(topmost.lo()); self.const_caller_location( diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 3e68afbfabd..3e895c6b280 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -137,7 +137,7 @@ impl<'tcx> ValTreeCreationError<'tcx> { pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>; pub type EvalStaticInitializerRawResult<'tcx> = Result<ConstAllocation<'tcx>, ErrorHandled>; -pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>; +pub type EvalToConstValueResult<'tcx> = Result<ConstValue, ErrorHandled>; pub type EvalToValTreeResult<'tcx> = Result<ValTree<'tcx>, ValTreeCreationError<'tcx>>; #[cfg(target_pointer_width = "64")] @@ -426,7 +426,12 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// Trying to set discriminant to the niched variant, but the value does not match. InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> }, /// ABI-incompatible argument types. - AbiMismatchArgument { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> }, + AbiMismatchArgument { + /// The index of the argument whose type is wrong. + arg_idx: usize, + caller_ty: Ty<'tcx>, + callee_ty: Ty<'tcx>, + }, /// ABI-incompatible return types. AbiMismatchReturn { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> }, } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 2d7ddd105bd..105736b9e24 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -143,10 +143,8 @@ impl<'tcx> MonoItem<'tcx> { }; // Similarly, the executable entrypoint must be instantiated exactly once. - if let Some((entry_def_id, _)) = tcx.entry_fn(()) { - if instance.def_id() == entry_def_id { - return InstantiationMode::GloballyShared { may_conflict: false }; - } + if tcx.is_entrypoint(instance.def_id()) { + return InstantiationMode::GloballyShared { may_conflict: false }; } // If the function is #[naked] or contains any other attribute that requires exactly-once diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 8e403dfddae..809cdb329f7 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1465,7 +1465,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { self.push(&format!("+ user_ty: {user_ty:?}")); } - let fmt_val = |val: ConstValue<'tcx>, ty: Ty<'tcx>| { + let fmt_val = |val: ConstValue, ty: Ty<'tcx>| { let tcx = self.tcx; rustc_data_structures::make_display(move |fmt| { pretty_print_const_value_tcx(tcx, val, ty, fmt) @@ -1562,16 +1562,12 @@ pub fn write_allocations<'tcx>( alloc.inner().provenance().ptrs().values().map(|p| p.alloc_id()) } - fn alloc_id_from_const_val(val: ConstValue<'_>) -> Option<AllocId> { + fn alloc_id_from_const_val(val: ConstValue) -> Option<AllocId> { match val { ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => Some(ptr.provenance.alloc_id()), ConstValue::Scalar(interpret::Scalar::Int { .. }) => None, ConstValue::ZeroSized => None, - ConstValue::Slice { .. } => { - // `u8`/`str` slices, shouldn't contain pointers that we want to print. - None - } - ConstValue::Indirect { alloc_id, .. } => { + ConstValue::Slice { alloc_id, .. } | ConstValue::Indirect { alloc_id, .. } => { // FIXME: we don't actually want to print all of these, since some are printed nicely directly as values inline in MIR. // Really we'd want `pretty_print_const_value` to decide which allocations to print, instead of having a separate visitor. Some(alloc_id) @@ -1885,7 +1881,7 @@ fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Resul fn comma_sep<'tcx>( tcx: TyCtxt<'tcx>, fmt: &mut Formatter<'_>, - elems: Vec<(ConstValue<'tcx>, Ty<'tcx>)>, + elems: Vec<(ConstValue, Ty<'tcx>)>, ) -> fmt::Result { let mut first = true; for (ct, ty) in elems { @@ -1900,7 +1896,7 @@ fn comma_sep<'tcx>( fn pretty_print_const_value_tcx<'tcx>( tcx: TyCtxt<'tcx>, - ct: ConstValue<'tcx>, + ct: ConstValue, ty: Ty<'tcx>, fmt: &mut Formatter<'_>, ) -> fmt::Result { @@ -1947,7 +1943,7 @@ fn pretty_print_const_value_tcx<'tcx>( let ct = tcx.lift(ct).unwrap(); let ty = tcx.lift(ty).unwrap(); if let Some(contents) = tcx.try_destructure_mir_constant_for_user_output(ct, ty) { - let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec(); + let fields: Vec<(ConstValue, Ty<'_>)> = contents.fields.to_vec(); match *ty.kind() { ty::Array(..) => { fmt.write_str("[")?; @@ -2028,7 +2024,7 @@ fn pretty_print_const_value_tcx<'tcx>( } pub(crate) fn pretty_print_const_value<'tcx>( - ct: ConstValue<'tcx>, + ct: ConstValue, ty: Ty<'tcx>, fmt: &mut Formatter<'_>, ) -> fmt::Result { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 3fc05f2caf2..a8a95c699d8 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -173,5 +173,5 @@ pub enum AnnotationSource { #[derive(Copy, Clone, Debug, HashStable)] pub struct DestructuredConstant<'tcx> { pub variant: Option<VariantIdx>, - pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)], + pub fields: &'tcx [(ConstValue, Ty<'tcx>)], } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index f138c5ca039..dab5900b4ab 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -153,8 +153,8 @@ impl EraseType for Result<mir::ConstAlloc<'_>, mir::interpret::ErrorHandled> { type Result = [u8; size_of::<Result<mir::ConstAlloc<'static>, mir::interpret::ErrorHandled>>()]; } -impl EraseType for Result<mir::ConstValue<'_>, mir::interpret::ErrorHandled> { - type Result = [u8; size_of::<Result<mir::ConstValue<'static>, mir::interpret::ErrorHandled>>()]; +impl EraseType for Result<mir::ConstValue, mir::interpret::ErrorHandled> { + type Result = [u8; size_of::<Result<mir::ConstValue, mir::interpret::ErrorHandled>>()]; } impl EraseType for EvalToValTreeResult<'_> { @@ -301,6 +301,7 @@ trivial! { rustc_middle::middle::resolve_bound_vars::ResolvedArg, rustc_middle::middle::stability::DeprecationEntry, rustc_middle::mir::ConstQualifs, + rustc_middle::mir::ConstValue, rustc_middle::mir::interpret::AllocId, rustc_middle::mir::interpret::CtfeProvenance, rustc_middle::mir::interpret::ErrorHandled, @@ -362,7 +363,6 @@ tcx_lifetime! { rustc_middle::mir::Const, rustc_middle::mir::DestructuredConstant, rustc_middle::mir::ConstAlloc, - rustc_middle::mir::ConstValue, rustc_middle::mir::interpret::GlobalId, rustc_middle::mir::interpret::LitToConstInput, rustc_middle::mir::interpret::EvalStaticInitializerRawResult, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ad7f4973e23..587349d4cf4 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1363,7 +1363,7 @@ rustc_queries! { } /// Converts a type-level constant value into a MIR constant value. - query valtree_to_const_val(key: ty::Value<'tcx>) -> mir::ConstValue<'tcx> { + query valtree_to_const_val(key: ty::Value<'tcx>) -> mir::ConstValue { desc { "converting type-level constant value to MIR constant value"} } @@ -1391,7 +1391,6 @@ rustc_queries! { desc { "checking effective visibilities" } } query check_private_in_public(_: ()) { - eval_always desc { "checking for private elements in public interfaces" } } @@ -2152,9 +2151,6 @@ rustc_queries! { desc { |tcx| "collecting child items of module `{}`", tcx.def_path_str(def_id) } separate_provide_extern } - query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option<CrateNum> { - desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) } - } /// Gets the number of definitions in a foreign crate. /// diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 730c1147684..3dd6d2c8928 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -838,6 +838,8 @@ pub enum PatKind<'tcx> { /// * integer, bool, char or float (represented as a valtree), which will be handled by /// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are /// much simpler. + /// * raw pointers derived from integers, other raw pointers will have already resulted in an + // error. /// * `String`, if `string_deref_patterns` is enabled. Constant { value: mir::Const<'tcx>, diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 275458fc85f..3bf80d37e65 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -566,10 +566,10 @@ impl<'tcx> AdtDef<'tcx> { let mut prev_discr = None::<Discr<'tcx>>; self.variants().iter_enumerated().map(move |(i, v)| { let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); - if let VariantDiscr::Explicit(expr_did) = v.discr { - if let Ok(new_discr) = self.eval_explicit_discr(tcx, expr_did) { - discr = new_discr; - } + if let VariantDiscr::Explicit(expr_did) = v.discr + && let Ok(new_discr) = self.eval_explicit_discr(tcx, expr_did) + { + discr = new_discr; } prev_discr = Some(discr); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 51db92ecd78..6f21160d1f6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -5,7 +5,7 @@ pub mod tls; use std::assert_matches::debug_assert_matches; -use std::borrow::Borrow; +use std::borrow::{Borrow, Cow}; use std::cmp::Ordering; use std::env::VarError; use std::ffi::OsStr; @@ -1041,11 +1041,13 @@ const NUM_PREINTERNED_TY_VARS: u32 = 100; const NUM_PREINTERNED_FRESH_TYS: u32 = 20; const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3; const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3; +const NUM_PREINTERNED_ANON_BOUND_TYS_I: u32 = 3; +const NUM_PREINTERNED_ANON_BOUND_TYS_V: u32 = 20; // This number may seem high, but it is reached in all but the smallest crates. const NUM_PREINTERNED_RE_VARS: u32 = 500; -const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2; -const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20; +const NUM_PREINTERNED_ANON_RE_BOUNDS_I: u32 = 3; +const NUM_PREINTERNED_ANON_RE_BOUNDS_V: u32 = 20; pub struct CommonTypes<'tcx> { pub unit: Ty<'tcx>, @@ -1088,6 +1090,11 @@ pub struct CommonTypes<'tcx> { /// Pre-interned `Infer(ty::FreshFloatTy(n))` for small values of `n`. pub fresh_float_tys: Vec<Ty<'tcx>>, + + /// Pre-interned values of the form: + /// `Bound(DebruijnIndex(i), BoundTy { var: v, kind: BoundTyKind::Anon})` + /// for small values of `i` and `v`. + pub anon_bound_tys: Vec<Vec<Ty<'tcx>>>, } pub struct CommonLifetimes<'tcx> { @@ -1101,9 +1108,9 @@ pub struct CommonLifetimes<'tcx> { pub re_vars: Vec<Region<'tcx>>, /// Pre-interned values of the form: - /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` + /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BoundRegionKind::Anon })` /// for small values of `i` and `v`. - pub re_late_bounds: Vec<Vec<Region<'tcx>>>, + pub anon_re_bounds: Vec<Vec<Region<'tcx>>>, } pub struct CommonConsts<'tcx> { @@ -1131,6 +1138,19 @@ impl<'tcx> CommonTypes<'tcx> { let fresh_float_tys: Vec<_> = (0..NUM_PREINTERNED_FRESH_FLOAT_TYS).map(|n| mk(Infer(ty::FreshFloatTy(n)))).collect(); + let anon_bound_tys = (0..NUM_PREINTERNED_ANON_BOUND_TYS_I) + .map(|i| { + (0..NUM_PREINTERNED_ANON_BOUND_TYS_V) + .map(|v| { + mk(ty::Bound( + ty::DebruijnIndex::from(i), + ty::BoundTy { var: ty::BoundVar::from(v), kind: ty::BoundTyKind::Anon }, + )) + }) + .collect() + }) + .collect(); + CommonTypes { unit: mk(Tuple(List::empty())), bool: mk(Bool), @@ -1161,6 +1181,7 @@ impl<'tcx> CommonTypes<'tcx> { fresh_tys, fresh_int_tys, fresh_float_tys, + anon_bound_tys, } } } @@ -1176,9 +1197,9 @@ impl<'tcx> CommonLifetimes<'tcx> { let re_vars = (0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect(); - let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I) + let anon_re_bounds = (0..NUM_PREINTERNED_ANON_RE_BOUNDS_I) .map(|i| { - (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V) + (0..NUM_PREINTERNED_ANON_RE_BOUNDS_V) .map(|v| { mk(ty::ReBound( ty::DebruijnIndex::from(i), @@ -1196,7 +1217,7 @@ impl<'tcx> CommonLifetimes<'tcx> { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased), re_vars, - re_late_bounds, + anon_re_bounds, } } } @@ -1625,7 +1646,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Allocates a read-only byte or string literal for `mir::interpret` with alignment 1. /// Returns the same `AllocId` if called again with the same bytes. - pub fn allocate_bytes_dedup(self, bytes: &[u8], salt: usize) -> interpret::AllocId { + pub fn allocate_bytes_dedup<'a>( + self, + bytes: impl Into<Cow<'a, [u8]>>, + salt: usize, + ) -> interpret::AllocId { // Create an allocation that just contains these bytes. let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes, ()); let alloc = self.mk_const_alloc(alloc); @@ -3373,6 +3398,11 @@ impl<'tcx> TyCtxt<'tcx> { self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]) } + /// Return the crate imported by given use item. + pub fn extern_mod_stmt_cnum(self, def_id: LocalDefId) -> Option<CrateNum> { + self.resolutions(()).extern_crate_map.get(&def_id).copied() + } + pub fn resolver_for_lowering(self) -> &'tcx Steal<(ty::ResolverAstLowering, Arc<ast::Crate>)> { self.resolver_for_lowering_raw(()).0 } @@ -3410,6 +3440,20 @@ impl<'tcx> TyCtxt<'tcx> { pub fn do_not_recommend_impl(self, def_id: DefId) -> bool { self.get_diagnostic_attr(def_id, sym::do_not_recommend).is_some() } + + /// Whether this def is one of the special bin crate entrypoint functions that must have a + /// monomorphization and also not be internalized in the bin crate. + pub fn is_entrypoint(self, def_id: DefId) -> bool { + if self.is_lang_item(def_id, LangItem::Start) { + return true; + } + if let Some((entry_def_id, _)) = self.entry_fn(()) + && entry_def_id == def_id + { + return true; + } + false + } } /// Parameter attributes that can only be determined by examining the body of a function instead @@ -3428,8 +3472,6 @@ pub struct DeducedParamAttrs { } pub fn provide(providers: &mut Providers) { - providers.extern_mod_stmt_cnum = - |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned(); providers.is_panic_runtime = |tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::panic_runtime); providers.is_compiler_builtins = diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 809717513c7..aed94f9aa04 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -107,8 +107,8 @@ impl abi::Integer { abi::Integer::I8 }; - // If there are no negative values, we can use the unsigned fit. - if min >= 0 { + // Pick the smallest fit. + if unsigned_fit <= signed_fit { (cmp::max(unsigned_fit, at_least), false) } else { (cmp::max(signed_fit, at_least), true) @@ -1055,11 +1055,11 @@ where _ => Some(this), }; - if let Some(variant) = data_variant { + if let Some(variant) = data_variant // We're not interested in any unions. - if let FieldsShape::Union(_) = variant.fields { - data_variant = None; - } + && let FieldsShape::Union(_) = variant.fields + { + data_variant = None; } let mut result = None; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a7cde2ad485..bb70c61cd14 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1988,29 +1988,21 @@ impl<'tcx> TyCtxt<'tcx> { self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id) } - /// If the given `DefId` describes an item belonging to a trait, - /// returns the `DefId` of the trait that the trait item belongs to; - /// otherwise, returns `None`. - pub fn trait_of_item(self, def_id: DefId) -> Option<DefId> { - if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { - let parent = self.parent(def_id); - if let DefKind::Trait | DefKind::TraitAlias = self.def_kind(parent) { - return Some(parent); - } - } - None + /// If the given `DefId` is an associated item, returns the `DefId` of the parent trait or impl. + pub fn assoc_parent(self, def_id: DefId) -> Option<DefId> { + self.def_kind(def_id).is_assoc().then(|| self.parent(def_id)) } - /// If the given `DefId` describes a method belonging to an impl, returns the - /// `DefId` of the impl that the method belongs to; otherwise, returns `None`. - pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> { - if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { - let parent = self.parent(def_id); - if let DefKind::Impl { .. } = self.def_kind(parent) { - return Some(parent); - } - } - None + /// If the given `DefId` is an associated item of a trait, + /// returns the `DefId` of the trait; otherwise, returns `None`. + pub fn trait_of_assoc(self, def_id: DefId) -> Option<DefId> { + self.assoc_parent(def_id).filter(|id| self.def_kind(id) == DefKind::Trait) + } + + /// If the given `DefId` is an associated item of an impl, + /// returns the `DefId` of the impl; otherwise returns `None`. + pub fn impl_of_assoc(self, def_id: DefId) -> Option<DefId> { + self.assoc_parent(def_id).filter(|id| matches!(self.def_kind(id), DefKind::Impl { .. })) } pub fn is_exportable(self, def_id: DefId) -> bool { @@ -2024,7 +2016,10 @@ impl<'tcx> TyCtxt<'tcx> { && let Some(def_id) = def_id.as_local() && let outer = self.def_span(def_id).ctxt().outer_expn_data() && matches!(outer.kind, ExpnKind::Macro(MacroKind::Derive, _)) - && self.has_attr(outer.macro_def_id.unwrap(), sym::rustc_builtin_macro) + && find_attr!( + self.get_all_attrs(outer.macro_def_id.unwrap()), + AttributeKind::RustcBuiltinMacro { .. } + ) { true } else { @@ -2178,7 +2173,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn is_const_default_method(self, def_id: DefId) -> bool { - matches!(self.trait_of_item(def_id), Some(trait_id) if self.is_const_trait(trait_id)) + matches!(self.trait_of_assoc(def_id), Some(trait_id) if self.is_const_trait(trait_id)) } pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 9ee64df0ad0..5c44b10ba71 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -86,7 +86,7 @@ macro_rules! define_helper { impl $helper { pub fn new() -> $helper { - $helper($tl.with(|c| c.replace(true))) + $helper($tl.replace(true)) } } @@ -100,12 +100,12 @@ macro_rules! define_helper { impl Drop for $helper { fn drop(&mut self) { - $tl.with(|c| c.set(self.0)) + $tl.set(self.0) } } pub fn $name() -> bool { - $tl.with(|c| c.get()) + $tl.get() } )+ } @@ -225,10 +225,10 @@ impl<'tcx> RegionHighlightMode<'tcx> { region: Option<ty::Region<'tcx>>, number: Option<usize>, ) { - if let Some(k) = region { - if let Some(n) = number { - self.highlighting_region(k, n); - } + if let Some(k) = region + && let Some(n) = number + { + self.highlighting_region(k, n); } } diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 51be93d9a72..5cf96072177 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -54,7 +54,7 @@ impl<'tcx> Region<'tcx> { ) -> Region<'tcx> { // Use a pre-interned one when possible. if let ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon } = bound_region - && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize()) + && let Some(inner) = tcx.lifetimes.anon_re_bounds.get(debruijn.as_usize()) && let Some(re) = inner.get(var.as_usize()).copied() { re diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index ab31d943408..a5fdce93e4b 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -4,6 +4,7 @@ //! to help with the tedium. use std::fmt::{self, Debug}; +use std::marker::PhantomData; use rustc_abi::TyAndLayout; use rustc_hir::def::Namespace; @@ -234,6 +235,7 @@ TrivialLiftImpls! { rustc_abi::ExternAbi, rustc_abi::Size, rustc_hir::Safety, + rustc_middle::mir::ConstValue, rustc_type_ir::BoundConstness, rustc_type_ir::PredicatePolarity, // tidy-alphabetical-end @@ -250,7 +252,7 @@ TrivialTypeTraversalImpls! { crate::mir::BlockTailInfo, crate::mir::BorrowKind, crate::mir::CastKind, - crate::mir::ConstValue<'tcx>, + crate::mir::ConstValue, crate::mir::CoroutineSavedLocal, crate::mir::FakeReadCause, crate::mir::Local, @@ -311,6 +313,13 @@ TrivialTypeTraversalAndLiftImpls! { /////////////////////////////////////////////////////////////////////////// // Lift implementations +impl<'tcx> Lift<TyCtxt<'tcx>> for PhantomData<&()> { + type Lifted = PhantomData<&'tcx ()>; + fn lift_to_interner(self, _: TyCtxt<'tcx>) -> Option<Self::Lifted> { + Some(PhantomData) + } +} + impl<'tcx, T: Lift<TyCtxt<'tcx>>> Lift<TyCtxt<'tcx>> for Option<T> { type Lifted = Option<T::Lifted>; fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8bb3b3f1263..4569596cfbe 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -485,7 +485,15 @@ impl<'tcx> Ty<'tcx> { index: ty::DebruijnIndex, bound_ty: ty::BoundTy, ) -> Ty<'tcx> { - Ty::new(tcx, Bound(index, bound_ty)) + // Use a pre-interned one when possible. + if let ty::BoundTy { var, kind: ty::BoundTyKind::Anon } = bound_ty + && let Some(inner) = tcx.types.anon_bound_tys.get(index.as_usize()) + && let Some(ty) = inner.get(var.as_usize()).copied() + { + ty + } else { + Ty::new(tcx, Bound(index, bound_ty)) + } } #[inline] diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 174892c6f4d..a7d07adf78f 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -32,7 +32,7 @@ use crate::ty::{ #[derive(Copy, Clone, Debug)] pub struct Discr<'tcx> { - /// Bit representation of the discriminant (e.g., `-128i8` is `0xFF_u128`). + /// Bit representation of the discriminant (e.g., `-1i8` is `0xFF_u128`). pub val: u128, pub ty: Ty<'tcx>, } |
