From c23a457e72abe608715ac76f076f47dc42af07a5 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 20:31:44 +0200 Subject: Merging upstream version 1.74.1+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_middle/src/ty/abstract_const.rs | 2 +- compiler/rustc_middle/src/ty/adjustment.rs | 8 +- compiler/rustc_middle/src/ty/adt.rs | 6 +- compiler/rustc_middle/src/ty/binding.rs | 2 +- compiler/rustc_middle/src/ty/codec.rs | 1 - compiler/rustc_middle/src/ty/consts.rs | 254 +++++++-------------- compiler/rustc_middle/src/ty/consts/int.rs | 5 + compiler/rustc_middle/src/ty/consts/kind.rs | 45 +++- compiler/rustc_middle/src/ty/context.rs | 111 +++++---- compiler/rustc_middle/src/ty/diagnostics.rs | 10 +- compiler/rustc_middle/src/ty/erase_regions.rs | 4 +- compiler/rustc_middle/src/ty/error.rs | 9 +- compiler/rustc_middle/src/ty/fast_reject.rs | 13 +- compiler/rustc_middle/src/ty/flags.rs | 24 +- compiler/rustc_middle/src/ty/fold.rs | 2 +- compiler/rustc_middle/src/ty/generic_args.rs | 20 +- compiler/rustc_middle/src/ty/generics.rs | 12 +- compiler/rustc_middle/src/ty/instance.rs | 18 +- compiler/rustc_middle/src/ty/layout.rs | 15 +- compiler/rustc_middle/src/ty/mod.rs | 97 ++++---- .../src/ty/normalize_erasing_regions.rs | 24 +- compiler/rustc_middle/src/ty/opaque_types.rs | 4 +- compiler/rustc_middle/src/ty/parameterized.rs | 2 +- compiler/rustc_middle/src/ty/print/mod.rs | 3 +- compiler/rustc_middle/src/ty/print/pretty.rs | 110 +++++---- compiler/rustc_middle/src/ty/relate.rs | 14 +- compiler/rustc_middle/src/ty/structural_impls.rs | 170 +++++--------- compiler/rustc_middle/src/ty/sty.rs | 84 +++++-- compiler/rustc_middle/src/ty/trait_def.rs | 4 + compiler/rustc_middle/src/ty/typeck_results.rs | 89 ++------ compiler/rustc_middle/src/ty/util.rs | 34 ++- compiler/rustc_middle/src/ty/visit.rs | 36 ++- compiler/rustc_middle/src/ty/vtable.rs | 6 +- compiler/rustc_middle/src/ty/walk.rs | 5 +- 34 files changed, 570 insertions(+), 673 deletions(-) (limited to 'compiler/rustc_middle/src/ty') diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index cdd835149..570f896ba 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -27,7 +27,7 @@ impl From for NotConstEvaluatable { } } -TrivialTypeTraversalAndLiftImpls! { NotConstEvaluatable } +TrivialTypeTraversalImpls! { NotConstEvaluatable } pub type BoundAbstractConst<'tcx> = Result>>, ErrorGuaranteed>; diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index 76931ceaa..c3e8991c6 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -76,7 +76,7 @@ pub enum PointerCoercion { /// At some point, of course, `Box` should move out of the compiler, in which /// case this is analogous to transforming a struct. E.g., `Box<[i32; 4]>` -> /// `Box<[i32]>` is an `Adjust::Unsize` with the target `Box<[i32]>`. -#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct Adjustment<'tcx> { pub kind: Adjust<'tcx>, pub target: Ty<'tcx>, @@ -88,7 +88,7 @@ impl<'tcx> Adjustment<'tcx> { } } -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub enum Adjust<'tcx> { /// Go from ! to any type. NeverToAny, @@ -110,7 +110,7 @@ pub enum Adjust<'tcx> { /// The target type is `U` in both cases, with the region and mutability /// being those shared by both the receiver and the returned reference. #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub struct OverloadedDeref<'tcx> { pub region: ty::Region<'tcx>, pub mutbl: hir::Mutability, @@ -182,7 +182,7 @@ impl From for hir::Mutability { } #[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable, Lift)] +#[derive(TypeFoldable, TypeVisitable)] pub enum AutoBorrow<'tcx> { /// Converts from T to &T. Ref(ty::Region<'tcx>, AutoBorrowMutability), diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index b4c6e0d97..f50969dd9 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -448,7 +448,7 @@ impl<'tcx> AdtDef<'tcx> { Res::Def(DefKind::Ctor(..), cid) => self.variant_with_ctor_id(cid), Res::Def(DefKind::Struct, _) | Res::Def(DefKind::Union, _) - | Res::Def(DefKind::TyAlias { .. }, _) + | Res::Def(DefKind::TyAlias, _) | Res::Def(DefKind::AssocTy, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } @@ -478,8 +478,8 @@ impl<'tcx> AdtDef<'tcx> { } Err(err) => { let msg = match err { - ErrorHandled::Reported(_) => "enum discriminant evaluation failed", - ErrorHandled::TooGeneric => "enum discriminant depends on generics", + ErrorHandled::Reported(..) => "enum discriminant evaluation failed", + ErrorHandled::TooGeneric(..) => "enum discriminant depends on generics", }; tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg); None diff --git a/compiler/rustc_middle/src/ty/binding.rs b/compiler/rustc_middle/src/ty/binding.rs index 2fec8ac90..af594bc5f 100644 --- a/compiler/rustc_middle/src/ty/binding.rs +++ b/compiler/rustc_middle/src/ty/binding.rs @@ -6,7 +6,7 @@ pub enum BindingMode { BindByValue(Mutability), } -TrivialTypeTraversalAndLiftImpls! { BindingMode } +TrivialTypeTraversalImpls! { BindingMode } impl BindingMode { pub fn convert(BindingAnnotation(by_ref, mutbl): BindingAnnotation) -> BindingMode { diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 7c05deae9..dff7ff8c6 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -566,6 +566,5 @@ impl_binder_encode_decode! { ty::TraitPredicate<'tcx>, ty::ExistentialPredicate<'tcx>, ty::TraitRef<'tcx>, - Vec>, ty::ExistentialTraitRef<'tcx>, } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index cce10417e..2518f0cf2 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,5 +1,5 @@ use crate::middle::resolve_bound_vars as rbv; -use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar}; +use crate::mir::interpret::{AllocId, ErrorHandled, LitToConstInput, Scalar}; use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; @@ -14,9 +14,8 @@ mod valtree; pub use int::*; pub use kind::*; -use rustc_span::ErrorGuaranteed; +use rustc_span::Span; use rustc_span::DUMMY_SP; -use rustc_target::abi::Size; pub use valtree::*; use super::sty::ConstKind; @@ -36,16 +35,6 @@ pub struct ConstData<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstData<'_>, 40); -enum EvalMode { - Typeck, - Mir, -} - -enum EvalResult<'tcx> { - ValTree(ty::ValTree<'tcx>), - ConstVal(ConstValue<'tcx>), -} - impl<'tcx> Const<'tcx> { #[inline] pub fn ty(self) -> Ty<'tcx> { @@ -165,7 +154,7 @@ impl<'tcx> Const<'tcx> { let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic"); - match Self::try_eval_lit_or_param(tcx, ty, expr) { + match Self::try_from_lit_or_param(tcx, ty, expr) { Some(v) => v, None => ty::Const::new_unevaluated( tcx, @@ -179,7 +168,7 @@ impl<'tcx> Const<'tcx> { } #[instrument(skip(tcx), level = "debug")] - fn try_eval_lit_or_param( + fn try_from_lit_or_param( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>, @@ -254,14 +243,6 @@ impl<'tcx> Const<'tcx> { } } - /// Panics if self.kind != ty::ConstKind::Value - pub fn to_valtree(self) -> ty::ValTree<'tcx> { - match self.kind() { - ty::ConstKind::Value(valtree) => valtree, - _ => bug!("expected ConstKind::Value, got {:?}", self.kind()), - } - } - #[inline] /// Creates a constant with the given integer value and interns it. pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self { @@ -294,33 +275,83 @@ impl<'tcx> Const<'tcx> { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } - /// Attempts to convert to a `ValTree` - pub fn try_to_valtree(self) -> Option> { + /// Returns the evaluated constant + #[inline] + pub fn eval( + self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + span: Option, + ) -> Result, ErrorHandled> { + assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); match self.kind() { - ty::ConstKind::Value(valtree) => Some(valtree), - _ => None, + ConstKind::Unevaluated(unevaluated) => { + // FIXME(eddyb) maybe the `const_eval_*` methods should take + // `ty::ParamEnvAnd` instead of having them separate. + let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env); + // try to resolve e.g. associated constants to their definition on an impl, and then + // evaluate the const. + let c = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?; + Ok(c.expect("`ty::Const::eval` called on a non-valtree-compatible type")) + } + ConstKind::Value(val) => Ok(val), + ConstKind::Error(g) => Err(g.into()), + ConstKind::Param(_) + | ConstKind::Infer(_) + | ConstKind::Bound(_, _) + | ConstKind::Placeholder(_) + | ConstKind::Expr(_) => Err(ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))), } } + /// Normalizes the constant to a value or an error if possible. + #[inline] + pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self { + match self.eval(tcx, param_env, None) { + Ok(val) => Self::new_value(tcx, val, self.ty()), + Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into(), self.ty()), + Err(ErrorHandled::TooGeneric(_span)) => self, + } + } + + #[inline] + pub fn try_eval_scalar( + self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> Option { + self.eval(tcx, param_env, None).ok()?.try_to_scalar() + } + #[inline] /// 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). - pub fn try_eval_bits( + pub fn try_eval_scalar_int( self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, - ty: Ty<'tcx>, - ) -> Option { - assert_eq!(self.ty(), ty); - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + ) -> Option { + self.try_eval_scalar(tcx, param_env)?.try_to_int().ok() + } + + #[inline] + /// 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). + pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { + let int = self.try_eval_scalar_int(tcx, param_env)?; + let size = + tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size; // if `ty` does not depend on generic parameters, use an empty param_env - self.eval(tcx, param_env).try_to_bits(size) + int.to_bits(size).ok() } #[inline] - pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - self.eval(tcx, param_env).try_to_bool() + /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. + pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u128 { + self.try_eval_bits(tcx, param_env) + .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self)) } #[inline] @@ -329,29 +360,12 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option { - self.eval(tcx, param_env).try_to_target_usize(tcx) - } - - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the - /// unevaluated constant. - pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> { - if let Some(val) = self.try_eval_for_typeck(tcx, param_env) { - match val { - Ok(val) => ty::Const::new_value(tcx, val, self.ty()), - Err(guar) => ty::Const::new_error(tcx, guar, self.ty()), - } - } else { - // Either the constant isn't evaluatable or ValTree creation failed. - self - } + self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok() } #[inline] - /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. - pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { - self.try_eval_bits(tcx, param_env, ty) - .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) + pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { + self.try_eval_scalar_int(tcx, param_env)?.try_into().ok() } #[inline] @@ -361,136 +375,30 @@ impl<'tcx> Const<'tcx> { .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary - /// return `None`. - // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. - pub fn try_eval_for_mir( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option, ErrorGuaranteed>> { - match self.try_eval_inner(tcx, param_env, EvalMode::Mir) { - Some(Ok(EvalResult::ValTree(_))) => unreachable!(), - Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)), - Some(Err(e)) => Some(Err(e)), - None => None, - } - } - - #[inline] - /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary - /// return `None`. - // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. - pub fn try_eval_for_typeck( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option, ErrorGuaranteed>> { - match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) { - Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)), - Some(Ok(EvalResult::ConstVal(_))) => unreachable!(), - Some(Err(e)) => Some(Err(e)), - None => None, + /// Panics if self.kind != ty::ConstKind::Value + pub fn to_valtree(self) -> ty::ValTree<'tcx> { + match self.kind() { + ty::ConstKind::Value(valtree) => valtree, + _ => bug!("expected ConstKind::Value, got {:?}", self.kind()), } } - #[inline] - fn try_eval_inner( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - eval_mode: EvalMode, - ) -> Option, ErrorGuaranteed>> { - assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); - if let ConstKind::Unevaluated(unevaluated) = self.kind() { - use crate::mir::interpret::ErrorHandled; - - // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` - // also does later, but we want to do it before checking for - // inference variables. - // Note that we erase regions *before* calling `with_reveal_all_normalized`, - // so that we don't try to invoke this query with - // any region variables. - - // HACK(eddyb) when the query key would contain inference variables, - // attempt using identity args and `ParamEnv` instead, that will succeed - // when the expression doesn't depend on any parameters. - // 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, unevaluated).has_non_region_infer() { - tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst { - def: unevaluated.def, - args: GenericArgs::identity_for_item(tcx, unevaluated.def), - }) - } else { - tcx.erase_regions(param_env) - .with_reveal_all_normalized(tcx) - .and(tcx.erase_regions(unevaluated)) - }; - - // FIXME(eddyb) maybe the `const_eval_*` methods should take - // `ty::ParamEnvAnd` instead of having them separate. - let (param_env, unevaluated) = param_env_and.into_parts(); - // try to resolve e.g. associated constants to their definition on an impl, and then - // evaluate the const. - match eval_mode { - EvalMode::Typeck => { - match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) { - // NOTE(eddyb) `val` contains no lifetimes/types/consts, - // and we use the original type, so nothing from `args` - // (which may be identity args, see above), - // can leak through `val` into the const we return. - Ok(val) => Some(Ok(EvalResult::ValTree(val?))), - Err(ErrorHandled::TooGeneric) => None, - Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), - } - } - EvalMode::Mir => { - match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) { - // NOTE(eddyb) `val` contains no lifetimes/types/consts, - // and we use the original type, so nothing from `args` - // (which may be identity args, see above), - // can leak through `val` into the const we return. - Ok(val) => Some(Ok(EvalResult::ConstVal(val))), - Err(ErrorHandled::TooGeneric) => None, - Err(ErrorHandled::Reported(e)) => Some(Err(e.into())), - } - } - } - } else { - None + /// Attempts to convert to a `ValTree` + pub fn try_to_valtree(self) -> Option> { + match self.kind() { + ty::ConstKind::Value(valtree) => Some(valtree), + _ => None, } } - #[inline] - pub fn try_to_value(self) -> Option> { - if let ConstKind::Value(val) = self.kind() { Some(val) } else { None } - } - #[inline] pub fn try_to_scalar(self) -> Option> { - self.try_to_value()?.try_to_scalar() - } - - #[inline] - pub fn try_to_scalar_int(self) -> Option { - self.try_to_value()?.try_to_scalar_int() - } - - #[inline] - pub fn try_to_bits(self, size: Size) -> Option { - self.try_to_scalar_int()?.to_bits(size).ok() - } - - #[inline] - pub fn try_to_bool(self) -> Option { - self.try_to_scalar_int()?.try_into().ok() + self.try_to_valtree()?.try_to_scalar() } #[inline] pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option { - self.try_to_value()?.try_to_target_usize(tcx) + self.try_to_valtree()?.try_to_target_usize(tcx) } pub fn is_ct_infer(self) -> bool { diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index b16163edf..9d99344d5 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -226,6 +226,11 @@ impl ScalarInt { } } + #[inline] + pub fn try_from_target_usize(i: impl Into, tcx: TyCtxt<'_>) -> Option { + Self::try_from_uint(i, tcx.data_layout.pointer_size) + } + #[inline] pub fn assert_bits(self, target_size: Size) -> u128 { self.to_bits(target_size).unwrap_or_else(|size| { diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index db4a15fbe..749b54ca0 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -2,13 +2,13 @@ use super::Const; use crate::mir; use crate::ty::abstract_const::CastKind; use crate::ty::GenericArgsRef; -use crate::ty::{self, List, Ty}; +use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; /// An unevaluated (potentially generic) constant used in the type-system. -#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct UnevaluatedConst<'tcx> { pub def: DefId, @@ -22,9 +22,37 @@ impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> { } impl<'tcx> UnevaluatedConst<'tcx> { + /// FIXME(RalfJung): I cannot explain what this does or why it makes sense, but not doing this + /// hurts performance. #[inline] - pub fn expand(self) -> mir::UnevaluatedConst<'tcx> { - mir::UnevaluatedConst { def: self.def, args: self.args, promoted: None } + pub(crate) fn prepare_for_eval( + self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> (ty::ParamEnv<'tcx>, Self) { + // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` + // also does later, but we want to do it before checking for + // inference variables. + // Note that we erase regions *before* calling `with_reveal_all_normalized`, + // so that we don't try to invoke this query with + // any region variables. + + // HACK(eddyb) when the query key would contain inference variables, + // attempt using identity args and `ParamEnv` instead, that will succeed + // when the expression doesn't depend on any parameters. + // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that + // we can call `infcx.const_eval_resolve` which handles inference variables. + if (param_env, self).has_non_region_infer() { + ( + tcx.param_env(self.def), + ty::UnevaluatedConst { + def: self.def, + args: ty::GenericArgs::identity_for_item(tcx, self.def), + }, + ) + } else { + (tcx.erase_regions(param_env).with_reveal_all_normalized(tcx), tcx.erase_regions(self)) + } } } @@ -55,6 +83,11 @@ static_assert_size!(super::ConstKind<'_>, 32); pub enum InferConst<'tcx> { /// Infer the value of the const. Var(ty::ConstVid<'tcx>), + /// Infer the value of the effect. + /// + /// For why this is separate from the `Var` variant above, see the + /// documentation on `EffectVid`. + EffectVar(ty::EffectVid<'tcx>), /// A fresh const variable. See `infer::freshen` for more details. Fresh(u32), } @@ -62,7 +95,9 @@ pub enum InferConst<'tcx> { impl HashStable for InferConst<'_> { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { match self { - InferConst::Var(_) => panic!("const variables should not be hashed: {self:?}"), + InferConst::Var(_) | InferConst::EffectVar(_) => { + panic!("const variables should not be hashed: {self:?}") + } InferConst::Fresh(i) => i.hash_stable(hcx, hasher), } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index be839e03c..c06b8b2df 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -39,7 +39,7 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, Lock, Lrc, MappedReadGuard, ReadGuard, WorkerLocal}; +use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{ DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan, @@ -50,7 +50,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir::{Constness, HirId, Node, TraitCandidate}; +use rustc_hir::{HirId, Node, TraitCandidate}; use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_query_system::dep_graph::DepNodeIndex; @@ -82,6 +82,7 @@ use std::ops::{Bound, Deref}; impl<'tcx> Interner for TyCtxt<'tcx> { type AdtDef = ty::AdtDef<'tcx>; type GenericArgsRef = ty::GenericArgsRef<'tcx>; + type GenericArg = ty::GenericArg<'tcx>; type DefId = DefId; type Binder = Binder<'tcx, T>; type Ty = Ty<'tcx>; @@ -317,7 +318,7 @@ pub struct CommonLifetimes<'tcx> { pub re_vars: Vec>, /// Pre-interned values of the form: - /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(None) })` + /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` /// for small values of `i` and `v`. pub re_late_bounds: Vec>>, } @@ -394,7 +395,7 @@ impl<'tcx> CommonLifetimes<'tcx> { .map(|v| { mk(ty::ReLateBound( ty::DebruijnIndex::from(i), - ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon(None) }, + ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon }, )) }) .collect() @@ -553,6 +554,10 @@ pub struct GlobalCtxt<'tcx> { /// Common consts, pre-interned for your convenience. pub consts: CommonConsts<'tcx>, + /// Hooks to be able to register functions in other crates that can then still + /// be called from rustc_middle. + pub(crate) hooks: crate::hooks::Providers, + untracked: Untracked, pub query_system: QuerySystem<'tcx>, @@ -647,7 +652,7 @@ impl<'tcx> TyCtxt<'tcx> { // 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); - self.create_memory_alloc(alloc) + self.reserve_and_set_memory_alloc(alloc) } /// Returns a range of the start/end indices specified with the @@ -702,6 +707,7 @@ impl<'tcx> TyCtxt<'tcx> { dep_graph: DepGraph, query_kinds: &'tcx [DepKindStruct<'tcx>], query_system: QuerySystem<'tcx>, + hooks: crate::hooks::Providers, ) -> GlobalCtxt<'tcx> { let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| { s.emit_fatal(err); @@ -720,6 +726,7 @@ impl<'tcx> TyCtxt<'tcx> { hir_arena, interners, dep_graph, + hooks, prof: s.prof.clone(), types: common_types, lifetimes: common_lifetimes, @@ -964,8 +971,8 @@ impl<'tcx> TyCtxt<'tcx> { i += 1; } - // Leak a read lock once we finish iterating on definitions, to prevent adding new ones. - definitions.leak(); + // Freeze definitions once we finish iterating on them, to prevent adding new ones. + definitions.freeze(); }) } @@ -974,10 +981,9 @@ impl<'tcx> TyCtxt<'tcx> { // definitions change. self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); - // Leak a read lock once we start iterating on definitions, to prevent adding new ones + // Freeze definitions once we start iterating on them, to prevent adding new ones // while iterating. If some query needs to add definitions, it should be `ensure`d above. - let definitions = self.untracked.definitions.leak(); - definitions.def_path_table() + self.untracked.definitions.freeze().def_path_table() } pub fn def_path_hash_to_def_index_map( @@ -986,17 +992,16 @@ impl<'tcx> TyCtxt<'tcx> { // Create a dependency to the crate to be sure we re-execute this when the amount of // definitions change. self.ensure().hir_crate(()); - // Leak a read lock once we start iterating on definitions, to prevent adding new ones + // Freeze definitions once we start iterating on them, to prevent adding new ones // while iterating. If some query needs to add definitions, it should be `ensure`d above. - let definitions = self.untracked.definitions.leak(); - definitions.def_path_hash_to_def_index_map() + self.untracked.definitions.freeze().def_path_hash_to_def_index_map() } /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries #[inline] - pub fn cstore_untracked(self) -> MappedReadGuard<'tcx, CrateStoreDyn> { - ReadGuard::map(self.untracked.cstore.read(), |c| &**c) + pub fn cstore_untracked(self) -> FreezeReadGuard<'tcx, CrateStoreDyn> { + FreezeReadGuard::map(self.untracked.cstore.read(), |c| &**c) } /// Give out access to the untracked data without any sanity checks. @@ -1006,7 +1011,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Note that this is *untracked* and should only be used within the query /// system if the result is otherwise tracked through queries #[inline] - pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> { + pub fn definitions_untracked(self) -> FreezeReadGuard<'tcx, Definitions> { self.untracked.definitions.read() } @@ -1109,7 +1114,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) && let hir::TyKind::Path(hir::QPath::Resolved( None, - hir::Path { res: hir::def::Res::Def(DefKind::TyAlias { .. }, def_id), .. }, )) = hir_output.kind + hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind && let Some(local_id) = def_id.as_local() && let Some(alias_ty) = self.hir().get_by_def_id(local_id).alias_ty() // it is type alias && let Some(alias_generics) = self.hir().get_by_def_id(local_id).generics() @@ -1216,6 +1221,25 @@ macro_rules! nop_lift { impl<'a, 'tcx> Lift<'tcx> for $ty { type Lifted = $lifted; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { + // Assert that the set has the right type. + // Given an argument that has an interned type, the return type has the type of + // the corresponding interner set. This won't actually return anything, we're + // just doing this to compute said type! + fn _intern_set_ty_from_interned_ty<'tcx, Inner>( + _x: Interned<'tcx, Inner>, + ) -> InternedSet<'tcx, Inner> { + unreachable!() + } + fn _type_eq(_x: &T, _y: &T) {} + fn _test<'tcx>(x: $lifted, tcx: TyCtxt<'tcx>) { + // If `x` is a newtype around an `Interned`, then `interner` is an + // interner of appropriate type. (Ideally we'd also check that `x` is a + // newtype with just that one field. Not sure how to do that.) + let interner = _intern_set_ty_from_interned_ty(x.0); + // Now check that this is the same type as `interners.$set`. + _type_eq(&interner, &tcx.interners.$set); + } + tcx.interners .$set .contains_pointer_to(&InternedInSet(&*self.0.0)) @@ -1232,6 +1256,11 @@ macro_rules! nop_list_lift { impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> { type Lifted = &'tcx List<$lifted>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { + // Assert that the set has the right type. + if false { + let _x: &InternedSet<'tcx, List<$lifted>> = &tcx.interners.$set; + } + if self.is_empty() { return Some(List::empty()); } @@ -1253,19 +1282,13 @@ nop_lift! {predicate; Clause<'a> => Clause<'tcx>} nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>} nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>} -nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>} -nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} -nop_list_lift! {projs; ProjectionKind => ProjectionKind} nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind} // This is the impl for `&'a GenericArgs<'a>`. nop_list_lift! {args; GenericArg<'a> => GenericArg<'tcx>} -CloneLiftImpls! { - Constness, - traits::WellFormedLoc, +TrivialLiftImpls! { ImplPolarity, - crate::mir::ReturnConstraint, } macro_rules! sty_debug_print { @@ -1296,25 +1319,26 @@ macro_rules! sty_debug_print { }; $(let mut $variant = total;)* - let shards = tcx.interners.type_.lock_shards(); - let types = shards.iter().flat_map(|shard| shard.keys()); - for &InternedInSet(t) in types { - let variant = match t.internee { - ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | - ty::Float(..) | ty::Str | ty::Never => continue, - ty::Error(_) => /* unimportant */ continue, - $(ty::$variant(..) => &mut $variant,)* - }; - let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER); - let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER); - let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER); - - variant.total += 1; - total.total += 1; - if lt { total.lt_infer += 1; variant.lt_infer += 1 } - if ty { total.ty_infer += 1; variant.ty_infer += 1 } - if ct { total.ct_infer += 1; variant.ct_infer += 1 } - if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 } + for shard in tcx.interners.type_.lock_shards() { + let types = shard.keys(); + for &InternedInSet(t) in types { + let variant = match t.internee { + ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | + ty::Float(..) | ty::Str | ty::Never => continue, + ty::Error(_) => /* unimportant */ continue, + $(ty::$variant(..) => &mut $variant,)* + }; + let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER); + let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER); + let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER); + + variant.total += 1; + total.total += 1; + if lt { total.lt_infer += 1; variant.lt_infer += 1 } + if ty { total.ty_infer += 1; variant.ty_infer += 1 } + if ct { total.ct_infer += 1; variant.ct_infer += 1 } + if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 } + } } writeln!(fmt, "Ty interner total ty lt ct all")?; $(writeln!(fmt, " {:18}: {uses:6} {usespc:4.1}%, \ @@ -1360,7 +1384,6 @@ impl<'tcx> TyCtxt<'tcx> { Placeholder, Generator, GeneratorWitness, - GeneratorWitnessMIR, Dynamic, Closure, Tuple, diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 5db9b775a..f03813a45 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -70,10 +70,10 @@ impl<'tcx> Ty<'tcx> { /// description in error messages. This is used in the primary span label. Beyond what /// `is_simple_ty` includes, it also accepts ADTs with no type arguments and references to /// ADTs with no type arguments. - pub fn is_simple_text(self) -> bool { + pub fn is_simple_text(self, tcx: TyCtxt<'tcx>) -> bool { match self.kind() { - Adt(_, args) => args.non_erasable_generics().next().is_none(), - Ref(_, ty, _) => ty.is_simple_text(), + Adt(def, args) => args.non_erasable_generics(tcx, def.did()).next().is_none(), + Ref(_, ty, _) => ty.is_simple_text(tcx), _ => self.is_simple_ty(), } } @@ -493,7 +493,7 @@ impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { Alias(Opaque, AliasTy { def_id, .. }) => { let parent = self.tcx.parent(def_id); let parent_ty = self.tcx.type_of(parent).instantiate_identity(); - if let DefKind::TyAlias { .. } | DefKind::AssocTy = self.tcx.def_kind(parent) + if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent) && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind() && parent_opaque_def_id == def_id { @@ -577,7 +577,7 @@ impl<'tcx> FallibleTypeFolder> for MakeSuggestableFolder<'tcx> { Alias(Opaque, AliasTy { def_id, .. }) => { let parent = self.tcx.parent(def_id); let parent_ty = self.tcx.type_of(parent).instantiate_identity(); - if let hir::def::DefKind::TyAlias { .. } | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent) + if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent) && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind() && parent_opaque_def_id == def_id { diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 7895993cc..3371ea3be 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -20,8 +20,8 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - // If there's nothing to erase avoid performing the query at all - if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { + // If there's nothing to erase or anonymize, avoid performing the query at all + if !value.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) { return value; } debug!("erase_regions({:?})", value); diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index bf6f082c2..459c8dfb5 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -11,7 +11,7 @@ use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::path::PathBuf; -#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] pub struct ExpectedFound { pub expected: T, pub found: T, @@ -28,7 +28,7 @@ impl ExpectedFound { } // Data structures used in type unification -#[derive(Copy, Clone, Debug, TypeVisitable, Lift, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, TypeVisitable, PartialEq, Eq)] #[rustc_pass_by_value] pub enum TypeError<'tcx> { Mismatch, @@ -242,8 +242,7 @@ impl<'tcx> Ty<'tcx> { ty::Dynamic(..) => "trait object".into(), ty::Closure(..) => "closure".into(), ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(), - ty::GeneratorWitness(..) | - ty::GeneratorWitnessMIR(..) => "generator witness".into(), + ty::GeneratorWitness(..) => "generator witness".into(), ty::Infer(ty::TyVar(_)) => "inferred type".into(), ty::Infer(ty::IntVar(_)) => "integer".into(), ty::Infer(ty::FloatVar(_)) => "floating-point number".into(), @@ -295,7 +294,7 @@ impl<'tcx> Ty<'tcx> { ty::Dynamic(..) => "trait object".into(), ty::Closure(..) => "closure".into(), ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(), - ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => "generator witness".into(), + ty::GeneratorWitness(..) => "generator witness".into(), ty::Tuple(..) => "tuple".into(), ty::Placeholder(..) => "higher-ranked type".into(), ty::Bound(..) => "bound type variable".into(), diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 668aa4521..16935d5b3 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -29,8 +29,7 @@ pub enum SimplifiedType { Trait(DefId), Closure(DefId), Generator(DefId), - GeneratorWitness(usize), - GeneratorWitnessMIR(DefId), + GeneratorWitness(DefId), Function(usize), Placeholder, } @@ -130,10 +129,7 @@ pub fn simplify_type<'tcx>( ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)), ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)), ty::Generator(def_id, _, _) => Some(SimplifiedType::Generator(def_id)), - ty::GeneratorWitness(tys) => { - Some(SimplifiedType::GeneratorWitness(tys.skip_binder().len())) - } - ty::GeneratorWitnessMIR(def_id, _) => Some(SimplifiedType::GeneratorWitnessMIR(def_id)), + ty::GeneratorWitness(def_id, _) => Some(SimplifiedType::GeneratorWitness(def_id)), ty::Never => Some(SimplifiedType::Never), ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())), ty::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())), @@ -169,7 +165,7 @@ impl SimplifiedType { | SimplifiedType::Trait(d) | SimplifiedType::Closure(d) | SimplifiedType::Generator(d) - | SimplifiedType::GeneratorWitnessMIR(d) => Some(d), + | SimplifiedType::GeneratorWitness(d) => Some(d), _ => None, } } @@ -240,7 +236,6 @@ impl DeepRejectCtxt { | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => bug!("unexpected impl_ty: {impl_ty}"), @@ -342,7 +337,7 @@ impl DeepRejectCtxt { ty::Error(_) => true, - ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => { + ty::GeneratorWitness(..) => { bug!("unexpected obligation type: {:?}", obligation_ty) } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index bbd4a6233..c23d553d9 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -59,18 +59,8 @@ impl FlagComputation { { let mut computation = FlagComputation::new(); - for bv in value.bound_vars() { - match bv { - ty::BoundVariableKind::Ty(_) => { - computation.flags |= TypeFlags::HAS_TY_LATE_BOUND; - } - ty::BoundVariableKind::Region(_) => { - computation.flags |= TypeFlags::HAS_RE_LATE_BOUND; - } - ty::BoundVariableKind::Const => { - computation.flags |= TypeFlags::HAS_CT_LATE_BOUND; - } - } + if !value.bound_vars().is_empty() { + computation.add_flags(TypeFlags::HAS_BINDER_VARS); } f(&mut computation, value.skip_binder()); @@ -121,11 +111,7 @@ impl FlagComputation { self.add_ty(args.tupled_upvars_ty()); } - &ty::GeneratorWitness(ts) => { - self.bound_computation(ts, |flags, ts| flags.add_tys(ts)); - } - - ty::GeneratorWitnessMIR(_, args) => { + ty::GeneratorWitness(_, args) => { let should_remove_further_specializable = !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); self.add_args(args); @@ -324,7 +310,9 @@ impl FlagComputation { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); match infer { InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH), - InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER), + InferConst::Var(_) | InferConst::EffectVar(_) => { + self.add_flags(TypeFlags::HAS_CT_INFER) + } } } ty::ConstKind::Bound(debruijn, _) => { diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 77cf6bee7..00529a1e0 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -385,7 +385,7 @@ impl<'tcx> TyCtxt<'tcx> { let index = entry.index(); let var = ty::BoundVar::from_usize(index); let kind = entry - .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None))) + .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon)) .expect_region(); let br = ty::BoundRegion { var, kind }; ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br) diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 97dab5cb4..72390e4bb 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -379,12 +379,17 @@ impl<'tcx> GenericArgs<'tcx> { self.iter().filter_map(|k| k.as_const()) } + /// Returns generic arguments that are not lifetimes or host effect params. #[inline] pub fn non_erasable_generics( &'tcx self, + tcx: TyCtxt<'tcx>, + def_id: DefId, ) -> impl DoubleEndedIterator> + 'tcx { - self.iter().filter_map(|k| match k.unpack() { - GenericArgKind::Lifetime(_) => None, + let generics = tcx.generics_of(def_id); + self.iter().enumerate().filter_map(|(i, k)| match k.unpack() { + _ if Some(i) == generics.host_effect_index => None, + ty::GenericArgKind::Lifetime(_) => None, generic => Some(generic), }) } @@ -440,7 +445,7 @@ impl<'tcx> GenericArgs<'tcx> { target_args: GenericArgsRef<'tcx>, ) -> GenericArgsRef<'tcx> { let defs = tcx.generics_of(source_ancestor); - tcx.mk_args_from_iter(target_args.iter().chain(self.iter().skip(defs.params.len()))) + tcx.mk_args_from_iter(target_args.iter().chain(self.iter().skip(defs.count()))) } pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> GenericArgsRef<'tcx> { @@ -450,6 +455,11 @@ impl<'tcx> GenericArgs<'tcx> { pub fn host_effect_param(&'tcx self) -> Option> { self.consts().rfind(|x| matches!(x.kind(), ty::ConstKind::Param(p) if p.name == sym::host)) } + + pub fn print_as_list(&self) -> String { + let v = self.iter().map(|arg| arg.to_string()).collect::>(); + format!("[{}]", v.join(", ")) + } } impl<'tcx> TypeFoldable> for GenericArgsRef<'tcx> { @@ -1019,7 +1029,7 @@ impl<'a, 'tcx> ArgFolder<'a, 'tcx> { /// Stores the user-given args to reach some fully qualified path /// (e.g., `::Item` or `::Item`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct UserArgs<'tcx> { /// The args for the item as given by the user. pub args: GenericArgsRef<'tcx>, @@ -1046,7 +1056,7 @@ pub struct UserArgs<'tcx> { /// the self type, giving `Foo`. Finally, we unify that with /// the self type here, which contains `?A` to be `&'static u32` #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] pub struct UserSelfTy<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 70a35f137..8e6c1cd4b 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -12,7 +12,7 @@ use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamT pub enum GenericParamDefKind { Lifetime, Type { has_default: bool, synthetic: bool }, - Const { has_default: bool }, + Const { has_default: bool, is_host_effect: bool }, } impl GenericParamDefKind { @@ -87,7 +87,7 @@ impl GenericParamDef { GenericParamDefKind::Type { has_default, .. } if has_default => { Some(tcx.type_of(self.def_id).map_bound(|t| t.into())) } - GenericParamDefKind::Const { has_default } if has_default => { + GenericParamDefKind::Const { has_default, .. } if has_default => { Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into())) } _ => None, @@ -187,7 +187,7 @@ impl<'tcx> Generics { GenericParamDefKind::Type { has_default, .. } => { own_defaults.types += has_default as usize; } - GenericParamDefKind::Const { has_default } => { + GenericParamDefKind::Const { has_default, .. } => { own_defaults.consts += has_default as usize; } } @@ -212,10 +212,12 @@ impl<'tcx> Generics { pub fn own_requires_monomorphization(&self) -> bool { for param in &self.params { match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + GenericParamDefKind::Type { .. } + | GenericParamDefKind::Const { is_host_effect: false, .. } => { return true; } - GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Lifetime + | GenericParamDefKind::Const { is_host_effect: true, .. } => {} } } false diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 8913bf76d..0b0a708e4 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -18,6 +18,9 @@ use std::fmt; /// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type /// simply couples a potentially generic `InstanceDef` with some args, and codegen and const eval /// will do all required substitution as they run. +/// +/// Note: the `Lift` impl is currently not used by rustc, but is used by +/// rustc_codegen_cranelift when the `jit` feature is enabled. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, Lift, TypeFoldable, TypeVisitable)] pub struct Instance<'tcx> { @@ -115,7 +118,7 @@ impl<'tcx> Instance<'tcx> { /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { let ty = tcx.type_of(self.def.def_id()); - tcx.subst_and_normalize_erasing_regions(self.args, param_env, ty) + tcx.instantiate_and_normalize_erasing_regions(self.args, param_env, ty) } /// Finds a crate that contains a monomorphization of this instance that @@ -139,7 +142,7 @@ impl<'tcx> Instance<'tcx> { } // If this a non-generic instance, it cannot be a shared monomorphization. - self.args.non_erasable_generics().next()?; + self.args.non_erasable_generics(tcx, self.def_id()).next()?; match self.def { InstanceDef::Item(def) => tcx @@ -344,6 +347,7 @@ impl<'tcx> Instance<'tcx> { pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> { let args = GenericArgs::for_item(tcx, def_id, |param, _| match param.kind { ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), + ty::GenericParamDefKind::Const { is_host_effect: true, .. } => tcx.consts.true_.into(), ty::GenericParamDefKind::Type { .. } => { bug!("Instance::mono: {:?} has type parameters", def_id) } @@ -576,7 +580,7 @@ impl<'tcx> Instance<'tcx> { self.def.has_polymorphic_mir_body().then_some(self.args) } - pub fn subst_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T + pub fn instantiate_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T where T: TypeFoldable> + Copy, { @@ -589,7 +593,7 @@ impl<'tcx> Instance<'tcx> { } #[inline(always)] - pub fn subst_mir_and_normalize_erasing_regions( + pub fn instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -599,14 +603,14 @@ impl<'tcx> Instance<'tcx> { T: TypeFoldable> + Clone, { if let Some(args) = self.args_for_mir_body() { - tcx.subst_and_normalize_erasing_regions(args, param_env, v) + tcx.instantiate_and_normalize_erasing_regions(args, param_env, v) } else { tcx.normalize_erasing_regions(param_env, v.skip_binder()) } } #[inline(always)] - pub fn try_subst_mir_and_normalize_erasing_regions( + pub fn try_instantiate_mir_and_normalize_erasing_regions( &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -616,7 +620,7 @@ impl<'tcx> Instance<'tcx> { T: TypeFoldable> + Clone, { if let Some(args) = self.args_for_mir_body() { - tcx.try_subst_and_normalize_erasing_regions(args, param_env, v) + tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v) } else { tcx.try_normalize_erasing_regions(param_env, v.skip_binder()) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index e362b3477..bccf5e839 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -4,7 +4,9 @@ use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, ConstKind, ReprOptions, Ty, TyCtxt, TypeVisitableExt}; use rustc_error_messages::DiagnosticMessage; -use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic}; +use rustc_errors::{ + DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg, +}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::IndexVec; @@ -265,6 +267,12 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { } } +impl<'tcx> IntoDiagnosticArg for LayoutError<'tcx> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + #[derive(Clone, Copy)] pub struct LayoutCx<'tcx, C> { pub tcx: C, @@ -802,7 +810,6 @@ where | ty::Never | ty::FnDef(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Foreign(..) | ty::Dynamic(_, _, ty::Dyn) => { bug!("TyAndLayout::field({:?}): not applicable", this) @@ -1110,6 +1117,10 @@ where fn is_unit(this: TyAndLayout<'tcx>) -> bool { matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0) } + + fn is_transparent(this: TyAndLayout<'tcx>) -> bool { + matches!(this.ty.kind(), ty::Adt(def, _) if def.repr().transparent()) + } } /// Calculates whether a function's ABI can unwind or not. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1274f427e..aa1e7f216 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -98,17 +98,16 @@ pub use self::sty::BoundRegionKind::*; pub use self::sty::{ AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, ConstKind, ConstVid, - EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, - FreeRegion, GenSig, GeneratorArgs, GeneratorArgsParts, InlineConstArgs, InlineConstArgsParts, - ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection, + EarlyBoundRegion, EffectVid, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, + FnSig, FreeRegion, GenSig, GeneratorArgs, GeneratorArgsParts, InlineConstArgs, + InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ - CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, - GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType, - UserTypeAnnotationIndex, + CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, TypeckResults, + UserType, UserTypeAnnotationIndex, }; pub mod _match; @@ -162,8 +161,6 @@ pub struct ResolverOutputs { #[derive(Debug)] pub struct ResolverGlobalCtxt { pub visibilities: FxHashMap, - /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error. - pub has_pub_restricted: bool, /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. pub expn_that_defined: FxHashMap, pub effective_visibilities: EffectiveVisibilities, @@ -238,7 +235,7 @@ pub struct ImplHeader<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, pub trait_ref: Option>, - pub predicates: Vec<(Predicate<'tcx>, Span)>, + pub predicates: Vec>, } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] @@ -282,6 +279,19 @@ impl fmt::Display for ImplPolarity { } } +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum Asyncness { + Yes, + No, +} + +impl Asyncness { + pub fn is_async(self) -> bool { + matches!(self, Asyncness::Yes) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)] pub enum Visibility { /// Visible everywhere (including in other crates). @@ -568,6 +578,11 @@ impl rustc_errors::IntoDiagnosticArg for Clause<'_> { pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo>>>); impl<'tcx> Clause<'tcx> { + pub fn from_projection_clause(tcx: TyCtxt<'tcx>, pred: PolyProjectionPredicate<'tcx>) -> Self { + let pred: Predicate<'tcx> = pred.to_predicate(tcx); + pred.expect_clause() + } + pub fn as_predicate(self) -> Predicate<'tcx> { Predicate(self.0) } @@ -1255,14 +1270,6 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> { } } -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { @@ -1289,18 +1296,6 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef } } -impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitRef<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { - ty::Binder::dummy(self).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitPredicate<'tcx> { - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { - ty::Binder::dummy(self) - } -} - impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx) @@ -1314,12 +1309,6 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> { } } -impl<'tcx> ToPredicate<'tcx> for OutlivesPredicate, ty::Region<'tcx>> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(PredicateKind::Clause(ClauseKind::RegionOutlives(self))).to_predicate(tcx) - } -} - impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx) @@ -1332,12 +1321,6 @@ impl<'tcx> ToPredicate<'tcx> for OutlivesPredicate, ty::Region<'tcx>> { } } -impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(ClauseKind::TypeOutlives(p))).to_predicate(tcx) - } -} - impl<'tcx> ToPredicate<'tcx> for ProjectionPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(self))).to_predicate(tcx) @@ -1357,13 +1340,6 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> { } } -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx) @@ -1512,7 +1488,7 @@ impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] #[derive(TypeFoldable, TypeVisitable)] pub struct OpaqueTypeKey<'tcx> { pub def_id: LocalDefId, @@ -1795,7 +1771,7 @@ impl<'tcx> ParamEnv<'tcx> { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] -#[derive(HashStable, Lift)] +#[derive(HashStable)] pub struct ParamEnvAnd<'tcx, T> { pub param_env: ParamEnv<'tcx>, pub value: T, @@ -2150,6 +2126,7 @@ impl<'tcx> TyCtxt<'tcx> { for attr in self.get_attrs(did, sym::repr) { for r in attr::parse_repr_attr(&self.sess, attr) { flags.insert(match r { + attr::ReprRust => ReprFlags::empty(), attr::ReprC => ReprFlags::IS_C, attr::ReprPacked(pack) => { let pack = Align::from_bytes(pack as u64).unwrap(); @@ -2215,10 +2192,6 @@ impl<'tcx> TyCtxt<'tcx> { // The name of a constructor is that of its parent. rustc_hir::definitions::DefPathData::Ctor => self .opt_item_name(DefId { krate: def_id.krate, index: def_key.parent.unwrap() }), - // The name of opaque types only exists in HIR. - rustc_hir::definitions::DefPathData::ImplTrait - if let Some(def_id) = def_id.as_local() => - self.hir().opt_name(self.hir().local_def_id_to_hir_id(def_id)), _ => def_key.get_opt_name(), } } @@ -2409,6 +2382,22 @@ impl<'tcx> TyCtxt<'tcx> { } } + pub fn get_attrs_by_path<'attr>( + self, + did: DefId, + attr: &'attr [Symbol], + ) -> impl Iterator + 'attr + where + 'tcx: 'attr, + { + let filter_fn = move |a: &&ast::Attribute| a.path_matches(&attr); + if let Some(did) = did.as_local() { + self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn) + } else { + self.item_attrs(did).iter().filter(filter_fn) + } + } + pub fn get_attr(self, did: impl Into, attr: Symbol) -> Option<&'tcx ast::Attribute> { if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) { let did: DefId = did.into(); diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 2415d50b2..fd125af20 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -134,8 +134,9 @@ impl<'tcx> TyCtxt<'tcx> { /// in-scope substitutions and then normalizing any associated /// types. /// Panics if normalization fails. In case normalization might fail - /// use `try_subst_and_normalize_erasing_regions` instead. - pub fn subst_and_normalize_erasing_regions( + /// use `try_instantiate_and_normalize_erasing_regions` instead. + #[instrument(level = "debug", skip(self))] + pub fn instantiate_and_normalize_erasing_regions( self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -144,22 +145,16 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - debug!( - "subst_and_normalize_erasing_regions(\ - param_args={:?}, \ - value={:?}, \ - param_env={:?})", - param_args, value, param_env, - ); let substituted = value.instantiate(self, param_args); self.normalize_erasing_regions(param_env, substituted) } /// Monomorphizes a type from the AST by first applying the /// in-scope substitutions and then trying to normalize any associated - /// types. Contrary to `subst_and_normalize_erasing_regions` this does + /// types. Contrary to `instantiate_and_normalize_erasing_regions` this does /// not assume that normalization succeeds. - pub fn try_subst_and_normalize_erasing_regions( + #[instrument(level = "debug", skip(self))] + pub fn try_instantiate_and_normalize_erasing_regions( self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -168,13 +163,6 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - debug!( - "subst_and_normalize_erasing_regions(\ - param_args={:?}, \ - value={:?}, \ - param_env={:?})", - param_args, value, param_env, - ); let substituted = value.instantiate(self, param_args); self.try_normalize_erasing_regions(param_env, substituted) } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 0ff5ac903..6491936c2 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -157,9 +157,9 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { Ty::new_generator(self.tcx, def_id, args, movability) } - ty::GeneratorWitnessMIR(def_id, args) => { + ty::GeneratorWitness(def_id, args) => { let args = self.fold_closure_args(def_id, args); - Ty::new_generator_witness_mir(self.tcx, def_id, args) + Ty::new_generator_witness(self.tcx, def_id, args) } ty::Param(param) => { diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index f1c389842..9aa673e44 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -62,6 +62,7 @@ trivially_parameterized_over_tcx! { crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::mir::ConstQualifs, ty::AssocItemContainer, + ty::Asyncness, ty::DeducedParamAttrs, ty::Generics, ty::ImplPolarity, @@ -131,5 +132,4 @@ parameterized_over_tcx! { ty::Predicate, ty::Clause, ty::ClauseKind, - ty::GeneratorDiagnosticData, } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 05871d0bc..aa8e2e307 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -271,7 +271,7 @@ fn characteristic_def_id_of_type_cached<'a>( ty::FnDef(def_id, _) | ty::Closure(def_id, _) | ty::Generator(def_id, _, _) - | ty::GeneratorWitnessMIR(def_id, _) + | ty::GeneratorWitness(def_id, _) | ty::Foreign(def_id) => Some(def_id), ty::Bool @@ -286,7 +286,6 @@ fn characteristic_def_id_of_type_cached<'a>( | ty::Infer(_) | ty::Bound(..) | ty::Error(_) - | ty::GeneratorWitness(..) | ty::Never | ty::Float(_) => None, } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ac0c88468..2d7350387 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -136,10 +136,8 @@ define_helper!( /// /// Regions not selected by the region highlight mode are presently /// unaffected. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Default)] pub struct RegionHighlightMode<'tcx> { - tcx: TyCtxt<'tcx>, - /// If enabled, when we see the selected region, use "`'N`" /// instead of the ordinary behavior. highlight_regions: [Option<(ty::Region<'tcx>, usize)>; 3], @@ -155,14 +153,6 @@ pub struct RegionHighlightMode<'tcx> { } impl<'tcx> RegionHighlightMode<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Self { - Self { - tcx, - highlight_regions: Default::default(), - highlight_bound_region: Default::default(), - } - } - /// If `region` and `number` are both `Some`, invokes /// `highlighting_region`. pub fn maybe_highlighting_region( @@ -188,8 +178,13 @@ impl<'tcx> RegionHighlightMode<'tcx> { } /// Convenience wrapper for `highlighting_region`. - pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) { - self.highlighting_region(ty::Region::new_var(self.tcx, vid), number) + pub fn highlighting_region_vid( + &mut self, + tcx: TyCtxt<'tcx>, + vid: ty::RegionVid, + number: usize, + ) { + self.highlighting_region(ty::Region::new_var(tcx, vid), number) } /// Returns `Some(n)` with the number to use for the given region, if any. @@ -365,7 +360,7 @@ pub trait PrettyPrinter<'tcx>: self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?; self.write_str("::")?; } else if let DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Trait - | DefKind::TyAlias { .. } | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind + | DefKind::TyAlias | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind { } else { // If not covered above, like for example items out of `impl` blocks, fallback. @@ -760,15 +755,18 @@ pub trait PrettyPrinter<'tcx>: // only affect certain debug messages (e.g. messages printed // from `rustc_middle::ty` during the computation of `tcx.predicates_of`), // and should have no effect on any compiler output. + // [Unless `-Zverbose` is used, e.g. in the output of + // `tests/ui/nll/ty-outlives/impl-trait-captures.rs`, for + // example.] if self.should_print_verbose() { // FIXME(eddyb) print this with `print_def_path`. - p!(write("Opaque({:?}, {:?})", def_id, args)); + p!(write("Opaque({:?}, {})", def_id, args.print_as_list())); return Ok(self); } let parent = self.tcx().parent(def_id); match self.tcx().def_kind(parent) { - DefKind::TyAlias { .. } | DefKind::AssocTy => { + DefKind::TyAlias | DefKind::AssocTy => { // NOTE: I know we should check for NO_QUERIES here, but it's alright. // `type_of` on a type alias or assoc type should never cause a cycle. if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) = @@ -797,7 +795,7 @@ pub trait PrettyPrinter<'tcx>: } ty::Str => p!("str"), ty::Generator(did, args, movability) => { - p!(write("[")); + p!(write("{{")); let generator_kind = self.tcx().generator_kind(did).unwrap(); let should_print_movability = self.should_print_verbose() || generator_kind == hir::GeneratorKind::Gen; @@ -838,13 +836,10 @@ pub trait PrettyPrinter<'tcx>: } } - p!("]") - } - ty::GeneratorWitness(types) => { - p!(in_binder(&types)); + p!("}}") } - ty::GeneratorWitnessMIR(did, args) => { - p!(write("[")); + ty::GeneratorWitness(did, args) => { + p!(write("{{")); if !self.tcx().sess.verbose() { p!("generator witness"); // FIXME(eddyb) should use `def_span`. @@ -863,10 +858,10 @@ pub trait PrettyPrinter<'tcx>: p!(print_def_path(did, args)); } - p!("]") + p!("}}") } ty::Closure(did, args) => { - p!(write("[")); + p!(write("{{")); if !self.should_print_verbose() { p!(write("closure")); // FIXME(eddyb) should use `def_span`. @@ -894,7 +889,7 @@ pub trait PrettyPrinter<'tcx>: p!(print_def_path(did, args)); if !args.as_closure().is_valid() { p!(" closure_args=(unavailable)"); - p!(write(" args={:?}", args)); + p!(write(" args={}", args.print_as_list())); } else { p!(" closure_kind_ty=", print(args.as_closure().kind_ty())); p!( @@ -906,7 +901,7 @@ pub trait PrettyPrinter<'tcx>: p!(")"); } } - p!("]"); + p!("}}"); } ty::Array(ty, sz) => p!("[", print(ty), "; ", print(sz), "]"), ty::Slice(ty) => p!("[", print(ty), "]"), @@ -1063,7 +1058,7 @@ pub trait PrettyPrinter<'tcx>: } for (assoc_item_def_id, term) in assoc_items { - // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks, + // Skip printing `<{generator@} as Generator<_>>::Return` from async blocks, // unless we can find out what generator return type it comes from. let term = if let Some(ty) = term.skip_binder().ty() && let ty::Alias(ty::Projection, proj) = ty.kind() @@ -1123,6 +1118,17 @@ pub trait PrettyPrinter<'tcx>: } } + if self.tcx().features().return_type_notation + && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) = self.tcx().opt_rpitit_info(def_id) + && let ty::Alias(_, alias_ty) = self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind() + && alias_ty.def_id == def_id + { + let num_args = self.tcx().generics_of(fn_def_id).count(); + write!(self, " {{ ")?; + self = self.print_def_path(fn_def_id, &args[..num_args])?; + write!(self, "() }}")?; + } + Ok(self) } @@ -1239,21 +1245,18 @@ pub trait PrettyPrinter<'tcx>: .generics_of(principal.def_id) .own_args_no_defaults(cx.tcx(), principal.args); - 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() { - let args = arg0.into_iter().chain(args); - let projections = projection0.into_iter().chain(projections); + let mut projections: Vec<_> = predicates.projection_bounds().collect(); + projections.sort_by_cached_key(|proj| { + cx.tcx().item_name(proj.item_def_id()).to_string() + }); + if !args.is_empty() || !projections.is_empty() { p!(generic_delimiters(|mut cx| { - cx = cx.comma_sep(args)?; - if arg0.is_some() && projection0.is_some() { + cx = cx.comma_sep(args.iter().copied())?; + if !args.is_empty() && !projections.is_empty() { write!(cx, ", ")?; } - cx.comma_sep(projections) + cx.comma_sep(projections.iter().copied()) })); } } @@ -1707,6 +1710,21 @@ pub trait PrettyPrinter<'tcx>: } } +pub(crate) fn pretty_print_const<'tcx>( + c: ty::Const<'tcx>, + fmt: &mut fmt::Formatter<'_>, + print_types: bool, +) -> fmt::Result { + ty::tls::with(|tcx| { + let literal = tcx.lift(c).unwrap(); + let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS); + cx.print_alloc_ids = true; + let cx = cx.pretty_print_const(literal, print_types)?; + fmt.write_str(&cx.into_buffer())?; + Ok(()) + }) +} + // HACK(eddyb) boxed to avoid moving around a large struct by-value. pub struct FmtPrinter<'a, 'tcx>(Box>); @@ -1767,7 +1785,7 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> { printed_type_count: 0, type_length_limit, truncated: false, - region_highlight_mode: RegionHighlightMode::new(tcx), + region_highlight_mode: RegionHighlightMode::default(), ty_infer_name_resolver: None, const_infer_name_resolver: None, })) @@ -2312,7 +2330,7 @@ impl<'a, 'tcx> ty::TypeFolder> for RegionFolder<'a, 'tcx> { // If this is an anonymous placeholder, don't rename. Otherwise, in some // async fns, we get a `for<'r> Send` bound match kind { - ty::BrAnon(..) | ty::BrEnv => r, + ty::BrAnon | ty::BrEnv => r, _ => { // Index doesn't matter, since this is just for naming and these never get bound let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind }; @@ -2433,7 +2451,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { binder_level_idx: ty::DebruijnIndex, br: ty::BoundRegion| { let (name, kind) = match br.kind { - ty::BrAnon(..) | ty::BrEnv => { + ty::BrAnon | ty::BrEnv => { let name = next_name(&self); if let Some(lt_idx) = lifetime_idx { @@ -2735,20 +2753,14 @@ forward_display_to_print! { // HACK(eddyb) these are exhaustive instead of generic, // because `for<'tcx>` isn't possible yet. - ty::PolyExistentialPredicate<'tcx>, ty::PolyExistentialProjection<'tcx>, ty::PolyExistentialTraitRef<'tcx>, ty::Binder<'tcx, ty::TraitRef<'tcx>>, ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, - ty::Binder<'tcx, TraitRefPrintOnlyTraitName<'tcx>>, ty::Binder<'tcx, ty::FnSig<'tcx>>, ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>, - ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>, ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, - ty::Binder<'tcx, ty::OutlivesPredicate, ty::Region<'tcx>>>, - ty::Binder<'tcx, ty::OutlivesPredicate, ty::Region<'tcx>>>, - ty::OutlivesPredicate, ty::Region<'tcx>>, ty::OutlivesPredicate, ty::Region<'tcx>> } @@ -2986,7 +2998,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N match child.res { def::Res::Def(DefKind::AssocTy, _) => {} - def::Res::Def(DefKind::TyAlias { .. }, _) => {} + def::Res::Def(DefKind::TyAlias, _) => {} def::Res::Def(defkind, def_id) => { if let Some(ns) = defkind.ns() { collect_fn(&child.ident, ns, def_id); diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 47512d350..e9d763afa 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -453,24 +453,14 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(Ty::new_generator(tcx, a_id, args, movability)) } - (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { - // Wrap our types with a temporary GeneratorWitness struct - // inside the binder so we can related them - let a_types = a_types.map_bound(GeneratorWitness); - let b_types = b_types.map_bound(GeneratorWitness); - // Then remove the GeneratorWitness for the result - let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0); - Ok(Ty::new_generator_witness(tcx, types)) - } - - (&ty::GeneratorWitnessMIR(a_id, a_args), &ty::GeneratorWitnessMIR(b_id, b_args)) + (&ty::GeneratorWitness(a_id, a_args), &ty::GeneratorWitness(b_id, b_args)) if a_id == b_id => { // All GeneratorWitness types with the same id represent // the (anonymous) type of the same generator expression. So // all of their regions should be equated. let args = relation.relate(a_args, b_args)?; - Ok(Ty::new_generator_witness_mir(tcx, a_id, args)) + Ok(Ty::new_generator_witness(tcx, a_id, args)) } (&ty::Closure(a_id, a_args), &ty::Closure(b_id, b_args)) if a_id == b_id => { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index f979ddd00..2adbe9e03 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -9,15 +9,13 @@ use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; -use rustc_index::{Idx, IndexVec}; use rustc_target::abi::TyAndLayout; use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, OptWithInfcx}; use std::fmt::{self, Debug}; use std::ops::ControlFlow; -use std::rc::Rc; -use std::sync::Arc; +use super::print::PrettyPrinter; use super::{GenericArg, GenericArgKind, Region}; impl fmt::Debug for ty::TraitDef { @@ -70,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { impl fmt::Debug for ty::BoundRegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::BrAnon(span) => write!(f, "BrAnon({span:?})"), + ty::BrAnon => write!(f, "BrAnon"), ty::BrNamed(did, name) => { if did.is_crate_root() { write!(f, "BrNamed({name})") @@ -138,6 +136,12 @@ impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> { } } +impl fmt::Debug for ty::EffectVid<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "?{}e", self.index) + } +} + impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths!(fmt::Display::fmt(self, f)) @@ -154,7 +158,7 @@ impl<'tcx> ty::DebugWithInfcx> for Ty<'tcx> { } impl<'tcx> fmt::Debug for Ty<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - with_no_trimmed_paths!(fmt::Display::fmt(self, f)) + with_no_trimmed_paths!(fmt::Debug::fmt(self.kind(), f)) } } @@ -253,6 +257,7 @@ impl<'tcx> fmt::Debug for ty::InferConst<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { InferConst::Var(var) => write!(f, "{var:?}"), + InferConst::EffectVar(var) => write!(f, "{var:?}"), InferConst::Fresh(var) => write!(f, "Fresh({var:?})"), } } @@ -267,6 +272,7 @@ impl<'tcx> DebugWithInfcx> for ty::InferConst<'tcx> { None => write!(f, "{:?}", this.data), Some(universe) => match *this.data { Var(vid) => write!(f, "?{}_{}c", vid.index, universe.index()), + EffectVar(vid) => write!(f, "?{}_{}e", vid.index, universe.index()), Fresh(_) => { unreachable!() } @@ -335,14 +341,27 @@ impl<'tcx> DebugWithInfcx> for ty::Const<'tcx> { this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { - // This reflects what `Const` looked liked before `Interned` was - // introduced. We print it like this to avoid having to update expected - // output in a lot of tests. + // If this is a value, we spend some effort to make it look nice. + if let ConstKind::Value(_) = this.data.kind() { + return ty::tls::with(move |tcx| { + // Somehow trying to lift the valtree results in lifetime errors, so we lift the + // entire constant. + let lifted = tcx.lift(*this.data).unwrap(); + let ConstKind::Value(valtree) = lifted.kind() else { + bug!("we checked that this is a valtree") + }; + let cx = FmtPrinter::new(tcx, Namespace::ValueNS); + let cx = + cx.pretty_print_const_valtree(valtree, lifted.ty(), /*print_ty*/ true)?; + f.write_str(&cx.into_buffer()) + }); + } + // Fall back to something verbose. write!( f, - "Const {{ ty: {:?}, kind: {:?} }}", - &this.map(|data| data.ty()), - &this.map(|data| data.kind()) + "{kind:?}: {ty:?}", + ty = &this.map(|data| data.ty()), + kind = &this.map(|data| data.kind()) ) } } @@ -434,22 +453,17 @@ impl<'tcx, T: DebugWithInfcx>> DebugWithInfcx> for ty: // For things for which the type library provides traversal implementations // for all Interners, we only need to provide a Lift implementation: -CloneLiftImpls! { - (), - bool, - usize, - u16, - u32, - u64, - String, - rustc_type_ir::DebruijnIndex, -} - -// For things about which the type library does not know, or does not -// provide any traversal implementations, we need to provide both a Lift -// implementation and traversal implementations (the latter only for -// TyCtxt<'_> interners). -TrivialTypeTraversalAndLiftImpls! { +TrivialLiftImpls! { + (), + bool, + usize, + u64, +} + +// For some things about which the type library does not know, or does not +// provide any traversal implementations, we need to provide a traversal +// implementation (only for TyCtxt<'_> interners). +TrivialTypeTraversalImpls! { ::rustc_target::abi::FieldIdx, ::rustc_target::abi::VariantIdx, crate::middle::region::Scope, @@ -459,17 +473,12 @@ TrivialTypeTraversalAndLiftImpls! { ::rustc_ast::NodeId, ::rustc_span::symbol::Symbol, ::rustc_hir::def::Res, - ::rustc_hir::def_id::DefId, ::rustc_hir::def_id::LocalDefId, ::rustc_hir::HirId, ::rustc_hir::MatchSource, - ::rustc_hir::Mutability, - ::rustc_hir::Unsafety, ::rustc_target::asm::InlineAsmRegOrRegClass, - ::rustc_target::spec::abi::Abi, crate::mir::coverage::CounterId, crate::mir::coverage::ExpressionId, - crate::mir::coverage::MappedExpressionIndex, crate::mir::Local, crate::mir::Promoted, crate::traits::Reveal, @@ -484,16 +493,12 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::AssocItem, crate::ty::AssocKind, crate::ty::AliasKind, - crate::ty::AliasRelationDirection, crate::ty::Placeholder, crate::ty::Placeholder, crate::ty::Placeholder, - crate::ty::ClosureKind, crate::ty::FreeRegion, crate::ty::InferTy, crate::ty::IntVarValue, - crate::ty::ParamConst, - crate::ty::ParamTy, crate::ty::adjustment::PointerCoercion, crate::ty::RegionVid, crate::ty::UniverseIndex, @@ -501,32 +506,30 @@ TrivialTypeTraversalAndLiftImpls! { ::rustc_span::Span, ::rustc_span::symbol::Ident, ::rustc_errors::ErrorGuaranteed, - interpret::Scalar, - rustc_target::abi::Size, ty::BoundVar, + ty::ValTree<'tcx>, } - +// For some things about which the type library does not know, or does not +// provide any traversal implementations, we need to provide a traversal +// implementation and a lift implementation (the former only for TyCtxt<'_> +// interners). TrivialTypeTraversalAndLiftImpls! { - ty::ValTree<'tcx>, + ::rustc_hir::def_id::DefId, + ::rustc_hir::Mutability, + ::rustc_hir::Unsafety, + ::rustc_target::spec::abi::Abi, + crate::ty::AliasRelationDirection, + crate::ty::ClosureKind, + crate::ty::ParamConst, + crate::ty::ParamTy, + interpret::Scalar, + interpret::AllocId, + rustc_target::abi::Size, } /////////////////////////////////////////////////////////////////////////// // Lift implementations -impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) { - type Lifted = (A::Lifted, B::Lifted); - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - Some((tcx.lift(self.0)?, tcx.lift(self.1)?)) - } -} - -impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>, C: Lift<'tcx>> Lift<'tcx> for (A, B, C) { - type Lifted = (A::Lifted, B::Lifted, C::Lifted); - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - Some((tcx.lift(self.0)?, tcx.lift(self.1)?, tcx.lift(self.2)?)) - } -} - impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option { type Lifted = Option; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { @@ -537,50 +540,6 @@ impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option { } } -impl<'tcx, T: Lift<'tcx>, E: Lift<'tcx>> Lift<'tcx> for Result { - type Lifted = Result; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - match self { - Ok(x) => tcx.lift(x).map(Ok), - Err(e) => tcx.lift(e).map(Err), - } - } -} - -impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Box { - type Lifted = Box; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - Some(Box::new(tcx.lift(*self)?)) - } -} - -impl<'tcx, T: Lift<'tcx> + Clone> Lift<'tcx> for Rc { - type Lifted = Rc; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - Some(Rc::new(tcx.lift(self.as_ref().clone())?)) - } -} - -impl<'tcx, T: Lift<'tcx> + Clone> Lift<'tcx> for Arc { - type Lifted = Arc; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - Some(Arc::new(tcx.lift(self.as_ref().clone())?)) - } -} -impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Vec { - type Lifted = Vec; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - self.into_iter().map(|v| tcx.lift(v)).collect() - } -} - -impl<'tcx, I: Idx, T: Lift<'tcx>> Lift<'tcx> for IndexVec { - type Lifted = IndexVec; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - self.into_iter().map(|e| tcx.lift(e)).collect() - } -} - impl<'a, 'tcx> Lift<'tcx> for Term<'a> { type Lifted = ty::Term<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { @@ -593,13 +552,6 @@ impl<'a, 'tcx> Lift<'tcx> for Term<'a> { ) } } -impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> { - type Lifted = ty::ParamEnv<'tcx>; - fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - tcx.lift(self.caller_bounds()) - .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal())) - } -} /////////////////////////////////////////////////////////////////////////// // Traversal implementations. @@ -705,9 +657,8 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { ty::Generator(did, args, movability) => { ty::Generator(did, args.try_fold_with(folder)?, movability) } - ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?), - ty::GeneratorWitnessMIR(did, args) => { - ty::GeneratorWitnessMIR(did, args.try_fold_with(folder)?) + ty::GeneratorWitness(did, args) => { + ty::GeneratorWitness(did, args.try_fold_with(folder)?) } ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?), ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?), @@ -756,8 +707,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { ty.visit_with(visitor) } ty::Generator(_did, ref args, _) => args.visit_with(visitor), - ty::GeneratorWitness(ref types) => types.visit_with(visitor), - ty::GeneratorWitnessMIR(_did, ref args) => args.visit_with(visitor), + ty::GeneratorWitness(_did, ref args) => args.visit_with(visitor), ty::Closure(_did, ref args) => args.visit_with(visitor), ty::Alias(_, ref data) => data.visit_with(visitor), diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 0291cdd6c..1e57392e0 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -69,7 +69,7 @@ pub struct FreeRegion { #[derive(HashStable)] pub enum BoundRegionKind { /// An anonymous region parameter for a given fn (&T) - BrAnon(Option), + BrAnon, /// Named region parameters for functions (a in &'a T) /// @@ -351,7 +351,7 @@ impl<'tcx> ClosureArgs<'tcx> { } /// Similar to `ClosureArgs`; see the above documentation for more. -#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] pub struct GeneratorArgs<'tcx> { pub args: GenericArgsRef<'tcx>, } @@ -725,7 +725,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) } ExistentialPredicate::Projection(p) => { - self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) + ty::Clause::from_projection_clause(tcx, self.rebind(p.with_self_ty(tcx, self_ty))) } ExistentialPredicate::AutoTrait(did) => { let generics = tcx.generics_of(did); @@ -1223,7 +1223,7 @@ impl<'tcx> AliasTy<'tcx> { DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent, DefKind::AssocTy => ty::Projection, DefKind::OpaqueTy => ty::Opaque, - DefKind::TyAlias { .. } => ty::Weak, + DefKind::TyAlias => ty::Weak, kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), } } @@ -1305,7 +1305,7 @@ impl<'tcx> AliasTy<'tcx> { } } -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub struct GenSig<'tcx> { pub resume_ty: Ty<'tcx>, pub yield_ty: Ty<'tcx>, @@ -1465,7 +1465,7 @@ impl<'tcx> Region<'tcx> { bound_region: ty::BoundRegion, ) -> Region<'tcx> { // Use a pre-interned one when possible. - if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region + if let ty::BoundRegion { var, kind: ty::BrAnon } = bound_region && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize()) && let Some(re) = inner.get(var.as_usize()).copied() { @@ -1577,6 +1577,20 @@ pub struct ConstVid<'tcx> { pub phantom: PhantomData<&'tcx ()>, } +/// An **effect** **v**ariable **ID**. +/// +/// Handling effect infer variables happens separately from const infer variables +/// because we do not want to reuse any of the const infer machinery. If we try to +/// relate an effect variable with a normal one, we would ICE, which can catch bugs +/// where we are not correctly using the effect var for an effect param. Fallback +/// is also implemented on top of having separate effect and normal const variables. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(TyEncodable, TyDecodable)] +pub struct EffectVid<'tcx> { + pub index: u32, + pub phantom: PhantomData<&'tcx ()>, +} + rustc_index::newtype_index! { /// A **region** (lifetime) **v**ariable **ID**. #[derive(HashStable)] @@ -1945,7 +1959,7 @@ impl<'tcx> Ty<'tcx> { (kind, tcx.def_kind(alias_ty.def_id)), (ty::Opaque, DefKind::OpaqueTy) | (ty::Projection | ty::Inherent, DefKind::AssocTy) - | (ty::Weak, DefKind::TyAlias { .. }) + | (ty::Weak, DefKind::TyAlias) ); Ty::new(tcx, Alias(kind, alias_ty)) } @@ -2150,19 +2164,11 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_generator_witness( - tcx: TyCtxt<'tcx>, - types: ty::Binder<'tcx, &'tcx List>>, - ) -> Ty<'tcx> { - Ty::new(tcx, GeneratorWitness(types)) - } - - #[inline] - pub fn new_generator_witness_mir( tcx: TyCtxt<'tcx>, id: DefId, args: GenericArgsRef<'tcx>, ) -> Ty<'tcx> { - Ty::new(tcx, GeneratorWitnessMIR(id, args)) + Ty::new(tcx, GeneratorWitness(id, args)) } // misc @@ -2536,7 +2542,7 @@ impl<'tcx> Ty<'tcx> { /// Checks whether a type recursively contains any closure /// - /// Example: `Option<[closure@file.rs:4:20]>` returns true + /// Example: `Option<{closure@file.rs:4:20}>` returns true pub fn contains_closure(self) -> bool { struct ContainsClosureVisitor; @@ -2692,7 +2698,6 @@ impl<'tcx> Ty<'tcx> { | ty::Dynamic(..) | ty::Closure(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never | ty::Tuple(_) | ty::Error(_) @@ -2728,13 +2733,14 @@ impl<'tcx> Ty<'tcx> { | ty::Ref(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Array(..) | ty::Closure(..) | ty::Never | ty::Error(_) // Extern types have metadata = (). | ty::Foreign(..) + // `dyn*` has no metadata + | ty::Dynamic(_, _, DynKind::DynStar) // If returned by `struct_tail_without_normalization` this is a unit struct // without any fields, or not a struct, and therefore is Sized. | ty::Adt(..) @@ -2743,7 +2749,7 @@ impl<'tcx> Ty<'tcx> { | ty::Tuple(..) => (tcx.types.unit, false), ty::Str | ty::Slice(_) => (tcx.types.usize, false), - ty::Dynamic(..) => { + ty::Dynamic(_, _, DynKind::Dyn) => { let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None); (tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]), false) }, @@ -2815,7 +2821,6 @@ impl<'tcx> Ty<'tcx> { | ty::Ref(..) | ty::Generator(..) | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Array(..) | ty::Closure(..) | ty::Never @@ -2857,7 +2862,7 @@ impl<'tcx> Ty<'tcx> { | ty::Uint(..) | ty::Float(..) => true, - // The voldemort ZSTs are fine. + // ZST which can't be named are fine. ty::FnDef(..) => true, ty::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(), @@ -2878,7 +2883,7 @@ impl<'tcx> Ty<'tcx> { // anything with custom metadata it might be more complicated. ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => false, - ty::Generator(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => false, + ty::Generator(..) | ty::GeneratorWitness(..) => false, // Might be, but not "trivial" so just giving the safe answer. ty::Adt(..) | ty::Closure(..) => false, @@ -2929,6 +2934,37 @@ impl<'tcx> Ty<'tcx> { _ => false, } } + + /// Returns `true` when the outermost type cannot be further normalized, + /// resolved, or substituted. This includes all primitive types, but also + /// things like ADTs and trait objects, sice even if their arguments or + /// nested types may be further simplified, the outermost [`TyKind`] or + /// type constructor remains the same. + pub fn is_known_rigid(self) -> bool { + match self.kind() { + Bool + | Char + | Int(_) + | Uint(_) + | Float(_) + | Adt(_, _) + | Foreign(_) + | Str + | Array(_, _) + | Slice(_) + | RawPtr(_) + | Ref(_, _, _) + | FnDef(_, _) + | FnPtr(_) + | Dynamic(_, _, _) + | Closure(_, _) + | Generator(_, _, _) + | GeneratorWitness(..) + | Never + | Tuple(_) => true, + Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false, + } + } } /// Extra information about why we ended up with a particular variance. @@ -2974,7 +3010,7 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(RegionKind<'_>, 28); + static_assert_size!(RegionKind<'_>, 24); static_assert_size!(TyKind<'_>, 32); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 6e55e7915..bf9b24493 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -90,6 +90,10 @@ pub struct TraitImpls { } impl TraitImpls { + pub fn is_empty(&self) -> bool { + self.blanket_impls.is_empty() && self.non_blanket_impls.is_empty() + } + pub fn blanket_impls(&self) -> &[DefId] { self.blanket_impls.as_slice() } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 327cd0a5d..a44224e4d 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -165,7 +165,7 @@ pub struct TypeckResults<'tcx> { /// reading places that are mentioned in a closure (because of _ patterns). However, /// to ensure the places are initialized, we introduce fake reads. /// Consider these two examples: - /// ``` (discriminant matching with only wildcard arm) + /// ```ignore (discriminant matching with only wildcard arm) /// let x: u8; /// let c = || match x { _ => () }; /// ``` @@ -173,7 +173,7 @@ pub struct TypeckResults<'tcx> { /// want to capture it. However, we do still want an error here, because `x` should have /// to be initialized at the point where c is created. Therefore, we add a "fake read" /// instead. - /// ``` (destructured assignments) + /// ```ignore (destructured assignments) /// let c = || { /// let (t1, t2) = t; /// } @@ -189,10 +189,6 @@ pub struct TypeckResults<'tcx> { /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`. pub rvalue_scopes: RvalueScopes, - /// Stores the type, expression, span and optional scope span of all types - /// that are live across the yield of this generator (if a generator). - pub generator_interior_types: ty::Binder<'tcx, Vec>>, - /// Stores the predicates that apply on generator witness types. /// formatting modified file tests/ui/generator/retain-resume-ref.rs pub generator_interior_predicates: @@ -212,49 +208,6 @@ pub struct TypeckResults<'tcx> { offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec)>, } -/// Whenever a value may be live across a generator yield, the type of that value winds up in the -/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such -/// captured types that can be useful for diagnostics. In particular, it stores the span that -/// caused a given type to be recorded, along with the scope that enclosed the value (which can -/// be used to find the await that the value is live across). -/// -/// For example: -/// -/// ```ignore (pseudo-Rust) -/// async move { -/// let x: T = expr; -/// foo.await -/// ... -/// } -/// ``` -/// -/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for -/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`. -#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct GeneratorInteriorTypeCause<'tcx> { - /// Type of the captured binding. - pub ty: Ty<'tcx>, - /// Span of the binding that was captured. - pub span: Span, - /// Span of the scope of the captured binding. - pub scope_span: Option, - /// Span of `.await` or `yield` expression. - pub yield_span: Span, - /// Expr which the type evaluated from. - pub expr: Option, -} - -// This type holds diagnostic information on generators and async functions across crate boundaries -// and is used to provide better error messages -#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)] -pub struct GeneratorDiagnosticData<'tcx> { - pub generator_interior_types: ty::Binder<'tcx, Vec>>, - pub hir_owner: DefId, - pub nodes_types: ItemLocalMap>, - pub adjustments: ItemLocalMap>>, -} - impl<'tcx> TypeckResults<'tcx> { pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> { TypeckResults { @@ -278,7 +231,6 @@ impl<'tcx> TypeckResults<'tcx> { closure_min_captures: Default::default(), closure_fake_reads: Default::default(), rvalue_scopes: Default::default(), - generator_interior_types: ty::Binder::dummy(Default::default()), generator_interior_predicates: Default::default(), treat_byte_string_as_slice: Default::default(), closure_size_eval: Default::default(), @@ -351,28 +303,6 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types } } - pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> { - let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| { - vec.iter() - .map(|item| { - GeneratorInteriorTypeCause { - ty: item.ty, - span: item.span, - scope_span: item.scope_span, - yield_span: item.yield_span, - expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment - } - }) - .collect::>() - }); - GeneratorDiagnosticData { - generator_interior_types: generator_interior_type, - hir_owner: self.hir_owner.to_def_id(), - nodes_types: self.node_types.clone(), - adjustments: self.adjustments.clone(), - } - } - pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> { self.node_type_opt(id).unwrap_or_else(|| { bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id))) @@ -654,7 +584,7 @@ rustc_index::newtype_index! { pub type CanonicalUserTypeAnnotations<'tcx> = IndexVec>; -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct CanonicalUserTypeAnnotation<'tcx> { pub user_ty: Box>, pub span: Span, @@ -714,7 +644,7 @@ impl<'tcx> CanonicalUserType<'tcx> { /// from constants that are named via paths, like `Foo::::new` and /// so forth. #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)] -#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable, Lift)] +#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)] pub enum UserType<'tcx> { Ty(Ty<'tcx>), @@ -722,3 +652,14 @@ pub enum UserType<'tcx> { /// given substitutions applied. TypeOf(DefId, UserArgs<'tcx>), } + +impl<'tcx> std::fmt::Display for UserType<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Ty(arg0) => { + ty::print::with_no_trimmed_paths!(write!(f, "Ty({})", arg0)) + } + Self::TypeOf(arg0, arg1) => write!(f, "TypeOf({:?}, {:?})", arg0, arg1), + } + } +} diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 564f982f8..964f38a65 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -156,7 +156,7 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::Enum | DefKind::Trait | DefKind::OpaqueTy - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -855,7 +855,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> { let hidden_ty = bty.instantiate(self.tcx, args); self.fold_ty(hidden_ty); } - let expanded_ty = Ty::new_generator_witness_mir(self.tcx, def_id, args); + let expanded_ty = Ty::new_generator_witness(self.tcx, def_id, args); self.expanded_cache.insert((def_id, args), expanded_ty); expanded_ty } @@ -888,7 +888,7 @@ impl<'tcx> TypeFolder> for OpaqueTypeExpander<'tcx> { t }; if self.expand_generators { - if let ty::GeneratorWitnessMIR(def_id, args) = *t.kind() { + if let ty::GeneratorWitness(def_id, args) = *t.kind() { t = self.expand_generator(def_id, args).unwrap_or(t); } } @@ -1025,8 +1025,7 @@ impl<'tcx> Ty<'tcx> { | ty::Dynamic(..) | ty::Foreign(_) | ty::Generator(..) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) + | ty::GeneratorWitness(..) | ty::Infer(_) | ty::Alias(..) | ty::Param(_) @@ -1065,8 +1064,7 @@ impl<'tcx> Ty<'tcx> { | ty::Dynamic(..) | ty::Foreign(_) | ty::Generator(..) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) + | ty::GeneratorWitness(..) | ty::Infer(_) | ty::Alias(..) | ty::Param(_) @@ -1099,8 +1097,10 @@ impl<'tcx> Ty<'tcx> { // This doesn't depend on regions, so try to minimize distinct // query keys used. // If normalization fails, we just use `query_ty`. - let query_ty = - tcx.try_normalize_erasing_regions(param_env, query_ty).unwrap_or(query_ty); + debug_assert!(!param_env.has_infer()); + let query_ty = tcx + .try_normalize_erasing_regions(param_env, query_ty) + .unwrap_or_else(|_| tcx.erase_regions(query_ty)); tcx.needs_drop_raw(param_env.and(query_ty)) } @@ -1194,10 +1194,7 @@ impl<'tcx> Ty<'tcx> { false } - ty::Foreign(_) - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) - | ty::Error(_) => false, + ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false, } } @@ -1292,8 +1289,6 @@ pub fn needs_drop_components<'tcx>( | ty::FnDef(..) | ty::FnPtr(_) | ty::Char - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::RawPtr(_) | ty::Ref(..) | ty::Str => Ok(SmallVec::new()), @@ -1333,7 +1328,8 @@ pub fn needs_drop_components<'tcx>( | ty::Placeholder(..) | ty::Infer(_) | ty::Closure(..) - | ty::Generator(..) => Ok(smallvec![ty]), + | ty::Generator(..) + | ty::GeneratorWitness(..) => Ok(smallvec![ty]), } } @@ -1364,11 +1360,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { // Not trivial because they have components, and instead of looking inside, // we'll just perform trait selection. - ty::Closure(..) - | ty::Generator(..) - | ty::GeneratorWitness(_) - | ty::GeneratorWitnessMIR(..) - | ty::Adt(..) => false, + ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) | ty::Adt(..) => false, ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty), diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 156eda477..95ba6c471 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -33,14 +33,6 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable> { } fn has_type_flags(&self, flags: TypeFlags) -> bool { - // N.B. Even though this uses a visitor, the visitor does not actually - // recurse through the whole `TypeVisitable` implementor type. - // - // Instead it stops on the first "level", visiting types, regions, - // consts and predicates just fetches their type flags. - // - // Thus this is a lot faster than it might seem and should be - // optimized to a simple field access. let res = self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags); trace!(?self, ?flags, ?res, "has_type_flags"); @@ -485,11 +477,36 @@ impl std::fmt::Debug for HasTypeFlagsVisitor { } } +// Note: this visitor traverses values down to the level of +// `Ty`/`Const`/`Predicate`, but not within those types. This is because the +// type flags at the outer layer are enough. So it's faster than it first +// looks, particular for `Ty`/`Predicate` where it's just a field access. +// +// N.B. The only case where this isn't totally true is binders, which also +// add `HAS_{RE,TY,CT}_LATE_BOUND` flag depending on the *bound variables* that +// are present, regardless of whether those bound variables are used. This +// is important for anonymization of binders in `TyCtxt::erase_regions`. We +// specifically detect this case in `visit_binder`. impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { type BreakTy = FoundFlags; + fn visit_binder>>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + // If we're looking for the HAS_BINDER_VARS flag, check if the + // binder has vars. This won't be present in the binder's bound + // value, so we need to check here too. + if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() { + return ControlFlow::Break(FoundFlags); + } + + t.super_visit_with(self) + } + #[inline] fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + // Note: no `super_visit_with` call. let flags = t.flags(); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) @@ -500,6 +517,7 @@ impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { #[inline] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + // Note: no `super_visit_with` call, as usual for `Region`. let flags = r.type_flags(); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) @@ -510,6 +528,7 @@ impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { #[inline] fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + // Note: no `super_visit_with` call. let flags = FlagComputation::for_const(c); trace!(r.flags=?flags); if flags.intersects(self.flags) { @@ -521,6 +540,7 @@ impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { #[inline] fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { + // Note: no `super_visit_with` call. if predicate.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 97402caa0..62f41921d 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -84,7 +84,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( let scalar = match entry { VtblEntry::MetadataDropInPlace => { let instance = ty::Instance::resolve_drop_in_place(tcx, ty); - let fn_alloc_id = tcx.create_fn_alloc(instance); + let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance); let fn_ptr = Pointer::from(fn_alloc_id); Scalar::from_pointer(fn_ptr, &tcx) } @@ -94,7 +94,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( VtblEntry::Method(instance) => { // Prepare the fn ptr we write into the vtable. let instance = instance.polymorphize(tcx); - let fn_alloc_id = tcx.create_fn_alloc(instance); + let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance); let fn_ptr = Pointer::from(fn_alloc_id); Scalar::from_pointer(fn_ptr, &tcx) } @@ -112,5 +112,5 @@ pub(super) fn vtable_allocation_provider<'tcx>( } vtable.mutability = Mutability::Not; - tcx.create_memory_alloc(tcx.mk_const_alloc(vtable)) + tcx.reserve_and_set_memory_alloc(tcx.mk_const_alloc(vtable)) } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 7c3d9ed39..a86ff64bd 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -190,14 +190,11 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) ty::Adt(_, args) | ty::Closure(_, args) | ty::Generator(_, args, _) - | ty::GeneratorWitnessMIR(_, args) + | ty::GeneratorWitness(_, args) | ty::FnDef(_, args) => { stack.extend(args.iter().rev()); } ty::Tuple(ts) => stack.extend(ts.iter().rev().map(GenericArg::from)), - ty::GeneratorWitness(ts) => { - stack.extend(ts.skip_binder().iter().rev().map(|ty| ty.into())); - } ty::FnPtr(sig) => { stack.push(sig.skip_binder().output().into()); stack.extend(sig.skip_binder().inputs().iter().copied().rev().map(|ty| ty.into())); -- cgit v1.2.3