Skip to content

Commit 7d3284e

Browse files
Create a new method to run coercion inside probe
1 parent 8fe3a9a commit 7d3284e

File tree

5 files changed

+48
-28
lines changed

5 files changed

+48
-28
lines changed

src/librustc_typeck/check/coercion.rs

+28-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ use check::{Diverges, FnCtxt};
6565
use rustc::hir;
6666
use rustc::hir::def_id::DefId;
6767
use rustc::infer::{Coercion, InferResult, InferOk, TypeTrace};
68-
use rustc::infer::type_variable::TypeVariableOrigin;
69-
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
68+
use rustc::infer::type_variable::{TypeVariableOrigin};
69+
use rustc::traits::{self, /*FulfillmentContext,*/ ObligationCause, ObligationCauseCode};
7070
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
7171
use rustc::ty::{self, LvaluePreference, TypeAndMut,
7272
Ty, ClosureSubsts};
@@ -78,6 +78,7 @@ use errors::DiagnosticBuilder;
7878
use syntax::abi;
7979
use syntax::feature_gate;
8080
use syntax::ptr::P;
81+
use syntax_pos;
8182

8283
use std::collections::VecDeque;
8384
use std::ops::Deref;
@@ -722,6 +723,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
722723
Ok(target)
723724
}
724725

726+
/// Same as `try_coerce()`, but without side-effects.
727+
pub fn can_coerce(&self,
728+
expr_ty: Ty<'tcx>,
729+
target: Ty<'tcx>)
730+
-> bool {
731+
// FIXME: This is a hack, but coercion wasn't made to be run
732+
// in a probe. It leaks obligations and bounds and things out
733+
// into the environment. For now we just save-and-restore the
734+
// fulfillment context.
735+
/*let saved_fulfillment_cx =
736+
mem::replace(
737+
&mut *self.inh.fulfillment_cx.borrow_mut(),
738+
FulfillmentContext::new());*/
739+
let source = self.resolve_type_vars_with_obligations(expr_ty);
740+
debug!("coercion::can({:?} -> {:?})", source, target);
741+
742+
let cause = self.cause(syntax_pos::DUMMY_SP, ObligationCauseCode::ExprAssignable);
743+
let coerce = Coerce::new(self, cause);
744+
let result = self.probe(|_| coerce.coerce::<hir::Expr>(&[], source, target)).is_ok();
745+
746+
//*self.inh.fulfillment_cx.borrow_mut() = saved_fulfillment_cx;
747+
748+
result
749+
}
750+
725751
/// Given some expressions, their known unified type and another expression,
726752
/// tries to unify the types, potentially inserting coercions on any of the
727753
/// provided expressions and returns their LUB (aka "common supertype").

src/librustc_typeck/check/demand.rs

+18-20
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,14 @@
1010

1111

1212
use check::FnCtxt;
13-
use rustc::ty::Ty;
14-
use rustc::infer::{InferOk, TypeOrigin};
13+
use rustc::infer::InferOk;
1514
use rustc::traits::ObligationCause;
16-
use rustc::ty;
1715

1816
use syntax::ast;
1917
use syntax_pos::{self, Span};
2018
use rustc::hir;
2119
use rustc::hir::def::Def;
22-
use rustc::ty::{self, AssociatedItem};
20+
use rustc::ty::{self, Ty, AssociatedItem};
2321
use errors::DiagnosticBuilder;
2422

2523
use super::method::probe;
@@ -81,24 +79,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
8179
if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) {
8280
let cause = self.misc(expr.span);
8381
let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
84-
let suggestions = if let Some(suggestions) = self.check_ref(expr,
85-
checked_ty,
86-
expected) {
87-
suggestions
82+
let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
83+
if let Some(suggestion) = self.check_ref(expr,
84+
checked_ty,
85+
expected) {
86+
err.help(&suggestion);
8887
} else {
8988
let mode = probe::Mode::MethodCall;
90-
self.probe_for_return_type(syntax_pos::DUMMY_SP,
91-
mode,
92-
expected,
93-
checked_ty,
94-
ast::DUMMY_NODE_ID)
89+
let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
90+
mode,
91+
expected,
92+
checked_ty,
93+
ast::DUMMY_NODE_ID);
94+
if suggestions.len() > 0 {
95+
err.help(&format!("here are some functions which \
96+
might fulfill your needs:\n - {}",
97+
self.get_best_match(&suggestions).join("\n")));
98+
}
9599
}
96-
let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
97-
if suggestions.len() > 0 {
98-
err.help(&format!("here are some functions which \
99-
might fulfill your needs:\n{}",
100-
self.get_best_match(&suggestions).join("\n")));
101-
};
102100
err.emit();
103101
}
104102
}
@@ -188,7 +186,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
188186
self.tcx.mk_region(ty::ReStatic),
189187
checked_ty),
190188
};
191-
if self.try_coerce(expr, ref_ty, expected).is_ok() {
189+
if self.can_coerce(ref_ty, expected) {
192190
if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
193191
return Some(format!("try with `{}{}`",
194192
match mutability.mutbl {

src/test/compile-fail/cross-borrow-trait.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ impl Trait for Foo {}
1717

1818
pub fn main() {
1919
let x: Box<Trait> = Box::new(Foo);
20-
let _y: &Trait = x; //~ ERROR mismatched types
20+
let _y: &Trait = x; //~ ERROR E0308
2121
//~| expected type `&Trait`
2222
//~| found type `std::boxed::Box<Trait>`
23-
//~| expected &Trait, found box
24-
//~| ERROR the trait bound `Box<Trait>: Trait` is not satisfied
2523
}

src/test/compile-fail/dst-bad-coercions.rs

-2
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,11 @@ pub fn main() {
2323
let x: *const S = &S;
2424
let y: &S = x; //~ ERROR mismatched types
2525
let y: &T = x; //~ ERROR mismatched types
26-
//~^ ERROR the trait bound `*const S: T` is not satisfied
2726

2827
// Test that we cannot convert from *-ptr to &S and &T (mut version)
2928
let x: *mut S = &mut S;
3029
let y: &S = x; //~ ERROR mismatched types
3130
let y: &T = x; //~ ERROR mismatched types
32-
//~^ ERROR the trait bound `*mut S: T` is not satisfied
3331

3432
// Test that we cannot convert an immutable ptr to a mutable one using *-ptrs
3533
let x: &mut T = &S; //~ ERROR mismatched types

src/test/compile-fail/issue-11374.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ pub fn for_stdin<'a>() -> Container<'a> {
3333
fn main() {
3434
let mut c = for_stdin();
3535
let mut v = Vec::new();
36-
c.read_to(v); //~ ERROR mismatched types
36+
c.read_to(v); //~ ERROR E0308
3737
}

0 commit comments

Comments
 (0)