about summary refs log tree commit diff
path: root/src/librustc_mir/borrow_check
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2019-01-17 21:07:27 +0000
committerMatthew Jasper <mjjasper1@gmail.com>2019-01-19 16:30:45 +0000
commitc76e55747b88949634438b6ed2e3f4dd24e799fc (patch)
treef4a7d5ae1604a47344849efa861fd1b0e9f761bb /src/librustc_mir/borrow_check
parent65fe2516346f10dc8d670e9fdfbd4e4f99a5b34b (diff)
downloadrust-c76e55747b88949634438b6ed2e3f4dd24e799fc.tar.gz
rust-c76e55747b88949634438b6ed2e3f4dd24e799fc.zip
Type check unnanotated constant items with NLL
Diffstat (limited to 'src/librustc_mir/borrow_check')
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs111
1 files changed, 49 insertions, 62 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 9ed1d49d05b..3e6aa358ee0 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -35,7 +35,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{Subst, Substs, UnpackedKind};
+use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSubsts};
 use rustc::ty::{
     self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserType,
     CanonicalUserTypeAnnotation, UserTypeAnnotationIndex,
@@ -283,7 +283,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 location.to_locations(),
                 ConstraintCategory::Boring,
             ) {
-                let annotation = self.cx.instantiated_type_annotations[&annotation_index];
+                let annotation = &self.mir.user_type_annotations[annotation_index];
                 span_mirbug!(
                     self,
                     constant,
@@ -293,6 +293,39 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                     terr,
                 );
             }
+        } else {
+            match *constant.literal {
+                ty::LazyConst::Unevaluated(def_id, substs) => {
+                    if let Err(terr) = self.cx.fully_perform_op(
+                        location.to_locations(),
+                        ConstraintCategory::Boring,
+                        self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+                            constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
+                        )),
+                    ) {
+                        span_mirbug!(
+                            self,
+                            constant,
+                            "bad constant type {:?} ({:?})",
+                            constant,
+                            terr
+                        );
+                    }
+                }
+                ty::LazyConst::Evaluated(lit) => {
+                    if let ty::FnDef(def_id, substs) = lit.ty.sty {
+                        let tcx = self.tcx();
+
+                        let instantiated_predicates = tcx
+                            .predicates_of(def_id)
+                            .instantiate(tcx, substs);
+                        self.cx.normalize_and_prove_instantiated_predicates(
+                            instantiated_predicates,
+                            location.to_locations(),
+                        );
+                    }
+                }
+            }
         }
     }
 
@@ -374,8 +407,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         }
     }
 
-    /// Checks that the constant's `ty` field matches up with what
-    /// would be expected from its literal.
+    /// Checks that the constant's `ty` field matches up with what would be
+    /// expected from its literal. Unevaluated constants and well-formed
+    /// constraints are checked by `visit_constant`.
     fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         debug!(
             "sanitize_constant(constant={:?}, location={:?})",
@@ -387,35 +421,6 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
             ty::LazyConst::Unevaluated(..) => return,
         };
 
