about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-04-15 23:59:25 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-04-15 23:59:25 +0300
commit3725cab5ac1cb6a32b59b7731ce1d6e114c0ae00 (patch)
treea6c1e706621a7acc7b572b1d13c29aa2d390852d
parent516570f2d6b2246cf2ae0269a201bd6a62c91881 (diff)
downloadrust-3725cab5ac1cb6a32b59b7731ce1d6e114c0ae00.tar.gz
rust-3725cab5ac1cb6a32b59b7731ce1d6e114c0ae00.zip
rustc_typeck: return InferOk from lookup_method_in_trait_adjusted.
-rw-r--r--src/librustc_typeck/check/autoderef.rs17
-rw-r--r--src/librustc_typeck/check/callee.rs3
-rw-r--r--src/librustc_typeck/check/method/confirm.rs3
-rw-r--r--src/librustc_typeck/check/method/mod.rs46
-rw-r--r--src/librustc_typeck/check/mod.rs22
-rw-r--r--src/librustc_typeck/check/op.rs17
6 files changed, 67 insertions, 41 deletions
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index bfb69d620ac..92fb02c6379 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -158,11 +158,16 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
                                    -> InferOk<'tcx, ()>
         where E: AsCoercionSite
     {
-        let methods: Vec<_> = self.steps
+        let Autoderef { fcx, span, mut obligations, steps, .. } = self;
+        let methods: Vec<_> = steps
             .iter()
             .map(|&(ty, kind)| {
                 if let AutoderefKind::Overloaded = kind {
-                    self.fcx.try_overloaded_deref(self.span, None, ty, pref)
+                    fcx.try_overloaded_deref(span, None, ty, pref)
+                        .map(|InferOk { value, obligations: o }| {
+                            obligations.extend(o);
+                            value
+                        })
                 } else {
                     None
                 }
@@ -172,7 +177,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
         debug!("finalize({:?}) - {:?},{:?}",
                pref,
                methods,
-               self.obligations);
+               obligations);
 
         for expr in exprs {
             let expr = expr.as_coercion_site();
@@ -180,14 +185,14 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
             for (n, method) in methods.iter().enumerate() {
                 if let &Some(method) = method {
                     let method_call = MethodCall::autoderef(expr.id, n as u32);
-                    self.fcx.tables.borrow_mut().method_map.insert(method_call, method);
+                    fcx.tables.borrow_mut().method_map.insert(method_call, method);
                 }
             }
         }
 
         InferOk {
             value: (),
-            obligations: self.obligations
+            obligations
         }
     }
 }
@@ -209,7 +214,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                 base_expr: Option<&hir::Expr>,
                                 base_ty: Ty<'tcx>,
                                 lvalue_pref: LvaluePreference)
-                                -> Option<MethodCallee<'tcx>> {
+                                -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!("try_overloaded_deref({:?},{:?},{:?},{:?})",
                span,
                base_expr,
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 70e585bd14f..32f130aca1c 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -173,7 +173,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                        adjusted_ty,
                                                        None) {
                 None => continue,
-                Some(method_callee) => {
+                Some(ok) => {
+                    let method_callee = self.register_infer_ok_obligations(ok);
                     return Some(method_callee);
                 }
             }
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index e64ad775d52..26ba965fe5c 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -543,7 +543,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                                                                Some(&base_expr),
                                                                self.node_ty(base_expr.id),
                                                                PreferMutLvalue);
-                        let method = method.expect("re-trying deref failed");
+                        let ok = method.expect("re-trying deref failed");
+                        let method = self.register_infer_ok_obligations(ok);
                         self.tables.borrow_mut().method_map.insert(method_call, method);
                     }
                 }
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 9ecf0ffa71e..7dd2699a6ea 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -17,7 +17,8 @@ use rustc::ty::subst::Substs;
 use rustc::traits;
 use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
-use rustc::infer;
+use rustc::ty::subst::Subst;
+use rustc::infer::{self, InferOk};
 
 use syntax::ast;
 use syntax_pos::Span;
@@ -159,7 +160,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                   trait_def_id: DefId,
                                   self_ty: ty::Ty<'tcx>,
                                   opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
