]> git.lizzy.rs Git - rust.git/commitdiff
Create a new method to run coercion inside probe
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Wed, 9 Nov 2016 23:25:45 +0000 (00:25 +0100)
committerGuillaume Gomez <guillaume1.gomez@gmail.com>
Fri, 21 Apr 2017 14:13:26 +0000 (16:13 +0200)
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/demand.rs
src/test/compile-fail/cross-borrow-trait.rs
src/test/compile-fail/dst-bad-coercions.rs
src/test/compile-fail/issue-11374.rs

index c6a1f6cfc0d7fff01b72258e9ce19969dbd4ab55..a769b55c520baa159af2e5330d4f48ea12f93626 100644 (file)
@@ -65,8 +65,8 @@
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::infer::{Coercion, InferResult, InferOk, TypeTrace};
-use rustc::infer::type_variable::TypeVariableOrigin;
-use rustc::traits::{self, ObligationCause, ObligationCauseCode};
+use rustc::infer::type_variable::{TypeVariableOrigin};
+use rustc::traits::{self, /*FulfillmentContext,*/ ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
 use rustc::ty::{self, LvaluePreference, TypeAndMut,
                 Ty, ClosureSubsts};
@@ -78,6 +78,7 @@
 use syntax::abi;
 use syntax::feature_gate;
 use syntax::ptr::P;
+use syntax_pos;
 
 use std::collections::VecDeque;
 use std::ops::Deref;
@@ -722,6 +723,31 @@ pub fn try_coerce(&self,
         Ok(target)
     }
 
+    /// Same as `try_coerce()`, but without side-effects.
+    pub fn can_coerce(&self,
+                      expr_ty: Ty<'tcx>,
+                      target: Ty<'tcx>)
+                      -> bool {
+        // FIXME: This is a hack, but coercion wasn't made to be run
+        // in a probe. It leaks obligations and bounds and things out
+        // into the environment. For now we just save-and-restore the
+        // fulfillment context.
+        /*let saved_fulfillment_cx =
+            mem::replace(
+                &mut *self.inh.fulfillment_cx.borrow_mut(),
+                FulfillmentContext::new());*/
+        let source = self.resolve_type_vars_with_obligations(expr_ty);
+        debug!("coercion::can({:?} -> {:?})", source, target);
+
+        let cause = self.cause(syntax_pos::DUMMY_SP, ObligationCauseCode::ExprAssignable);
+        let coerce = Coerce::new(self, cause);
+        let result = self.probe(|_| coerce.coerce::<hir::Expr>(&[], source, target)).is_ok();
+
+        //*self.inh.fulfillment_cx.borrow_mut() = saved_fulfillment_cx;
+
+        result
+    }
+
     /// Given some expressions, their known unified type and another expression,
     /// tries to unify the types, potentially inserting coercions on any of the
     /// provided expressions and returns their LUB (aka "common supertype").
index 2933f35abfb6a9260eef9fb0cc76dc5e51ab2692..0fd98232becfa03f7722b14628050b6936d19b69 100644 (file)
 
 
 use check::FnCtxt;
-use rustc::ty::Ty;
-use rustc::infer::{InferOk, TypeOrigin};
+use rustc::infer::InferOk;
 use rustc::traits::ObligationCause;
-use rustc::ty;
 
 use syntax::ast;
 use syntax_pos::{self, Span};
 use rustc::hir;
 use rustc::hir::def::Def;
-use rustc::ty::{self, AssociatedItem};
+use rustc::ty::{self, Ty, AssociatedItem};
 use errors::DiagnosticBuilder;
 
 use super::method::probe;
@@ -81,24 +79,24 @@ pub fn demand_coerce(&self,
         if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) {
             let cause = self.misc(expr.span);
             let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
-            let suggestions = if let Some(suggestions) = self.check_ref(expr,
-                                                                        checked_ty,
-                                                                        expected) {
-                suggestions
+            let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
+            if let Some(suggestion) = self.check_ref(expr,
+                                                     checked_ty,
+                                                     expected) {
+                err.help(&suggestion);
             } else {
                 let mode = probe::Mode::MethodCall;
-                self.probe_for_return_type(syntax_pos::DUMMY_SP,
-                                           mode,
-                                           expected,
-                                           checked_ty,
-                                           ast::DUMMY_NODE_ID)
+                let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
+                                                             mode,
+                                                             expected,
+                                                             checked_ty,
+                                                             ast::DUMMY_NODE_ID);
+                if suggestions.len() > 0 {
+                    err.help(&format!("here are some functions which \
+                                       might fulfill your needs:\n - {}",
+                                      self.get_best_match(&suggestions).join("\n")));
+                }
             }
-            let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
-            if suggestions.len() > 0 {
-                err.help(&format!("here are some functions which \
-                                   might fulfill your needs:\n{}",
-                                  self.get_best_match(&suggestions).join("\n")));
-            };
             err.emit();
         }
     }
@@ -188,7 +186,7 @@ fn check_ref(&self,
                                                        self.tcx.mk_region(ty::ReStatic),
                                                        checked_ty),
                 };
-                if self.try_coerce(expr, ref_ty, expected).is_ok() {
+                if self.can_coerce(ref_ty, expected) {
                     if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
                         return Some(format!("try with `{}{}`",
                                             match mutability.mutbl {
index ee67a30fa1c370af731795d653dd0ac913eab1f7..847a82c082651f1a4550cc7bfc34aefa873f2fa3 100644 (file)
@@ -17,9 +17,7 @@ impl Trait for Foo {}
 
 pub fn main() {
     let x: Box<Trait> = Box::new(Foo);
-    let _y: &Trait = x; //~  ERROR mismatched types
+    let _y: &Trait = x; //~ ERROR E0308
                         //~| expected type `&Trait`
                         //~| found type `std::boxed::Box<Trait>`
-                        //~| expected &Trait, found box
-                        //~| ERROR the trait bound `Box<Trait>: Trait` is not satisfied
 }
index ff2e2d619a5ec7017a094a3929743355d8578295..883c16b0895816076c8326de14e232ea9154ca74 100644 (file)
@@ -23,13 +23,11 @@ pub fn main() {
     let x: *const S = &S;
     let y: &S = x; //~ ERROR mismatched types
     let y: &T = x; //~ ERROR mismatched types
-                   //~^ ERROR the trait bound `*const S: T` is not satisfied
 
     // Test that we cannot convert from *-ptr to &S and &T (mut version)
     let x: *mut S = &mut S;
     let y: &S = x; //~ ERROR mismatched types
     let y: &T = x; //~ ERROR mismatched types
-                   //~^ ERROR the trait bound `*mut S: T` is not satisfied
 
     // Test that we cannot convert an immutable ptr to a mutable one using *-ptrs
     let x: &mut T = &S; //~ ERROR mismatched types
index f78786a2889dab5df60ce1d813fef94b1f00b6b8..1e444a6bebf9b23b573465a7090f60b174d52fa3 100644 (file)
@@ -33,5 +33,5 @@ pub fn for_stdin<'a>() -> Container<'a> {
 fn main() {
     let mut c = for_stdin();
     let mut v = Vec::new();
-    c.read_to(v); //~ ERROR mismatched types
+    c.read_to(v); //~ ERROR E0308
 }