diff options
Diffstat (limited to 'compiler/rustc_middle/src/ty/util.rs')
-rw-r--r-- | compiler/rustc_middle/src/ty/util.rs | 137 |
1 files changed, 90 insertions, 47 deletions
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 47c1ce807..d0d1dcc58 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1,7 +1,9 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use crate::mir; use crate::ty::layout::IntegerExt; +use crate::ty::query::TyCtxtAt; use crate::ty::{ self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, @@ -15,6 +17,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_index::bit_set::GrowableBitSet; +use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_span::{sym, DUMMY_SP}; use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout}; @@ -257,7 +260,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::Tuple(_) => break, - ty::Projection(_) | ty::Opaque(..) => { + ty::Alias(..) => { let normalized = normalize(ty); if ty == normalized { return ty; @@ -330,8 +333,7 @@ impl<'tcx> TyCtxt<'tcx> { break; } } - (ty::Projection(_) | ty::Opaque(..), _) - | (_, ty::Projection(_) | ty::Opaque(..)) => { + (ty::Alias(..), _) | (_, ty::Alias(..)) => { // If either side is a projection, attempt to // progress via normalization. (Should be safe to // apply to both sides as normalization is @@ -639,24 +641,17 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.type_of(def_id)) } - pub fn bound_trait_impl_trait_tys( + pub fn bound_return_position_impl_trait_in_trait_tys( self, def_id: DefId, ) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> { - ty::EarlyBinder(self.collect_trait_impl_trait_tys(def_id)) + ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id)) } pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> { ty::EarlyBinder(self.fn_sig(def_id)) } - pub fn bound_impl_trait_ref( - self, - def_id: DefId, - ) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> { - self.impl_trait_ref(def_id).map(|i| ty::EarlyBinder(i)) - } - pub fn bound_explicit_item_bounds( self, def_id: DefId, @@ -664,33 +659,88 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.explicit_item_bounds(def_id)) } - pub fn bound_item_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> { - ty::EarlyBinder(self.item_bounds(def_id)) - } - - pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> { - ty::EarlyBinder(self.const_param_default(def_id)) + pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> { + ty::EarlyBinder(self.impl_subject(def_id)) } - pub fn bound_predicates_of( + /// Returns names of captured upvars for closures and generators. + /// + /// Here are some examples: + /// - `name__field1__field2` when the upvar is captured by value. + /// - `_ref__name__field` when the upvar is captured by reference. + /// + /// For generators this only contains upvars that are shared by all states. + pub fn closure_saved_names_of_captured_variables( self, def_id: DefId, - ) -> ty::EarlyBinder<ty::generics::GenericPredicates<'tcx>> { - ty::EarlyBinder(self.predicates_of(def_id)) + ) -> SmallVec<[String; 16]> { + let body = self.optimized_mir(def_id); + + body.var_debug_info + .iter() + .filter_map(|var| { + let is_ref = match var.value { + mir::VarDebugInfoContents::Place(place) + if place.local == mir::Local::new(1) => + { + // The projection is either `[.., Field, Deref]` or `[.., Field]`. It + // implies whether the variable is captured by value or by reference. + matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref) + } + _ => return None, + }; + let prefix = if is_ref { "_ref__" } else { "" }; + Some(prefix.to_owned() + var.name.as_str()) + }) + .collect() } - pub fn bound_explicit_predicates_of( + // FIXME(eddyb) maybe precompute this? Right now it's computed once + // per generator monomorphization, but it doesn't depend on substs. + pub fn generator_layout_and_saved_local_names( self, def_id: DefId, - ) -> ty::EarlyBinder<ty::generics::GenericPredicates<'tcx>> { - ty::EarlyBinder(self.explicit_predicates_of(def_id)) + ) -> ( + &'tcx ty::GeneratorLayout<'tcx>, + IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>, + ) { + let tcx = self; + let body = tcx.optimized_mir(def_id); + let generator_layout = body.generator_layout().unwrap(); + let mut generator_saved_local_names = + IndexVec::from_elem(None, &generator_layout.field_tys); + + let state_arg = mir::Local::new(1); + for var in &body.var_debug_info { + let mir::VarDebugInfoContents::Place(place) = &var.value else { continue }; + if place.local != state_arg { + continue; + } + match place.projection[..] { + [ + // Deref of the `Pin<&mut Self>` state argument. + mir::ProjectionElem::Field(..), + mir::ProjectionElem::Deref, + // Field of a variant of the state. + mir::ProjectionElem::Downcast(_, variant), + mir::ProjectionElem::Field(field, _), + ] => { + let name = &mut generator_saved_local_names + [generator_layout.variant_fields[variant][field]]; + if name.is_none() { + name.replace(var.name); + } + } + _ => {} + } + } + (generator_layout, generator_saved_local_names) } +} - pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> { - ty::EarlyBinder(self.impl_subject(def_id)) +impl<'tcx> TyCtxtAt<'tcx> { + pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> { + ty::EarlyBinder(self.type_of(def_id)) } } @@ -750,7 +800,7 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Opaque(def_id, substs) = *t.kind() { + if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() { self.expand_opaque_ty(def_id, substs).unwrap_or(t) } else if t.has_opaque_types() { t.super_fold_with(self) @@ -862,10 +912,9 @@ impl<'tcx> Ty<'tcx> { | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Infer(_) - | ty::Opaque(..) + | ty::Alias(..) | ty::Param(_) - | ty::Placeholder(_) - | ty::Projection(_) => false, + | ty::Placeholder(_) => false, } } @@ -902,10 +951,9 @@ impl<'tcx> Ty<'tcx> { | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Infer(_) - | ty::Opaque(..) + | ty::Alias(..) | ty::Param(_) - | ty::Placeholder(_) - | ty::Projection(_) => false, + | ty::Placeholder(_) => false, } } @@ -1025,12 +1073,9 @@ impl<'tcx> Ty<'tcx> { // // FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be // called for known, fully-monomorphized types. - ty::Projection(_) - | ty::Opaque(..) - | ty::Param(_) - | ty::Bound(..) - | ty::Placeholder(_) - | ty::Infer(_) => false, + ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => { + false + } ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false, } @@ -1161,18 +1206,17 @@ pub fn needs_drop_components<'tcx>( // These require checking for `Copy` bounds or `Adt` destructors. ty::Adt(..) - | ty::Projection(..) + | ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(..) - | ty::Opaque(..) | ty::Infer(_) | ty::Closure(..) | ty::Generator(..) => Ok(smallvec![ty]), } } -pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { +pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { match *ty.kind() { ty::Bool | ty::Char @@ -1189,13 +1233,12 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { | ty::Never | ty::Foreign(_) => true, - ty::Opaque(..) + ty::Alias(..) | ty::Dynamic(..) | ty::Error(_) | ty::Bound(..) | ty::Param(_) | ty::Placeholder(_) - | ty::Projection(_) | ty::Infer(_) => false, // Not trivial because they have components, and instead of looking inside, |