提交 498595a3 编写于 作者: N Niko Matsakis

Teach project to unify the return type even if a precise match is not

possible.  There is some amount of duplication as a result (similar to
select) -- I am not happy about this but not sure how to fix it
without deeper rewrites.
上级 c9e1c445
......@@ -80,37 +80,23 @@ pub fn poly_project_and_unify_type<'cx,'tcx>(
obligation.repr(selcx.tcx()));
let infcx = selcx.infcx();
let result = infcx.try(|snapshot| {
infcx.try(|snapshot| {
let (skol_predicate, skol_map) =
infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot);
let skol_obligation = obligation.with(skol_predicate);
match project_and_unify_type(selcx, &skol_obligation) {
Ok(Some(obligations)) => {
Ok(result) => {
match infcx.leak_check(&skol_map, snapshot) {
Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, &obligations)),
Err(e) => Err(Some(MismatchedProjectionTypes { err: e })),
Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, &result)),
Err(e) => Err(MismatchedProjectionTypes { err: e }),
}
}
Ok(None) => {
// Signal ambiguity using Err just so that infcx.try()
// rolls back the snapshot. We adapt below.
Err(None)
}
Err(e) => {
Err(Some(e))
Err(e)
}
}
});
// Above, we use Err(None) to signal ambiguity so that the
// snapshot will be rolled back. But here, we want to translate to
// Ok(None). Kind of weird.
match result {
Ok(obligations) => Ok(Some(obligations)),
Err(None) => Ok(None),
Err(Some(e)) => Err(e),
}
})
}
/// Evaluates constraints of the form:
......@@ -132,7 +118,10 @@ fn project_and_unify_type<'cx,'tcx>(
obligation.cause.clone(),
obligation.recursion_depth) {
Some(n) => n,
None => { return Ok(None); }
None => {
consider_unification_despite_ambiguity(selcx, obligation);
return Ok(None);
}
};
debug!("project_and_unify_type: normalized_ty={} obligations={}",
......@@ -147,6 +136,50 @@ fn project_and_unify_type<'cx,'tcx>(
}
}
fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext<'cx,'tcx>,
obligation: &ProjectionObligation<'tcx>) {
debug!("consider_unification_despite_ambiguity(obligation={})",
obligation.repr(selcx.tcx()));
let def_id = obligation.predicate.projection_ty.trait_ref.def_id;
match selcx.tcx().lang_items.fn_trait_kind(def_id) {
Some(_) => { }
None => { return; }
}
let infcx = selcx.infcx();
let self_ty = obligation.predicate.projection_ty.trait_ref.self_ty();
let self_ty = infcx.shallow_resolve(self_ty);
debug!("consider_unification_despite_ambiguity: self_ty.sty={:?}",
self_ty.sty);
match self_ty.sty {
ty::ty_closure(closure_def_id, _, substs) => {
let closure_typer = selcx.closure_typer();
let closure_type = closure_typer.closure_type(closure_def_id, substs);
let ty::Binder((_, ret_type)) =
util::closure_trait_ref_and_return_type(infcx.tcx,
def_id,
self_ty,
&closure_type.sig,
util::TupleArgumentsFlag::No);
let (ret_type, _) =
infcx.replace_late_bound_regions_with_fresh_var(
obligation.cause.span,
infer::AssocTypeProjection(obligation.predicate.projection_ty.item_name),
&ty::Binder(ret_type));
debug!("consider_unification_despite_ambiguity: ret_type={:?}",
ret_type.repr(selcx.tcx()));
let origin = infer::RelateOutputImplTypes(obligation.cause.span);
let obligation_ty = obligation.predicate.ty;
match infer::mk_eqty(infcx, true, origin, obligation_ty, ret_type) {
Ok(()) => { }
Err(_) => { /* ignore errors */ }
}
}
_ => { }
}
}
/// Normalizes any associated type projections in `value`, replacing
/// them with a fully resolved type where possible. The return value
/// combines the normalized result and any additional obligations that
......
......@@ -277,8 +277,7 @@ pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
/// the argument types can only be helpful to the user, because
/// once they patch up the kind of closure that is expected, the
/// argment types won't really change.
fn consider_unification_despite_ambiguity(&mut self, obligation: &TraitObligation<'tcx>)
{
fn consider_unification_despite_ambiguity(&mut self, obligation: &TraitObligation<'tcx>) {
// Is this a `C : FnFoo(...)` trait reference for some trait binding `FnFoo`?
match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) {
Some(_) => { }
......
......@@ -9,7 +9,7 @@
// except according to those terms.
fn foo(i: int) -> int { i + 1 }
fn foo(i: isize) -> isize { i + 1 }
fn apply<A, F>(f: F, v: A) -> A where F: FnOnce(A) -> A { f(v) }
......
......@@ -14,9 +14,9 @@
#![feature(box_syntax)]
#![feature(unboxed_closures)]
struct A { a: Box<int> }
struct A { a: Box<isize> }
fn foo() -> Box<FnMut() -> int + 'static> {
fn foo() -> Box<FnMut() -> isize + 'static> {
let k = box 22;
let _u = A {a: k.clone()};
let result = |&mut:| 22;
......
......@@ -11,7 +11,7 @@
#![feature(unboxed_closures)]
fn main() {
let mut zero = |&mut:| {};
let () = zero.call_mut(());
let mut zero = || {};
let () = zero();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册