]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_mir/borrow_check/nll/type_check/mod.rs
port the relate-types code from NLL type-check into a type-op
[rust.git] / src / librustc_mir / borrow_check / nll / type_check / mod.rs
index 7737fcc765d801133f36a35790953d4c449f50a9..bbbe02fda6a84dd145035e0e6331b5117d3b100a 100644 (file)
@@ -23,7 +23,7 @@
 use borrow_check::nll::type_check::free_region_relations::{
     CreateResult, UniversalRegionRelations,
 };
-use borrow_check::nll::universal_regions::UniversalRegions;
+use borrow_check::nll::universal_regions::{DefiningTy, UniversalRegions};
 use borrow_check::nll::ToRegionVid;
 use dataflow::move_paths::MoveData;
 use dataflow::FlowAtLocation;
@@ -42,7 +42,7 @@
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSelfTy, UserSubsts};
+use rustc::ty::subst::{Subst, Substs, UnpackedKind};
 use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
 use std::rc::Rc;
 use std::{fmt, iter};
@@ -128,7 +128,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
     let mut constraints = MirTypeckRegionConstraints {
         liveness_constraints: LivenessValues::new(elements),
         outlives_constraints: ConstraintSet::default(),
-        closure_bounds_mapping: FxHashMap(),
+        closure_bounds_mapping: Default::default(),
         type_tests: Vec::default(),
     };
     let mut placeholder_indices = PlaceholderIndices::default();
@@ -845,7 +845,7 @@ fn new(
             region_bound_pairs,
             implicit_region_bound,
             borrowck_context,
-            reported_errors: FxHashSet(),
+            reported_errors: Default::default(),
             universal_region_relations,
         }
     }
@@ -975,122 +975,43 @@ fn relate_type_and_user_type(
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
-        let tcx = self.tcx();
-
         debug!(
-            "relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
-            a, v, user_ty, locations
+            "relate_type_and_user_type(a={:?}, v={:?}, user_ty={:?}, locations={:?})",
+            a, v, user_ty, locations,
         );
 
-        // The `TypeRelating` code assumes that "unresolved inference
-        // variables" appear in the "a" side, so flip `Contravariant`
-        // ambient variance to get the right relationship.
-        let v1 = ty::Contravariant.xform(v);
-
         match user_ty {
             UserTypeAnnotation::Ty(canonical_ty) => {
                 let (ty, _) = self.infcx
                     .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty);
 
-                self.relate_types(ty, v1, a, locations, category)?;
+                // The `TypeRelating` code assumes that "unresolved inference
+                // variables" appear in the "a" side, so flip `Contravariant`
+                // ambient variance to get the right relationship.
+                let v1 = ty::Contravariant.xform(v);
 
-                self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
+                self.relate_types(ty, v1, a, locations, category)?;
             }
             UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
                 let (
-                    UserSubsts {
-                        substs,
-                        user_self_ty,
-                    },
+                    user_substs,
                     _,
                 ) = self.infcx
                     .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
 
-                let ty = self.tcx().type_of(def_id);
-                let ty = ty.subst(tcx, substs);
-                let ty = self.normalize(ty, locations);
-
-                self.relate_types(ty, v1, a, locations, category)?;
-
-                if let Some(UserSelfTy {
-                    impl_def_id,
-                    self_ty,
-                }) = user_self_ty
-                {
-                    let impl_self_ty = tcx.type_of(impl_def_id);
-                    let impl_self_ty = impl_self_ty.subst(tcx, &substs);
-                    let impl_self_ty = self.normalize(impl_self_ty, locations);
-
-                    // There may be type variables in `substs` and hence
-                    // in `impl_self_ty`, but they should all have been
-                    // resolved to some fixed value during the first call
-                    // to `relate`, above. Therefore, if we use
-                    // `resolve_type_vars_if_possible` we should get to
-                    // something without type variables. This is important
-                    // because the `b` type in `relate_with_variance`
-                    // below is not permitted to have inference variables.
-                    let impl_self_ty = self.infcx.resolve_type_vars_if_possible(&impl_self_ty);
-                    assert!(!impl_self_ty.has_infer_types());
-
-                    self.eq_types(self_ty, impl_self_ty, locations, category)?;
-                }
-
-                // Prove the predicates coming along with `def_id`.
-                //
-                // Also, normalize the `instantiated_predicates`
-                // because otherwise we wind up with duplicate "type
-                // outlives" error messages.
-                let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
-                let instantiated_predicates = self.fold_to_region_vid(instantiated_predicates);
-                self.normalize_and_prove_instantiated_predicates(
-                    instantiated_predicates,
+                self.fully_perform_op(
                     locations,
-                );
-
-                // In addition to proving the predicates, we have to
-                // prove that `ty` is well-formed -- this is because
-                // the WF of `ty` is predicated on the substs being
-                // well-formed, and we haven't proven *that*. We don't
-                // want to prove the WF of types from  `substs` directly because they
-                // haven't been normalized.
-                //
-                // FIXME(nmatsakis): Well, perhaps we should normalize
-                // them?  This would only be relevant if some input
-                // type were ill-formed but did not appear in `ty`,
-                // which...could happen with normalization...
-                self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
+                    category,
+                    self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+                        a, v, def_id, user_substs,
+                    )),
+                )?;
             }
         }
 
         Ok(())
     }
 
