Skip to content

Commit b0c4728

Browse files
committed
auto merge of #18022 : nikomatsakis/rust/issue-18019, r=pcwalton
Only consider impliciy unboxed closure impl if the obligation is actually for `Fn`, `FnMut`, or `FnOnce`. Fixes #18019 r? @pcwalton
2 parents 93e589c + f4a7d32 commit b0c4728

File tree

3 files changed

+56
-36
lines changed

3 files changed

+56
-36
lines changed

src/librustc/middle/traits/select.rs

+20-29
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
608608
* unified during the confirmation step.
609609
*/
610610

611+
let tcx = self.tcx();
612+
let kind = if Some(obligation.trait_ref.def_id) == tcx.lang_items.fn_trait() {
613+
ty::FnUnboxedClosureKind
614+
} else if Some(obligation.trait_ref.def_id) == tcx.lang_items.fn_mut_trait() {
615+
ty::FnMutUnboxedClosureKind
616+
} else if Some(obligation.trait_ref.def_id) == tcx.lang_items.fn_once_trait() {
617+
ty::FnOnceUnboxedClosureKind
618+
} else {
619+
return Ok(()); // not a fn trait, ignore
620+
};
621+
611622
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
612623
let closure_def_id = match ty::get(self_ty).sty {
613624
ty::ty_unboxed_closure(id, _) => id,
@@ -622,37 +633,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
622633
self_ty.repr(self.tcx()),
623634
obligation.repr(self.tcx()));
624635

625-
let tcx = self.tcx();
626-
let fn_traits = [
627-
(ty::FnUnboxedClosureKind, tcx.lang_items.fn_trait()),
628-
(ty::FnMutUnboxedClosureKind, tcx.lang_items.fn_mut_trait()),
629-
(ty::FnOnceUnboxedClosureKind, tcx.lang_items.fn_once_trait()),
630-
];
631-
for tuple in fn_traits.iter() {
632-
let kind = match tuple {
633-
&(kind, Some(ref fn_trait))
634-
if *fn_trait == obligation.trait_ref.def_id =>
635-
{
636-
kind
637-
}
638-
_ => continue,
639-
};
640-
641-
// Check to see whether the argument and return types match.
642-
let closure_kind = match self.typer.unboxed_closures().borrow().find(&closure_def_id) {
643-
Some(closure) => closure.kind,
644-
None => {
645-
self.tcx().sess.span_bug(
646-
obligation.cause.span,
647-
format!("No entry for unboxed closure: {}",
648-
closure_def_id.repr(self.tcx())).as_slice());
649-
}
650-
};
651-
652-
if closure_kind != kind {
653-
continue;
636+
let closure_kind = match self.typer.unboxed_closures().borrow().find(&closure_def_id) {
637+
Some(closure) => closure.kind,
638+
None => {
639+
self.tcx().sess.span_bug(
640+
obligation.cause.span,
641+
format!("No entry for unboxed closure: {}",
642+
closure_def_id.repr(self.tcx())).as_slice());
654643
}
644+
};
655645

646+
if closure_kind == kind {
656647
candidates.vec.push(UnboxedClosureCandidate(closure_def_id));
657648
}
658649

src/test/compile-fail/type-params-in-different-spaces-2.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,25 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// Test static calls to make sure that we align the Self and input
12+
// type parameters on a trait correctly.
13+
1114
trait Tr<T> {
1215
fn op(T) -> Self;
1316
}
1417

15-
// these compile as if Self: Tr<U>, even tho only Self: Tr<Self or T>
1618
trait A: Tr<Self> {
1719
fn test<U>(u: U) -> Self {
1820
Tr::op(u) //~ ERROR not implemented
1921
}
2022
}
23+
2124
trait B<T>: Tr<T> {
2225
fn test<U>(u: U) -> Self {
2326
Tr::op(u) //~ ERROR not implemented
2427
}
2528
}
2629

27-
impl<T> Tr<T> for T {
28-
fn op(t: T) -> T { t }
29-
}
30-
impl<T> A for T {}
31-
3230
fn main() {
33-
std::io::println(A::test((&7306634593706211700, 8)));
3431
}
3532

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we correctly infer that `E` must be `()` here. This is
12+
// known because there is just one impl that could apply where
13+
// `Self=()`.
14+
15+
pub trait FromError<E> {
16+
fn from_error(err: E) -> Self;
17+
}
18+
19+
impl<E> FromError<E> for E {
20+
fn from_error(err: E) -> E {
21+
err
22+
}
23+
}
24+
25+
fn test() -> Result<(), ()> {
26+
Err(FromError::from_error(()))
27+
}
28+
29+
fn main() {
30+
let result = (|| Err(FromError::from_error(())))();
31+
let foo: () = result.unwrap_or(());
32+
}

0 commit comments

Comments
 (0)