Skip to content

Commit 0eccd5f

Browse files
skip some layers in const drop confirmation
1 parent e3f01b2 commit 0eccd5f

File tree

1 file changed

+91
-70
lines changed

1 file changed

+91
-70
lines changed

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+91-70
Original file line numberDiff line numberDiff line change
@@ -1103,90 +1103,111 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11031103
let tcx = self.tcx();
11041104
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
11051105

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);
11551106
let mut nested = vec![];
1107+
let cause = obligation.derived_cause(BuiltinDerivedObligation);
11561108

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
11581111
if let Some(impl_def_id) = impl_def_id {
11591112
nested.extend(self.confirm_impl_candidate(obligation, impl_def_id).nested);
11601113
}
11611114

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
11711193
.rebind(ty::TraitPredicate {
11721194
trait_ref: ty::TraitRef {
11731195
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, &[]),
11751197
},
11761198
constness: ty::BoundConstness::ConstIfConst,
11771199
polarity: ty::ImplPolarity::Positive,
11781200
})
1179-
.to_predicate(tcx),
1180-
&mut nested,
1181-
)
1182-
});
1201+
.to_predicate(tcx);
11831202

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+
}
11901211
}
11911212

11921213
Ok(ImplSourceConstDropData { nested })

0 commit comments

Comments
 (0)