-    /// Replace all free regions in `value` with their NLL `RegionVid`
-    /// equivalents; if not in NLL, does nothing. This is never
-    /// particularly necessary -- we'll do it lazilly as we process
-    /// the value anyway -- but in some specific cases it is useful to
-    /// normalize so we can suppress duplicate error messages.
-    fn fold_to_region_vid<T>(
-        &self,
-        value: T
-    ) -> T
-    where T: TypeFoldable<'tcx>
-    {
-        if let Some(borrowck_context) = &self.borrowck_context {
-            self.tcx().fold_regions(&value, &mut false, |r, _debruijn| {
-                if r.has_free_regions() {
-                    self.tcx().mk_region(ty::RegionKind::ReVar(
-                        borrowck_context.universal_regions.to_region_vid(r),
-                    ))
-                } else {
-                    r
-                }
-            })
-        } else {
-            value
-        }
-    }
-
     fn eq_opaque_type_and_type(
         &mut self,
         revealed_ty: Ty<'tcx>,
@@ -1209,7 +1130,23 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
                 // of lowering. Assignments to other sorts of places *are* interesting
                 // though.
                 let category = match *place {
-                    Place::Local(RETURN_PLACE) => ConstraintCategory::Return,
+                    Place::Local(RETURN_PLACE) => if let Some(BorrowCheckContext {
+                        universal_regions:
+                            UniversalRegions {
+                                defining_ty: DefiningTy::Const(def_id, _),
+                                ..
+                            },
+                        ..
+                    }) = self.borrowck_context
+                    {
+                        if tcx.is_static(*def_id).is_some() {
+                            ConstraintCategory::UseAsStatic
+                        } else {
+                            ConstraintCategory::UseAsConst
+                        }
+                    } else {
+                        ConstraintCategory::Return
+                    },
                     Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
                         ConstraintCategory::Boring
                     }
@@ -1391,6 +1328,7 @@ fn check_terminator(
                 ref func,
                 ref args,
                 ref destination,
+                from_hir_call,
                 ..
             } => {
                 let func_ty = func.ty(mir, tcx);
@@ -1435,7 +1373,7 @@ fn check_terminator(
                     }
                 }
 
-                self.check_call_inputs(mir, term, &sig, args, term_location);
+                self.check_call_inputs(mir, term, &sig, args, term_location, from_hir_call);
             }
             TerminatorKind::Assert {
                 ref cond, ref msg, ..
@@ -1493,7 +1431,25 @@ fn check_call_dest(
             Some((ref dest, _target_block)) => {
                 let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
                 let category = match *dest {
-                    Place::Local(RETURN_PLACE) => ConstraintCategory::Return,
+                    Place::Local(RETURN_PLACE) => {
+                        if let Some(BorrowCheckContext {
+                            universal_regions:
+                                UniversalRegions {
+                                    defining_ty: DefiningTy::Const(def_id, _),
+                                    ..
+                                },
+                            ..
+                        }) = self.borrowck_context
+                        {
+                            if tcx.is_static(*def_id).is_some() {
+                                ConstraintCategory::UseAsStatic
+                            } else {
+                                ConstraintCategory::UseAsConst
+                            }
+                        } else {
+                            ConstraintCategory::Return
+                        }
+                    }
                     Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
                         ConstraintCategory::Boring
                     }
@@ -1538,6 +1494,7 @@ fn check_call_inputs(
         sig: &ty::FnSig<'tcx>,
         args: &[Operand<'tcx>],
         term_location: Location,
+        from_hir_call: bool,
     ) {
         debug!("check_call_inputs({:?}, {:?})", sig, args);
         if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.variadic) {
@@ -1545,12 +1502,14 @@ fn check_call_inputs(
         }
         for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() {
             let op_arg_ty = op_arg.ty(mir, self.tcx());
-            if let Err(terr) = self.sub_types(
-                op_arg_ty,
-                fn_arg,
-                term_location.to_locations(),
-                ConstraintCategory::CallArgument,
-            ) {
+            let category = if from_hir_call {
+                ConstraintCategory::CallArgument
+            } else {
+                ConstraintCategory::Boring
+            };
+            if let Err(terr) =
+                self.sub_types(op_arg_ty, fn_arg, term_location.to_locations(), category)
+            {
                 span_mirbug!(
                     self,
                     term,