fix treatment of parameters and associated types
This commit is contained in:
parent
1cc5a87c08
commit
640000a7c0
3 changed files with 96 additions and 17 deletions
|
@ -1142,27 +1142,49 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
});
|
||||
}
|
||||
|
||||
if ty::trait_has_default_impl(self.tcx(), def_id) {
|
||||
match self_ty.sty {
|
||||
ty::ty_trait(..) => {},
|
||||
ty::ty_trait(..) |
|
||||
ty::ty_param(..) |
|
||||
ty::ty_projection(..) => {
|
||||
// In these cases, we don't know what the actual
|
||||
// type is. Therefore, we cannot break it down
|
||||
// into its constituent types. So we don't
|
||||
// consider the `..` impl but instead just add no
|
||||
// candidates: this means that typeck will only
|
||||
// succeed if there is another reason to believe
|
||||
// that this obligation holds. That could be a
|
||||
// where-clause or, in the case of an object type,
|
||||
// it could be that the object type lists the
|
||||
// trait (e.g. `Foo+Send : Send`). See
|
||||
// `compile-fail/typeck-default-trait-impl-send-param.rs`
|
||||
// for an example of a test case that exercises
|
||||
// this path.
|
||||
}
|
||||
ty::ty_infer(ty::TyVar(_)) => {
|
||||
// the defaulted impl might apply, we don't know
|
||||
if ty::trait_has_default_impl(self.tcx(), def_id) {
|
||||
candidates.ambiguous = true;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if ty::trait_has_default_impl(self.tcx(), def_id) {
|
||||
match self.constituent_types_for_ty(self_ty) {
|
||||
Some(_) => {
|
||||
if self.constituent_types_for_ty(self_ty).is_some() {
|
||||
candidates.vec.push(DefaultImplCandidate(def_id.clone()))
|
||||
}
|
||||
None => {
|
||||
} else {
|
||||
// We don't yet know what the constituent
|
||||
// types are. So call it ambiguous for now,
|
||||
// though this is a bit stronger than
|
||||
// necessary: that is, we know that the
|
||||
// defaulted impl applies, but we can't
|
||||
// process the confirmation step without
|
||||
// knowing the constituent types. (Anyway, in
|
||||
// the particular case of defaulted impls, it
|
||||
// doesn't really matter much either way,
|
||||
// since we won't be aiding inference by
|
||||
// processing the confirmation step.)
|
||||
candidates.ambiguous = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1632,6 +1654,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// For default impls, we need to break apart a type into its
|
||||
/// "constituent types" -- meaning, the types that it contains.
|
||||
///
|
||||
/// Here are some (simple) examples:
|
||||
///
|
||||
/// ```
|
||||
/// (i32, u32) -> [i32, u32]
|
||||
/// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32]
|
||||
/// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
|
||||
/// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
|
||||
/// ```
|
||||
fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option<Vec<Ty<'tcx>>> {
|
||||
match t.sty {
|
||||
ty::ty_uint(_) |
|
||||
|
@ -1641,7 +1674,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
ty::ty_bare_fn(..) |
|
||||
ty::ty_str |
|
||||
ty::ty_err |
|
||||
ty::ty_param(..) |
|
||||
ty::ty_infer(ty::IntVar(_)) |
|
||||
ty::ty_infer(ty::FloatVar(_)) |
|
||||
ty::ty_char => {
|
||||
|
@ -1649,8 +1681,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
ty::ty_trait(..) |
|
||||
ty::ty_param(..) |
|
||||
ty::ty_projection(..) |
|
||||
ty::ty_infer(_) => {
|
||||
ty::ty_infer(ty::TyVar(_)) => {
|
||||
self.tcx().sess.bug(
|
||||
&format!(
|
||||
"asked to assemble constituent types of unexpected type: {}",
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that we do not consider associated types to be sendable without
|
||||
// some applicable trait bound (and we don't ICE).
|
||||
|
||||
trait Trait {
|
||||
type AssocType;
|
||||
fn dummy(&self) { }
|
||||
}
|
||||
fn bar<T:Trait+Send>() {
|
||||
is_send::<T::AssocType>(); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn is_send<T:Send>() {
|
||||
}
|
||||
|
||||
fn main() { }
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2015 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that we do not consider parameter types to be sendable without
|
||||
// an explicit trait bound.
|
||||
|
||||
fn foo<T>() {
|
||||
is_send::<T>() //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn is_send<T:Send>() {
|
||||
}
|
||||
|
||||
fn main() { }
|
Loading…
Add table
Reference in a new issue