|
| 1 | +use rustc_middle::query::Providers; |
| 2 | +use rustc_middle::ty::{self, Ty, TyCtxt}; |
| 3 | + |
| 4 | +pub fn provide(providers: &mut Providers) { |
| 5 | + *providers = Providers { layout_generators, ..*providers }; |
| 6 | +} |
| 7 | + |
| 8 | +/// Computes the generators present in the layout of a type. |
| 9 | +/// This expects a normalized input type with regions erased. |
| 10 | +fn layout_generators<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::List<Ty<'tcx>> { |
| 11 | + let mut generators = Vec::new(); |
| 12 | + |
| 13 | + let inner = |generators: &mut Vec<_>, ty: Ty<'tcx>| { |
| 14 | + let list = tcx.layout_generators(ty); |
| 15 | + for generator in list.iter() { |
| 16 | + generators.push(generator); |
| 17 | + } |
| 18 | + }; |
| 19 | + |
| 20 | + match *ty.kind() { |
| 21 | + // These can't contain generators in their layout |
| 22 | + ty::Bool |
| 23 | + | ty::Char |
| 24 | + | ty::Int(_) |
| 25 | + | ty::Uint(_) |
| 26 | + | ty::Float(_) |
| 27 | + | ty::FnPtr(_) |
| 28 | + | ty::FnDef(..) |
| 29 | + | ty::Never |
| 30 | + | ty::Ref(..) |
| 31 | + | ty::RawPtr(..) |
| 32 | + | ty::Str => {} |
| 33 | + |
| 34 | + ty::Array(element, _) => { |
| 35 | + inner(&mut generators, element); |
| 36 | + } |
| 37 | + |
| 38 | + ty::Generator(..) => { |
| 39 | + generators.push(ty); |
| 40 | + } |
| 41 | + |
| 42 | + ty::Closure(_, ref args) => { |
| 43 | + let tys = args.as_closure().upvar_tys(); |
| 44 | + tys.iter().for_each(|ty| inner(&mut generators, ty)); |
| 45 | + } |
| 46 | + |
| 47 | + ty::Tuple(tys) => { |
| 48 | + tys.iter().for_each(|ty| inner(&mut generators, ty)); |
| 49 | + } |
| 50 | + |
| 51 | + ty::Adt(def, args) => { |
| 52 | + def.variants().iter().for_each(|v| { |
| 53 | + v.fields.iter().for_each(|field| { |
| 54 | + let ty = field.ty(tcx, args); |
| 55 | + let ty = tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty); |
| 56 | + inner(&mut generators, ty) |
| 57 | + }) |
| 58 | + }); |
| 59 | + } |
| 60 | + |
| 61 | + ty::Slice(..) | ty::Dynamic(..) | ty::Foreign(..) => { |
| 62 | + bug!("these are unsized") |
| 63 | + } |
| 64 | + |
| 65 | + ty::Alias(..) |
| 66 | + | ty::Bound(..) |
| 67 | + | ty::GeneratorWitness(..) |
| 68 | + | ty::GeneratorWitnessMIR(..) |
| 69 | + | ty::Infer(_) |
| 70 | + | ty::Error(_) |
| 71 | + | ty::Placeholder(..) |
| 72 | + | ty::Param(_) => { |
| 73 | + bug!("unexpected type") |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + tcx.mk_type_list(&generators) |
| 78 | +} |
0 commit comments