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};
use syntax::abi;
use syntax::feature_gate;
use syntax::ptr::P;
+use syntax_pos;
use std::collections::VecDeque;
use std::ops::Deref;
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").
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;
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();
}
}
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 {
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
}
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
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
}