diff options
Diffstat (limited to 'compiler/rustc_middle/src')
19 files changed, 207 insertions, 123 deletions
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index f2627885d03..41d8c7ffdb9 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -129,7 +129,7 @@ impl<'tcx> UnifyKey for ty::ConstVid<'tcx> { } impl<'tcx> UnifyValue for ConstVarValue<'tcx> { - type Error = (ty::Const<'tcx>, ty::Const<'tcx>); + type Error = NoError; fn unify_values(&value1: &Self, &value2: &Self) -> Result<Self, Self::Error> { Ok(match (value1.val, value2.val) { diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index a8c7505329c..734c31192c7 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -36,7 +36,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_resolve( self, param_env: ty::ParamEnv<'tcx>, - ct: ty::Unevaluated<'tcx>, + ct: mir::UnevaluatedConst<'tcx>, span: Option<Span>, ) -> EvalToConstValueResult<'tcx> { // Cannot resolve `Unevaluated` constants that contain inference @@ -49,7 +49,11 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { + match ty::Instance::resolve_opt_const_arg( + self, param_env, + // FIXME: maybe have a seperate version for resolving mir::UnevaluatedConst? + ct.def, ct.substs, + ) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: ct.promoted }; self.const_eval_global_id(param_env, cid, span) @@ -63,7 +67,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_resolve_for_typeck( self, param_env: ty::ParamEnv<'tcx>, - ct: ty::Unevaluated<'tcx, ()>, + ct: ty::UnevaluatedConst<'tcx>, span: Option<Span>, ) -> EvalToValTreeResult<'tcx> { // Cannot resolve `Unevaluated` constants that contain inference diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 86ffce8ceb4..78a16788815 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2055,7 +2055,7 @@ pub enum ConstantKind<'tcx> { Ty(ty::Const<'tcx>), /// An unevaluated mir constant which is not part of the type system. - Unevaluated(ty::Unevaluated<'tcx, Option<Promoted>>, Ty<'tcx>), + Unevaluated(UnevaluatedConst<'tcx>, Ty<'tcx>), /// This constant cannot go back into the type system, as it represents /// something the type system cannot handle (e.g. pointers). @@ -2315,12 +2315,11 @@ impl<'tcx> ConstantKind<'tcx> { ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty }) .substs; - let uneval = ty::Unevaluated { + let uneval = UnevaluatedConst { def: ty::WithOptConstParam::unknown(def_id).to_global(), substs, promoted: None, }; - debug_assert!(!uneval.has_free_regions()); Self::Unevaluated(uneval, ty) @@ -2404,7 +2403,7 @@ impl<'tcx> ConstantKind<'tcx> { let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); let span = tcx.hir().span(hir_id); - let uneval = ty::Unevaluated::new(def.to_global(), substs); + let uneval = UnevaluatedConst::new(def.to_global(), substs); debug!(?span, ?param_env); match tcx.const_eval_resolve(param_env, uneval, Some(span)) { @@ -2417,7 +2416,7 @@ impl<'tcx> ConstantKind<'tcx> { // Error was handled in `const_eval_resolve`. Here we just create a // new unevaluated const and error hard later in codegen Self::Unevaluated( - ty::Unevaluated { + UnevaluatedConst { def: def.to_global(), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), promoted: None, @@ -2440,6 +2439,34 @@ impl<'tcx> ConstantKind<'tcx> { } } +/// An unevaluated (potentially generic) constant used in MIR. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] +#[derive(Hash, HashStable)] +pub struct UnevaluatedConst<'tcx> { + pub def: ty::WithOptConstParam<DefId>, + pub substs: SubstsRef<'tcx>, + pub promoted: Option<Promoted>, +} + +impl<'tcx> UnevaluatedConst<'tcx> { + // FIXME: probably should get rid of this method. It's also wrong to + // shrink and then later expand a promoted. + #[inline] + pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> { + ty::UnevaluatedConst { def: self.def, substs: self.substs } + } +} + +impl<'tcx> UnevaluatedConst<'tcx> { + #[inline] + pub fn new( + def: ty::WithOptConstParam<DefId>, + substs: SubstsRef<'tcx>, + ) -> UnevaluatedConst<'tcx> { + UnevaluatedConst { def, substs, promoted: Default::default() } + } +} + /// A collection of projections into user types. /// /// They are projections because a binding can occur a part of a diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 0b42137d4e3..05dcfba77b2 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -466,10 +466,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { ty::ConstKind::Param(p) => format!("Param({})", p), ty::ConstKind::Unevaluated(uv) => { format!( - "Unevaluated({}, {:?}, {:?})", + "Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def.did), uv.substs, - uv.promoted, ) } ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)), diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 9d098c8083e..8e18cad442e 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -3,6 +3,7 @@ use rustc_ast::InlineAsmTemplatePiece; use super::*; +use crate::mir; use crate::ty; TrivialTypeTraversalAndLiftImpls! { @@ -50,6 +51,25 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> { } } +impl<'tcx> TypeFoldable<'tcx> for mir::UnevaluatedConst<'tcx> { + fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + folder.try_fold_mir_unevaluated(self) + } +} + +impl<'tcx> TypeSuperFoldable<'tcx> for mir::UnevaluatedConst<'tcx> { + fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(mir::UnevaluatedConst { + def: self.def, + substs: self.substs.try_fold_with(folder)?, + promoted: self.promoted, + }) + } +} + impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { #[inline(always)] fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs index be19bb486d4..a136ca4d8c3 100644 --- a/compiler/rustc_middle/src/mir/type_visitable.rs +++ b/compiler/rustc_middle/src/mir/type_visitable.rs @@ -1,6 +1,7 @@ //! `TypeVisitable` implementations for MIR types use super::*; +use crate::mir; impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> { fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { @@ -8,6 +9,18 @@ impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> { } } +impl<'tcx> TypeVisitable<'tcx> for mir::UnevaluatedConst<'tcx> { + fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + visitor.visit_mir_unevaluated(*self) + } +} + +impl<'tcx> TypeSuperVisitable<'tcx> for mir::UnevaluatedConst<'tcx> { + fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + self.substs.visit_with(visitor) + } +} + impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { visitor.visit_mir_const(*self) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7ea8c9ed3d3..121a5b9f492 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -377,7 +377,7 @@ rustc_queries! { } query try_unify_abstract_consts(key: - ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()> + ty::ParamEnvAnd<'tcx, (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx> )>) -> bool { desc { |tcx| "trying to unify the generic constants {} and {}", diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 8e0a1f1f9ac..641e53f2a15 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -30,7 +30,7 @@ pub struct AbstractConst<'tcx> { impl<'tcx> AbstractConst<'tcx> { pub fn new( tcx: TyCtxt<'tcx>, - uv: ty::Unevaluated<'tcx, ()>, + uv: ty::UnevaluatedConst<'tcx>, ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> { let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?; debug!("AbstractConst::new({:?}) = {:?}", uv, inner); diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 4bc821dcfa1..315e3794f15 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -78,10 +78,9 @@ impl<'tcx> Const<'tcx> { match Self::try_eval_lit_or_param(tcx, ty, expr) { Some(v) => v, None => tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { + kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: def.to_global(), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), - promoted: (), }), ty, }), diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 4550152804e..c444ec23563 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,7 +1,7 @@ use std::convert::TryInto; +use crate::mir; use crate::mir::interpret::{AllocId, ConstValue, Scalar}; -use crate::mir::Promoted; use crate::ty::subst::{InternalSubsts, SubstsRef}; use crate::ty::ParamEnv; use crate::ty::{self, TyCtxt, TypeVisitable}; @@ -12,40 +12,34 @@ use rustc_target::abi::Size; use super::ScalarInt; -/// An unevaluated, potentially generic, constant. +/// An unevaluated (potentially generic) constant used in the type-system. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Hash, HashStable)] -pub struct Unevaluated<'tcx, P = Option<Promoted>> { +pub struct UnevaluatedConst<'tcx> { pub def: ty::WithOptConstParam<DefId>, pub substs: SubstsRef<'tcx>, - pub promoted: P, } -impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> { +impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { format!("{:?}", self).into_diagnostic_arg() } } -impl<'tcx> Unevaluated<'tcx> { +impl<'tcx> UnevaluatedConst<'tcx> { #[inline] - pub fn shrink(self) -> Unevaluated<'tcx, ()> { - debug_assert_eq!(self.promoted, None); - Unevaluated { def: self.def, substs: self.substs, promoted: () } + pub fn expand(self) -> mir::UnevaluatedConst<'tcx> { + mir::UnevaluatedConst { def: self.def, substs: self.substs, promoted: None } } } -impl<'tcx> Unevaluated<'tcx, ()> { +impl<'tcx> UnevaluatedConst<'tcx> { #[inline] - pub fn expand(self) -> Unevaluated<'tcx> { - Unevaluated { def: self.def, substs: self.substs, promoted: None } - } -} - -impl<'tcx, P: Default> Unevaluated<'tcx, P> { - #[inline] - pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> { - Unevaluated { def, substs, promoted: Default::default() } + pub fn new( + def: ty::WithOptConstParam<DefId>, + substs: SubstsRef<'tcx>, + ) -> UnevaluatedConst<'tcx> { + UnevaluatedConst { def, substs } } } @@ -67,7 +61,7 @@ pub enum ConstKind<'tcx> { /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other /// variants when the code is monomorphic enough for that. - Unevaluated(Unevaluated<'tcx, ()>), + Unevaluated(UnevaluatedConst<'tcx>), /// Used to hold computed value. Value(ty::ValTree<'tcx>), @@ -185,8 +179,6 @@ impl<'tcx> ConstKind<'tcx> { if let ConstKind::Unevaluated(unevaluated) = self { use crate::mir::interpret::ErrorHandled; - assert_eq!(unevaluated.promoted, ()); - // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` // also does later, but we want to do it before checking for // inference variables. @@ -204,10 +196,9 @@ impl<'tcx> ConstKind<'tcx> { // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that // we can call `infcx.const_eval_resolve` which handles inference variables. let param_env_and = if param_env_and.needs_infer() { - tcx.param_env(unevaluated.def.did).and(ty::Unevaluated { + tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst { def: unevaluated.def, substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did), - promoted: (), }) } else { param_env_and diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 8d019a3bad8..41bb3c71401 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -384,14 +384,7 @@ impl DeepRejectCtxt { // they might unify with any value. ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => true, ty::ConstKind::Value(obl) => match k { - ty::ConstKind::Value(imp) => { - // FIXME(valtrees): Once we have valtrees, we can just - // compare them directly here. - match (obl.try_to_scalar_int(), imp.try_to_scalar_int()) { - (Some(obl), Some(imp)) => obl == imp, - _ => true, - } - } + ty::ConstKind::Value(imp) => obl == imp, _ => true, }, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 98b8a7386fe..a6d0678e99d 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -34,7 +34,7 @@ impl FlagComputation { result.flags } - pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags { + pub fn for_unevaluated_const(uv: ty::UnevaluatedConst<'_>) -> TypeFlags { let mut result = FlagComputation::new(); result.add_unevaluated_const(uv); result.flags @@ -313,7 +313,7 @@ impl FlagComputation { } } - fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'_, P>) { + fn add_unevaluated_const(&mut self, ct: ty::UnevaluatedConst<'_>) { self.add_substs(ct.substs); self.add_flags(TypeFlags::HAS_CT_PROJECTION); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index cac95e14a23..e4234442fae 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -128,7 +128,17 @@ pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> { c.super_fold_with(self) } - fn fold_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> { + fn fold_ty_unevaluated( + &mut self, + uv: ty::UnevaluatedConst<'tcx>, + ) -> ty::UnevaluatedConst<'tcx> { + uv.super_fold_with(self) + } + + fn fold_mir_unevaluated( + &mut self, + uv: mir::UnevaluatedConst<'tcx>, + ) -> mir::UnevaluatedConst<'tcx> { uv.super_fold_with(self) } @@ -172,10 +182,17 @@ pub trait FallibleTypeFolder<'tcx>: Sized { c.try_super_fold_with(self) } - fn try_fold_unevaluated( + fn try_fold_ty_unevaluated( + &mut self, + c: ty::UnevaluatedConst<'tcx>, + ) -> Result<ty::UnevaluatedConst<'tcx>, Self::Error> { + c.try_super_fold_with(self) + } + + fn try_fold_mir_unevaluated( &mut self, - c: ty::Unevaluated<'tcx>, - ) -> Result<ty::Unevaluated<'tcx>, Self::Error> { + c: mir::UnevaluatedConst<'tcx>, + ) -> Result<mir::UnevaluatedConst<'tcx>, Self::Error> { c.try_super_fold_with(self) } @@ -225,11 +242,18 @@ where Ok(self.fold_const(c)) } - fn try_fold_unevaluated( + fn try_fold_ty_unevaluated( + &mut self, + c: ty::UnevaluatedConst<'tcx>, + ) -> Result<ty::UnevaluatedConst<'tcx>, !> { + Ok(self.fold_ty_unevaluated(c)) + } + + fn try_fold_mir_unevaluated( &mut self, - c: ty::Unevaluated<'tcx>, - ) -> Result<ty::Unevaluated<'tcx>, !> { - Ok(self.fold_unevaluated(c)) + c: mir::UnevaluatedConst<'tcx>, + ) -> Result<mir::UnevaluatedConst<'tcx>, !> { + Ok(self.fold_mir_unevaluated(c)) } fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 982aacc7686..63dd213a085 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -73,7 +73,7 @@ pub use self::closure::{ CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ - Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, Unevaluated, ValTree, + Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, @@ -682,7 +682,7 @@ pub enum PredicateKind<'tcx> { Coerce(CoercePredicate<'tcx>), /// Constant initializer must evaluate successfully. - ConstEvaluatable(ty::Unevaluated<'tcx, ()>), + ConstEvaluatable(ty::UnevaluatedConst<'tcx>), /// Constants must be equal. The first component is the const that is expected. ConstEquate(Const<'tcx>, Const<'tcx>), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b6cd5396b1d..99e5722ddad 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1088,17 +1088,9 @@ pub trait PrettyPrinter<'tcx>: .generics_of(principal.def_id) .own_substs_no_defaults(cx.tcx(), principal.substs); - // Don't print `'_` if there's no unerased regions. - let print_regions = args.iter().any(|arg| match arg.unpack() { - GenericArgKind::Lifetime(r) => !r.is_erased(), - _ => false, - }); - let mut args = args.iter().cloned().filter(|arg| match arg.unpack() { - GenericArgKind::Lifetime(_) => print_regions, - _ => true, - }); let mut projections = predicates.projection_bounds(); + let mut args = args.iter().cloned(); let arg0 = args.next(); let projection0 = projections.next(); if arg0.is_some() || projection0.is_some() { @@ -1201,9 +1193,7 @@ pub trait PrettyPrinter<'tcx>: } match ct.kind() { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { - assert_eq!(promoted, ()); - + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => { match self.tcx().def_kind(def.did) { DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => { p!(print_value_path(def.did, substs)) @@ -1847,22 +1837,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { ) -> Result<Self::Path, Self::Error> { self = print_prefix(self)?; - // Don't print `'_` if there's no unerased regions. - let print_regions = self.tcx.sess.verbose() - || args.iter().any(|arg| match arg.unpack() { - GenericArgKind::Lifetime(r) => !r.is_erased(), - _ => false, - }); - let args = args.iter().cloned().filter(|arg| match arg.unpack() { - GenericArgKind::Lifetime(_) => print_regions, - _ => true, - }); - - if args.clone().next().is_some() { + if args.first().is_some() { if self.in_value { write!(self, "::")?; } - self.generic_delimiters(|cx| cx.comma_sep(args)) + self.generic_delimiters(|cx| cx.comma_sep(args.iter().cloned())) } else { Ok(self) } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 0d97d4acdfc..cdb618e030a 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -621,11 +621,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `generic_const_exprs` can // be stabilized. - (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) - if au.def == bu.def && au.promoted == bu.promoted => - { - assert_eq!(au.promoted, ()); - + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => { let substs = relation.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), @@ -633,11 +629,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( bu.substs, )?; return Ok(tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { - def: au.def, - substs, - promoted: (), - }), + kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: au.def, substs }), ty: a.ty(), })); } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 004fcffdc40..3b42f4b51fc 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -829,45 +829,29 @@ impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for ty::UnevaluatedConst<'tcx> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { - folder.try_fold_unevaluated(self) + folder.try_fold_ty_unevaluated(self) } } -impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx> { +impl<'tcx> TypeVisitable<'tcx> for ty::UnevaluatedConst<'tcx> { fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - visitor.visit_unevaluated(*self) + visitor.visit_ty_unevaluated(*self) } } -impl<'tcx> TypeSuperFoldable<'tcx> for ty::Unevaluated<'tcx> { +impl<'tcx> TypeSuperFoldable<'tcx> for ty::UnevaluatedConst<'tcx> { fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>( self, folder: &mut F, ) -> Result<Self, F::Error> { - Ok(ty::Unevaluated { - def: self.def, - substs: self.substs.try_fold_with(folder)?, - promoted: self.promoted, - }) + Ok(ty::UnevaluatedConst { def: self.def, substs: self.substs.try_fold_with(folder)? }) } } -impl<'tcx> TypeSuperVisitable<'tcx> for ty::Unevaluated<'tcx> { +impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> { fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.substs.visit_with(visitor) } } - -impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { - fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { - Ok(self.expand().try_fold_with(folder)?.shrink()) - } -} - -impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx, ()> { - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - self.expand().visit_with(visitor) - } -} diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d2f73f274f8..258fb2e2f9f 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -19,7 +19,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::vec::Idx; use rustc_macros::HashStable; -use rustc_span::symbol::{kw, Symbol}; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi; use std::borrow::Cow; @@ -1133,9 +1133,13 @@ pub struct ProjectionTy<'tcx> { impl<'tcx> ProjectionTy<'tcx> { pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - let parent = tcx.parent(self.item_def_id); - assert_eq!(tcx.def_kind(parent), DefKind::Trait); - parent + match tcx.def_kind(self.item_def_id) { + DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id), + DefKind::ImplTraitPlaceholder => { + tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id)) + } + kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"), + } } /// Extracts the underlying trait reference and own substs from this projection. @@ -2207,6 +2211,35 @@ impl<'tcx> Ty<'tcx> { } } } + + // If `self` is a primitive, return its [`Symbol`]. + pub fn primitive_symbol(self) -> Option<Symbol> { + match self.kind() { + ty::Bool => Some(sym::bool), + ty::Char => Some(sym::char), + ty::Float(f) => match f { + ty::FloatTy::F32 => Some(sym::f32), + ty::FloatTy::F64 => Some(sym::f64), + }, + ty::Int(f) => match f { + ty::IntTy::Isize => Some(sym::isize), + ty::IntTy::I8 => Some(sym::i8), + ty::IntTy::I16 => Some(sym::i16), + ty::IntTy::I32 => Some(sym::i32), + ty::IntTy::I64 => Some(sym::i64), + ty::IntTy::I128 => Some(sym::i128), + }, + ty::Uint(f) => match f { + ty::UintTy::Usize => Some(sym::usize), + ty::UintTy::U8 => Some(sym::u8), + ty::UintTy::U16 => Some(sym::u16), + ty::UintTy::U32 => Some(sym::u32), + ty::UintTy::U64 => Some(sym::u64), + ty::UintTy::U128 => Some(sym::u128), + }, + _ => None, + } + } } /// Extra information about why we ended up with a particular variance. diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 5f8cb578202..9c3b6a794e1 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -199,7 +199,17 @@ pub trait TypeVisitor<'tcx>: Sized { c.super_visit_with(self) } - fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> { + fn visit_ty_unevaluated( + &mut self, + uv: ty::UnevaluatedConst<'tcx>, + ) -> ControlFlow<Self::BreakTy> { + uv.super_visit_with(self) + } + + fn visit_mir_unevaluated( + &mut self, + uv: mir::UnevaluatedConst<'tcx>, + ) -> ControlFlow<Self::BreakTy> { uv.super_visit_with(self) } @@ -597,7 +607,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { #[inline] #[instrument(level = "trace", ret)] - fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> { + fn visit_ty_unevaluated( + &mut self, + uv: ty::UnevaluatedConst<'tcx>, + ) -> ControlFlow<Self::BreakTy> { let flags = FlagComputation::for_unevaluated_const(uv); trace!(r.flags=?flags); if flags.intersects(self.flags) { @@ -607,6 +620,19 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { } } + fn visit_mir_unevaluated( + &mut self, + uv: mir::UnevaluatedConst<'tcx>, + ) -> ControlFlow<Self::BreakTy> { + let flags = FlagComputation::for_unevaluated_const(uv.shrink()); + trace!(r.flags=?flags); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } + } + #[inline] #[instrument(level = "trace", ret)] fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { |
