mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
rollup merge of #20593: nikomatsakis/unused-tps-in-impl
Conflicts: src/libcollections/lib.rs src/librustc/lib.rs src/libserialize/lib.rs src/libstd/lib.rs
This commit is contained in:
commit
3892dd1eaa
@ -1417,7 +1417,7 @@ pub type MutTraversal<'a, K, V> = AbsTraversal<ElemsAndEdges<Zip<slice::Iter<'a,
|
||||
/// An owning traversal over a node's entries and edges
|
||||
pub type MoveTraversal<K, V> = AbsTraversal<MoveTraversalImpl<K, V>>;
|
||||
|
||||
|
||||
#[old_impl_check]
|
||||
impl<K, V, E, Impl: TraversalImpl<K, V, E>> Iterator for AbsTraversal<Impl> {
|
||||
type Item = TraversalItem<K, V, E>;
|
||||
|
||||
@ -1433,6 +1433,7 @@ impl<K, V, E, Impl: TraversalImpl<K, V, E>> Iterator for AbsTraversal<Impl> {
|
||||
}
|
||||
}
|
||||
|
||||
#[old_impl_check]
|
||||
impl<K, V, E, Impl: TraversalImpl<K, V, E>> DoubleEndedIterator for AbsTraversal<Impl> {
|
||||
fn next_back(&mut self) -> Option<TraversalItem<K, V, E>> {
|
||||
let tail_is_edge = self.tail_is_edge;
|
||||
|
@ -22,6 +22,7 @@
|
||||
html_playground_url = "http://play.rust-lang.org/")]
|
||||
|
||||
#![feature(unsafe_destructor, slicing_syntax)]
|
||||
#![feature(old_impl_check)]
|
||||
#![no_std]
|
||||
|
||||
#[macro_use]
|
||||
|
@ -25,6 +25,7 @@
|
||||
#![feature(quote)]
|
||||
#![feature(slicing_syntax, unsafe_destructor)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(old_impl_check)]
|
||||
|
||||
extern crate arena;
|
||||
extern crate flate;
|
||||
|
@ -669,6 +669,7 @@ impl LintPass for UnusedAttributes {
|
||||
|
||||
// FIXME: #19470 this shouldn't be needed forever
|
||||
"old_orphan_check",
|
||||
"old_impl_check",
|
||||
];
|
||||
|
||||
static CRATE_ATTRS: &'static [&'static str] = &[
|
||||
|
@ -1350,6 +1350,7 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for ty::Binder<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[old_impl_check]
|
||||
impl<'tcx, S, H, K, V> Repr<'tcx> for HashMap<K,V,H>
|
||||
where K : Hash<S> + Eq + Repr<'tcx>,
|
||||
V : Repr<'tcx>,
|
||||
|
@ -35,7 +35,7 @@ use middle::lang_items::SizedTraitLangItem;
|
||||
use middle::region;
|
||||
use middle::resolve_lifetime;
|
||||
use middle::subst;
|
||||
use middle::subst::{Substs};
|
||||
use middle::subst::{Substs, TypeSpace};
|
||||
use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
|
||||
use middle::ty::{self, RegionEscape, Ty, TypeScheme};
|
||||
use middle::ty_fold::{self, TypeFolder, TypeFoldable};
|
||||
@ -47,6 +47,7 @@ use util::ppaux;
|
||||
use util::ppaux::{Repr,UserString};
|
||||
use write_ty_to_tcx;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
use syntax::abi;
|
||||
@ -644,6 +645,10 @@ fn convert(ccx: &CollectCtxt, it: &ast::Item) {
|
||||
Some(selfty),
|
||||
None);
|
||||
}
|
||||
|
||||
enforce_impl_ty_params_are_constrained(ccx.tcx,
|
||||
generics,
|
||||
local_def(it.id));
|
||||
},
|
||||
ast::ItemTrait(_, _, _, ref trait_methods) => {
|
||||
let trait_def = trait_def_of_item(ccx, it);
|
||||
@ -1605,3 +1610,96 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that all the type parameters on an impl
|
||||
fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
ast_generics: &ast::Generics,
|
||||
impl_def_id: ast::DefId)
|
||||
{
|
||||
let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
|
||||
let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
|
||||
|
||||
// The trait reference is an input, so find all type parameters
|
||||
// reachable from there, to start (if this is an inherent impl,
|
||||
// then just examine the self type).
|
||||
let mut input_parameters: HashSet<_> =
|
||||
impl_trait_ref.iter()
|
||||
.flat_map(|t| t.input_types().iter()) // Types in trait ref, if any
|
||||
.chain(Some(impl_scheme.ty).iter()) // Self type, always
|
||||
.flat_map(|t| t.walk())
|
||||
.filter_map(to_opt_param_ty)
|
||||
.collect();
|
||||
|
||||
loop {
|
||||
let num_inputs = input_parameters.len();
|
||||
|
||||
let mut projection_predicates =
|
||||
impl_scheme.generics.predicates
|
||||
.iter()
|
||||
.filter_map(|predicate| {
|
||||
match *predicate {
|
||||
// Ignore higher-ranked binders. For the purposes
|
||||
// of this check, they don't matter because they
|
||||
// only affect named regions, and we're just
|
||||
// concerned about type parameters here.
|
||||
ty::Predicate::Projection(ref data) => Some(data.0.clone()),
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
|
||||
for projection in projection_predicates {
|
||||
// Special case: watch out for some kind of sneaky attempt
|
||||
// to project out an associated type defined by this very trait.
|
||||
if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref {
|
||||
continue;
|
||||
}
|
||||
|
||||
let relies_only_on_inputs =
|
||||
projection.projection_ty.trait_ref.input_types().iter()
|
||||
.flat_map(|t| t.walk())
|
||||
.filter_map(to_opt_param_ty)
|
||||
.all(|t| input_parameters.contains(&t));
|
||||
|
||||
if relies_only_on_inputs {
|
||||
input_parameters.extend(
|
||||
projection.ty.walk().filter_map(to_opt_param_ty));
|
||||
}
|
||||
}
|
||||
|
||||
if input_parameters.len() == num_inputs {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
|
||||
let param_ty = ty::ParamTy { space: TypeSpace,
|
||||
idx: index as u32,
|
||||
name: ty_param.ident.name };
|
||||
if !input_parameters.contains(¶m_ty) {
|
||||
if ty::has_attr(tcx, impl_def_id, "old_impl_check") {
|
||||
tcx.sess.span_warn(
|
||||
ty_param.span,
|
||||
format!("the type parameter `{}` is not constrained by the \
|
||||
impl trait, self type, or predicates",
|
||||
param_ty.user_string(tcx)).as_slice());
|
||||
} else {
|
||||
tcx.sess.span_err(
|
||||
ty_param.span,
|
||||
format!("the type parameter `{}` is not constrained by the \
|
||||
impl trait, self type, or predicates",
|
||||
param_ty.user_string(tcx)).as_slice());
|
||||
tcx.sess.span_help(
|
||||
ty_param.span,
|
||||
format!("you can temporarily opt out of this rule by placing \
|
||||
the `#[old_impl_check]` attribute on the impl").as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_opt_param_ty<'tcx>(ty: Ty<'tcx>) -> Option<ty::ParamTy> {
|
||||
match ty.sty {
|
||||
ty::ty_param(ref d) => Some(d.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -156,6 +156,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
#[old_impl_check]
|
||||
impl<
|
||||
K: Encodable + Hash<X> + Eq,
|
||||
V: Encodable,
|
||||
@ -175,6 +176,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
#[old_impl_check]
|
||||
impl<
|
||||
K: Decodable + Hash<S> + Eq,
|
||||
V: Decodable,
|
||||
@ -195,6 +197,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
#[old_impl_check]
|
||||
impl<
|
||||
T: Encodable + Hash<X> + Eq,
|
||||
X,
|
||||
@ -212,6 +215,7 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
#[old_impl_check]
|
||||
impl<
|
||||
T: Decodable + Hash<S> + Eq,
|
||||
S,
|
||||
|
@ -24,6 +24,7 @@ Core encoding and decoding interfaces.
|
||||
html_playground_url = "http://play.rust-lang.org/")]
|
||||
#![allow(unknown_features)]
|
||||
#![feature(slicing_syntax)]
|
||||
#![feature(old_impl_check)]
|
||||
|
||||
// test harness access
|
||||
#[cfg(test)] extern crate test;
|
||||
|
@ -439,6 +439,7 @@ impl<K, V, M> SearchResult<K, V, M> {
|
||||
}
|
||||
}
|
||||
|
||||
#[old_impl_check]
|
||||
impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
fn make_hash<X: ?Sized + Hash<S>>(&self, x: &X) -> SafeHash {
|
||||
table::make_hash(&self.hasher, x)
|
||||
@ -517,6 +518,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> {
|
||||
}
|
||||
}
|
||||
|
||||
#[old_impl_check]
|
||||
impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
/// Creates an empty hashmap which will use the given hasher to hash keys.
|
||||
///
|
||||
@ -1188,6 +1190,7 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V, H> {
|
||||
fn eq(&self, other: &HashMap<K, V, H>) -> bool {
|
||||
if self.len() != other.len() { return false; }
|
||||
@ -1199,9 +1202,11 @@ impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V,
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<K: Eq + Hash<S>, V: Eq, S, H: Hasher<S>> Eq for HashMap<K, V, H> {}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "HashMap {{"));
|
||||
@ -1216,6 +1221,7 @@ impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H>
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
|
||||
#[stable]
|
||||
fn default() -> HashMap<K, V, H> {
|
||||
@ -1224,6 +1230,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H>
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> Index<Q> for HashMap<K, V, H>
|
||||
where Q: BorrowFrom<K> + Hash<S> + Eq
|
||||
{
|
||||
@ -1236,6 +1243,7 @@ impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> Index<Q> for HashMap<K, V,
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> IndexMut<Q> for HashMap<K, V, H>
|
||||
where Q: BorrowFrom<K> + Hash<S> + Eq
|
||||
{
|
||||
@ -1465,6 +1473,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
|
||||
fn from_iter<T: Iterator<Item=(K, V)>>(iter: T) -> HashMap<K, V, H> {
|
||||
let lower = iter.size_hint().0;
|
||||
@ -1475,6 +1484,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for Has
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Extend<(K, V)> for HashMap<K, V, H> {
|
||||
fn extend<T: Iterator<Item=(K, V)>>(&mut self, mut iter: T) {
|
||||
for (k, v) in iter {
|
||||
|
@ -125,6 +125,7 @@ impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
|
||||
}
|
||||
}
|
||||
|
||||
#[old_impl_check]
|
||||
impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
||||
/// Creates a new empty hash set which will use the given hasher to hash
|
||||
/// keys.
|
||||
@ -568,6 +569,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
|
||||
fn eq(&self, other: &HashSet<T, H>) -> bool {
|
||||
if self.len() != other.len() { return false; }
|
||||
@ -577,9 +579,11 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "HashSet {{"));
|
||||
@ -594,6 +598,7 @@ impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {
|
||||
fn from_iter<I: Iterator<Item=T>>(iter: I) -> HashSet<T, H> {
|
||||
let lower = iter.size_hint().0;
|
||||
@ -604,6 +609,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T,
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Extend<T> for HashSet<T, H> {
|
||||
fn extend<I: Iterator<Item=T>>(&mut self, mut iter: I) {
|
||||
for k in iter {
|
||||
@ -613,6 +619,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> Extend<T> for HashSet<T, H> {
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
|
||||
#[stable]
|
||||
fn default() -> HashSet<T, H> {
|
||||
@ -621,6 +628,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
|
||||
BitOr<&'b HashSet<T, H>> for &'a HashSet<T, H> {
|
||||
type Output = HashSet<T, H>;
|
||||
@ -651,6 +659,7 @@ BitOr<&'b HashSet<T, H>> for &'a HashSet<T, H> {
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
|
||||
BitAnd<&'b HashSet<T, H>> for &'a HashSet<T, H> {
|
||||
type Output = HashSet<T, H>;
|
||||
@ -681,6 +690,7 @@ BitAnd<&'b HashSet<T, H>> for &'a HashSet<T, H> {
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
|
||||
BitXor<&'b HashSet<T, H>> for &'a HashSet<T, H> {
|
||||
type Output = HashSet<T, H>;
|
||||
@ -711,6 +721,7 @@ BitXor<&'b HashSet<T, H>> for &'a HashSet<T, H> {
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
|
||||
Sub<&'b HashSet<T, H>> for &'a HashSet<T, H> {
|
||||
type Output = HashSet<T, H>;
|
||||
@ -813,6 +824,7 @@ impl<'a, K: 'a> Iterator for Drain<'a, K> {
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<'a, T, S, H> Iterator for Intersection<'a, T, H>
|
||||
where T: Eq + Hash<S>, H: Hasher<S>
|
||||
{
|
||||
@ -836,6 +848,7 @@ impl<'a, T, S, H> Iterator for Intersection<'a, T, H>
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<'a, T, S, H> Iterator for Difference<'a, T, H>
|
||||
where T: Eq + Hash<S>, H: Hasher<S>
|
||||
{
|
||||
@ -859,6 +872,7 @@ impl<'a, T, S, H> Iterator for Difference<'a, T, H>
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, H>
|
||||
where T: Eq + Hash<S>, H: Hasher<S>
|
||||
{
|
||||
@ -869,6 +883,7 @@ impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, H>
|
||||
}
|
||||
|
||||
#[stable]
|
||||
#[old_impl_check]
|
||||
impl<'a, T, S, H> Iterator for Union<'a, T, H>
|
||||
where T: Eq + Hash<S>, H: Hasher<S>
|
||||
{
|
||||
|
@ -1603,6 +1603,7 @@ pub struct IncomingConnections<'a, A: ?Sized +'a> {
|
||||
inc: &'a mut A,
|
||||
}
|
||||
|
||||
#[old_impl_check]
|
||||
impl<'a, T, A: ?Sized + Acceptor<T>> Iterator for IncomingConnections<'a, A> {
|
||||
type Item = IoResult<T>;
|
||||
|
||||
|
@ -107,6 +107,7 @@
|
||||
#![feature(linkage, thread_local, asm)]
|
||||
#![feature(phase, lang_items, unsafe_destructor)]
|
||||
#![feature(slicing_syntax, unboxed_closures)]
|
||||
#![feature(old_impl_check)]
|
||||
|
||||
// Don't link to std. We are std.
|
||||
#![no_std]
|
||||
|
@ -979,8 +979,8 @@ pub enum Sign {
|
||||
Plus
|
||||
}
|
||||
|
||||
impl<T> Sign where T: Int {
|
||||
pub fn new(n: T) -> Sign {
|
||||
impl Sign {
|
||||
pub fn new<T:Int>(n: T) -> Sign {
|
||||
if n < Int::zero() {
|
||||
Minus
|
||||
} else {
|
||||
|
@ -86,6 +86,9 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
|
||||
// A way to temporarily opt out of the new orphan rules. This will *never* be accepted.
|
||||
("old_orphan_check", Deprecated),
|
||||
|
||||
// A way to temporarily opt out of the new impl rules. This will *never* be accepted.
|
||||
("old_impl_check", Deprecated),
|
||||
|
||||
// OIBIT specific features
|
||||
("optin_builtin_traits", Active),
|
||||
|
||||
@ -294,6 +297,13 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
|
||||
i.span,
|
||||
"the new orphan check rules will eventually be strictly enforced");
|
||||
}
|
||||
|
||||
if attr::contains_name(i.attrs[],
|
||||
"old_impl_check") {
|
||||
self.gate_feature("old_impl_check",
|
||||
i.span,
|
||||
"`#[old_impl_check]` will be removed in the future");
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
|
@ -18,8 +18,8 @@ pub fn foo<T>() -> int {
|
||||
|
||||
// issue 8134
|
||||
struct Foo;
|
||||
impl<T> Foo {
|
||||
pub fn foo(&self) {
|
||||
impl Foo {
|
||||
pub fn foo<T>(&self) {
|
||||
static X: uint = 1;
|
||||
}
|
||||
}
|
||||
@ -33,8 +33,8 @@ impl<T: std::iter::Iterator<Item=char>> Parser<T> {
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
impl<T> Foo {
|
||||
pub fn bar(&self) {
|
||||
impl Foo {
|
||||
pub fn bar<T>(&self) {
|
||||
static X: uint = 1;
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,9 @@
|
||||
// aux-build:coherence-lib.rs
|
||||
|
||||
extern crate "coherence-lib" as lib;
|
||||
use lib::Remote;
|
||||
use lib::Remote1;
|
||||
|
||||
impl<T> Remote for int { }
|
||||
impl<T> Remote1<T> for int { }
|
||||
//~^ ERROR E0117
|
||||
|
||||
fn main() { }
|
||||
|
35
src/test/compile-fail/impl-unused-tps-inherent.rs
Normal file
35
src/test/compile-fail/impl-unused-tps-inherent.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// 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.
|
||||
|
||||
struct MyType;
|
||||
|
||||
struct MyType1<T>(T);
|
||||
|
||||
trait Bar {
|
||||
type Out;
|
||||
}
|
||||
|
||||
impl<T> MyType {
|
||||
//~^ ERROR the type parameter `T` is not constrained
|
||||
}
|
||||
|
||||
impl<T> MyType1<T> {
|
||||
// OK, T is used in `Foo<T>`.
|
||||
}
|
||||
|
||||
impl<T,U> MyType1<T> {
|
||||
//~^ ERROR the type parameter `U` is not constrained
|
||||
}
|
||||
|
||||
impl<T,U> MyType1<T> where T: Bar<Out=U> {
|
||||
// OK, T is used in `Foo<T>`.
|
||||
}
|
||||
|
||||
fn main() { }
|
72
src/test/compile-fail/impl-unused-tps.rs
Normal file
72
src/test/compile-fail/impl-unused-tps.rs
Normal file
@ -0,0 +1,72 @@
|
||||
// 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.
|
||||
|
||||
trait Foo<A> {
|
||||
fn get(&self, A: &A) { }
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
type Out;
|
||||
}
|
||||
|
||||
impl<T> Foo<T> for [int;0] {
|
||||
// OK, T is used in `Foo<T>`.
|
||||
}
|
||||
|
||||
impl<T,U> Foo<T> for [int;1] {
|
||||
//~^ ERROR the type parameter `U` is not constrained
|
||||
}
|
||||
|
||||
impl<T,U> Foo<T> for [int;2] where T : Bar<Out=U> {
|
||||
// OK, `U` is now constrained by the output type parameter.
|
||||
}
|
||||
|
||||
impl<T:Bar<Out=U>,U> Foo<T> for [int;3] {
|
||||
// OK, same as above but written differently.
|
||||
}
|
||||
|
||||
impl<T,U> Foo<T> for U {
|
||||
// OK, T, U are used everywhere. Note that the coherence check
|
||||
// hasn't executed yet, so no errors about overlap.
|
||||
}
|
||||
|
||||
impl<T,U> Bar for T {
|
||||
//~^ ERROR the type parameter `U` is not constrained
|
||||
|
||||
type Out = U;
|
||||
|
||||
// Using `U` in an associated type within the impl is not good enough!
|
||||
}
|
||||
|
||||
impl<T,U> Bar for T
|
||||
where T : Bar<Out=U>
|
||||
{
|
||||
//~^^^ ERROR the type parameter `U` is not constrained
|
||||
|
||||
// This crafty self-referential attempt is still no good.
|
||||
}
|
||||
|
||||
impl<T,U,V> Foo<T> for T
|
||||
where (T,U): Bar<Out=V>
|
||||
{
|
||||
//~^^^ ERROR the type parameter `U` is not constrained
|
||||
//~| ERROR the type parameter `V` is not constrained
|
||||
|
||||
// Here, `V` is bound by an output type parameter, but the inputs
|
||||
// are not themselves constrained.
|
||||
}
|
||||
|
||||
impl<T,U,V> Foo<(T,U)> for T
|
||||
where (T,U): Bar<Out=V>
|
||||
{
|
||||
// As above, but both T and U ARE constrained.
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -22,27 +22,28 @@ trait Stream {
|
||||
fn result(&self) -> u64;
|
||||
}
|
||||
|
||||
trait StreamHasher<S: Stream> {
|
||||
fn stream(&self) -> S;
|
||||
trait StreamHasher {
|
||||
type S : Stream;
|
||||
fn stream(&self) -> Self::S;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
trait StreamHash<S: Stream, H: StreamHasher<S>>: Hash<H> {
|
||||
fn input_stream(&self, stream: &mut S);
|
||||
trait StreamHash<H: StreamHasher>: Hash<H> {
|
||||
fn input_stream(&self, stream: &mut H::S);
|
||||
}
|
||||
|
||||
impl<S: Stream, H: StreamHasher<S>> Hash<H> for u8 {
|
||||
impl<H: StreamHasher> Hash<H> for u8 {
|
||||
fn hash2(&self, hasher: &H) -> u64 {
|
||||
let mut stream = hasher.stream();
|
||||
self.input_stream(&mut stream); //~ ERROR type annotations required
|
||||
stream.result()
|
||||
Stream::result(&stream)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Stream, H: StreamHasher<S>> StreamHash<S, H> for u8 {
|
||||
fn input_stream(&self, stream: &mut S) {
|
||||
stream.input(&[*self]);
|
||||
impl<H: StreamHasher> StreamHash<H> for u8 {
|
||||
fn input_stream(&self, stream: &mut H::S) {
|
||||
Stream::input(&*stream, &[*self]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ trait Deserializable {
|
||||
}
|
||||
|
||||
impl<'a, T: Deserializable> Deserializable for &'a str {
|
||||
//~^ ERROR unable to infer enough type information
|
||||
//~^ ERROR type parameter `T` is not constrained
|
||||
fn deserialize_token<D: Deserializer<'a>>(_x: D, _y: &'a str) -> &'a str {
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ struct Col<D, C> {
|
||||
trait Collection { fn len(&self) -> uint; }
|
||||
|
||||
impl<T, M: MatrixShape> Collection for Col<M, uint> {
|
||||
//~^ ERROR unable to infer enough type information
|
||||
//~^ ERROR type parameter `T` is not constrained
|
||||
fn len(&self) -> uint {
|
||||
unimplemented!()
|
||||
}
|
||||
|
@ -30,17 +30,23 @@ impl Vec2 {
|
||||
}
|
||||
|
||||
// Right-hand-side operator visitor pattern
|
||||
trait RhsOfVec2Mul<Result> { fn mul_vec2_by(&self, lhs: &Vec2) -> Result; }
|
||||
trait RhsOfVec2Mul {
|
||||
type Result;
|
||||
|
||||
fn mul_vec2_by(&self, lhs: &Vec2) -> Self::Result;
|
||||
}
|
||||
|
||||
// Vec2's implementation of Mul "from the other side" using the above trait
|
||||
impl<Res, Rhs: RhsOfVec2Mul<Res>> Mul<Rhs> for Vec2 {
|
||||
impl<Res, Rhs: RhsOfVec2Mul<Result=Res>> Mul<Rhs> for Vec2 {
|
||||
type Output = Res;
|
||||
|
||||
fn mul(self, rhs: Rhs) -> Res { rhs.mul_vec2_by(&self) }
|
||||
}
|
||||
|
||||
// Implementation of 'f64 as right-hand-side of Vec2::Mul'
|
||||
impl RhsOfVec2Mul<Vec2> for f64 {
|
||||
impl RhsOfVec2Mul for f64 {
|
||||
type Result = Vec2;
|
||||
|
||||
fn mul_vec2_by(&self, lhs: &Vec2) -> Vec2 { lhs.vmul(*self) }
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user