-                                  -> Option<ty::MethodCallee<'tcx>> {
+                                  -> Option<InferOk<'tcx, ty::MethodCallee<'tcx>>> {
         self.lookup_method_in_trait_adjusted(span,
                                              self_expr,
                                              m_name,
@@ -190,7 +191,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                            unsize: bool,
                                            self_ty: ty::Ty<'tcx>,
                                            opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
-                                           -> Option<ty::MethodCallee<'tcx>> {
+                                           -> Option<InferOk<'tcx, ty::MethodCallee<'tcx>>> {
         debug!("lookup_in_trait_adjusted(self_ty={:?}, self_expr={:?}, \
                 m_name={}, trait_def_id={:?})",
                self_ty,
@@ -236,6 +237,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         assert_eq!(generics.regions.len(), 0);
 
         debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
+        let mut obligations = vec![];
 
         // Instantiate late-bound regions and substitute the trait
         // parameters into the method type to get the actual method type.
@@ -248,10 +250,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
                                                                     infer::FnCall,
                                                                     &fn_sig).0;
-        let fn_sig = self.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
+        let fn_sig = fn_sig.subst(self.tcx, substs);
+        let fn_sig = match self.normalize_associated_types_in_as_infer_ok(span, &fn_sig) {
+            InferOk { value, obligations: o } => {
+                obligations.extend(o);
+                value
+            }
+        };
         let transformed_self_ty = fn_sig.inputs()[0];
-        let method_ty = tcx.mk_fn_def(def_id, trait_ref.substs,
-                                     ty::Binder(fn_sig));
+        let method_ty = tcx.mk_fn_def(def_id, substs, ty::Binder(fn_sig));
 
         debug!("lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
                method_ty,
@@ -265,18 +272,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         //
         // Note that as the method comes from a trait, it should not have
         // any late-bound regions appearing in its bounds.
-        let method_bounds = self.instantiate_bounds(span, def_id, trait_ref.substs);
-        assert!(!method_bounds.has_escaping_regions());
-        self.add_obligations_for_parameters(traits::ObligationCause::misc(span, self.body_id),
-                                            &method_bounds);
+        let bounds = self.tcx.item_predicates(def_id).instantiate(self.tcx, substs);
+        let bounds = match self.normalize_associated_types_in_as_infer_ok(span, &bounds) {
+            InferOk { value, obligations: o } => {
+                obligations.extend(o);
+                value
+            }
+        };
+        assert!(!bounds.has_escaping_regions());
 
-        // Also register an obligation for the method type being well-formed.
-        self.register_wf_obligation(method_ty, span, traits::MiscObligation);
+        let cause = traits::ObligationCause::misc(span, self.body_id);
+        obligations.extend(traits::predicates_for_generics(cause.clone(), &bounds));
 
-        // FIXME(#18653) -- Try to resolve obligations, giving us more
-        // typing information, which can sometimes be needed to avoid
-        // pathological region inference failures.
-        self.select_obligations_where_possible();
+        // Also add an obligation for the method type being well-formed.
+        obligations.push(traits::Obligation::new(cause, ty::Predicate::WellFormed(method_ty)));
 
         // Insert any adjustments needed (always an autoref of some mutability).
         if let Some(self_expr) = self_expr {
@@ -317,7 +326,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         debug!("callee = {:?}", callee);
 
-        Some(callee)
+        Some(InferOk {
+            obligations,
+            value: callee
+        })
     }
 
     pub fn resolve_ufcs(&self,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 2e69ad4cc61..8b40cb140ae 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1749,14 +1749,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                           -> ty::InstantiatedPredicates<'tcx> {
         let bounds = self.tcx.item_predicates(def_id);
         let result = bounds.instantiate(self.tcx, substs);
-        let result = self.normalize_associated_types_in(span, &result.predicates);
+        let result = self.normalize_associated_types_in(span, &result);
         debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}",
                bounds,
                substs,
                result);
-        ty::InstantiatedPredicates {
-            predicates: result
-        }
+        result
     }
 
     /// Replace all anonymized types with fresh inference variables
@@ -1799,7 +1797,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
         where T : TypeFoldable<'tcx>
     {
-        self.inh.normalize_associated_types_in(span, self.body_id, value)
+        let ok = self.normalize_associated_types_in_as_infer_ok(span, value);
+        self.register_infer_ok_obligations(ok)
+    }
+
+    fn normalize_associated_types_in_as_infer_ok<T>(&self, span: Span, value: &T)
+                                                    -> InferOk<'tcx, T>
+        where T : TypeFoldable<'tcx>
+    {
+        self.inh.normalize_associated_types_in_as_infer_ok(span, self.body_id, value)
     }
 
     pub fn write_nil(&self, node_id: ast::NodeId) {
@@ -2171,8 +2177,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // If some lookup succeeds, write callee into table and extract index/element
         // type from the method signature.
         // If some lookup succeeded, install method in table
-        method.map(|method| {
+        method.map(|ok| {
             debug!("try_index_step: success, using overloaded indexing");
+            let method = self.register_infer_ok_obligations(ok);
             self.tables.borrow_mut().method_map.insert(method_call, method);
             (input_ty, self.make_overloaded_lvalue_return_type(method).ty)
         })
@@ -3302,8 +3309,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
                         if let Some(mt) = oprnd_t.builtin_deref(true, NoPreference) {
                             oprnd_t = mt.ty;
-                        } else if let Some(method) = self.try_overloaded_deref(
+                        } else if let Some(ok) = self.try_overloaded_deref(
                                 expr.span, Some(&oprnd), oprnd_t, lvalue_pref) {
+                            let method = self.register_infer_ok_obligations(ok);
                             oprnd_t = self.make_overloaded_lvalue_return_type(method).ty;
                             self.tables.borrow_mut().method_map.insert(MethodCall::expr(expr.id),
                                                                            method);
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index cc33bd8754d..5b174aaf895 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -398,20 +398,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         let method = match trait_did {
             Some(trait_did) => {
-                self.lookup_method_in_trait_adjusted(expr.span,
-                                                     Some(lhs_expr),
-                                                     opname,
-                                                     trait_did,
-                                                     0,
-                                                     false,
-                                                     lhs_ty,
-                                                     Some(other_tys))
+                self.lookup_method_in_trait(expr.span,
+                                            Some(lhs_expr),
+                                            opname,
+                                            trait_did,
+                                            lhs_ty,
+                                            Some(other_tys))
             }
             None => None
         };
 
         match method {
-            Some(method) => {
+            Some(ok) => {
+                let method = self.register_infer_ok_obligations(ok);
                 let method_ty = method.ty;
 
                 // HACK(eddyb) Fully qualified path to work around a resolve bug.