|
10 | 10 | use rustc_data_structures::base_n;
|
11 | 11 | use rustc_data_structures::fx::FxHashMap;
|
12 | 12 | use rustc_hir as hir;
|
| 13 | +use rustc_hir::lang_items::LangItem; |
13 | 14 | use rustc_middle::ty::layout::IntegerExt;
|
14 | 15 | use rustc_middle::ty::TypeVisitableExt;
|
15 | 16 | use rustc_middle::ty::{
|
@@ -1165,6 +1166,40 @@ pub fn typeid_for_instance<'tcx>(
|
1165 | 1166 | tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1));
|
1166 | 1167 | instance.args = instance.args.rebase_onto(tcx, impl_id, abstract_trait_args);
|
1167 | 1168 | }
|
| 1169 | + } else if tcx.is_closure_like(instance.def_id()) { |
| 1170 | + // We're either a closure or a coroutine. Our goal is to find the trait we're defined on, |
| 1171 | + // instantiate it, and take the type of its only method as our own. |
| 1172 | + let closure_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); |
| 1173 | + if let Some((trait_id, inputs)) = match closure_ty.kind() { |
| 1174 | + ty::Closure(_def_id, args) => { |
| 1175 | + let closure_args = ty::ClosureArgs { args }; |
| 1176 | + let trait_id = tcx.fn_trait_kind_to_def_id(closure_args.kind()).unwrap(); |
| 1177 | + let tuple_args = |
| 1178 | + tcx.instantiate_bound_regions_with_erased(closure_args.sig()).inputs()[0]; |
| 1179 | + Some((trait_id, tuple_args)) |
| 1180 | + } |
| 1181 | + ty::Coroutine(_def_id, args) => Some(( |
| 1182 | + tcx.require_lang_item(LangItem::Coroutine, None), |
| 1183 | + ty::CoroutineArgs { args }.resume_ty(), |
| 1184 | + )), |
| 1185 | + ty::CoroutineClosure(_def_id, _args) => None, |
| 1186 | + x => bug!("Unexpected type kind for closure-like: {x:?}"), |
| 1187 | + } { |
| 1188 | + let trait_ref = ty::TraitRef::new(tcx, trait_id, [closure_ty, inputs]); |
| 1189 | + let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref)); |
| 1190 | + let abstract_args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1)); |
| 1191 | + // There should be exactly one method on this trait, and it should be the one we're |
| 1192 | + // defining. |
| 1193 | + let call = tcx |
| 1194 | + .associated_items(trait_id) |
| 1195 | + .in_definition_order() |
| 1196 | + .find(|it| it.kind == ty::AssocKind::Fn) |
| 1197 | + .expect("No call-family function on closure-like Fn trait?") |
| 1198 | + .def_id; |
| 1199 | + |
| 1200 | + instance.def = ty::InstanceDef::Virtual(call, 0); |
| 1201 | + instance.args = abstract_args; |
| 1202 | + } |
1168 | 1203 | }
|
1169 | 1204 |
|
1170 | 1205 | let fn_abi = tcx
|
|
0 commit comments