about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2015-04-28 10:06:23 +0200
committerFelix S. Klock II <pnkfelix@pnkfx.org>2015-04-30 14:27:53 +0200
commitdb88e5a498ff8a4c7aa6951095e2d217822b11bf (patch)
tree6d6a2043f42f74569ebeffdceefa1170b65eb61c /src
parentc76d66e9238840d96b1910ba57a839ef7902485c (diff)
downloadrust-db88e5a498ff8a4c7aa6951095e2d217822b11bf.tar.gz
rust-db88e5a498ff8a4c7aa6951095e2d217822b11bf.zip
dropck: Rejectways trait bounds can indirectly access borrowed data.
Namely, we need to catch cases like `trait Child : Parent { }` where
`Parent` itself defines methods.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/check/dropck.rs80
1 files changed, 48 insertions, 32 deletions
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 5391060cb01..8545e73c4f9 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -450,41 +450,57 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
 
             let dtor_typescheme = ty::lookup_item_type(rcx.tcx(), impl_did);
             let dtor_generics = dtor_typescheme.generics;
-            let dtor_predicates = ty::lookup_predicates(rcx.tcx(), impl_did);
-
-            let has_pred_of_interest = dtor_predicates.predicates.iter().any(|pred| {
-                // In `impl<T> Drop where ...`, assume most predicates
-                // represent capability on `T` via which a destructor
-                // could access borrowed data. But some bounds (Sized,
-                // Copy, etc), have no items, i.e. no added capabilty
-                // for such type-specific access.
-
-                let result = match *pred {
-                    ty::Predicate::Trait(ty::Binder(ref t_pred)) => {
-                        let def_id = t_pred.trait_ref.def_id;
-                        // A OIBIT (or even a normal builtin) trait
-                        // defines no associated items, and is
-                        // uninteresting from point of view of dropck.
-                        ty::trait_items(rcx.tcx(), def_id).len() != 0
-                    }
-                    ty::Predicate::Equate(..) |
-                    ty::Predicate::RegionOutlives(..) |
-                    ty::Predicate::TypeOutlives(..) |
-                    ty::Predicate::Projection(..) => {
-                        // for now, assume all other where-clauses may
-                        // give the drop implementation the capabilty
-                        // to access borrowed data.
-                        true
-                    }
-                };
 
-                if result {
-                    debug!("typ: {} has interesting dtor due to generic preds, e.g. {}",
-                           typ.repr(rcx.tcx()), pred.repr(rcx.tcx()));
+            let mut has_pred_of_interest = false;
+
+            let mut seen_items = Vec::new();
+            let mut items_to_inspect = vec![impl_did];
+            'items: while let Some(item_def_id) = items_to_inspect.pop() {
+                if seen_items.contains(&item_def_id) {
+                    continue;
+                }
+
+                for pred in ty::lookup_predicates(rcx.tcx(), item_def_id).predicates {
+                    let result = match pred {
+                        ty::Predicate::Equate(..) |
+                        ty::Predicate::RegionOutlives(..) |
+                        ty::Predicate::TypeOutlives(..) |
+                        ty::Predicate::Projection(..) => {
+                            // For now, assume all these where-clauses
+                            // may give drop implementation capabilty
+                            // to access borrowed data.
+                            true
+                        }
+
+                        ty::Predicate::Trait(ty::Binder(ref t_pred)) => {
+                            let def_id = t_pred.trait_ref.def_id;
+                            if ty::trait_items(rcx.tcx(), def_id).len() != 0 {
+                                // If trait has items, assume it adds
+                                // capability to access borrowed data.
+                                true
+                            } else {
+                                // Trait without items is itself
+                                // uninteresting from POV of dropck.
+                                //
+                                // However, may have parent w/ items;
+                                // so schedule checking of predicates,
+                                items_to_inspect.push(def_id);
+                                // and say "no capability found" for now.
+                                false
+                            }
+                        }
+                    };
+
+                    if result {
+                        has_pred_of_interest = true;
+                        debug!("typ: {} has interesting dtor due to generic preds, e.g. {}",
+                               typ.repr(rcx.tcx()), pred.repr(rcx.tcx()));
+                        break 'items;
+                    }
                 }
 
-                result
-            });
+                seen_items.push(item_def_id);
+            }
 
             // In `impl<'a> Drop ...`, we automatically assume
             // `'a` is meaningful and thus represents a bound