]> git.lizzy.rs Git - rust.git/commitdiff
rustc_typeck: use FnCtxt in coercion, instead of mimicking a combiner.
authorEduard Burtescu <edy.burt@gmail.com>
Sat, 17 Jan 2015 20:44:42 +0000 (22:44 +0200)
committerEduard Burtescu <edy.burt@gmail.com>
Thu, 29 Jan 2015 22:27:12 +0000 (00:27 +0200)
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/mod.rs

index e375647bc2839fd6e4264be35b14066434899565..79d57d957abccce0867664abae0dd8872b73369d 100644 (file)
 //! sort of a minor point so I've opted to leave it for later---after all
 //! we may want to adjust precisely when coercions occur.
 
-use middle::infer::{cres, Coercion, InferCtxt, TypeOrigin, TypeTrace};
-use middle::infer::combine::{CombineFields, Combine};
-use middle::infer::sub::Sub;
+use check::FnCtxt;
 
+use middle::infer::{self, cres, Coercion, TypeTrace};
+use middle::infer::combine::Combine;
+use middle::infer::sub::Sub;
 use middle::subst;
 use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe};
 use middle::ty::{mt};
 
 use syntax::ast;
 
-// Note: Coerce is not actually a combiner, in that it does not
-// conform to the same interface, though it performs a similar
-// function.
-pub struct Coerce<'f, 'tcx: 'f>(pub CombineFields<'f, 'tcx>);
+struct Coerce<'a, 'tcx: 'a> {
+    fcx: &'a FnCtxt<'a, 'tcx>,
+    trace: TypeTrace<'tcx>
+}
+
+type CoerceResult<'tcx> = cres<'tcx, Option<ty::AutoAdjustment<'tcx>>>;
 
 impl<'f, 'tcx> Coerce<'f, 'tcx> {
-    pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f, 'tcx> {
-        let Coerce(ref v) = *self; v
+    fn tcx(&self) -> &ty::ctxt<'tcx> {
+        self.fcx.tcx()
     }
 
-    fn tcx(&self) -> &ty::ctxt<'tcx> {
-        self.get_ref().infcx.tcx
+    fn subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
+        let sub = Sub(self.fcx.infcx().combine_fields(false, self.trace.clone()));
+        try!(sub.tys(a, b));
+        Ok(None) // No coercion required.
     }
 
-    pub fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
+    fn unpack_actual_value<T, F>(&self, a: Ty<'tcx>, f: F) -> T where
+        F: FnOnce(Ty<'tcx>) -> T,
+    {
+        f(self.fcx.infcx().shallow_resolve(a))
+    }
+
+    fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
         debug!("Coerce.tys({} => {})",
                a.repr(self.tcx()),
                b.repr(self.tcx()));
@@ -179,25 +190,12 @@ pub fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
         })
     }
 
