diff options
| author | Michael Goulet <michael@errs.io> | 2021-11-30 21:30:05 -0800 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2022-03-31 08:04:53 -0700 |
| commit | de04c05dea10fc03cb626338ce1d55f4c90f58b0 (patch) | |
| tree | 0a5347cfe1642013b5a97ad421b275c18471daf7 /compiler/rustc_ty_utils/src | |
| parent | df20355fa9fa5e9fb89be4e4bfee8a643bb7a23e (diff) | |
Specialize suggestion for Option<T>
Diffstat (limited to 'compiler/rustc_ty_utils/src')
| -rw-r--r-- | compiler/rustc_ty_utils/src/representability.rs | 70 |
1 files changed, 47 insertions, 23 deletions
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index b8f3efe6462..7efc82efd15 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -17,12 +17,20 @@ use std::cmp; pub enum Representability { Representable, ContainsRecursive, - SelfRecursive(Vec<Span>), + /// Return a list of types that are included in themselves: + /// the spans where they are self-included, and (if found) + /// the HirId of the FieldDef that defines the self-inclusion. + SelfRecursive(Vec<(Span, Option<hir::HirId>)>), } /// Check whether a type is representable. This means it cannot contain unboxed /// structural recursion. This check is needed for structs and enums. -pub fn ty_is_representable<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, sp: Span) -> Representability { +pub fn ty_is_representable<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + sp: Span, + field_id: Option<hir::HirId>, +) -> Representability { debug!("is_type_representable: {:?}", ty); // To avoid a stack overflow when checking an enum variant or struct that // contains a different, structurally recursive type, maintain a stack of @@ -38,11 +46,12 @@ pub fn ty_is_representable<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, sp: Span) -> R let mut force_result = false; let r = is_type_structurally_recursive( tcx, - sp, &mut seen, &mut shadow_seen, &mut representable_cache, ty, + sp, + field_id, &mut force_result, ); debug!("is_type_representable: {:?} is {:?}", ty, r); @@ -61,11 +70,12 @@ fn fold_repr<It: Iterator<Item = Representability>>(iter: It) -> Representabilit fn are_inner_types_recursive<'tcx>( tcx: TyCtxt<'tcx>, - sp: Span, seen: &mut Vec<Ty<'tcx>>, shadow_seen: &mut Vec<ty::AdtDef<'tcx>>, representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>, ty: Ty<'tcx>, + sp: Span, + field_id: Option<hir::HirId>, force_result: &mut bool, ) -> Representability { debug!("are_inner_types_recursive({:?}, {:?}, {:?})", ty, seen, shadow_seen); @@ -75,11 +85,12 @@ fn are_inner_types_recursive<'tcx>( fold_repr(fields.iter().map(|ty| { is_type_structurally_recursive( tcx, - sp, seen, shadow_seen, representable_cache, ty, + sp, + field_id, force_result, ) })) @@ -88,20 +99,26 @@ fn are_inner_types_recursive<'tcx>( // FIXME(#11924) Behavior undecided for zero-length vectors. ty::Array(ty, _) => is_type_structurally_recursive( tcx, - sp, seen, shadow_seen, representable_cache, *ty, + sp, + field_id, force_result, ), ty::Adt(def, substs) => { // Find non representable fields with their spans fold_repr(def.all_fields().map(|field| { let ty = field.ty(tcx, substs); - let span = match field.did.as_local().and_then(|id| tcx.hir().find_by_def_id(id)) { - Some(hir::Node::Field(field)) => field.ty.span, - _ => sp, + let (sp, field_id) = match field + .did + .as_local() + .map(|id| tcx.hir().local_def_id_to_hir_id(id)) + .and_then(|id| tcx.hir().find(id)) + { + Some(hir::Node::Field(field)) => (field.ty.span, Some(field.hir_id)), + _ => (sp, field_id), }; let mut result = None; @@ -130,7 +147,7 @@ fn are_inner_types_recursive<'tcx>( // result without adjusting). if shadow_seen.len() > seen.len() && shadow_seen.first() == Some(def) { *force_result = true; - result = Some(Representability::SelfRecursive(vec![span])); + result = Some(Representability::SelfRecursive(vec![(sp, field_id)])); } if result == None { @@ -161,16 +178,17 @@ fn are_inner_types_recursive<'tcx>( result = Some( match is_type_structurally_recursive( tcx, - span, &mut nested_seen, shadow_seen, representable_cache, raw_adt_ty, + sp, + field_id, force_result, ) { Representability::SelfRecursive(_) => { if *force_result { - Representability::SelfRecursive(vec![span]) + Representability::SelfRecursive(vec![(sp, field_id)]) } else { Representability::ContainsRecursive } @@ -208,15 +226,16 @@ fn are_inner_types_recursive<'tcx>( result = Some( match is_type_structurally_recursive( tcx, - span, seen, shadow_seen, representable_cache, ty, + sp, + field_id, force_result, ) { Representability::SelfRecursive(_) => { - Representability::SelfRecursive(vec![span]) + Representability::SelfRecursive(vec![(sp, field_id)]) } x => x, }, @@ -247,29 +266,31 @@ fn same_adt<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool { // contain any types on stack `seen`? fn is_type_structurally_recursive<'tcx>( tcx: TyCtxt<'tcx>, - sp: Span, seen: &mut Vec<Ty<'tcx>>, shadow_seen: &mut Vec<ty::AdtDef<'tcx>>, representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>, ty: Ty<'tcx>, + sp: Span, + field_id: Option<hir::HirId>, force_result: &mut bool, ) -> Representability { - debug!("is_type_structurally_recursive: {:?} {:?}", ty, sp); + debug!("is_type_structurally_recursive: {:?} {:?} {:?}", ty, sp, field_id); if let Some(representability) = representable_cache.get(&ty) { debug!( - "is_type_structurally_recursive: {:?} {:?} - (cached) {:?}", - ty, sp, representability + "is_type_structurally_recursive: {:?} {:?} {:?} - (cached) {:?}", + ty, sp, field_id, representability ); return representability.clone(); } let representability = is_type_structurally_recursive_inner( tcx, - sp, seen, shadow_seen, representable_cache, ty, + sp, + field_id, force_result, ); @@ -279,11 +300,12 @@ fn is_type_structurally_recursive<'tcx>( fn is_type_structurally_recursive_inner<'tcx>( tcx: TyCtxt<'tcx>, - sp: Span, seen: &mut Vec<Ty<'tcx>>, shadow_seen: &mut Vec<ty::AdtDef<'tcx>>, representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>, ty: Ty<'tcx>, + sp: Span, + field_id: Option<hir::HirId>, force_result: &mut bool, ) -> Representability { match ty.kind() { @@ -305,7 +327,7 @@ fn is_type_structurally_recursive_inner<'tcx>( if let Some(&seen_adt) = iter.next() { if same_adt(seen_adt, *def) { debug!("SelfRecursive: {:?} contains {:?}", seen_adt, ty); - return Representability::SelfRecursive(vec![sp]); + return Representability::SelfRecursive(vec![(sp, field_id)]); } } @@ -335,11 +357,12 @@ fn is_type_structurally_recursive_inner<'tcx>( shadow_seen.push(*def); let out = are_inner_types_recursive( tcx, - sp, seen, shadow_seen, representable_cache, ty, + sp, + field_id, force_result, ); shadow_seen.pop(); @@ -350,11 +373,12 @@ fn is_type_structurally_recursive_inner<'tcx>( // No need to push in other cases. are_inner_types_recursive( tcx, - sp, seen, shadow_seen, representable_cache, ty, + sp, + field_id, force_result, ) } |
