]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_ty/needs_drop.rs
Auto merge of #68679 - matthewjasper:needs-type-op, r=varkor
[rust.git] / src / librustc_ty / needs_drop.rs
index 1a65acb1f984b34c4ae3c37dbde76cd0e6137a11..0f71246c73759353a7d8a45bd1f1b6f20355b066 100644 (file)
@@ -12,9 +12,9 @@
 fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
     let adt_fields =
         move |adt_def: &ty::AdtDef| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter().copied());
-    // If we don't know a type doesn't need drop, say it's a type parameter
-    // without a `Copy` bound, then we conservatively return that it needs
-    // drop.
+    // If we don't know a type doesn't need drop, for example if it's a type
+    // parameter without a `Copy` bound, then we conservatively return that it
+    // needs drop.
     let res = NeedsDropTypes::new(tcx, query.param_env, query.value, adt_fields).next().is_some();
     debug!("needs_drop_raw({:?}) = {:?}", query, res);
     res
@@ -25,9 +25,10 @@ struct NeedsDropTypes<'tcx, F> {
     param_env: ty::ParamEnv<'tcx>,
     query_ty: Ty<'tcx>,
     seen_tys: FxHashSet<Ty<'tcx>>,
-    /// A stack of types left to process. Each round, we pop something from the
-    /// stack and check if it needs drop. If the result depends on whether some
-    /// other types need drop we push them onto the stack.
+    /// A stack of types left to process, and the recursion depth when we
+    /// pushed that type. Each round, we pop something from the stack and check
+    /// if it needs drop. If the result depends on whether some other types
+    /// need drop we push them onto the stack.
     unchecked_tys: Vec<(Ty<'tcx>, usize)>,
     recursion_limit: usize,
     adt_components: F,
@@ -76,30 +77,25 @@ fn next(&mut self) -> Option<NeedsDropResult<Ty<'tcx>>> {
                 return Some(Err(AlwaysRequiresDrop));
             }
 
-            let components = match needs_drop_components(ty) {
+            let components = match needs_drop_components(ty, &tcx.data_layout) {
                 Err(e) => return Some(Err(e)),
                 Ok(components) => components,
             };
             debug!("needs_drop_components({:?}) = {:?}", ty, components);
 
+            let queue_type = move |this: &mut Self, component: Ty<'tcx>| {
+                if this.seen_tys.insert(component) {
+                    this.unchecked_tys.push((component, level + 1));
+                }
+            };
+
             for component in components {
                 match component.kind {
                     _ if component.is_copy_modulo_regions(tcx, self.param_env, DUMMY_SP) => (),
 
-                    ty::Array(elem_ty, len) => {
-                        // Zero-length arrays never contain anything to drop.
-                        if len.try_eval_usize(tcx, self.param_env) != Some(0) {
-                            if self.seen_tys.insert(elem_ty) {
-                                self.unchecked_tys.push((elem_ty, level + 1));
-                            }
-                        }
-                    }
-
                     ty::Closure(def_id, substs) => {
                         for upvar_ty in substs.as_closure().upvar_tys(def_id, tcx) {
-                            if self.seen_tys.insert(upvar_ty) {
-                                self.unchecked_tys.push((upvar_ty, level + 1));
-                            }
+                            queue_type(self, upvar_ty);
                         }
                     }
 
@@ -116,21 +112,19 @@ fn next(&mut self) -> Option<NeedsDropResult<Ty<'tcx>>> {
                                 self.param_env,
                                 required_ty.subst(tcx, substs),
                             );
-                            if self.seen_tys.insert(subst_ty) {
-                                self.unchecked_tys.push((subst_ty, level + 1));
-                            }
+                            queue_type(self, subst_ty);
                         }
                     }
-                    ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
+                    ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
                         if ty == component {
-                            // Return the type to the caller so they can decide
-                            // what to do with it.
+                            // Return the type to the caller: they may be able
+                            // to normalize further than we can.
                             return Some(Ok(component));
-                        } else if self.seen_tys.insert(component) {
+                        } else {
                             // Store the type for later. We can't return here
                             // because we would then lose any other components
                             // of the type.
-                            self.unchecked_tys.push((component, level + 1));
+                            queue_type(self, component);
                         }
                     }
                     _ => return Some(Err(AlwaysRequiresDrop)),