diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 4040b452e9988..2a45d536066ef 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -608,6 +608,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { * unified during the confirmation step. */ + let tcx = self.tcx(); + let kind = if Some(obligation.trait_ref.def_id) == tcx.lang_items.fn_trait() { + ty::FnUnboxedClosureKind + } else if Some(obligation.trait_ref.def_id) == tcx.lang_items.fn_mut_trait() { + ty::FnMutUnboxedClosureKind + } else if Some(obligation.trait_ref.def_id) == tcx.lang_items.fn_once_trait() { + ty::FnOnceUnboxedClosureKind + } else { + return Ok(()); // not a fn trait, ignore + }; + let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); let closure_def_id = match ty::get(self_ty).sty { ty::ty_unboxed_closure(id, _) => id, @@ -622,37 +633,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self_ty.repr(self.tcx()), obligation.repr(self.tcx())); - let tcx = self.tcx(); - let fn_traits = [ - (ty::FnUnboxedClosureKind, tcx.lang_items.fn_trait()), - (ty::FnMutUnboxedClosureKind, tcx.lang_items.fn_mut_trait()), - (ty::FnOnceUnboxedClosureKind, tcx.lang_items.fn_once_trait()), - ]; - for tuple in fn_traits.iter() { - let kind = match tuple { - &(kind, Some(ref fn_trait)) - if *fn_trait == obligation.trait_ref.def_id => - { - kind - } - _ => continue, - }; - - // Check to see whether the argument and return types match. - let closure_kind = match self.typer.unboxed_closures().borrow().find(&closure_def_id) { - Some(closure) => closure.kind, - None => { - self.tcx().sess.span_bug( - obligation.cause.span, - format!("No entry for unboxed closure: {}", - closure_def_id.repr(self.tcx())).as_slice()); - } - }; - - if closure_kind != kind { - continue; + let closure_kind = match self.typer.unboxed_closures().borrow().find(&closure_def_id) { + Some(closure) => closure.kind, + None => { + self.tcx().sess.span_bug( + obligation.cause.span, + format!("No entry for unboxed closure: {}", + closure_def_id.repr(self.tcx())).as_slice()); } + }; + if closure_kind == kind { candidates.vec.push(UnboxedClosureCandidate(closure_def_id)); } diff --git a/src/test/compile-fail/type-params-in-different-spaces-2.rs b/src/test/compile-fail/type-params-in-different-spaces-2.rs index d1bbda932cb73..9be64bf534679 100644 --- a/src/test/compile-fail/type-params-in-different-spaces-2.rs +++ b/src/test/compile-fail/type-params-in-different-spaces-2.rs @@ -8,28 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test static calls to make sure that we align the Self and input +// type parameters on a trait correctly. + trait Tr { fn op(T) -> Self; } -// these compile as if Self: Tr, even tho only Self: Tr trait A: Tr { fn test(u: U) -> Self { Tr::op(u) //~ ERROR not implemented } } + trait B: Tr { fn test(u: U) -> Self { Tr::op(u) //~ ERROR not implemented } } -impl Tr for T { - fn op(t: T) -> T { t } -} -impl A for T {} - fn main() { - std::io::println(A::test((&7306634593706211700, 8))); } diff --git a/src/test/run-pass/multidispatch-infer-from-single-impl.rs b/src/test/run-pass/multidispatch-infer-from-single-impl.rs new file mode 100644 index 0000000000000..f4ca67548fd53 --- /dev/null +++ b/src/test/run-pass/multidispatch-infer-from-single-impl.rs @@ -0,0 +1,32 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we correctly infer that `E` must be `()` here. This is +// known because there is just one impl that could apply where +// `Self=()`. + +pub trait FromError { + fn from_error(err: E) -> Self; +} + +impl FromError for E { + fn from_error(err: E) -> E { + err + } +} + +fn test() -> Result<(), ()> { + Err(FromError::from_error(())) +} + +fn main() { + let result = (|| Err(FromError::from_error(())))(); + let foo: () = result.unwrap_or(()); +}