diff options
Diffstat (limited to 'compiler/rustc_middle')
20 files changed, 193 insertions, 126 deletions
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index f74cea23c24..ded1c580572 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -35,6 +35,8 @@ middle_assert_shl_overflow = middle_assert_shr_overflow = attempt to shift right by `{$val}`, which would overflow +middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty} is unsafe + middle_bounds_check = index out of bounds: the length is {$len} but the index is {$index} @@ -110,6 +112,8 @@ middle_type_length_limit = reached the type-length limit while instantiating `{$ middle_unknown_layout = the type `{$ty}` has an unknown layout +middle_unsupported_union = we don't support unions yet: '{$ty_name}' + middle_values_too_big = values of the type `{$ty}` are too big for the target architecture diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 750531b638e..eaccd8c360e 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -87,6 +87,7 @@ macro_rules! arena_types { [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>, [decode] attribute: rustc_hir::Attribute, [] name_set: rustc_data_structures::unord::UnordSet<rustc_span::Symbol>, + [] autodiff_item: rustc_ast::expand::autodiff_attrs::AutoDiffItem, [] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::Symbol>, [] pats: rustc_middle::ty::PatternKind<'tcx>, diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index b0187a1848c..b30d3a950c6 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -37,6 +37,20 @@ pub struct OpaqueHiddenTypeMismatch<'tcx> { pub sub: TypeMismatchReason, } +#[derive(Diagnostic)] +#[diag(middle_unsupported_union)] +pub struct UnsupportedUnion { + pub ty_name: String, +} + +#[derive(Diagnostic)] +#[diag(middle_autodiff_unsafe_inner_const_ref)] +pub struct AutodiffUnsafeInnerConstRef { + #[primary_span] + pub span: Span, + pub ty: String, +} + #[derive(Subdiagnostic)] pub enum TypeMismatchReason { #[label(middle_conflict_types)] diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index cc980f6e62a..1784665bcae 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -1,4 +1,5 @@ use rustc_abi::Align; +use rustc_ast::expand::autodiff_attrs::AutoDiffAttrs; use rustc_attr_parsing::{InlineAttr, InstructionSetAttr, OptimizeAttr}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::Symbol; @@ -52,6 +53,8 @@ pub struct CodegenFnAttrs { /// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around /// the function entry. pub patchable_function_entry: Option<PatchableFunctionEntry>, + /// For the `#[autodiff]` macros. + pub autodiff_item: Option<AutoDiffAttrs>, } #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] @@ -160,6 +163,7 @@ impl CodegenFnAttrs { instruction_set: None, alignment: None, patchable_function_entry: None, + autodiff_item: None, } } diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index 111ac990bc7..51a079e8bc1 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -45,15 +45,22 @@ pub enum ObjectLifetimeDefault { Param(DefId), } -/// Maps the id of each lifetime reference to the lifetime decl +/// Maps the id of each bound variable reference to the variable decl /// that it corresponds to. -#[derive(HashStable, Debug)] +#[derive(Debug, Default, HashStable)] pub struct ResolveBoundVars { - /// Maps from every use of a named (not anonymous) lifetime to a - /// `Region` describing how that region is bound + // Maps from every use of a named (not anonymous) bound var to a + // `ResolvedArg` describing how that variable is bound. pub defs: SortedMap<ItemLocalId, ResolvedArg>, + // Maps relevant hir items to the bound vars on them. These include: + // - function defs + // - function pointers + // - closures + // - trait refs + // - bound types (like `T` in `for<'a> T<'a>: Foo`) pub late_bound_vars: SortedMap<ItemLocalId, Vec<ty::BoundVariableKind>>, + // List captured variables for each opaque type. pub opaque_captured_lifetimes: LocalDefIdMap<Vec<(ResolvedArg, LocalDefId)>>, } diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 66d97fda433..923160cc0cc 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -250,7 +250,7 @@ impl<'tcx> Const<'tcx> { // Dont use the outer ty as on invalid code we can wind up with them not being the same. // this then results in allowing const eval to add `1_i64 + 1_usize` in cases where the mir // was originally `({N: usize} + 1_usize)` under `generic_const_exprs`. - ty::ConstKind::Value(ty, _) => ty, + ty::ConstKind::Value(cv) => cv.ty, _ => *ty, } } @@ -264,7 +264,7 @@ impl<'tcx> Const<'tcx> { pub fn is_required_const(&self) -> bool { match self { Const::Ty(_, c) => match c.kind() { - ty::ConstKind::Value(_, _) => false, // already a value, cannot error + ty::ConstKind::Value(_) => false, // already a value, cannot error _ => true, }, Const::Val(..) => false, // already a value, cannot error @@ -276,11 +276,11 @@ impl<'tcx> Const<'tcx> { pub fn try_to_scalar(self) -> Option<Scalar> { match self { Const::Ty(_, c) => match c.kind() { - ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => { + ty::ConstKind::Value(cv) if cv.ty.is_primitive() => { // A valtree of a type where leaves directly represent the scalar const value. // Just checking whether it is a leaf is insufficient as e.g. references are leafs // but the leaf value is the value they point to, not the reference itself! - Some(valtree.unwrap_leaf().into()) + Some(cv.valtree.unwrap_leaf().into()) } _ => None, }, @@ -295,9 +295,7 @@ impl<'tcx> Const<'tcx> { match self { Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x), Const::Ty(_, c) => match c.kind() { - ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => { - Some(valtree.unwrap_leaf()) - } + ty::ConstKind::Value(cv) if cv.ty.is_primitive() => Some(cv.valtree.unwrap_leaf()), _ => None, }, _ => None, @@ -328,7 +326,7 @@ impl<'tcx> Const<'tcx> { } match c.kind() { - ConstKind::Value(ty, val) => Ok(tcx.valtree_to_const_val((ty, val))), + ConstKind::Value(cv) => Ok(tcx.valtree_to_const_val(cv)), ConstKind::Expr(_) => { bug!("Normalization of `ty::ConstKind::Expr` is unimplemented") } @@ -353,13 +351,13 @@ impl<'tcx> Const<'tcx> { typing_env: ty::TypingEnv<'tcx>, ) -> Option<Scalar> { if let Const::Ty(_, c) = self - && let ty::ConstKind::Value(ty, val) = c.kind() - && ty.is_primitive() + && let ty::ConstKind::Value(cv) = c.kind() + && cv.ty.is_primitive() { // Avoid the `valtree_to_const_val` query. Can only be done on primitive types that // are valtree leaves, and *not* on references. (References should return the // pointer here, which valtrees don't represent.) - Some(val.unwrap_leaf().into()) + Some(cv.valtree.unwrap_leaf().into()) } else { self.eval(tcx, typing_env, DUMMY_SP).ok()?.try_to_scalar() } @@ -473,7 +471,7 @@ impl<'tcx> Const<'tcx> { // A valtree may be a reference. Valtree references correspond to a // different allocation each time they are evaluated. Valtrees for primitive // types are fine though. - ty::ConstKind::Value(ty, _) => ty.is_primitive(), + ty::ConstKind::Value(cv) => cv.ty.is_primitive(), ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false, // This can happen if evaluation of a constant failed. The result does not matter // much since compilation is doomed. diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 6fa3fa2432d..e49fc376a13 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -1,6 +1,7 @@ use std::fmt; use std::hash::Hash; +use rustc_ast::expand::autodiff_attrs::AutoDiffItem; use rustc_attr_parsing::InlineAttr; use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::fingerprint::Fingerprint; @@ -246,6 +247,7 @@ impl ToStableHashKey<StableHashingContext<'_>> for MonoItem<'_> { pub struct MonoItemPartitions<'tcx> { pub codegen_units: &'tcx [CodegenUnit<'tcx>], pub all_mono_items: &'tcx DefIdSet, + pub autodiff_items: &'tcx [AutoDiffItem], } #[derive(Debug, HashStable)] diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 3b4fba97e60..a318bacb866 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1441,7 +1441,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { ty::ConstKind::Unevaluated(uv) => { format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,) } - ty::ConstKind::Value(_, val) => format!("ty::Valtree({})", fmt_valtree(&val)), + ty::ConstKind::Value(cv) => { + format!("ty::Valtree({})", fmt_valtree(&cv.valtree)) + } // No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`. ty::ConstKind::Error(_) => "Error".to_string(), // These variants shouldn't exist in the MIR. diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index e243425c0b7..949d8303385 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -95,7 +95,7 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { } } -impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) { +impl<'tcx> Key for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) { type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { @@ -550,7 +550,7 @@ impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) { } } -impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) { +impl<'tcx> Key for ty::Value<'tcx> { type Cache<V> = DefaultCache<Self, V>; fn default_span(&self, _: TyCtxt<'_>) -> Span { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d83bc19a6a2..41e9858030c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1256,9 +1256,9 @@ rustc_queries! { desc { "evaluating type-level constant" } } - /// Converts a type level constant value into `ConstValue` - query valtree_to_const_val(key: (Ty<'tcx>, ty::ValTree<'tcx>)) -> mir::ConstValue<'tcx> { - desc { "converting type-level constant value to mir constant value"} + /// Converts a type-level constant value into a MIR constant value. + query valtree_to_const_val(key: ty::Value<'tcx>) -> mir::ConstValue<'tcx> { + desc { "converting type-level constant value to MIR constant value"} } /// Destructures array, ADT or tuple constants into the constants @@ -1437,9 +1437,9 @@ rustc_queries! { desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key) } } - query vtable_entries(key: ty::PolyTraitRef<'tcx>) + query vtable_entries(key: ty::TraitRef<'tcx>) -> &'tcx [ty::VtblEntry<'tcx>] { - desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) } + desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id) } } query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize { @@ -1451,7 +1451,7 @@ rustc_queries! { key.1, key.0 } } - query vtable_allocation(key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId { + query vtable_allocation(key: (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>)) -> mir::interpret::AllocId { desc { |tcx| "vtable const allocation for <{} as {}>", key.0, key.1.map(|trait_ref| format!("{trait_ref}")).unwrap_or("_".to_owned()) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 31055276422..d77fb1cc91e 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -5,7 +5,6 @@ use rustc_error_messages::MultiSpan; use rustc_macros::HashStable; use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; -use crate::mir::interpret::Scalar; use crate::ty::{self, Ty, TyCtxt}; mod int; @@ -110,8 +109,8 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Value(ty, val)) + pub fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree })) } #[inline] @@ -214,47 +213,31 @@ impl<'tcx> Const<'tcx> { Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize) } - /// Panics if self.kind != ty::ConstKind::Value - pub fn to_valtree(self) -> (ty::ValTree<'tcx>, Ty<'tcx>) { + /// Panics if `self.kind != ty::ConstKind::Value`. + pub fn to_value(self) -> ty::Value<'tcx> { match self.kind() { - ty::ConstKind::Value(ty, valtree) => (valtree, ty), + ty::ConstKind::Value(cv) => cv, _ => bug!("expected ConstKind::Value, got {:?}", self.kind()), } } - /// Attempts to convert to a `ValTree` - pub fn try_to_valtree(self) -> Option<(ty::ValTree<'tcx>, Ty<'tcx>)> { + /// Attempts to convert to a value. + /// + /// Note that this does not evaluate the constant. + pub fn try_to_value(self) -> Option<ty::Value<'tcx>> { match self.kind() { - ty::ConstKind::Value(ty, valtree) => Some((valtree, ty)), + ty::ConstKind::Value(cv) => Some(cv), _ => None, } } - #[inline] - pub fn try_to_scalar(self) -> Option<(Scalar, Ty<'tcx>)> { - let (valtree, ty) = self.try_to_valtree()?; - Some((valtree.try_to_scalar()?, ty)) - } - - pub fn try_to_bool(self) -> Option<bool> { - self.try_to_valtree()?.0.try_to_scalar_int()?.try_to_bool().ok() - } - + /// Convenience method to extract the value of a usize constant, + /// useful to get the length of an array type. + /// + /// Note that this does not evaluate the constant. #[inline] pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { - self.try_to_valtree()?.0.try_to_target_usize(tcx) - } - - /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of - /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it - /// contains const generic parameters or pointers). - #[inline] - pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> { - let (scalar, ty) = self.try_to_scalar()?; - let scalar = scalar.try_to_scalar_int().ok()?; - let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(ty); - let size = tcx.layout_of(input).ok()?.size; - Some(scalar.to_bits(size)) + self.try_to_value()?.try_to_target_usize(tcx) } pub fn is_ct_infer(self) -> bool { diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 9f9bf41c335..d914b7576dc 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -1,11 +1,9 @@ -use rustc_macros::{HashStable, TyDecodable, TyEncodable}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use super::ScalarInt; use crate::mir::interpret::Scalar; use crate::ty::{self, Ty, TyCtxt}; -#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq)] -#[derive(HashStable)] /// This datastructure is used to represent the value of constants used in the type system. /// /// We explicitly choose a different datastructure from the way values are processed within @@ -18,6 +16,8 @@ use crate::ty::{self, Ty, TyCtxt}; /// /// `ValTree` does not have this problem with representation, as it only contains integers or /// lists of (nested) `ValTree`. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +#[derive(HashStable, TyEncodable, TyDecodable)] pub enum ValTree<'tcx> { /// integers, `bool`, `char` are represented as scalars. /// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values @@ -79,10 +79,6 @@ impl<'tcx> ValTree<'tcx> { } } - pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { - self.try_to_scalar_int().map(|s| s.to_target_usize(tcx)) - } - /// Get the values inside the ValTree as a slice of bytes. This only works for /// constants with types &str, &[u8], or [u8; _]. pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx [u8]> { @@ -107,3 +103,54 @@ impl<'tcx> ValTree<'tcx> { ) } } + +/// A type-level constant value. +/// +/// Represents a typed, fully evaluated constant. +#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] +pub struct Value<'tcx> { + pub ty: Ty<'tcx>, + pub valtree: ValTree<'tcx>, +} + +impl<'tcx> Value<'tcx> { + /// Attempts to extract the raw bits from the constant. + /// + /// Fails if the value can't be represented as bits (e.g. because it is a reference + /// or an aggregate). + #[inline] + pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> { + let (ty::Bool | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Float(_)) = self.ty.kind() else { + return None; + }; + let scalar = self.valtree.try_to_scalar_int()?; + let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(self.ty); + let size = tcx.layout_of(input).ok()?.size; + Some(scalar.to_bits(size)) + } + + pub fn try_to_bool(self) -> Option<bool> { + if !self.ty.is_bool() { + return None; + } + self.valtree.try_to_scalar_int()?.try_to_bool().ok() + } + + pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { + if !self.ty.is_usize() { + return None; + } + self.valtree.try_to_scalar_int().map(|s| s.to_target_usize(tcx)) + } +} + +impl<'tcx> rustc_type_ir::inherent::ValueConst<TyCtxt<'tcx>> for Value<'tcx> { + fn ty(self) -> Ty<'tcx> { + self.ty + } + + fn valtree(self) -> ValTree<'tcx> { + self.valtree + } +} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0c22c056dab..69f6fc0ad8a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -142,10 +142,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type ParamConst = ty::ParamConst; type BoundConst = ty::BoundVar; - type ValueConst = ty::ValTree<'tcx>; + type ValueConst = ty::Value<'tcx>; type ExprConst = ty::Expr<'tcx>; - type Region = Region<'tcx>; + type ValTree = ty::ValTree<'tcx>; + type Region = Region<'tcx>; type EarlyParamRegion = ty::EarlyParamRegion; type LateParamRegion = ty::LateParamRegion; type BoundRegion = ty::BoundRegion; @@ -1118,15 +1119,18 @@ impl<'tcx> CommonConsts<'tcx> { }; CommonConsts { - unit: mk_const(ty::ConstKind::Value(types.unit, ty::ValTree::zst())), - true_: mk_const(ty::ConstKind::Value( - types.bool, - ty::ValTree::Leaf(ty::ScalarInt::TRUE), - )), - false_: mk_const(ty::ConstKind::Value( - types.bool, - ty::ValTree::Leaf(ty::ScalarInt::FALSE), - )), + unit: mk_const(ty::ConstKind::Value(ty::Value { + ty: types.unit, + valtree: ty::ValTree::zst(), + })), + true_: mk_const(ty::ConstKind::Value(ty::Value { + ty: types.bool, + valtree: ty::ValTree::Leaf(ty::ScalarInt::TRUE), + })), + false_: mk_const(ty::ConstKind::Value(ty::Value { + ty: types.bool, + valtree: ty::ValTree::Leaf(ty::ScalarInt::FALSE), + })), } } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 0af57f636aa..ec0498b168c 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -381,7 +381,7 @@ impl FlagComputation { self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER); self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } - ty::ConstKind::Value(ty, _) => self.add_ty(ty), + ty::ConstKind::Value(cv) => self.add_ty(cv.ty), ty::ConstKind::Expr(e) => self.add_args(e.args()), ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0d41a1d7dbf..3ced64b5b80 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -504,6 +504,9 @@ impl<'tcx> SizeSkeleton<'tcx> { } } + // Pattern types are always the same size as their base. + ty::Pat(base, _) => SizeSkeleton::compute(base, tcx, typing_env), + _ => Err(err), } } @@ -855,7 +858,12 @@ where } let mk_dyn_vtable = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| { - let min_count = ty::vtable_min_entries(tcx, principal); + let min_count = ty::vtable_min_entries( + tcx, + principal.map(|principal| { + tcx.instantiate_bound_regions_with_erased(principal) + }), + ); Ty::new_imm_ref( tcx, tcx.lifetimes.re_static, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8cd632790a8..88eea6101b5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -60,7 +60,7 @@ pub use self::closure::{ place_to_string_for_capture, }; pub use self::consts::{ - Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, + Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, Value, }; pub use self::context::{ CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 027a4315b4b..018fcc66aee 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1484,8 +1484,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { _ => write!(self, "_")?, }, ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)), - ty::ConstKind::Value(ty, value) => { - return self.pretty_print_const_valtree(value, ty, print_ty); + ty::ConstKind::Value(cv) => { + return self.pretty_print_const_valtree(cv.valtree, cv.ty, print_ty); } ty::ConstKind::Bound(debruijn, bound_var) => { @@ -1637,33 +1637,32 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { match ty.kind() { // Byte strings (&[u8; N]) ty::Ref(_, inner, _) => { - if let ty::Array(elem, len) = inner.kind() { - if let ty::Uint(ty::UintTy::U8) = elem.kind() { - if let ty::ConstKind::Value(_, ty::ValTree::Leaf(int)) = len.kind() { - match self.tcx().try_get_global_alloc(prov.alloc_id()) { - Some(GlobalAlloc::Memory(alloc)) => { - let len = int.to_bits(self.tcx().data_layout.pointer_size); - let range = - AllocRange { start: offset, size: Size::from_bytes(len) }; - if let Ok(byte_str) = - alloc.inner().get_bytes_strip_provenance(&self.tcx(), range) - { - p!(pretty_print_byte_str(byte_str)) - } else { - p!("<too short allocation>") - } - } - // FIXME: for statics, vtables, and functions, we could in principle print more detail. - Some(GlobalAlloc::Static(def_id)) => { - p!(write("<static({:?})>", def_id)) - } - Some(GlobalAlloc::Function { .. }) => p!("<function>"), - Some(GlobalAlloc::VTable(..)) => p!("<vtable>"), - None => p!("<dangling pointer>"), + if let ty::Array(elem, len) = inner.kind() + && let ty::Uint(ty::UintTy::U8) = elem.kind() + && let ty::ConstKind::Value(cv) = len.kind() + && let ty::ValTree::Leaf(int) = cv.valtree + { + match self.tcx().try_get_global_alloc(prov.alloc_id()) { + Some(GlobalAlloc::Memory(alloc)) => { + let len = int.to_bits(self.tcx().data_layout.pointer_size); + let range = AllocRange { start: offset, size: Size::from_bytes(len) }; + if let Ok(byte_str) = + alloc.inner().get_bytes_strip_provenance(&self.tcx(), range) + { + p!(pretty_print_byte_str(byte_str)) + } else { + p!("<too short allocation>") } - return Ok(()); } + // FIXME: for statics, vtables, and functions, we could in principle print more detail. + Some(GlobalAlloc::Static(def_id)) => { + p!(write("<static({:?})>", def_id)) + } + Some(GlobalAlloc::Function { .. }) => p!("<function>"), + Some(GlobalAlloc::VTable(..)) => p!("<vtable>"), + None => p!("<dangling pointer>"), } + return Ok(()); } } ty::FnPtr(..) => { @@ -1786,6 +1785,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { Ok(()) } + // FIXME(valtrees): Accept `ty::Value` instead of `Ty` and `ty::ValTree` separately. fn pretty_print_const_valtree( &mut self, valtree: ty::ValTree<'tcx>, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 68cb56f3583..9e9de4fb064 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -162,16 +162,15 @@ impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> { impl<'tcx> fmt::Debug for ty::Const<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // If this is a value, we spend some effort to make it look nice. - if let ConstKind::Value(_, _) = self.kind() { + if let ConstKind::Value(_) = self.kind() { return ty::tls::with(move |tcx| { - // Somehow trying to lift the valtree results in lifetime errors, so we lift the - // entire constant. + // ValTrees aren't interned, so we lift the entire constant. let lifted = tcx.lift(*self).unwrap(); - let ConstKind::Value(ty, valtree) = lifted.kind() else { + let ConstKind::Value(cv) = lifted.kind() else { bug!("we checked that this is a valtree") }; let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS); - cx.pretty_print_const_valtree(valtree, ty, /*print_ty*/ true)?; + cx.pretty_print_const_valtree(cv.valtree, cv.ty, /*print_ty*/ true)?; f.write_str(&cx.into_buffer()) }); } @@ -589,9 +588,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> { } ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?), ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?), - ConstKind::Value(t, v) => { - ConstKind::Value(t.try_fold_with(folder)?, v.try_fold_with(folder)?) - } + ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?), ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?), ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), }; @@ -610,10 +607,7 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> { } ConstKind::Placeholder(p) => p.visit_with(visitor), ConstKind::Unevaluated(uv) => uv.visit_with(visitor), - ConstKind::Value(t, v) => { - try_visit!(t.visit_with(visitor)); - v.visit_with(visitor) - } + ConstKind::Value(v) => v.visit_with(visitor), ConstKind::Error(e) => e.visit_with(visitor), ConstKind::Expr(e) => e.visit_with(visitor), } diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 455bd16ff8c..6c9e0e7c0eb 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -7,7 +7,7 @@ use rustc_type_ir::elaborate; use crate::mir::interpret::{ AllocId, AllocInit, Allocation, CTFE_ALLOC_SALT, Pointer, Scalar, alloc_range, }; -use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt}; +use crate::ty::{self, Instance, TraitRef, Ty, TyCtxt}; #[derive(Clone, Copy, PartialEq, HashStable)] pub enum VtblEntry<'tcx> { @@ -22,7 +22,7 @@ pub enum VtblEntry<'tcx> { /// dispatchable associated function Method(Instance<'tcx>), /// pointer to a separate supertrait vtable, can be used by trait upcasting coercion - TraitVPtr(PolyTraitRef<'tcx>), + TraitVPtr(TraitRef<'tcx>), } impl<'tcx> fmt::Debug for VtblEntry<'tcx> { @@ -59,7 +59,7 @@ pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2; // function is an accurate approximation. We verify this when actually computing the vtable below. pub(crate) fn vtable_min_entries<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, + trait_ref: Option<ty::ExistentialTraitRef<'tcx>>, ) -> usize { let mut count = TyCtxt::COMMON_VTABLE_ENTRIES.len(); let Some(trait_ref) = trait_ref else { @@ -67,7 +67,7 @@ pub(crate) fn vtable_min_entries<'tcx>( }; // This includes self in supertraits. - for def_id in elaborate::supertrait_def_ids(tcx, trait_ref.def_id()) { + for def_id in elaborate::supertrait_def_ids(tcx, trait_ref.def_id) { count += tcx.own_existential_vtable_entries(def_id).len(); } @@ -83,7 +83,7 @@ pub(crate) fn vtable_min_entries<'tcx>( /// initial contents.) pub(super) fn vtable_allocation_provider<'tcx>( tcx: TyCtxt<'tcx>, - key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), + key: (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), ) -> AllocId { let (ty, poly_trait_ref) = key; @@ -118,7 +118,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( for (idx, entry) in vtable_entries.iter().enumerate() { let idx: u64 = u64::try_from(idx).unwrap(); - let scalar = match entry { + let scalar = match *entry { VtblEntry::MetadataDropInPlace => { if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) { let instance = ty::Instance::resolve_drop_in_place(tcx, ty); @@ -134,13 +134,12 @@ pub(super) fn vtable_allocation_provider<'tcx>( VtblEntry::Vacant => continue, VtblEntry::Method(instance) => { // Prepare the fn ptr we write into the vtable. - let fn_alloc_id = tcx.reserve_and_set_fn_alloc(*instance, CTFE_ALLOC_SALT); + let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT); let fn_ptr = Pointer::from(fn_alloc_id); Scalar::from_pointer(fn_ptr, &tcx) } VtblEntry::TraitVPtr(trait_ref) => { - let super_trait_ref = trait_ref - .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); + let super_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref); let supertrait_alloc_id = tcx.vtable_allocation((ty, Some(super_trait_ref))); let vptr = Pointer::from(supertrait_alloc_id); Scalar::from_pointer(vptr, &tcx) diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 2dcba8c2f82..3e8a3d1a289 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -206,7 +206,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::ConstKind::Bound(..) | ty::ConstKind::Error(_) => {} - ty::ConstKind::Value(ty, _) => stack.push(ty.into()), + ty::ConstKind::Value(cv) => stack.push(cv.ty.into()), ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()), ty::ConstKind::Unevaluated(ct) => { |
