diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-02-20 05:16:59 -0500 |
|---|---|---|
| committer | Flavio Percoco <flaper87@gmail.com> | 2015-02-22 02:14:27 +0100 |
| commit | 640000a7c0d49e03b22c635e98679d5cffb18f1a (patch) | |
| tree | 2b75623419f81650b81c812442e5808ee95d7687 | |
| parent | 1cc5a87c08fb1e9c6214e3370c78e3c217a0bae4 (diff) | |
fix treatment of parameters and associated types
| -rw-r--r-- | src/librustc/middle/traits/select.rs | 67 | ||||
| -rw-r--r-- | src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs | 25 | ||||
| -rw-r--r-- | src/test/compile-fail/typeck-default-trait-impl-send-param.rs | 21 |
3 files changed, 96 insertions, 17 deletions
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 04c555632e1..f824ec50dc4 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -1142,23 +1142,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); } - match self_ty.sty { - ty::ty_trait(..) => {}, - ty::ty_infer(ty::TyVar(_)) => { - // the defaulted impl might apply, we don't know - if ty::trait_has_default_impl(self.tcx(), def_id) { + if ty::trait_has_default_impl(self.tcx(), def_id) { + match self_ty.sty { + 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 candidates.ambiguous = true; } - } - _ => { - if ty::trait_has_default_impl(self.tcx(), def_id) { - match self.constituent_types_for_ty(self_ty) { - Some(_) => { - candidates.vec.push(DefaultImplCandidate(def_id.clone())) - } - None => { - candidates.ambiguous = true; - } + _ => { + if self.constituent_types_for_ty(self_ty).is_some() { + candidates.vec.push(DefaultImplCandidate(def_id.clone())) + } 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; } } } @@ -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: {}", diff --git a/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs b/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs new file mode 100644 index 00000000000..8a9d53731c5 --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs @@ -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() { } diff --git a/src/test/compile-fail/typeck-default-trait-impl-send-param.rs b/src/test/compile-fail/typeck-default-trait-impl-send-param.rs new file mode 100644 index 00000000000..185e9dcb3bd --- /dev/null +++ b/src/test/compile-fail/typeck-default-trait-impl-send-param.rs @@ -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() { } |
