about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-01-08 20:16:30 -0500
committerNiko Matsakis <niko@alum.mit.edu>2016-01-08 20:20:02 -0500
commit83710b44716cb078fde8992acc4f28839eefbe51 (patch)
treeb5db47793063bd16387885e3a32de5bc57659078
parenta3cbfa58be12a3ae0c4efd71c3e8c39554924e08 (diff)
downloadrust-83710b44716cb078fde8992acc4f28839eefbe51.tar.gz
rust-83710b44716cb078fde8992acc4f28839eefbe51.zip
permit coercions if `[error]` is found in either type
-rw-r--r--src/librustc_typeck/check/coercion.rs55
-rw-r--r--src/test/compile-fail/issue-19692.rs2
-rw-r--r--src/test/compile-fail/issue-3973.rs2
3 files changed, 29 insertions, 30 deletions
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 85f0aa3bbd3..f91f13f586c 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -68,7 +68,7 @@ use middle::traits::{predicate_for_trait_def, report_selection_error};
 use middle::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
 use middle::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
 use middle::ty::adjustment::{AdjustUnsafeFnPointer};
-use middle::ty::{self, LvaluePreference, TypeAndMut, Ty};
+use middle::ty::{self, LvaluePreference, TypeAndMut, Ty, HasTypeFlags};
 use middle::ty::error::TypeError;
 use middle::ty::relate::RelateResult;
 use util::common::indent;
@@ -110,10 +110,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                a,
                b);
 
+        let a = self.fcx.infcx().shallow_resolve(a);
+
+        // Just ignore error types.
+        if a.references_error() || b.references_error() {
+            return Ok(None);
+        }
+
         // Consider coercing the subtype to a DST
-        let unsize = self.unpack_actual_value(a, |a| {
-            self.coerce_unsized(a, b)
-        });
+        let unsize = self.coerce_unsized(a, b);
         if unsize.is_ok() {
             return unsize;
         }
@@ -124,39 +129,33 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         // See above for details.
         match b.sty {
             ty::TyRawPtr(mt_b) => {
-                return self.unpack_actual_value(a, |a| {
-                    self.coerce_unsafe_ptr(a, b, mt_b.mutbl)
-                });
+                return self.coerce_unsafe_ptr(a, b, mt_b.mutbl);
             }
 
             ty::TyRef(_, mt_b) => {
-                return self.unpack_actual_value(a, |a| {
-                    self.coerce_borrowed_pointer(expr_a, a, b, mt_b.mutbl)
-                });
+                return self.coerce_borrowed_pointer(expr_a, a, b, mt_b.mutbl);
             }
 
             _ => {}
         }
 
-        self.unpack_actual_value(a, |a| {
-            match a.sty {
-                ty::TyBareFn(Some(_), a_f) => {
-                    // Function items are coercible to any closure
-                    // type; function pointers are not (that would
-                    // require double indirection).
-                    self.coerce_from_fn_item(a, a_f, b)
-                }
-                ty::TyBareFn(None, a_f) => {
-                    // We permit coercion of fn pointers to drop the
-                    // unsafe qualifier.
-                    self.coerce_from_fn_pointer(a, a_f, b)
-                }
-                _ => {
-                    // Otherwise, just use subtyping rules.
-                    self.subtype(a, b)
-                }
+        match a.sty {
+            ty::TyBareFn(Some(_), a_f) => {
+                // Function items are coercible to any closure
+                // type; function pointers are not (that would
+                // require double indirection).
+                self.coerce_from_fn_item(a, a_f, b)
             }
-        })
+            ty::TyBareFn(None, a_f) => {
+                // We permit coercion of fn pointers to drop the
+                // unsafe qualifier.
+                self.coerce_from_fn_pointer(a, a_f, b)
+            }
+            _ => {
+                // Otherwise, just use subtyping rules.
+                self.subtype(a, b)
+            }
+        }
     }
 
     /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
diff --git a/src/test/compile-fail/issue-19692.rs b/src/test/compile-fail/issue-19692.rs
index ca1715445e5..53ad2416878 100644
--- a/src/test/compile-fail/issue-19692.rs
+++ b/src/test/compile-fail/issue-19692.rs
@@ -12,7 +12,7 @@ struct Homura;
 
 fn akemi(homura: Homura) {
     let Some(ref madoka) = Some(homura.kaname()); //~ ERROR no method named `kaname` found
-    madoka.clone();
+    madoka.clone(); //~ ERROR the type of this value must be known
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/issue-3973.rs b/src/test/compile-fail/issue-3973.rs
index 92456760b05..54eb2a90829 100644
--- a/src/test/compile-fail/issue-3973.rs
+++ b/src/test/compile-fail/issue-3973.rs
@@ -31,5 +31,5 @@ impl ToString_ for Point {
 fn main() {
     let p = Point::new(0.0, 0.0);
     //~^ ERROR no associated item named `new` found for type `Point` in the current scope
-    println!("{}", p.to_string());
+    println!("{}", p.to_string()); //~ ERROR type of this value must be known
 }