Create a new method to run coercion inside probe
This commit is contained in:
parent
8fe3a9a8f1
commit
7d3284ebc1
@ -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").
|
||||
|
@ -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 @@ 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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user