diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2016-11-10 00:25:45 +0100 |
|---|---|---|
| committer | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2017-04-21 16:13:26 +0200 |
| commit | 7d3284ebc18f3d4087d71352421726b2240a7c20 (patch) | |
| tree | bb5a1583238ff48e4421631419831d3cc51ffbb4 | |
| parent | 8fe3a9a8f123fa759d35000bfbfb623167a76409 (diff) | |
| download | rust-7d3284ebc18f3d4087d71352421726b2240a7c20.tar.gz rust-7d3284ebc18f3d4087d71352421726b2240a7c20.zip | |
Create a new method to run coercion inside probe
| -rw-r--r-- | src/librustc_typeck/check/coercion.rs | 30 | ||||
| -rw-r--r-- | src/librustc_typeck/check/demand.rs | 38 | ||||
| -rw-r--r-- | src/test/compile-fail/cross-borrow-trait.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/dst-bad-coercions.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-11374.rs | 2 |
5 files changed, 48 insertions, 28 deletions
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index c6a1f6cfc0d..a769b55c520 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -65,8 +65,8 @@ use check::{Diverges, FnCtxt}; 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 errors::DiagnosticBuilder; 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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"). diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 2933f35abfb..0fd98232bec 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -10,16 +10,14 @@ 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 { diff --git a/src/test/compile-fail/cross-borrow-trait.rs b/src/test/compile-fail/cross-borrow-trait.rs index ee67a30fa1c..847a82c0826 100644 --- a/src/test/compile-fail/cross-borrow-trait.rs +++ b/src/test/compile-fail/cross-borrow-trait.rs @@ -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 } diff --git a/src/test/compile-fail/dst-bad-coercions.rs b/src/test/compile-fail/dst-bad-coercions.rs index ff2e2d619a5..883c16b0895 100644 --- a/src/test/compile-fail/dst-bad-coercions.rs +++ b/src/test/compile-fail/dst-bad-coercions.rs @@ -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 diff --git a/src/test/compile-fail/issue-11374.rs b/src/test/compile-fail/issue-11374.rs index f78786a2889..1e444a6bebf 100644 --- a/src/test/compile-fail/issue-11374.rs +++ b/src/test/compile-fail/issue-11374.rs @@ -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 } |