-    pub fn subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
-        match Sub(self.get_ref().clone()).tys(a, b) {
-            Ok(_) => Ok(None),         // No coercion required.
-            Err(ref e) => Err(*e)
-        }
-    }
-
-    pub fn unpack_actual_value<T, F>(&self, a: Ty<'tcx>, f: F) -> T where
-        F: FnOnce(Ty<'tcx>) -> T,
-    {
-        f(self.get_ref().infcx.shallow_resolve(a))
-    }
-
     // ~T -> &T or &mut T -> &T (including where T = [U] or str)
-    pub fn coerce_borrowed_pointer(&self,
-                                   a: Ty<'tcx>,
-                                   b: Ty<'tcx>,
-                                   mutbl_b: ast::Mutability)
-                                   -> CoerceResult<'tcx> {
+    fn coerce_borrowed_pointer(&self,
+                               a: Ty<'tcx>,
+                               b: Ty<'tcx>,
+                               mutbl_b: ast::Mutability)
+                               -> CoerceResult<'tcx> {
         debug!("coerce_borrowed_pointer(a={}, b={})",
                a.repr(self.tcx()),
                b.repr(self.tcx()));
@@ -208,9 +206,8 @@ pub fn coerce_borrowed_pointer(&self,
         // to type check, we will construct the type that `&M*expr` would
         // yield.
 
-        let sub = Sub(self.get_ref().clone());
-        let coercion = Coercion(self.get_ref().trace.clone());
-        let r_borrow = self.get_ref().infcx.next_region_var(coercion);
+        let coercion = Coercion(self.trace.clone());
+        let r_borrow = self.fcx.infcx().next_region_var(coercion);
 
         let inner_ty = match a.sty {
             ty::ty_uniq(_) => return Err(ty::terr_mismatch),
@@ -220,15 +217,14 @@ pub fn coerce_borrowed_pointer(&self,
                 }
                 mt_a.ty
             }
-            _ => {
-                return self.subtype(a, b);
-            }
+            _ => return self.subtype(a, b)
         };
 
         let a_borrowed = ty::mk_rptr(self.tcx(),
                                      self.tcx().mk_region(r_borrow),
                                      mt {ty: inner_ty, mutbl: mutbl_b});
-        try!(sub.tys(a_borrowed, b));
+        try!(self.subtype(a_borrowed, b));
+        if let Err(original_err) = self.subtype(a_borrowed, b) {
 
         Ok(Some(AdjustDerefRef(AutoDerefRef {
             autoderefs: 1,
@@ -253,8 +249,6 @@ fn coerce_unsized(&self,
         // we can't unify [T] with U. But to properly support DST, we need to allow
         // that, at which point we will need extra checks on b here.
 
-        let sub = Sub(self.get_ref().clone());
-
         match (&a.sty, &b.sty) {
             (&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_rptr(_, mt_b)) => {
                 self.unpack_actual_value(t_a, |a| {
@@ -264,12 +258,12 @@ fn coerce_unsized(&self,
                                 return Err(ty::terr_mutability);
                             }
 
-                            let coercion = Coercion(self.get_ref().trace.clone());
-                            let r_borrow = self.get_ref().infcx.next_region_var(coercion);
+                            let coercion = Coercion(self.trace.clone());
+                            let r_borrow = self.fcx.infcx().next_region_var(coercion);
                             let ty = ty::mk_rptr(self.tcx(),
                                                  self.tcx().mk_region(r_borrow),
                                                  ty::mt{ty: ty, mutbl: mt_b.mutbl});
-                            try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
+                            try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
                             debug!("Success, coerced with AutoDerefRef(1, \
                                     AutoPtr(AutoUnsize({:?})))", kind);
                             Ok(Some(AdjustDerefRef(AutoDerefRef {
@@ -292,7 +286,7 @@ fn coerce_unsized(&self,
 
                             let ty = ty::mk_ptr(self.tcx(),
                                                  ty::mt{ty: ty, mutbl: mt_b.mutbl});
-                            try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
+                            try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
                             debug!("Success, coerced with AutoDerefRef(1, \
                                     AutoPtr(AutoUnsize({:?})))", kind);
                             Ok(Some(AdjustDerefRef(AutoDerefRef {
@@ -310,7 +304,7 @@ fn coerce_unsized(&self,
                     match self.unsize_ty(t_a, a, t_b) {
                         Some((ty, kind)) => {
                             let ty = ty::mk_uniq(self.tcx(), ty);
-                            try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
+                            try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
                             debug!("Success, coerced with AutoDerefRef(1, \
                                     AutoUnsizeUniq({:?}))", kind);
                             Ok(Some(AdjustDerefRef(AutoDerefRef {
@@ -362,12 +356,10 @@ fn unsize_ty(&self,
                     let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
                     assert!(ty_substs_a.len() == ty_substs_b.len());
 
-                    let sub = Sub(self.get_ref().clone());
-
                     let mut result = None;
                     let mut tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
                     for (i, (tp_a, tp_b)) in tps {
-                        if self.get_ref().infcx.try(|_| sub.tys(*tp_a, *tp_b)).is_ok() {
+                        if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
                             continue;
                         }
                         match
@@ -380,7 +372,7 @@ fn unsize_ty(&self,
                                 let mut new_substs = substs_a.clone();
                                 new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
                                 let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
-                                if self.get_ref().infcx.try(|_| sub.tys(ty, ty_b)).is_err() {
+                                if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
                                     debug!("Unsized type parameter '{}', but still \
                                             could not match types {} and {}",
                                            ppaux::ty_to_string(tcx, *tp_a),
@@ -416,8 +408,8 @@ fn coerce_borrowed_object(&self,
                a.repr(tcx),
                b.repr(tcx), b_mutbl);
 
-        let coercion = Coercion(self.get_ref().trace.clone());
-        let r_a = self.get_ref().infcx.next_region_var(coercion);
+        let coercion = Coercion(self.trace.clone());
+        let r_a = self.fcx.infcx().next_region_var(coercion);
 
         self.coerce_object(a, b, b_mutbl,
                            |tr| ty::mk_rptr(tcx, tcx.mk_region(r_a),
@@ -501,11 +493,11 @@ fn coerce_from_fn_item(&self,
         })
     }
 
-    pub fn coerce_unsafe_ptr(&self,
-                             a: Ty<'tcx>,
-                             b: Ty<'tcx>,
-                             mutbl_b: ast::Mutability)
-                             -> CoerceResult<'tcx> {
+    fn coerce_unsafe_ptr(&self,
+                         a: Ty<'tcx>,
+                         b: Ty<'tcx>,
+                         mutbl_b: ast::Mutability)
+                         -> CoerceResult<'tcx> {
         debug!("coerce_unsafe_ptr(a={}, b={})",
                a.repr(self.tcx()),
                b.repr(self.tcx()));
@@ -534,21 +526,25 @@ pub fn coerce_unsafe_ptr(&self,
     }
 }
 
-pub type CoerceResult<'tcx> = cres<'tcx, Option<ty::AutoAdjustment<'tcx>>>;
-
-pub fn mk_coercety<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
-                             a_is_expected: bool,
-                             origin: TypeOrigin,
+pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                             expr: &ast::Expr,
                              a: Ty<'tcx>,
                              b: Ty<'tcx>)
-                             -> CoerceResult<'tcx> {
-    debug!("mk_coercety({} -> {})", a.repr(cx.tcx), b.repr(cx.tcx));
-    indent(|| {
-        cx.commit_if_ok(|| {
-            let trace = TypeTrace::types(origin, a_is_expected, a, b);
-            Coerce(cx.combine_fields(a_is_expected, trace)).tys(a, b)
+                             -> cres<'tcx, ()> {
+    debug!("mk_assignty({} -> {})", a.repr(fcx.tcx()), b.repr(fcx.tcx()));
+    let adjustment = try!(indent(|| {
+        fcx.infcx().commit_if_ok(|| {
+            let origin = infer::ExprAssignable(expr.span);
+            Coerce {
+                fcx: fcx,
+                trace: infer::TypeTrace::types(origin, false, a, b)
+            }.coerce(a, b)
         })
-    })
+    }));
+    if let Some(adjustment) = adjustment {
+        fcx.write_adjustment(expr.id, expr.span, adjustment);
+    }
+    Ok(())
 }
 
 fn can_coerce_mutbls(from_mutbl: ast::Mutability,
index 8188835718cd61456f7db35c5148b43dc8b7fc81..6f2d0cb3667418023cc69a0d954305d84bab85cb 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-use check::FnCtxt;
+use check::{coercion, FnCtxt};
 use middle::ty::{self, Ty};
 use middle::infer;
 
@@ -62,7 +62,7 @@ pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
            expr_ty.repr(fcx.ccx.tcx));
     let expr_ty = fcx.resolve_type_vars_if_possible(expr_ty);
     let expected = fcx.resolve_type_vars_if_possible(expected);
-    match fcx.mk_assignty(expr, expr_ty, expected) {
+    match coercion::mk_assignty(fcx, expr, expr_ty, expected) {
       Ok(()) => { /* ok */ }
       Err(ref err) => {
         fcx.report_mismatched_types(sp, expected, expr_ty, err);
index 799c7a355b786adc44589dcbb417b244a7dc928e..8d1a43cb08194cb589d40ce5946f4ee0ae86258d 100644 (file)
@@ -1726,24 +1726,6 @@ pub fn mk_subty(&self,
         infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
     }
 
-    pub fn mk_assignty(&self,
-                       expr: &ast::Expr,
-                       sub: Ty<'tcx>,
-                       sup: Ty<'tcx>)
-                       -> Result<(), ty::type_err<'tcx>> {
-        match try!(coercion::mk_coercety(self.infcx(),
-                                         false,
-                                         infer::ExprAssignable(expr.span),
-                                         sub,
-                                         sup)) {
-            None => {}
-            Some(adjustment) => {
-                self.write_adjustment(expr.id, expr.span, adjustment);
-            }
-        }
-        Ok(())
-    }
-
     pub fn mk_eqty(&self,
                    a_is_expected: bool,
                    origin: infer::TypeOrigin,