@@ -1103,90 +1103,111 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1103
1103
let tcx = self . tcx ( ) ;
1104
1104
let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
1105
1105
1106
- // Skip binder here (*)
1107
- let nested_tys = match * self_ty. skip_binder ( ) . kind ( ) {
1108
- ty:: Bool
1109
- | ty:: Char
1110
- | ty:: Int ( _)
1111
- | ty:: Uint ( _)
1112
- | ty:: Float ( _)
1113
- | ty:: Infer ( ty:: IntVar ( _) )
1114
- | ty:: Infer ( ty:: FloatVar ( _) )
1115
- | ty:: Str
1116
- | ty:: RawPtr ( _)
1117
- | ty:: Ref ( ..)
1118
- | ty:: FnDef ( ..)
1119
- | ty:: FnPtr ( _)
1120
- | ty:: Never => vec ! [ ] ,
1121
-
1122
- ty:: Adt ( def, substs) => def. all_fields ( ) . map ( |f| f. ty ( tcx, substs) ) . collect ( ) ,
1123
-
1124
- ty:: Array ( ty, _) | ty:: Slice ( ty) => vec ! [ ty] ,
1125
-
1126
- ty:: Tuple ( tys) => tys. iter ( ) . map ( |ty| ty. expect_ty ( ) ) . collect ( ) ,
1127
-
1128
- ty:: Closure ( _, substs) => vec ! [ substs. as_closure( ) . tupled_upvars_ty( ) ] ,
1129
-
1130
- ty:: Generator ( _, substs, _) => {
1131
- vec ! [ substs. as_generator( ) . tupled_upvars_ty( ) , substs. as_generator( ) . witness( ) ]
1132
- }
1133
-
1134
- ty:: GeneratorWitness ( tys) => tcx. erase_late_bound_regions ( tys) . to_vec ( ) ,
1135
-
1136
- ty:: Opaque ( _, _)
1137
- | ty:: Dynamic ( _, _)
1138
- | ty:: Error ( _)
1139
- | ty:: Bound ( _, _)
1140
- | ty:: Param ( _)
1141
- | ty:: Placeholder ( _)
1142
- | ty:: Foreign ( _)
1143
- | ty:: Projection ( _)
1144
- | ty:: Infer ( _) => {
1145
- unreachable ! ( ) ;
1146
- }
1147
- } ;
1148
-
1149
- info ! (
1150
- "confirm_const_drop_candidate: self_ty={:?}, nested_tys={:?} impl_def_id={:?}" ,
1151
- self_ty, nested_tys, impl_def_id
1152
- ) ;
1153
-
1154
- let cause = obligation. derived_cause ( BuiltinDerivedObligation ) ;
1155
1106
let mut nested = vec ! [ ] ;
1107
+ let cause = obligation. derived_cause ( BuiltinDerivedObligation ) ;
1156
1108
1157
- // If we have a custom `impl const Drop`, then check it like a regular impl candidate.
1109
+ // If we have a custom `impl const Drop`, then
1110
+ // first check it like a regular impl candidate
1158
1111
if let Some ( impl_def_id) = impl_def_id {
1159
1112
nested. extend ( self . confirm_impl_candidate ( obligation, impl_def_id) . nested ) ;
1160
1113
}
1161
1114
1162
- for ty in nested_tys {
1163
- let predicate = self . infcx . commit_unconditionally ( |_| {
1164
- normalize_with_depth_to (
1165
- self ,
1166
- obligation. param_env ,
1167
- cause. clone ( ) ,
1168
- obligation. recursion_depth + 1 ,
1169
- // Rebinding here (*)
1170
- self_ty
1115
+ // We want to confirm the ADT's fields if we have an ADT
1116
+ let mut stack = match * self_ty. skip_binder ( ) . kind ( ) {
1117
+ ty:: Adt ( def, substs) => def. all_fields ( ) . map ( |f| f. ty ( tcx, substs) ) . collect ( ) ,
1118
+ _ => vec ! [ self_ty. skip_binder( ) ] ,
1119
+ } ;
1120
+
1121
+ while let Some ( nested_ty) = stack. pop ( ) {
1122
+ match * nested_ty. kind ( ) {
1123
+ // We know these types are trivially drop
1124
+ ty:: Bool
1125
+ | ty:: Char
1126
+ | ty:: Int ( _)
1127
+ | ty:: Uint ( _)
1128
+ | ty:: Float ( _)
1129
+ | ty:: Infer ( ty:: IntVar ( _) )
1130
+ | ty:: Infer ( ty:: FloatVar ( _) )
1131
+ | ty:: Str
1132
+ | ty:: RawPtr ( _)
1133
+ | ty:: Ref ( ..)
1134
+ | ty:: FnDef ( ..)
1135
+ | ty:: FnPtr ( _)
1136
+ | ty:: Never => { }
1137
+
1138
+ // These types are built-in, so we can fast-track by registering
1139
+ // nested predicates for their constituient type(s)
1140
+ ty:: Array ( ty, _) | ty:: Slice ( ty) => {
1141
+ stack. push ( ty) ;
1142
+ }
1143
+ ty:: Tuple ( tys) => {
1144
+ stack. extend ( tys. iter ( ) . map ( |ty| ty. expect_ty ( ) ) ) ;
1145
+ }
1146
+ ty:: Closure ( _, substs) => {
1147
+ stack. push ( substs. as_closure ( ) . tupled_upvars_ty ( ) ) ;
1148
+ }
1149
+ ty:: Generator ( _, substs, _) => {
1150
+ let generator = substs. as_generator ( ) ;
1151
+ stack. extend ( [ generator. tupled_upvars_ty ( ) , generator. witness ( ) ] ) ;
1152
+ }
1153
+ ty:: GeneratorWitness ( tys) => {
1154
+ stack. extend ( tcx. erase_late_bound_regions ( tys) . to_vec ( ) ) ;
1155
+ }
1156
+
1157
+ // If we have a projection type, make sure to normalize it so we replace it
1158
+ // with a fresh infer variable
1159
+ ty:: Projection ( ..) => {
1160
+ self . infcx . commit_unconditionally ( |_| {
1161
+ let predicate = normalize_with_depth_to (
1162
+ self ,
1163
+ obligation. param_env ,
1164
+ cause. clone ( ) ,
1165
+ obligation. recursion_depth + 1 ,
1166
+ self_ty
1167
+ . rebind ( ty:: TraitPredicate {
1168
+ trait_ref : ty:: TraitRef {
1169
+ def_id : self . tcx ( ) . require_lang_item ( LangItem :: Drop , None ) ,
1170
+ substs : self . tcx ( ) . mk_substs_trait ( nested_ty, & [ ] ) ,
1171
+ } ,
1172
+ constness : ty:: BoundConstness :: ConstIfConst ,
1173
+ polarity : ty:: ImplPolarity :: Positive ,
1174
+ } )
1175
+ . to_predicate ( tcx) ,
1176
+ & mut nested,
1177
+ ) ;
1178
+
1179
+ nested. push ( Obligation :: with_depth (
1180
+ cause. clone ( ) ,
1181
+ obligation. recursion_depth + 1 ,
1182
+ obligation. param_env ,
1183
+ predicate,
1184
+ ) ) ;
1185
+ } ) ;
1186
+ }
1187
+
1188
+ // If we have any other type (e.g. an ADT), just register a nested obligation
1189
+ // since it's either not `const Drop` (and we raise an error during selection),
1190
+ // or it's an ADT (and we need to check for a custom impl during selection)
1191
+ _ => {
1192
+ let predicate = self_ty
1171
1193
. rebind ( ty:: TraitPredicate {
1172
1194
trait_ref : ty:: TraitRef {
1173
1195
def_id : self . tcx ( ) . require_lang_item ( LangItem :: Drop , None ) ,
1174
- substs : self . tcx ( ) . mk_substs_trait ( ty , & [ ] ) ,
1196
+ substs : self . tcx ( ) . mk_substs_trait ( nested_ty , & [ ] ) ,
1175
1197
} ,
1176
1198
constness : ty:: BoundConstness :: ConstIfConst ,
1177
1199
polarity : ty:: ImplPolarity :: Positive ,
1178
1200
} )
1179
- . to_predicate ( tcx) ,
1180
- & mut nested,
1181
- )
1182
- } ) ;
1201
+ . to_predicate ( tcx) ;
1183
1202
1184
- nested. push ( Obligation :: with_depth (
1185
- cause. clone ( ) ,
1186
- obligation. recursion_depth + 1 ,
1187
- obligation. param_env ,
1188
- predicate,
1189
- ) ) ;
1203
+ nested. push ( Obligation :: with_depth (
1204
+ cause. clone ( ) ,
1205
+ obligation. recursion_depth + 1 ,
1206
+ obligation. param_env ,
1207
+ predicate,
1208
+ ) ) ;
1209
+ }
1210
+ }
1190
1211
}
1191
1212
1192
1213
Ok ( ImplSourceConstDropData { nested } )
0 commit comments