]> git.lizzy.rs Git - rust.git/commitdiff
Wrap recursion in `ensure_sufficient_stack`.
authorjumbatm <30644300+jumbatm@users.noreply.github.com>
Mon, 17 Aug 2020 16:00:35 +0000 (02:00 +1000)
committerjumbatm <30644300+jumbatm@users.noreply.github.com>
Mon, 17 Aug 2020 16:01:05 +0000 (02:01 +1000)
src/librustc_lint/builtin.rs

index 2439fc666063455ef6601ccd29ce4ce54db3d70c..147eb8f06c81c451f2213829e5577232eba9e626 100644 (file)
@@ -29,6 +29,7 @@
 use rustc_ast::visit::{FnCtxt, FnKind};
 use rustc_ast_pretty::pprust::{self, expr_to_string};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
 use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType};
 use rustc_feature::{GateIssue, Stability};
@@ -2188,16 +2189,17 @@ fn structurally_same_type_impl<'tcx>(
                     kind.is_primitive() || matches!(kind, RawPtr(..) | Ref(..))
                 };
 
-                match (a_kind, b_kind) {
-                    (Adt(a_def, a_substs), Adt(b_def, b_substs)) => {
-                        let a = a.subst(cx.tcx, a_substs);
-                        let b = b.subst(cx.tcx, b_substs);
-                        debug!("Comparing {:?} and {:?}", a, b);
+                ensure_sufficient_stack(|| {
+                    match (a_kind, b_kind) {
+                        (Adt(a_def, a_substs), Adt(b_def, b_substs)) => {
+                            let a = a.subst(cx.tcx, a_substs);
+                            let b = b.subst(cx.tcx, b_substs);
+                            debug!("Comparing {:?} and {:?}", a, b);
 
-                        // Grab a flattened representation of all fields.
-                        let a_fields = a_def.variants.iter().flat_map(|v| v.fields.iter());
-                        let b_fields = b_def.variants.iter().flat_map(|v| v.fields.iter());
-                        compare_layouts(a, b)
+                            // Grab a flattened representation of all fields.
+                            let a_fields = a_def.variants.iter().flat_map(|v| v.fields.iter());
+                            let b_fields = b_def.variants.iter().flat_map(|v| v.fields.iter());
+                            compare_layouts(a, b)
                             && a_fields.eq_by(
                                 b_fields,
                                 |&ty::FieldDef { did: a_did, .. },
@@ -2211,88 +2213,89 @@ fn structurally_same_type_impl<'tcx>(
                                     )
                                 },
                             )
-                    }
-                    (Array(a_ty, a_const), Array(b_ty, b_const)) => {
-                        // For arrays, we also check the constness of the type.
-                        a_const.val == b_const.val
-                            && structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
-                    }
-                    (Slice(a_ty), Slice(b_ty)) => {
-                        structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
-                    }
-                    (RawPtr(a_tymut), RawPtr(b_tymut)) => {
-                        a_tymut.mutbl == b_tymut.mutbl
-                            && structurally_same_type_impl(
-                                seen_types,
-                                cx,
-                                &a_tymut.ty,
-                                &b_tymut.ty,
-                                ckind,
-                            )
-                    }
-                    (Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => {
-                        // For structural sameness, we don't need the region to be same.
-                        a_mut == b_mut
-                            && structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
-                    }
-                    (FnDef(..), FnDef(..)) => {
-                        let a_poly_sig = a.fn_sig(tcx);
-                        let b_poly_sig = b.fn_sig(tcx);
-
-                        // As we don't compare regions, skip_binder is fine.
-                        let a_sig = a_poly_sig.skip_binder();
-                        let b_sig = b_poly_sig.skip_binder();
-
-                        (a_sig.abi, a_sig.unsafety, a_sig.c_variadic)
-                            == (b_sig.abi, b_sig.unsafety, b_sig.c_variadic)
-                            && a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {
-                                structurally_same_type_impl(seen_types, cx, a, b, ckind)
-                            })
-                            && structurally_same_type_impl(
-                                seen_types,
-                                cx,
-                                a_sig.output(),
-                                b_sig.output(),
-                                ckind,
-                            )
-                    }
-                    (Tuple(a_substs), Tuple(b_substs)) => {
-                        a_substs.types().eq_by(b_substs.types(), |a_ty, b_ty| {
+                        }
+                        (Array(a_ty, a_const), Array(b_ty, b_const)) => {
+                            // For arrays, we also check the constness of the type.
+                            a_const.val == b_const.val
+                                && structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
+                        }
+                        (Slice(a_ty), Slice(b_ty)) => {
                             structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
-                        })
-                    }
-                    // For these, it's not quite as easy to define structural-sameness quite so easily.
-                    // For the purposes of this lint, take the conservative approach and mark them as
-                    // not structurally same.
-                    (Dynamic(..), Dynamic(..))
-                    | (Error(..), Error(..))
-                    | (Closure(..), Closure(..))
-                    | (Generator(..), Generator(..))
-                    | (GeneratorWitness(..), GeneratorWitness(..))
-                    | (Projection(..), Projection(..))
-                    | (Opaque(..), Opaque(..)) => false,
-
-                    // These definitely should have been caught above.
-                    (Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
-
-                    // An Adt and a primitive or pointer type. This can be FFI-safe if non-null
-                    // enum layout optimisation is being applied.
-                    (Adt(..), other_kind) | (other_kind, Adt(..))
-                        if is_primitive_or_pointer(other_kind) =>
-                    {
-                        let (primitive, adt) =
-                            if is_primitive_or_pointer(&a.kind) { (a, b) } else { (b, a) };
-                        if let Some(ty) = crate::types::repr_nullable_ptr(cx, adt, ckind) {
-                            ty == primitive
-                        } else {
-                            compare_layouts(a, b)
                         }
+                        (RawPtr(a_tymut), RawPtr(b_tymut)) => {
+                            a_tymut.mutbl == b_tymut.mutbl
+                                && structurally_same_type_impl(
+                                    seen_types,
+                                    cx,
+                                    &a_tymut.ty,
+                                    &b_tymut.ty,
+                                    ckind,
+                                )
+                        }
+                        (Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => {
+                            // For structural sameness, we don't need the region to be same.
+                            a_mut == b_mut
+                                && structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
+                        }
+                        (FnDef(..), FnDef(..)) => {
+                            let a_poly_sig = a.fn_sig(tcx);
+                            let b_poly_sig = b.fn_sig(tcx);
+
+                            // As we don't compare regions, skip_binder is fine.
+                            let a_sig = a_poly_sig.skip_binder();
+                            let b_sig = b_poly_sig.skip_binder();
+
+                            (a_sig.abi, a_sig.unsafety, a_sig.c_variadic)
+                                == (b_sig.abi, b_sig.unsafety, b_sig.c_variadic)
+                                && a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {
+                                    structurally_same_type_impl(seen_types, cx, a, b, ckind)
+                                })
+                                && structurally_same_type_impl(
+                                    seen_types,
+                                    cx,
+                                    a_sig.output(),
+                                    b_sig.output(),
+                                    ckind,
+                                )
+                        }
+                        (Tuple(a_substs), Tuple(b_substs)) => {
+                            a_substs.types().eq_by(b_substs.types(), |a_ty, b_ty| {
+                                structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
+                            })
+                        }
+                        // For these, it's not quite as easy to define structural-sameness quite so easily.
+                        // For the purposes of this lint, take the conservative approach and mark them as
+                        // not structurally same.
+                        (Dynamic(..), Dynamic(..))
+                        | (Error(..), Error(..))
+                        | (Closure(..), Closure(..))
+                        | (Generator(..), Generator(..))
+                        | (GeneratorWitness(..), GeneratorWitness(..))
+                        | (Projection(..), Projection(..))
+                        | (Opaque(..), Opaque(..)) => false,
+
+                        // These definitely should have been caught above.
+                        (Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
+
+                        // An Adt and a primitive or pointer type. This can be FFI-safe if non-null
+                        // enum layout optimisation is being applied.
+                        (Adt(..), other_kind) | (other_kind, Adt(..))
+                            if is_primitive_or_pointer(other_kind) =>
+                        {
+                            let (primitive, adt) =
+                                if is_primitive_or_pointer(&a.kind) { (a, b) } else { (b, a) };
+                            if let Some(ty) = crate::types::repr_nullable_ptr(cx, adt, ckind) {
+                                ty == primitive
+                            } else {
+                                compare_layouts(a, b)
+                            }
+                        }
+                        // Otherwise, just compare the layouts. This may fail to lint for some
+                        // incompatible types, but at the very least, will stop reads into
+                        // uninitialised memory.
+                        _ => compare_layouts(a, b),
                     }
-                    // Otherwise, just compare the layouts. This may fail to lint for some
-                    // incompatible types, but at the very least, will stop reads into
-                    // uninitialised memory.
-                    _ => compare_layouts(a, b),
-                }
+                })
             }
         }
         let mut seen_types = FxHashSet::default();