-        // FIXME(#46702) -- We need some way to get the predicates
-        // associated with the "pre-evaluated" form of the
-        // constant. For example, consider that the constant
-        // may have associated constant projections (`<Foo as
-        // Trait<'a, 'b>>::SOME_CONST`) that impose
-        // constraints on `'a` and `'b`. These constraints
-        // would be lost if we just look at the normalized
-        // value.
-        if let ty::FnDef(def_id, substs) = literal.ty.sty {
-            let tcx = self.tcx();
-            let type_checker = &mut self.cx;
-
-            // FIXME -- For now, use the substitutions from
-            // `value.ty` rather than `value.val`. The
-            // renumberer will rewrite them to independent
-            // sets of regions; in principle, we ought to
-            // derive the type of the `value.val` from "first
-            // principles" and equate with value.ty, but as we
-            // are transitioning to the miri-based system, we
-            // don't have a handy function for that, so for
-            // now we just ignore `value.val` regions.
-
-            let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
-            type_checker.normalize_and_prove_instantiated_predicates(
-                instantiated_predicates,
-                location.to_locations(),
-            );
-        }
-
         debug!("sanitize_constant: expected_ty={:?}", literal.ty);
 
         if let Err(terr) = self.cx.eq_types(
@@ -740,15 +745,6 @@ struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> {
     reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
     borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
     universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>,
-    /// For each user-type annotation (identified by a UserTypeAnnotationIndex), we create
-    /// an "instantiated" version at the beginning of type check, which replaces each
-    /// canonical variable with a fresh inference variable. These instantiated versions are
-    /// stored either in this field or in user_substs, depending on the kind of user-type
-    /// annotation. They are then referenced by the code which has the job of enforcing these
-    /// annotations. Part of the reason for this setup is that it allows us to enforce basic
-    /// WF criteria on the types even if the code that referenced them is dead
-    /// code (see #54943).
-    instantiated_type_annotations: FxHashMap<UserTypeAnnotationIndex, Ty<'tcx>>,
 }
 
 struct BorrowCheckContext<'a, 'tcx: 'a> {
@@ -905,23 +901,19 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             borrowck_context,
             reported_errors: Default::default(),
             universal_region_relations,
-            instantiated_type_annotations: Default::default(),
         };
-        checker.instantiate_user_type_annotations();
+        checker.check_user_type_annotations();
         checker
     }
 
-    /// Instantiate canonical types from user type annotations in the `Mir` into the
-    /// `TypeChecker`. Used when relating user type annotations and when checking if
-    /// annotations are well-formed.
-    fn instantiate_user_type_annotations(&mut self) {
+    /// Equate the inferred type and the annotated type for user type annotations
+    fn check_user_type_annotations(&mut self) {
         debug!(
-            "instantiate_user_type_annotations: user_type_annotations={:?}",
+            "check_user_type_annotations: user_type_annotations={:?}",
              self.mir.user_type_annotations
         );
-        for annotation_index in self.mir.user_type_annotations.indices() {
-            let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } =
-                self.mir.user_type_annotations[annotation_index];
+        for user_annotation in &self.mir.user_type_annotations {
+            let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
             let (annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
                 span, user_ty
             );
@@ -937,7 +929,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     ) {
                         span_mirbug!(
                             self,
-                            self.mir.user_type_annotations[annotation_index],
+                            user_annotation,
                             "bad user type ({:?} = {:?}): {:?}",
                             ty,
                             inferred_ty,
@@ -961,7 +953,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     ) {
                         span_mirbug!(
                             self,
-                            self.mir.user_type_annotations[annotation_index],
+                            user_annotation,
                             "bad user type AscribeUserType({:?}, {:?} {:?}): {:?}",
                             inferred_ty,
                             def_id,
@@ -971,12 +963,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     }
                 },
             }
-            self.instantiated_type_annotations.insert(annotation_index, inferred_ty);
         }
-        debug!(
-            "instantiate_user_type_annotations: instantiated_type_annotations={:?}",
-            self.instantiated_type_annotations,
-        );
     }
 
     /// Given some operation `op` that manipulates types, proves
@@ -1108,7 +1095,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             a, v, user_ty, locations,
         );
 
-        let annotated_type = self.instantiated_type_annotations[&user_ty.base];
+        let annotated_type = self.mir.user_type_annotations[user_ty.base].inferred_ty;
         let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
 
         let tcx = self.infcx.tcx;
@@ -1293,7 +1280,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         location.to_locations(),
                         ConstraintCategory::Boring,
                     ) {
-                        let annotation = self.instantiated_type_annotations[&annotation_index];
+                        let annotation = &mir.user_type_annotations[annotation_index];
                         span_mirbug!(
                             self,
                             stmt,
@@ -1352,7 +1339,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     Locations::All(stmt.source_info.span),
                     ConstraintCategory::TypeAnnotation,
                 ) {
-                    let annotation = self.instantiated_type_annotations[&projection.base];
+                    let annotation = &mir.user_type_annotations[projection.base];
                     span_mirbug!(
                         self,
                         stmt,