11//! Utilities for computing drop info about types.
22
3- use chalk_ir:: cast:: Cast ;
4- use hir_def:: AdtId ;
5- use hir_def:: lang_item:: LangItem ;
6- use hir_def:: signatures:: StructFlags ;
3+ use hir_def:: { AdtId , lang_item:: LangItem , signatures:: StructFlags } ;
4+ use rustc_hash:: FxHashSet ;
5+ use rustc_type_ir:: inherent:: { AdtDef , IntoKind , SliceLike } ;
76use stdx:: never;
87use triomphe:: Arc ;
98
10- use crate :: next_solver:: DbInterner ;
11- use crate :: next_solver:: mapping:: { ChalkToNextSolver , NextSolverToChalk } ;
129use crate :: {
13- AliasTy , Canonical , CanonicalVarKinds , ConcreteConst , ConstScalar , ConstValue , InEnvironment ,
14- Interner , ProjectionTy , TraitEnvironment , Ty , TyBuilder , TyKind , db:: HirDatabase ,
10+ TraitEnvironment , consteval_nextsolver ,
11+ db:: HirDatabase ,
1512 method_resolution:: TyFingerprint ,
13+ next_solver:: {
14+ Ty , TyKind ,
15+ infer:: { InferCtxt , traits:: ObligationCause } ,
16+ obligation_ctxt:: ObligationCtxt ,
17+ } ,
1618} ;
1719
1820fn has_destructor ( db : & dyn HirDatabase , adt : AdtId ) -> bool {
@@ -45,27 +47,52 @@ pub enum DropGlue {
4547 HasDropGlue ,
4648}
4749
48- pub ( crate ) fn has_drop_glue (
49- db : & dyn HirDatabase ,
50- ty : Ty ,
51- env : Arc < TraitEnvironment < ' _ > > ,
50+ pub fn has_drop_glue < ' db > (
51+ infcx : & InferCtxt < ' db > ,
52+ ty : Ty < ' db > ,
53+ env : Arc < TraitEnvironment < ' db > > ,
5254) -> DropGlue {
53- match ty. kind ( Interner ) {
54- TyKind :: Adt ( adt, subst) => {
55- if has_destructor ( db, adt. 0 ) {
55+ has_drop_glue_impl ( infcx, ty, env, & mut FxHashSet :: default ( ) )
56+ }
57+
58+ fn has_drop_glue_impl < ' db > (
59+ infcx : & InferCtxt < ' db > ,
60+ ty : Ty < ' db > ,
61+ env : Arc < TraitEnvironment < ' db > > ,
62+ visited : & mut FxHashSet < Ty < ' db > > ,
63+ ) -> DropGlue {
64+ let mut ocx = ObligationCtxt :: new ( infcx) ;
65+ let ty = ocx. structurally_normalize_ty ( & ObligationCause :: dummy ( ) , env. env , ty) . unwrap_or ( ty) ;
66+
67+ if !visited. insert ( ty) {
68+ // Recursive type.
69+ return DropGlue :: None ;
70+ }
71+
72+ let db = infcx. interner . db ;
73+ match ty. kind ( ) {
74+ TyKind :: Adt ( adt_def, subst) => {
75+ let adt_id = adt_def. def_id ( ) . 0 ;
76+ if has_destructor ( db, adt_id) {
5677 return DropGlue :: HasDropGlue ;
5778 }
58- match adt . 0 {
79+ match adt_id {
5980 AdtId :: StructId ( id) => {
60- if db. struct_signature ( id) . flags . contains ( StructFlags :: IS_MANUALLY_DROP ) {
81+ if db
82+ . struct_signature ( id)
83+ . flags
84+ . intersects ( StructFlags :: IS_MANUALLY_DROP | StructFlags :: IS_PHANTOM_DATA )
85+ {
6186 return DropGlue :: None ;
6287 }
63- db. field_types ( id. into ( ) )
88+ db. field_types_ns ( id. into ( ) )
6489 . iter ( )
6590 . map ( |( _, field_ty) | {
66- db. has_drop_glue (
67- field_ty. clone ( ) . substitute ( Interner , subst) ,
91+ has_drop_glue_impl (
92+ infcx,
93+ field_ty. instantiate ( infcx. interner , subst) ,
6894 env. clone ( ) ,
95+ visited,
6996 )
7097 } )
7198 . max ( )
@@ -78,12 +105,14 @@ pub(crate) fn has_drop_glue(
78105 . variants
79106 . iter ( )
80107 . map ( |& ( variant, _, _) | {
81- db. field_types ( variant. into ( ) )
108+ db. field_types_ns ( variant. into ( ) )
82109 . iter ( )
83110 . map ( |( _, field_ty) | {
84- db. has_drop_glue (
85- field_ty. clone ( ) . substitute ( Interner , subst) ,
111+ has_drop_glue_impl (
112+ infcx,
113+ field_ty. instantiate ( infcx. interner , subst) ,
86114 env. clone ( ) ,
115+ visited,
87116 )
88117 } )
89118 . max ( )
@@ -93,123 +122,70 @@ pub(crate) fn has_drop_glue(
93122 . unwrap_or ( DropGlue :: None ) ,
94123 }
95124 }
96- TyKind :: Tuple ( _, subst) => subst
97- . iter ( Interner )
98- . map ( |ty| ty. assert_ty_ref ( Interner ) )
99- . map ( |ty| db. has_drop_glue ( ty. clone ( ) , env. clone ( ) ) )
125+ TyKind :: Tuple ( tys) => tys
126+ . iter ( )
127+ . map ( |ty| has_drop_glue_impl ( infcx, ty, env. clone ( ) , visited) )
100128 . max ( )
101129 . unwrap_or ( DropGlue :: None ) ,
102130 TyKind :: Array ( ty, len) => {
103- if let ConstValue :: Concrete ( ConcreteConst { interned : ConstScalar :: Bytes ( len, _) } ) =
104- & len. data ( Interner ) . value
105- {
106- match ( & * * len) . try_into ( ) {
107- Ok ( len) => {
108- let len = usize:: from_le_bytes ( len) ;
109- if len == 0 {
110- // Arrays of size 0 don't have drop glue.
111- return DropGlue :: None ;
112- }
113- }
114- Err ( _) => {
115- never ! ( "const array size with non-usize len" ) ;
116- }
117- }
131+ if consteval_nextsolver:: try_const_usize ( db, len) == Some ( 0 ) {
132+ // Arrays of size 0 don't have drop glue.
133+ return DropGlue :: None ;
118134 }
119- db . has_drop_glue ( ty . clone ( ) , env)
135+ has_drop_glue_impl ( infcx , ty , env, visited )
120136 }
121- TyKind :: Slice ( ty) => db . has_drop_glue ( ty . clone ( ) , env) ,
137+ TyKind :: Slice ( ty) => has_drop_glue_impl ( infcx , ty , env, visited ) ,
122138 TyKind :: Closure ( closure_id, subst) => {
123- let closure_id = ( * closure_id) . into ( ) ;
124- let owner = db. lookup_intern_closure ( closure_id) . 0 ;
139+ let owner = db. lookup_intern_closure ( closure_id. 0 ) . 0 ;
125140 let infer = db. infer ( owner) ;
126- let ( captures, _) = infer. closure_info ( closure_id) ;
141+ let ( captures, _) = infer. closure_info ( closure_id. 0 ) ;
127142 let env = db. trait_environment_for_body ( owner) ;
128- let interner = DbInterner :: conjure ( ) ;
129143 captures
130144 . iter ( )
131145 . map ( |capture| {
132- db. has_drop_glue (
133- capture. ty ( db, subst. to_nextsolver ( interner) ) . to_chalk ( interner) ,
134- env. clone ( ) ,
135- )
146+ has_drop_glue_impl ( infcx, capture. ty ( db, subst) , env. clone ( ) , visited)
136147 } )
137148 . max ( )
138149 . unwrap_or ( DropGlue :: None )
139150 }
140151 // FIXME: Handle coroutines.
141- TyKind :: Coroutine ( ..) | TyKind :: CoroutineWitness ( ..) => DropGlue :: None ,
152+ TyKind :: Coroutine ( ..) | TyKind :: CoroutineWitness ( ..) | TyKind :: CoroutineClosure ( ..) => {
153+ DropGlue :: None
154+ }
142155 TyKind :: Ref ( ..)
143- | TyKind :: Raw ( ..)
156+ | TyKind :: RawPtr ( ..)
144157 | TyKind :: FnDef ( ..)
145158 | TyKind :: Str
146159 | TyKind :: Never
147- | TyKind :: Scalar ( _)
148- | TyKind :: Function ( _)
160+ | TyKind :: Bool
161+ | TyKind :: Char
162+ | TyKind :: Int ( _)
163+ | TyKind :: Uint ( _)
164+ | TyKind :: Float ( _)
165+ | TyKind :: FnPtr ( ..)
149166 | TyKind :: Foreign ( _)
150- | TyKind :: Error => DropGlue :: None ,
151- TyKind :: Dyn ( _) => DropGlue :: HasDropGlue ,
152- TyKind :: AssociatedType ( assoc_type_id, subst) => projection_has_drop_glue (
153- db,
154- env,
155- ProjectionTy { associated_ty_id : * assoc_type_id, substitution : subst. clone ( ) } ,
156- ty,
157- ) ,
158- TyKind :: Alias ( AliasTy :: Projection ( projection) ) => {
159- projection_has_drop_glue ( db, env, projection. clone ( ) , ty)
160- }
161- TyKind :: OpaqueType ( ..) | TyKind :: Alias ( AliasTy :: Opaque ( _) ) => {
162- if is_copy ( db, ty, env) {
167+ | TyKind :: Error ( _)
168+ | TyKind :: Bound ( ..)
169+ | TyKind :: Placeholder ( ..) => DropGlue :: None ,
170+ TyKind :: Dynamic ( ..) => DropGlue :: HasDropGlue ,
171+ TyKind :: Alias ( ..) => {
172+ if infcx. type_is_copy_modulo_regions ( env. env , ty) {
163173 DropGlue :: None
164174 } else {
165175 DropGlue :: HasDropGlue
166176 }
167177 }
168- TyKind :: Placeholder ( _ ) | TyKind :: BoundVar ( _) => {
169- if is_copy ( db , ty, env ) {
178+ TyKind :: Param ( _) => {
179+ if infcx . type_is_copy_modulo_regions ( env . env , ty) {
170180 DropGlue :: None
171181 } else {
172182 DropGlue :: DependOnParams
173183 }
174184 }
175- TyKind :: InferenceVar ( ..) => unreachable ! ( "inference vars shouldn't exist out of inference" ) ,
176- }
177- }
178-
179- fn projection_has_drop_glue (
180- db : & dyn HirDatabase ,
181- env : Arc < TraitEnvironment < ' _ > > ,
182- projection : ProjectionTy ,
183- ty : Ty ,
184- ) -> DropGlue {
185- let normalized = db. normalize_projection ( projection, env. clone ( ) ) ;
186- match normalized. kind ( Interner ) {
187- TyKind :: Alias ( AliasTy :: Projection ( _) ) | TyKind :: AssociatedType ( ..) => {
188- if is_copy ( db, ty, env) { DropGlue :: None } else { DropGlue :: DependOnParams }
185+ TyKind :: Infer ( ..) => unreachable ! ( "inference vars shouldn't exist out of inference" ) ,
186+ TyKind :: Pat ( ..) | TyKind :: UnsafeBinder ( ..) => {
187+ never ! ( "we do not handle pattern and unsafe binder types" ) ;
188+ DropGlue :: None
189189 }
190- _ => db. has_drop_glue ( normalized, env) ,
191190 }
192191}
193-
194- fn is_copy ( db : & dyn HirDatabase , ty : Ty , env : Arc < TraitEnvironment < ' _ > > ) -> bool {
195- let Some ( copy_trait) = LangItem :: Copy . resolve_trait ( db, env. krate ) else {
196- return false ;
197- } ;
198- let trait_ref = TyBuilder :: trait_ref ( db, copy_trait) . push ( ty) . build ( ) ;
199- let goal = Canonical {
200- value : InEnvironment :: new (
201- & env. env . to_chalk ( DbInterner :: new_with ( db, Some ( env. krate ) , env. block ) ) ,
202- trait_ref. cast ( Interner ) ,
203- ) ,
204- binders : CanonicalVarKinds :: empty ( Interner ) ,
205- } ;
206- db. trait_solve ( env. krate , env. block , goal) . certain ( )
207- }
208-
209- pub ( crate ) fn has_drop_glue_cycle_result (
210- _db : & dyn HirDatabase ,
211- _ty : Ty ,
212- _env : Arc < TraitEnvironment < ' _ > > ,
213- ) -> DropGlue {
214- DropGlue :: None
215- }
0 commit comments