about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorvarkor <github@varkor.com>2019-03-08 01:15:23 +0000
committervarkor <github@varkor.com>2019-05-01 23:10:05 +0100
commitd7fdeffafce754e0abb2bdac23f01d44ec526eb8 (patch)
tree93694c608e19eddcd7ce9384fcc61c5e01c585f1 /src
parent77447deb2184d618abb26a16fde43d153f85c3b8 (diff)
downloadrust-d7fdeffafce754e0abb2bdac23f01d44ec526eb8.tar.gz
rust-d7fdeffafce754e0abb2bdac23f01d44ec526eb8.zip
Add generic consts to `BottomUpFolder`
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/librustc/infer/opaque_types/mod.rs5
-rw-r--r--src/librustc/ty/fold.rs22
-rw-r--r--src/librustc_typeck/check/wfcheck.rs5
-rw-r--r--src/librustc_typeck/check/writeback.rs42
4 files changed, 60 insertions, 14 deletions
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index b1d00914647..6d855821181 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -676,8 +676,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
         let tcx = self.infcx.tcx;
         value.fold_with(&mut BottomUpFolder {
             tcx,
-            reg_op: |reg| reg,
-            fldop: |ty| {
+            ty_op: |ty| {
                 if let ty::Opaque(def_id, substs) = ty.sty {
                     // Check that this is `impl Trait` type is
                     // declared by `parent_def_id` -- i.e., one whose
@@ -776,6 +775,8 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
 
                 ty
             },
+            lt_op: |lt| lt,
+            ct_op: |ct| ct,
         })
     }
 
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 7f58a436fcf..afd94757b23 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -193,29 +193,37 @@ pub trait TypeVisitor<'tcx> : Sized {
 ///////////////////////////////////////////////////////////////////////////
 // Some sample folders
 
-pub struct BottomUpFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a, F, G>
+pub struct BottomUpFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a, F, G, H>
     where F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
           G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
+          H: FnMut(&'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx>,
 {
     pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    pub fldop: F,
-    pub reg_op: G,
+    pub ty_op: F,
+    pub lt_op: G,
+    pub ct_op: H,
 }
 
-impl<'a, 'gcx, 'tcx, F, G> TypeFolder<'gcx, 'tcx> for BottomUpFolder<'a, 'gcx, 'tcx, F, G>
+impl<'a, 'gcx, 'tcx, F, G, H> TypeFolder<'gcx, 'tcx> for BottomUpFolder<'a, 'gcx, 'tcx, F, G, H>
     where F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
           G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
+          H: FnMut(&'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx>,
 {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        let t1 = ty.super_fold_with(self);
-        (self.fldop)(t1)
+        let t = ty.super_fold_with(self);
+        (self.ty_op)(t)
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         let r = r.super_fold_with(self);
-        (self.reg_op)(r)
+        (self.lt_op)(r)
+    }
+
+    fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+        let c = c.super_fold_with(self);
+        (self.ct_op)(c)
     }
 }
 
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 37be1c3b5b7..8ee30c0d2d3 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -616,7 +616,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
     let mut substituted_predicates = Vec::new();
     ty.fold_with(&mut ty::fold::BottomUpFolder {
         tcx: fcx.tcx,
-        fldop: |ty| {
+        ty_op: |ty| {
             if let ty::Opaque(def_id, substs) = ty.sty {
                 trace!("check_existential_types: opaque_ty, {:?}, {:?}", def_id, substs);
                 let generics = tcx.generics_of(def_id);
@@ -739,7 +739,8 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
             } // if let Opaque
             ty
         },
-        reg_op: |reg| reg,
+        lt_op: |lt| lt,
+        ct_op: |ct| ct,
     });
     substituted_predicates
 }
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 80da3fd9751..d16d69e9233 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -11,7 +11,8 @@ use rustc::infer::InferCtxt;
 use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
 use rustc::ty::subst::UnpackedKind;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, Const, LazyConst};
+use rustc::mir::interpret::ConstValue;
 use rustc::util::nodemap::DefIdSet;
 use rustc_data_structures::sync::Lrc;
 use std::mem;
@@ -488,7 +489,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                 // figures out the concrete type with `U`, but the stored type is with `T`
                 instantiated_ty.fold_with(&mut BottomUpFolder {
                     tcx: self.tcx().global_tcx(),
-                    fldop: |ty| {
+                    ty_op: |ty| {
                         trace!("checking type {:?}", ty);
                         // find a type parameter
                         if let ty::Param(..) = ty.sty {
@@ -520,7 +521,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                         }
                         ty
                     },
-                    reg_op: |region| {
+                    lt_op: |region| {
                         match region {
                             // ignore static regions
                             ty::ReStatic => region,
@@ -564,6 +565,41 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                             }
                         }
                     },
+                    ct_op: |ct| {
+                        trace!("checking const {:?}", ct);
+                        // find a const parameter
+                        if let LazyConst::Evaluated(Const { ty, val }) = ct {
+                            if let ConstValue::Param(..) = val {
+                                // look it up in the substitution list
+                                assert_eq!(opaque_defn.substs.len(), generics.params.len());
+                                for (subst, param) in opaque_defn.substs.iter()
+                                                                        .zip(&generics.params) {
+                                    if let UnpackedKind::Const(subst) = subst.unpack() {
+                                        if subst == ct {
+                                            // found it in the substitution list, replace with the
+                                            // parameter from the existential type
+                                            return self.tcx()
+                                                .global_tcx()
+                                                .mk_const_param(param.index, param.name, ty);
+                                        }
+                                    }
+                                }
+                                self.tcx()
+                                    .sess
+                                    .struct_span_err(
+                                        span,
+                                        &format!(
+                                            "const parameter `{}` is part of concrete type but not \
+                                             used in parameter list for existential type",
+                                            ct,
+                                        ),
+                                    )
+                                    .emit();
+                                return self.tcx().types.ct_err;
+                            }
+                        }
+                        ct
+                    }
                 })
             };