diff options
| author | Ralf Jung <post@ralfj.de> | 2022-06-28 11:03:50 -0400 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2022-06-28 11:03:50 -0400 |
| commit | 5fc1dd11a93b57d795e352e6c8718d5ffbb74dbb (patch) | |
| tree | d3f4ce6ad86c224062b8a1294a044d04755f138b /compiler | |
| parent | 7f08d04d60d03e1a52dae61ce6aa50996898702b (diff) | |
| download | rust-5fc1dd11a93b57d795e352e6c8718d5ffbb74dbb.tar.gz rust-5fc1dd11a93b57d795e352e6c8718d5ffbb74dbb.zip | |
emit Retag for compound types with reference fields
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_mir_transform/src/add_retag.rs | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 0495439385b..0f87e638d26 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -33,8 +33,9 @@ fn is_stable(place: PlaceRef<'_>) -> bool { }) } -/// Determine whether this type may be a reference (or box), and thus needs retagging. -fn may_be_reference(ty: Ty<'_>) -> bool { +/// Determine whether this type may contain a reference (or box), and thus needs retagging. +/// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this. +fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool { match ty.kind() { // Primitive types that are not references ty::Bool @@ -50,8 +51,20 @@ fn may_be_reference(ty: Ty<'_>) -> bool { // References ty::Ref(..) => true, ty::Adt(..) if ty.is_box() => true, - // Compound types are not references - ty::Array(..) | ty::Slice(..) | ty::Tuple(..) | ty::Adt(..) => false, + // Compound types: recurse + ty::Array(ty, _) | ty::Slice(ty) => { + // This does not branch so we keep the depth the same. + may_contain_reference(*ty, depth, tcx) + } + ty::Tuple(tys) => { + depth == 0 || tys.iter().any(|ty| may_contain_reference(ty, depth - 1, tcx)) + } + ty::Adt(adt, subst) => { + depth == 0 + || adt.variants().iter().any(|v| { + v.fields.iter().any(|f| may_contain_reference(f.ty(tcx, subst), depth - 1, tcx)) + }) + } // Conservative fallback _ => true, } @@ -83,7 +96,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // FIXME: Instead of giving up for unstable places, we should introduce // a temporary and retag on that. is_stable(place.as_ref()) - && may_be_reference(place.ty(&*local_decls, tcx).ty) + && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx) && is_not_temp(&local_decls[place.local]) }; let place_base_raw = |place: &Place<'tcx>| { |
