From ef5aa6ac3efb8601d7c9733d727b090b96c06ffe Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 27 May 2020 23:23:46 +0200 Subject: [PATCH 1/4] compare consts using ptr equality --- .../infer/canonical/canonicalizer.rs | 6 ++-- src/librustc_infer/infer/canonical/mod.rs | 8 ++--- src/librustc_infer/infer/fudge.rs | 4 +-- src/librustc_infer/infer/higher_ranked/mod.rs | 8 ++--- src/librustc_infer/infer/resolve.rs | 2 +- src/librustc_middle/arena.rs | 2 ++ src/librustc_middle/infer/canonical.rs | 8 ++--- src/librustc_middle/ty/codec.rs | 5 ++- src/librustc_middle/ty/context.rs | 36 +++++++++++++++---- src/librustc_middle/ty/fold.rs | 12 +++---- src/librustc_middle/ty/print/pretty.rs | 2 +- src/librustc_middle/ty/relate.rs | 2 +- src/librustc_middle/ty/structural_impls.rs | 2 +- src/librustc_middle/ty/sty.rs | 29 ++++++++++++--- src/librustc_mir/interpret/eval_context.rs | 4 +-- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir/transform/promote_consts.rs | 6 ++-- src/librustc_mir_build/hair/cx/expr.rs | 19 +++++----- src/librustc_mir_build/hair/pattern/_match.rs | 3 +- src/librustc_mir_build/hair/pattern/mod.rs | 2 +- src/librustc_trait_selection/opaque_types.rs | 2 +- src/librustc_trait_selection/traits/wf.rs | 4 +-- src/librustc_traits/chalk/db.rs | 8 ++--- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/writeback.rs | 2 +- src/librustc_typeck/collect.rs | 5 ++- 26 files changed, 114 insertions(+), 71 deletions(-) diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index c2dae6ba4f83d..5f1ce0671f7bd 100644 --- a/src/librustc_infer/infer/canonical/canonicalizer.rs +++ b/src/librustc_infer/infer/canonical/canonicalizer.rs @@ -658,10 +658,8 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { self.fold_const(bound_to) } else { let var = self.canonical_var(info, const_var.into()); - self.tcx().mk_const(ty::Const { - val: ty::ConstKind::Bound(self.binder_index, var), - ty: self.fold_ty(const_var.ty), - }) + self.tcx() + .mk_const(self.fold_ty(const_var.ty), ty::ConstKind::Bound(self.binder_index, var)) } } } diff --git a/src/librustc_infer/infer/canonical/mod.rs b/src/librustc_infer/infer/canonical/mod.rs index 7f58b29a73f36..2ba77a1ed34eb 100644 --- a/src/librustc_infer/infer/canonical/mod.rs +++ b/src/librustc_infer/infer/canonical/mod.rs @@ -152,10 +152,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let universe_mapped = universe_map(universe); let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, name }; self.tcx - .mk_const(ty::Const { - val: ty::ConstKind::Placeholder(placeholder_mapped), - ty: self.tcx.types.err, // FIXME(const_generics) - }) + .mk_const( + self.tcx.types.err, // FIXME(const_generics) + ty::ConstKind::Placeholder(placeholder_mapped), + ) .into() } } diff --git a/src/librustc_infer/infer/fudge.rs b/src/librustc_infer/infer/fudge.rs index c6651108df53d..0193688552f0f 100644 --- a/src/librustc_infer/infer/fudge.rs +++ b/src/librustc_infer/infer/fudge.rs @@ -232,13 +232,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> { } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { val: ty::ConstKind::Infer(ty::InferConst::Var(vid)), ty } = ct { + if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.val { if self.const_vars.0.contains(&vid) { // This variable was created during the fudging. // Recreate it with a fresh variable here. let idx = (vid.index - self.const_vars.0.start.index) as usize; let origin = self.const_vars.1[idx]; - self.infcx.next_const_var(ty, origin) + self.infcx.next_const_var(ct.ty, origin) } else { ct } diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs index ef18918c1772f..872e4dce38077 100644 --- a/src/librustc_infer/infer/higher_ranked/mod.rs +++ b/src/librustc_infer/infer/higher_ranked/mod.rs @@ -98,13 +98,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let fld_c = |bound_var: ty::BoundVar, ty| { - self.tcx.mk_const(ty::Const { - val: ty::ConstKind::Placeholder(ty::PlaceholderConst { + self.tcx.mk_const( + ty, + ty::ConstKind::Placeholder(ty::PlaceholderConst { universe: next_universe, name: bound_var, }), - ty, - }) + ) }; let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t, fld_c); diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs index e28cf49c7f253..a3492dada5513 100644 --- a/src/librustc_infer/infer/resolve.rs +++ b/src/librustc_infer/infer/resolve.rs @@ -228,7 +228,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { match c.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { self.err = Some(FixupError::UnresolvedConst(vid)); - return self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: c.ty }); + return self.tcx().mk_const(c.ty, ty::ConstKind::Error); } ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("Unexpected const in full const resolver: {:?}", c); diff --git a/src/librustc_middle/arena.rs b/src/librustc_middle/arena.rs index 9b9207312e8dd..6b98b4b337596 100644 --- a/src/librustc_middle/arena.rs +++ b/src/librustc_middle/arena.rs @@ -71,6 +71,8 @@ macro_rules! arena_types { // Interned types [] tys: rustc_middle::ty::TyS<$tcx>, + [] const_: rustc_middle::ty::Const<$tcx>, + // HIR query types [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>, [few] hir_definitions: rustc_hir::definitions::Definitions, diff --git a/src/librustc_middle/infer/canonical.rs b/src/librustc_middle/infer/canonical.rs index 9433d282ad297..c433279a6ac4d 100644 --- a/src/librustc_middle/infer/canonical.rs +++ b/src/librustc_middle/infer/canonical.rs @@ -328,10 +328,10 @@ impl<'tcx> CanonicalVarValues<'tcx> { .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(i))) .into(), GenericArgKind::Const(ct) => tcx - .mk_const(ty::Const { - ty: ct.ty, - val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)), - }) + .mk_const( + ct.ty, + ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)), + ) .into(), }) .collect(), diff --git a/src/librustc_middle/ty/codec.rs b/src/librustc_middle/ty/codec.rs index c4d5bd7e60255..2dcd41eebb08e 100644 --- a/src/librustc_middle/ty/codec.rs +++ b/src/librustc_middle/ty/codec.rs @@ -291,7 +291,10 @@ pub fn decode_const(decoder: &mut D) -> Result<&'tcx ty::Const<'tcx>, D::Erro where D: TyDecoder<'tcx>, { - Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?)) + // FIXME: we temporarily have a `Const` on the stack here, + // as we compare `Const`s using ptr equality, this is dangerous. + let ct: ty::Const<'tcx> = Decodable::decode(decoder)?; + Ok(decoder.tcx().mk_const(ct.ty, ct.val)) } #[inline] diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 5b53ab1778e3f..9917c229dac79 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -28,9 +28,9 @@ use crate::ty::TyKind::*; use crate::ty::{self, DefIdTree, Ty, TypeAndMut}; use crate::ty::{AdtDef, AdtKind, Const, Region}; use crate::ty::{BindingMode, BoundVar}; +use crate::ty::{ConstKind, InferConst, ParamConst}; use crate::ty::{ConstVid, FloatVar, FloatVid, IntVar, IntVid, TyVar, TyVid}; use crate::ty::{ExistentialPredicate, Predicate, PredicateKind}; -use crate::ty::{InferConst, ParamConst}; use crate::ty::{InferTy, ParamTy, PolyFnSig, ProjectionTy}; use crate::ty::{List, TyKind, TyS}; use rustc_ast::ast; @@ -856,9 +856,10 @@ impl<'tcx> CommonConsts<'tcx> { let mk_const = |c| interners.const_.intern(c, |c| Interned(interners.arena.alloc(c))).0; CommonConsts { - unit: mk_const(ty::Const { - val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::zst())), + unit: mk_const(Const { ty: types.unit, + val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::zst())), + _priv: ty::sty::PrivateMarker(()), }), } } @@ -1909,6 +1910,21 @@ impl<'tcx> Borrow> for Interned<'tcx, TyS<'tcx>> { } } +impl<'tcx> PartialEq for Interned<'tcx, Const<'tcx>> { + fn eq(&self, other: &Interned<'tcx, Const<'tcx>>) -> bool { + self.0.ty == other.0.ty && self.0.val == other.0.val + } +} + +impl<'tcx> Eq for Interned<'tcx, Const<'tcx>> {} + +impl<'tcx> Hash for Interned<'tcx, Const<'tcx>> { + fn hash(&self, s: &mut H) { + self.0.ty.hash(s); + self.0.val.hash(s); + } +} + // N.B., an `Interned>` compares and hashes as its elements. impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, List> { fn eq(&self, other: &Interned<'tcx, List>) -> bool { @@ -2022,7 +2038,6 @@ macro_rules! direct_interners { direct_interners!( region: mk_region(RegionKind), - const_: mk_const(Const<'tcx>), predicate_kind: intern_predicate_kind(PredicateKind<'tcx>), ); @@ -2086,6 +2101,13 @@ impl<'tcx> TyCtxt<'tcx> { self.interners.intern_ty(st) } + #[inline] + pub fn mk_const(&self, ty: Ty<'tcx>, val: ConstKind<'tcx>) -> &'tcx Const<'tcx> { + let ct = Const { ty, val, _priv: super::sty::PrivateMarker(()) }; + + self.interners.const_.intern(ct, |ct| Interned(self.arena.alloc(ct))).0 + } + #[inline] pub fn mk_predicate(&self, kind: PredicateKind<'tcx>) -> Predicate<'tcx> { let kind = self.intern_predicate_kind(kind); @@ -2307,7 +2329,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> { - self.mk_const(ty::Const { val: ty::ConstKind::Infer(InferConst::Var(v)), ty }) + self.mk_const(ty, ty::ConstKind::Infer(InferConst::Var(v))) } #[inline] @@ -2327,7 +2349,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_const_infer(self, ic: InferConst<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - self.mk_const(ty::Const { val: ty::ConstKind::Infer(ic), ty }) + self.mk_const(ty, ty::ConstKind::Infer(ic)) } #[inline] @@ -2337,7 +2359,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_const_param(self, index: u32, name: Symbol, ty: Ty<'tcx>) -> &'tcx Const<'tcx> { - self.mk_const(ty::Const { val: ty::ConstKind::Param(ParamConst { index, name }), ty }) + self.mk_const(ty, ty::ConstKind::Param(ParamConst { index, name })) } pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { diff --git a/src/librustc_middle/ty/fold.rs b/src/librustc_middle/ty/fold.rs index 248dd00ef47be..941209deeeec5 100644 --- a/src/librustc_middle/ty/fold.rs +++ b/src/librustc_middle/ty/fold.rs @@ -509,10 +509,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty } = *ct { + if let ty::ConstKind::Bound(debruijn, bound_const) = ct.val { if debruijn == self.current_index { let fld_c = &mut self.fld_c; - let ct = fld_c(bound_const, ty); + let ct = fld_c(bound_const, ct.ty); ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32()) } else { ct @@ -551,9 +551,7 @@ impl<'tcx> TyCtxt<'tcx> { { // identity for bound types and consts let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty)); - let fld_c = |bound_ct, ty| { - self.mk_const(ty::Const { val: ty::ConstKind::Bound(ty::INNERMOST, bound_ct), ty }) - }; + let fld_c = |bound_ct, ty| self.mk_const(ty, ty::ConstKind::Bound(ty::INNERMOST, bound_ct)); self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c) } @@ -788,7 +786,7 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty } = *ct { + if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.val { if self.amount == 0 || debruijn < self.current_index { ct } else { @@ -799,7 +797,7 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { debruijn.shifted_out(self.amount) } }; - self.tcx.mk_const(ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty }) + self.tcx.mk_const(ct.ty, ty::ConstKind::Bound(debruijn, bound_ct)) } } else { ct.super_fold_with(self) diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 10426cf856188..dace94ad44a06 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -1160,7 +1160,7 @@ pub trait PrettyPrinter<'tcx>: (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => { let contents = self.tcx().destructure_const( ty::ParamEnv::reveal_all() - .and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })), + .and(self.tcx().mk_const(ty, ty::ConstKind::Value(ct))), ); let fields = contents.fields.iter().copied(); diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index 594ffbcd83613..decc5e8ff596b 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -617,7 +617,7 @@ pub fn super_relate_consts>( } _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), }; - new_const_val.map(|val| tcx.mk_const(ty::Const { val, ty: a.ty })) + new_const_val.map(|val| tcx.mk_const(a.ty, val)) } impl<'tcx> Relate<'tcx> for &'tcx ty::List> { diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index 569a8d90bfcc3..120f82870df2f 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -1019,7 +1019,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { let ty = self.ty.fold_with(folder); let val = self.val.fold_with(folder); - folder.tcx().mk_const(ty::Const { ty, val }) + folder.tcx().mk_const(ty, val) } fn fold_with>(&self, folder: &mut F) -> Self { diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 370702f7f221d..80e775d8a7428 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -25,10 +25,12 @@ use rustc_macros::HashStable; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_target::abi::{Size, VariantIdx}; use rustc_target::spec::abi; + use std::borrow::Cow; use std::cmp::Ordering; use std::marker::PhantomData; use std::ops::Range; +use std::ptr; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] #[derive(HashStable, TypeFoldable, Lift)] @@ -2178,21 +2180,38 @@ impl<'tcx> TyS<'tcx> { } /// Typed constant value. -#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Debug, Hash, RustcEncodable, RustcDecodable, Eq, Ord, PartialOrd)] #[derive(HashStable)] pub struct Const<'tcx> { pub ty: Ty<'tcx>, pub val: ConstKind<'tcx>, + + /// We compare `Const` by pointer equality. This would be incorrect + /// if we were able to create Const values on the stack. + /// + /// Only allow the creation of consts using `tcx.mk_const(ty, val)`. + pub _priv: PrivateMarker, +} + +impl<'tcx> PartialEq for Const<'tcx> { + fn eq(&self, other: &Const<'tcx>) -> bool { + // All `Const` should be interned. + ptr::eq(self, other) + } } +#[derive(Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)] +#[derive(HashStable)] +pub struct PrivateMarker(pub(super) ()); + #[cfg(target_arch = "x86_64")] static_assert_size!(Const<'_>, 48); impl<'tcx> Const<'tcx> { /// Literals and const generic parameters are eagerly converted to a constant, everything else /// becomes `Unevaluated`. - pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self { + pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Const<'tcx> { debug!("Const::from_anon_const(id={:?})", def_id); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); @@ -2260,13 +2279,13 @@ impl<'tcx> Const<'tcx> { ), }; - tcx.mk_const(ty::Const { val, ty }) + tcx.mk_const(ty, val) } #[inline] /// Interns the given value as a constant. pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { - tcx.mk_const(Self { val: ConstKind::Value(val), ty }) + tcx.mk_const(ty, ConstKind::Value(val)) } #[inline] @@ -2357,7 +2376,7 @@ impl<'tcx> Const<'tcx> { Ok(val) => Const::from_value(tcx, val, self.ty), Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => self, Err(ErrorHandled::Reported(ErrorReported)) => { - tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty: self.ty }) + tcx.mk_const(self.ty, ty::ConstKind::Error) } } } else { diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 4f91257e2ef83..5cfa144e9708b 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -849,8 +849,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not // return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call // `ecx.const_eval`. - let const_ = ty::Const { val: ty::ConstKind::Value(val), ty }; - self.eval_const_to_op(&const_, None) + let const_ = self.tcx.mk_const(ty, ty::ConstKind::Value(val)); + self.eval_const_to_op(const_, None) } pub fn const_eval_raw( diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index f69343f4d7500..92000e6411354 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -606,7 +606,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Operand::Constant(Box::new(Constant { span, user_ty: None, - literal: self.tcx.mk_const(*ty::Const::from_scalar(self.tcx, scalar, ty)), + literal: ty::Const::from_scalar(self.tcx, scalar, ty), })) } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 13a8b9a1000c9..1d72a139cef75 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -954,9 +954,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Operand::Constant(Box::new(Constant { span, user_ty: None, - literal: tcx.mk_const(ty::Const { + literal: tcx.mk_const( ty, - val: ty::ConstKind::Unevaluated( + ty::ConstKind::Unevaluated( def_id, InternalSubsts::for_item(tcx, def_id, |param, _| { if let ty::GenericParamDefKind::Lifetime = param.kind { @@ -967,7 +967,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { }), Some(promoted_id), ), - }), + ), })) }; let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut(); diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index 114bf5710402f..f06fa77ff5f96 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -627,10 +627,11 @@ fn make_mirror_unadjusted<'a, 'tcx>( // in case we are offsetting from a computed discriminant // and not the beginning of discriminants (which is always `0`) let substs = InternalSubsts::identity_for_item(cx.tcx(), did); - let lhs = mk_const(cx.tcx().mk_const(ty::Const { - val: ty::ConstKind::Unevaluated(did, substs, None), - ty: var_ty, - })); + let lhs = + mk_const(cx.tcx().mk_const( + var_ty, + ty::ConstKind::Unevaluated(did, substs, None), + )); let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset }; Expr { temp_lifetime, ty: var_ty, span: expr.span, kind: bin }.to_ref() } @@ -814,7 +815,7 @@ fn convert_path_expr<'a, 'tcx>( let name = cx.tcx.hir().name(hir_id); let val = ty::ConstKind::Param(ty::ParamConst::new(index, name)); ExprKind::Literal { - literal: cx.tcx.mk_const(ty::Const { val, ty: cx.tables().node_type(expr.hir_id) }), + literal: cx.tcx.mk_const(cx.tables().node_type(expr.hir_id), val), user_ty: None, } } @@ -823,10 +824,10 @@ fn convert_path_expr<'a, 'tcx>( let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res); debug!("convert_path_expr: (const) user_ty={:?}", user_ty); ExprKind::Literal { - literal: cx.tcx.mk_const(ty::Const { - val: ty::ConstKind::Unevaluated(def_id, substs, None), - ty: cx.tables().node_type(expr.hir_id), - }), + literal: cx.tcx.mk_const( + cx.tables().node_type(expr.hir_id), + ty::ConstKind::Unevaluated(def_id, substs, None), + ), user_ty, } } diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 626e531c807b7..55891eb9de7e9 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -376,6 +376,7 @@ impl<'tcx> PatternFolder<'tcx> for LiteralExpander<'tcx> { Const { val: ty::ConstKind::Value(val), ty: ty::TyS { kind: ty::Ref(_, crty, _), .. }, + .. }, }, ) => Pat { @@ -399,7 +400,7 @@ impl<'tcx> PatternFolder<'tcx> for LiteralExpander<'tcx> { ( &ty::Ref(_, rty, _), &PatKind::Constant { - value: Const { val, ty: ty::TyS { kind: ty::Ref(_, crty, _), .. } }, + value: Const { val, ty: ty::TyS { kind: ty::Ref(_, crty, _), .. }, .. }, }, ) => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty), diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs index e9aa7f597beb6..13f30c838c093 100644 --- a/src/librustc_mir_build/hair/pattern/mod.rs +++ b/src/librustc_mir_build/hair/pattern/mod.rs @@ -936,7 +936,7 @@ macro_rules! CloneImpls { } CloneImpls! { <'tcx> - Span, Field, Mutability, Symbol, hir::HirId, usize, ty::Const<'tcx>, + Span, Field, Mutability, Symbol, hir::HirId, usize, &'tcx ty::Const<'tcx>, Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef, SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>, UserTypeProjection, PatTyProj<'tcx> diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index 484677ded249f..c2fbd6cc37727 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -971,7 +971,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { ) .emit(); - self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty }) + self.tcx().mk_const(ct.ty, ty::ConstKind::Error) } } } diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index 5118859765ed7..e9cb492b22379 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -309,7 +309,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { /// Pushes the obligations required for an array length to be WF /// into `self.out`. - fn compute_array_len(&mut self, constant: ty::Const<'tcx>) { + fn compute_array_len(&mut self, constant: &ty::Const<'tcx>) { if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.val { assert!(promoted.is_none()); @@ -385,7 +385,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { ty::Array(subty, len) => { self.require_sized(subty, traits::SliceOrArrayElem); // FIXME(eddyb) handle `GenericArgKind::Const` above instead. - self.compute_array_len(*len); + self.compute_array_len(len); } ty::Tuple(ref tys) => { diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index a2aee9b6ef74d..5db079c96882a 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -494,10 +494,10 @@ fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { .into(), ty::GenericParamDefKind::Const => tcx - .mk_const(ty::Const { - val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), - ty: tcx.type_of(param.def_id), - }) + .mk_const( + tcx.type_of(param.def_id), + ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), + ) .into(), }) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 9a5fe9552d35a..5fe738eeeb72b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -836,7 +836,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ct_infer(ty, Some(param), span).into() } else { // We've already errored above about the mismatch. - tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty }).into() + tcx.mk_const(ty, ty::ConstKind::Error).into() } } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 154ca391aa5fd..b43c4769d7f2f 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -698,7 +698,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct); self.report_const_error(ct); self.replaced_with_error = true; - self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty }) + self.tcx().mk_const(ct.ty, ty::ConstKind::Error) } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 355b4fc413f42..1e111b2339fc6 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -319,7 +319,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { ) -> &'tcx Const<'tcx> { bad_placeholder_type(self.tcx(), vec![span]).emit(); - self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty }) + self.tcx().mk_const(ty, ty::ConstKind::Error) } fn projected_ty_from_poly_trait_ref( @@ -2043,8 +2043,7 @@ fn associated_item_predicates( } ty::GenericParamDefKind::Const => { unimplemented_error("const"); - tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty: tcx.type_of(param.def_id) }) - .into() + tcx.mk_const(tcx.type_of(param.def_id), ty::ConstKind::Error).into() } } }; From 0dd91a65b87243fc87b507761c01b7d86b9d74ac Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 29 May 2020 10:25:17 +0200 Subject: [PATCH 2/4] meh --- src/librustc_data_structures/stable_hasher.rs | 4 +-- src/librustc_middle/ty/context.rs | 19 ++++++-------- src/librustc_middle/ty/sty.rs | 25 +++++++------------ 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 97b02eaef35d0..89ce283ff4887 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -218,14 +218,14 @@ impl HashStable for ::std::num::NonZeroUsize { impl HashStable for f32 { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let val: u32 = unsafe { ::std::mem::transmute(*self) }; + let val: u32 = self.to_bits(); val.hash_stable(ctx, hasher); } } impl HashStable for f64 { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - let val: u64 = unsafe { ::std::mem::transmute(*self) }; + let val: u64 = self.to_bits(); val.hash_stable(ctx, hasher); } } diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 9917c229dac79..7781fa03426ac 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -853,14 +853,10 @@ impl<'tcx> CommonLifetimes<'tcx> { impl<'tcx> CommonConsts<'tcx> { fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> { - let mk_const = |c| interners.const_.intern(c, |c| Interned(interners.arena.alloc(c))).0; + let mk_const = |ct| interners.const_.intern(ct, |ct| Interned(interners.arena.alloc(unsafe { std::mem::transmute(ct) }))).0; CommonConsts { - unit: mk_const(Const { - ty: types.unit, - val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::zst())), - _priv: ty::sty::PrivateMarker(()), - }), + unit: mk_const(super::sty::InternedConst { ty: types.unit, val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::zst())) }), } } } @@ -1990,9 +1986,9 @@ impl<'tcx> Borrow<[Predicate<'tcx>]> for Interned<'tcx, List>> { } } -impl<'tcx> Borrow> for Interned<'tcx, Const<'tcx>> { - fn borrow<'a>(&'a self) -> &'a Const<'tcx> { - &self.0 +impl<'tcx> Borrow> for Interned<'tcx, Const<'tcx>> { + fn borrow<'a>(&'a self) -> &'a super::sty::InternedConst<'tcx> { + unsafe { mem::transmute(self) } } } @@ -2103,9 +2099,8 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_const(&self, ty: Ty<'tcx>, val: ConstKind<'tcx>) -> &'tcx Const<'tcx> { - let ct = Const { ty, val, _priv: super::sty::PrivateMarker(()) }; - - self.interners.const_.intern(ct, |ct| Interned(self.arena.alloc(ct))).0 + let ct = super::sty::InternedConst { ty, val }; + self.interners.const_.intern(ct, |ct| Interned(self.arena.alloc(unsafe { mem::transmute(ct) }))).0 } #[inline] diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 80e775d8a7428..7b4a7aae56efb 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -30,7 +30,6 @@ use std::borrow::Cow; use std::cmp::Ordering; use std::marker::PhantomData; use std::ops::Range; -use std::ptr; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] #[derive(HashStable, TypeFoldable, Lift)] @@ -2180,30 +2179,24 @@ impl<'tcx> TyS<'tcx> { } /// Typed constant value. -#[derive(Debug, Hash, RustcEncodable, RustcDecodable, Eq, Ord, PartialOrd)] +#[derive(Debug, Hash, RustcEncodable, RustcDecodable, PartialEq, Eq, Ord, PartialOrd)] #[derive(HashStable)] +#[repr(C)] pub struct Const<'tcx> { pub ty: Ty<'tcx>, pub val: ConstKind<'tcx>, - - /// We compare `Const` by pointer equality. This would be incorrect - /// if we were able to create Const values on the stack. - /// - /// Only allow the creation of consts using `tcx.mk_const(ty, val)`. - pub _priv: PrivateMarker, } -impl<'tcx> PartialEq for Const<'tcx> { - fn eq(&self, other: &Const<'tcx>) -> bool { - // All `Const` should be interned. - ptr::eq(self, other) - } +#[derive(Debug, Hash, RustcEncodable, RustcDecodable, PartialEq, Eq, Ord, PartialOrd)] +#[derive(HashStable)] +#[repr(C)] +pub struct InternedConst<'tcx> { + pub ty: Ty<'tcx>, + pub val: ConstKind<'tcx>, } -#[derive(Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)] -#[derive(HashStable)] -pub struct PrivateMarker(pub(super) ()); + #[cfg(target_arch = "x86_64")] static_assert_size!(Const<'_>, 48); From fbaa782ec77f237b7b1eb7a99c94613820449aeb Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 29 May 2020 18:03:55 +0200 Subject: [PATCH 3/4] aba --- src/librustc_middle/ty/codec.rs | 7 +++++++ src/librustc_middle/ty/context.rs | 2 +- src/librustc_middle/ty/mod.rs | 2 +- src/librustc_middle/ty/sty.rs | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/librustc_middle/ty/codec.rs b/src/librustc_middle/ty/codec.rs index 2dcd41eebb08e..8630312534901 100644 --- a/src/librustc_middle/ty/codec.rs +++ b/src/librustc_middle/ty/codec.rs @@ -490,6 +490,13 @@ macro_rules! implement_ty_decoder { } } + impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::InternedConst<'tcx>> + for $DecoderName<$($typaram),*> { + fn specialized_decode(&mut self) -> Result<&'tcx ty::InternedConst<'tcx>, Self::Error> { + decode_const(self).map(|ct| unsafe { std::mem::transmute(ct) }) + } + } + impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation> for $DecoderName<$($typaram),*> { fn specialized_decode( diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 7781fa03426ac..190af2fdd4edd 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -856,7 +856,7 @@ impl<'tcx> CommonConsts<'tcx> { let mk_const = |ct| interners.const_.intern(ct, |ct| Interned(interners.arena.alloc(unsafe { std::mem::transmute(ct) }))).0; CommonConsts { - unit: mk_const(super::sty::InternedConst { ty: types.unit, val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::zst())) }), + unit: mk_const(super::InternedConst { ty: types.unit, val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::zst())) }), } } } diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index aad3c6889c3ce..1ab74f4587c9a 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -57,7 +57,7 @@ pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar, DebruijnIndex, INNER pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region}; pub use self::sty::{CanonicalPolyFnSig, FnSig, GenSig, PolyFnSig, PolyGenSig}; pub use self::sty::{ClosureSubsts, GeneratorSubsts, TypeAndMut, UpvarSubsts}; -pub use self::sty::{Const, ConstKind, ExistentialProjection, PolyExistentialProjection}; +pub use self::sty::{Const, InternedConst, ConstKind, ExistentialProjection, PolyExistentialProjection}; pub use self::sty::{ConstVid, FloatVid, IntVid, RegionVid, TyVid}; pub use self::sty::{ExistentialPredicate, InferConst, InferTy, ParamConst, ParamTy, ProjectionTy}; pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 7b4a7aae56efb..e7899301d4b71 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -2406,6 +2406,7 @@ impl<'tcx> Const<'tcx> { } impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {} +impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx InternedConst<'tcx> {} /// Represents a constant in Rust. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)] From f07b417b7edbdef7ec6295bea7d2aeae3a211479 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Fri, 29 May 2020 19:44:46 +0200 Subject: [PATCH 4/4] rg --- src/librustc_middle/ty/codec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_middle/ty/codec.rs b/src/librustc_middle/ty/codec.rs index 8630312534901..dce8f01d97120 100644 --- a/src/librustc_middle/ty/codec.rs +++ b/src/librustc_middle/ty/codec.rs @@ -293,7 +293,7 @@ where { // FIXME: we temporarily have a `Const` on the stack here, // as we compare `Const`s using ptr equality, this is dangerous. - let ct: ty::Const<'tcx> = Decodable::decode(decoder)?; + let ct: ty::InternedConst<'tcx> = Decodable::decode(decoder)?; Ok(decoder.tcx().mk_const(ct.ty, ct.val)) }