]> git.lizzy.rs Git - rust.git/commitdiff
rustc: provide adt_sized_constraint as an on-demand query.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Sat, 15 Apr 2017 12:40:38 +0000 (15:40 +0300)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Sat, 15 Apr 2017 12:40:38 +0000 (15:40 +0300)
src/librustc/ty/mod.rs
src/librustc_driver/driver.rs

index 3da9383762bc6c682889daef12a5be762b0215cc..09eacb40aef7e28dba37b92563f9c476e2967ded 100644 (file)
@@ -1695,85 +1695,21 @@ pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Destructor> {
     /// Due to normalization being eager, this applies even if
     /// the associated type is behind a pointer, e.g. issue #31299.
     pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
-        self.calculate_sized_constraint_inner(tcx.global_tcx(), &mut Vec::new())
-    }
-
-    /// Calculates the Sized-constraint.
-    ///
-    /// As the Sized-constraint of enums can be a *set* of types,
-    /// the Sized-constraint may need to be a set also. Because introducing
-    /// a new type of IVar is currently a complex affair, the Sized-constraint
-    /// may be a tuple.
-    ///
-    /// In fact, there are only a few options for the constraint:
-    ///     - `bool`, if the type is always Sized
-    ///     - an obviously-unsized type
-    ///     - a type parameter or projection whose Sizedness can't be known
-    ///     - a tuple of type parameters or projections, if there are multiple
-    ///       such.
-    ///     - a TyError, if a type contained itself. The representability
-    ///       check should catch this case.
-    fn calculate_sized_constraint_inner(&self,
-                                        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                        stack: &mut Vec<DefId>)
-                                        -> Ty<'tcx>
-    {
-        if let Some(ty) = tcx.maps.adt_sized_constraint.borrow().get(&self.did) {
-            return ty;
-        }
-
-        // Follow the memoization pattern: push the computation of
-        // DepNode::SizedConstraint as our current task.
-        let _task = tcx.dep_graph.in_task(DepNode::SizedConstraint(self.did));
-
-        if stack.contains(&self.did) {
-            debug!("calculate_sized_constraint: {:?} is recursive", self);
-            // This should be reported as an error by `check_representable`.
-            //
-            // Consider the type as Sized in the meanwhile to avoid
-            // further errors.
-            tcx.maps.adt_sized_constraint.borrow_mut().insert(self.did, tcx.types.err);
-            return tcx.types.err;
-        }
-
-        stack.push(self.did);
-
-        let tys : Vec<_> =
-            self.variants.iter().flat_map(|v| {
-                v.fields.last()
-            }).flat_map(|f| {
-                let ty = tcx.item_type(f.did);
-                self.sized_constraint_for_ty(tcx, stack, ty)
-            }).collect();
-
-        let self_ = stack.pop().unwrap();
-        assert_eq!(self_, self.did);
-
-        let ty = match tys.len() {
-            _ if tys.references_error() => tcx.types.err,
-            0 => tcx.types.bool,
-            1 => tys[0],
-            _ => tcx.intern_tup(&tys[..], false)
-        };
-
-        let old = tcx.maps.adt_sized_constraint.borrow().get(&self.did).cloned();
-        match old {
-            Some(old_ty) => {
-                debug!("calculate_sized_constraint: {:?} recurred", self);
-                assert_eq!(old_ty, tcx.types.err);
-                old_ty
-            }
-            None => {
-                debug!("calculate_sized_constraint: {:?} => {:?}", self, ty);
-                tcx.maps.adt_sized_constraint.borrow_mut().insert(self.did, ty);
-                ty
+        match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) {
+            Ok(ty) => ty,
+            Err(_) => {
+                debug!("adt_sized_constraint: {:?} is recursive", self);
+                // This should be reported as an error by `check_representable`.
+                //
+                // Consider the type as Sized in the meanwhile to avoid
+                // further errors.
+                tcx.types.err
             }
         }
     }
 
     fn sized_constraint_for_ty(&self,
                                tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                               stack: &mut Vec<DefId>,
                                ty: Ty<'tcx>)
                                -> Vec<Ty<'tcx>> {
         let result = match ty.sty {
@@ -1791,23 +1727,23 @@ fn sized_constraint_for_ty(&self,
             TyTuple(ref tys, _) => {
                 match tys.last() {
                     None => vec![],
-                    Some(ty) => self.sized_constraint_for_ty(tcx, stack, ty)
+                    Some(ty) => self.sized_constraint_for_ty(tcx, ty)
                 }
             }
 
             TyAdt(adt, substs) => {
                 // recursive case
                 let adt_ty =
-                    adt.calculate_sized_constraint_inner(tcx, stack)
+                    adt.sized_constraint(tcx)
                        .subst(tcx, substs);
                 debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
                        ty, adt_ty);
                 if let ty::TyTuple(ref tys, _) = adt_ty.sty {
                     tys.iter().flat_map(|ty| {
-                        self.sized_constraint_for_ty(tcx, stack, ty)
+                        self.sized_constraint_for_ty(tcx, ty)
                     }).collect()
                 } else {
-                    self.sized_constraint_for_ty(tcx, stack, adt_ty)
+                    self.sized_constraint_for_ty(tcx, adt_ty)
                 }
             }
 
@@ -2703,9 +2639,56 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     panic!("associated item not found for def_id: {:?}", def_id);
 }
 
+/// Calculates the Sized-constraint.
+///
+/// As the Sized-constraint of enums can be a *set* of types,
+/// the Sized-constraint may need to be a set also. Because introducing
+/// a new type of IVar is currently a complex affair, the Sized-constraint
+/// may be a tuple.
+///
+/// In fact, there are only a few options for the constraint:
+///     - `bool`, if the type is always Sized
+///     - an obviously-unsized type
+///     - a type parameter or projection whose Sizedness can't be known
+///     - a tuple of type parameters or projections, if there are multiple
+///       such.
+///     - a TyError, if a type contained itself. The representability
+///       check should catch this case.
+fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                  def_id: DefId)
+                                  -> Ty<'tcx> {
+    let def = tcx.lookup_adt_def(def_id);
+
+    let tys: Vec<_> = def.variants.iter().flat_map(|v| {
+        v.fields.last()
+    }).flat_map(|f| {
+        let ty = tcx.item_type(f.did);
+        def.sized_constraint_for_ty(tcx, ty)
+    }).collect();
+
+    let ty = match tys.len() {
+        _ if tys.references_error() => tcx.types.err,
+        0 => tcx.types.bool,
+        1 => tys[0],
+        _ => tcx.intern_tup(&tys[..], false)
+    };
+
+    debug!("adt_sized_constraint: {:?} => {:?}", def, ty);
+
+    ty
+}
+
 pub fn provide(providers: &mut ty::maps::Providers) {
     *providers = ty::maps::Providers {
         associated_item,
+        adt_sized_constraint,
+        ..*providers
+    };
+}
+
+pub fn provide_extern(providers: &mut ty::maps::Providers) {
+    *providers = ty::maps::Providers {
+        adt_sized_constraint,
         ..*providers
     };
 }
index 6b136d0fa0cbbd425c198fa421f877c2d11367c0..48d9719e76c4d0faa0924006d8e7fdd1c01280de 100644 (file)
@@ -898,6 +898,7 @@ macro_rules! try_with_f {
 
     let mut extern_providers = ty::maps::Providers::default();
     cstore::provide(&mut extern_providers);
+    ty::provide_extern(&mut extern_providers);
 
     TyCtxt::create_and_enter(sess,
                              local_providers,