Skip to content

Commit 640000a

Browse files
nikomatsakisflaper87
authored andcommitted
fix treatment of parameters and associated types
1 parent 1cc5a87 commit 640000a

File tree

3 files changed

+96
-17
lines changed

3 files changed

+96
-17
lines changed

src/librustc/middle/traits/select.rs

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,23 +1142,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11421142
});
11431143
}
11441144

1145-
match self_ty.sty {
1146-
ty::ty_trait(..) => {},
1147-
ty::ty_infer(ty::TyVar(_)) => {
1148-
// the defaulted impl might apply, we don't know
1149-
if ty::trait_has_default_impl(self.tcx(), def_id) {
1145+
if ty::trait_has_default_impl(self.tcx(), def_id) {
1146+
match self_ty.sty {
1147+
ty::ty_trait(..) |
1148+
ty::ty_param(..) |
1149+
ty::ty_projection(..) => {
1150+
// In these cases, we don't know what the actual
1151+
// type is. Therefore, we cannot break it down
1152+
// into its constituent types. So we don't
1153+
// consider the `..` impl but instead just add no
1154+
// candidates: this means that typeck will only
1155+
// succeed if there is another reason to believe
1156+
// that this obligation holds. That could be a
1157+
// where-clause or, in the case of an object type,
1158+
// it could be that the object type lists the
1159+
// trait (e.g. `Foo+Send : Send`). See
1160+
// `compile-fail/typeck-default-trait-impl-send-param.rs`
1161+
// for an example of a test case that exercises
1162+
// this path.
1163+
}
1164+
ty::ty_infer(ty::TyVar(_)) => {
1165+
// the defaulted impl might apply, we don't know
11501166
candidates.ambiguous = true;
11511167
}
1152-
}
1153-
_ => {
1154-
if ty::trait_has_default_impl(self.tcx(), def_id) {
1155-
match self.constituent_types_for_ty(self_ty) {
1156-
Some(_) => {
1157-
candidates.vec.push(DefaultImplCandidate(def_id.clone()))
1158-
}
1159-
None => {
1160-
candidates.ambiguous = true;
1161-
}
1168+
_ => {
1169+
if self.constituent_types_for_ty(self_ty).is_some() {
1170+
candidates.vec.push(DefaultImplCandidate(def_id.clone()))
1171+
} else {
1172+
// We don't yet know what the constituent
1173+
// types are. So call it ambiguous for now,
1174+
// though this is a bit stronger than
1175+
// necessary: that is, we know that the
1176+
// defaulted impl applies, but we can't
1177+
// process the confirmation step without
1178+
// knowing the constituent types. (Anyway, in
1179+
// the particular case of defaulted impls, it
1180+
// doesn't really matter much either way,
1181+
// since we won't be aiding inference by
1182+
// processing the confirmation step.)
1183+
candidates.ambiguous = true;
11621184
}
11631185
}
11641186
}
@@ -1632,6 +1654,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16321654
}
16331655
}
16341656

1657+
/// For default impls, we need to break apart a type into its
1658+
/// "constituent types" -- meaning, the types that it contains.
1659+
///
1660+
/// Here are some (simple) examples:
1661+
///
1662+
/// ```
1663+
/// (i32, u32) -> [i32, u32]
1664+
/// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32]
1665+
/// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
1666+
/// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
1667+
/// ```
16351668
fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option<Vec<Ty<'tcx>>> {
16361669
match t.sty {
16371670
ty::ty_uint(_) |
@@ -1641,16 +1674,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16411674
ty::ty_bare_fn(..) |
16421675
ty::ty_str |
16431676
ty::ty_err |
1644-
ty::ty_param(..) |
16451677
ty::ty_infer(ty::IntVar(_)) |
16461678
ty::ty_infer(ty::FloatVar(_)) |
16471679
ty::ty_char => {
16481680
Some(Vec::new())
16491681
}
16501682

16511683
ty::ty_trait(..) |
1684+
ty::ty_param(..) |
16521685
ty::ty_projection(..) |
1653-
ty::ty_infer(_) => {
1686+
ty::ty_infer(ty::TyVar(_)) => {
16541687
self.tcx().sess.bug(
16551688
&format!(
16561689
"asked to assemble constituent types of unexpected type: {}",
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2015 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 do not consider associated types to be sendable without
12+
// some applicable trait bound (and we don't ICE).
13+
14+
trait Trait {
15+
type AssocType;
16+
fn dummy(&self) { }
17+
}
18+
fn bar<T:Trait+Send>() {
19+
is_send::<T::AssocType>(); //~ ERROR not implemented
20+
}
21+
22+
fn is_send<T:Send>() {
23+
}
24+
25+
fn main() { }
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2015 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 do not consider parameter types to be sendable without
12+
// an explicit trait bound.
13+
14+
fn foo<T>() {
15+
is_send::<T>() //~ ERROR not implemented
16+
}
17+
18+
fn is_send<T:Send>() {
19+
}
20+
21+
fn main() { }

0 commit comments

Comments
 (0)