%token TRAIT
%token TYPE
%token UNSAFE
+%token DEFAULT
%token USE
%token WHILE
%token CONTINUE
| %empty { $$ = mk_none(); }
;
+maybe_default_maybe_unsafe
+: DEFAULT UNSAFE { $$ = mk_atom("DefaultUnsafe"); }
+| DEFAULT { $$ = mk_atom("Default"); }
+| UNSAFE { $$ = mk_atom("Unsafe"); }
+| %empty { $$ = mk_none(); }
+
trait_method
: type_method { $$ = mk_node("Required", 1, $1); }
| method { $$ = mk_node("Provided", 1, $1); }
// they are ambiguous with traits. We do the same here, regrettably,
// by splitting ty into ty and ty_prim.
item_impl
-: maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8);
}
-| maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
}
-| maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10);
}
-| maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
{
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11);
}
-| maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
+| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
{
$$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
}
-| maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
+| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
{
$$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
}
$2,
mk_node("TTTok", 1, mk_atom("]")));
}
-;
+;
\ No newline at end of file
hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
trait_ref)
}
- ItemKind::Impl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
+ ItemKind::Impl(unsafety,
+ polarity,
+ defaultness,
+ ref generics,
+ ref ifce,
+ ref ty,
+ ref impl_items) => {
let new_impl_items = impl_items.iter()
.map(|item| self.lower_impl_item_ref(item))
.collect();
hir::ItemImpl(self.lower_unsafety(unsafety),
self.lower_impl_polarity(polarity),
+ self.lower_defaultness(defaultness, true /* [1] */),
self.lower_generics(generics),
ifce,
self.lower_ty(ty),
}
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
}
+
+ // [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to
+ // not cause an assertion failure inside the `lower_defaultness` function
}
fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
/// An implementation, eg `impl<A> Trait for Foo { .. }`
ItemImpl(Unsafety,
ImplPolarity,
+ Defaultness,
Generics,
Option<TraitRef>, // (optional) trait this impl implements
P<Ty>, // self
}
hir::ItemImpl(unsafety,
polarity,
+ defaultness,
ref generics,
ref opt_trait,
ref ty,
ref impl_items) => {
self.head("")?;
self.print_visibility(&item.vis)?;
+ self.print_defaultness(defaultness)?;
self.print_unsafety(unsafety)?;
self.word_nbsp("impl")?;
}
}
+ pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) -> io::Result<()> {
+ match defaultness {
+ hir::Defaultness::Default { .. } => self.word_nbsp("default")?,
+ hir::Defaultness::Final => (),
+ }
+ Ok(())
+ }
+
pub fn print_struct(&mut self,
struct_def: &hir::VariantData,
generics: &hir::Generics,
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(ii.span.lo)?;
self.print_outer_attributes(&ii.attrs)?;
-
- match ii.defaultness {
- hir::Defaultness::Default { .. } => self.word_nbsp("default")?,
- hir::Defaultness::Final => (),
- }
+ self.print_defaultness(ii.defaultness)?;
match ii.node {
hir::ImplItemKind::Const(ref ty, expr) => {
ItemUnion(variant_data, generics),
ItemTrait(unsafety, generics, bounds, item_refs),
ItemDefaultImpl(unsafety, trait_ref),
- ItemImpl(unsafety, impl_polarity, generics, trait_ref, ty, impl_item_refs)
+ ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
});
impl_stable_hash_for!(struct hir::TraitItemRef {
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
// impl info
+ fn impl_defaultness(&self, def: DefId) -> hir::Defaultness;
fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;
// trait/impl-item info
fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
// impl info
+ fn impl_defaultness(&self, def: DefId) -> hir::Defaultness { bug!("impl_defaultness") }
fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
// trait/impl-item info
}
match item.node {
- hir::ItemImpl(_, _, ref generics, ..) |
+ hir::ItemImpl(_, _, _, ref generics, ..) |
hir::ItemFn(.., ref generics, _) => {
generics_require_inlining(generics)
}
// does too.
let impl_node_id = self.tcx.hir.as_local_node_id(impl_did).unwrap();
match self.tcx.hir.expect_item(impl_node_id).node {
- hir::ItemImpl(_, _, ref generics, ..) => {
+ hir::ItemImpl(_, _, _, ref generics, ..) => {
generics_require_inlining(generics)
}
_ => false
hir::ItemStruct(_, ref generics) |
hir::ItemUnion(_, ref generics) |
hir::ItemTrait(_, ref generics, ..) |
- hir::ItemImpl(_, _, ref generics, ..) => {
+ hir::ItemImpl(_, _, _, ref generics, ..) => {
// These kinds of items have only early bound lifetime parameters.
let mut index = if let hir::ItemTrait(..) = item.node {
1 // Self comes before lifetimes
}
match parent.node {
hir::ItemTrait(_, ref generics, ..) |
- hir::ItemImpl(_, _, ref generics, ..) => {
+ hir::ItemImpl(_, _, _, ref generics, ..) => {
index += (generics.lifetimes.len() + generics.ty_params.len()) as u32;
}
_ => {}
// being invoked).
node_item.item.defaultness.has_value()
} else {
- node_item.item.defaultness.is_default()
+ node_item.item.defaultness.is_default() ||
+ selcx.tcx().impl_is_default(node_item.node.def_id())
};
// Only reveal a specializable default if we're past type-checking
use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
use ty::outlives::Component;
use util::nodemap::FxHashSet;
+use hir::{self};
+use traits::specialize::specialization_graph::NodeItem;
use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
};
ty::Binder((trait_ref, sig.skip_binder().output()))
}
+
+ pub fn impl_is_default(self, node_item_def_id: DefId) -> bool {
+ match self.hir.as_local_node_id(node_item_def_id) {
+ Some(node_id) => {
+ let item = self.hir.expect_item(node_id);
+ if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
+ defaultness.is_default()
+ } else {
+ false
+ }
+ }
+ None => {
+ self.global_tcx()
+ .sess
+ .cstore
+ .impl_defaultness(node_item_def_id)
+ .is_default()
+ }
+ }
+ }
+
+ pub fn impl_item_is_final(self, node_item: &NodeItem<hir::Defaultness>) -> bool {
+ node_item.item.is_final() && !self.impl_is_default(node_item.node.def_id())
+ }
}
pub enum TupleArgumentsFlag { Yes, No }
result
}
+ fn impl_defaultness(&self, def: DefId) -> hir::Defaultness
+ {
+ self.dep_graph.read(DepNode::MetaData(def));
+ self.get_crate_data(def.krate).get_impl_defaultness(def.index)
+ }
+
fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
self.dep_graph.read(DepNode::MetaData(impl_def));
self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index)
self.get_impl_data(id).polarity
}
+ pub fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness {
+ self.get_impl_data(id).defaultness
+ }
+
pub fn get_coerce_unsized_info(&self,
id: DefIndex)
-> Option<ty::adjustment::CoerceUnsizedInfo> {
hir::ItemDefaultImpl(..) => {
let data = ImplData {
polarity: hir::ImplPolarity::Positive,
+ defaultness: hir::Defaultness::Final,
parent_impl: None,
coerce_unsized_info: None,
trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
EntryKind::DefaultImpl(self.lazy(&data))
}
- hir::ItemImpl(_, polarity, ..) => {
+ hir::ItemImpl(_, polarity, defaultness, ..) => {
let trait_ref = tcx.impl_trait_ref(def_id);
let parent = if let Some(trait_ref) = trait_ref {
let trait_def = tcx.trait_def(trait_ref.def_id);
let data = ImplData {
polarity: polarity,
+ defaultness: defaultness,
parent_impl: parent,
coerce_unsized_info: coerce_unsized_info,
trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
#[derive(RustcEncodable, RustcDecodable)]
pub struct ImplData<'tcx> {
pub polarity: hir::ImplPolarity,
+ pub defaultness: hir::Defaultness,
pub parent_impl: Option<DefId>,
/// This is `Some` only for impls of `CoerceUnsized`.
impl_stable_hash_for!(struct ImplData<'tcx> {
polarity,
+ defaultness,
parent_impl,
coerce_unsized_info,
trait_ref
}
None => {
if let Some(NodeItem(item)) = self.tcx.hir.get_if_local(id) {
- if let hir::ItemImpl(_, _, _, _, ref ty, _) = item.node {
+ if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node {
trait_id = self.lookup_def_id(ty.id);
}
}
let parent_node_id = hir_map.get_parent_node(ii.id);
let is_impl_generic = match hir_map.expect_item(parent_node_id) {
&hir::Item {
- node: hir::ItemImpl(_, _, ref generics, ..),
+ node: hir::ItemImpl(_, _, _, ref generics, ..),
..
} => {
generics.is_type_parameterized()
let tcx = scx.tcx();
match item.node {
hir::ItemImpl(_,
+ _,
_,
ref generics,
..,
.map(|node_item| node_item.map(|parent| parent.defaultness));
if let Some(parent) = parent {
- if parent.item.is_final() {
+ if tcx.impl_item_is_final(&parent) {
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
}
}
///
/// won't be allowed unless there's an *explicit* implementation of `Send`
/// for `T`
- hir::ItemImpl(_, hir::ImplPolarity::Positive, _,
+ hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _,
ref trait_ref, ref self_ty, _) => {
self.check_impl(item, self_ty, trait_ref);
}
- hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), ..) => {
+ hir::ItemImpl(_, hir::ImplPolarity::Negative, _, _, Some(_), ..) => {
// FIXME(#27579) what amount of WF checking do we need for neg impls?
let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();
hir::ItemDefaultImpl(unsafety, _) => {
self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive);
}
- hir::ItemImpl(unsafety, polarity, ref generics, Some(_), _, _) => {
+ hir::ItemImpl(unsafety, polarity, _, ref generics, ..) => {
self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
}
_ => {}
NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
- ItemImpl(_, _, ref generics, ..) |
+ ItemImpl(_, _, _, ref generics, ..) |
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
- ItemImpl(_, _, ref generics, ..) => generics,
+ ItemImpl(_, _, _, ref generics, ..) => generics,
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
- ItemImpl(_, _, ref generics, ..) |
+ ItemImpl(_, _, _, ref generics, ..) |
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
pub struct Impl {
pub unsafety: hir::Unsafety,
pub polarity: hir::ImplPolarity,
+ pub defaultness: hir::Defaultness,
pub generics: hir::Generics,
pub trait_: Option<hir::TraitRef>,
pub for_: P<hir::Ty>,
om.traits.push(t);
},
- hir::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref item_ids) => {
+ hir::ItemImpl(unsafety,
+ polarity,
+ defaultness,
+ ref gen,
+ ref tr,
+ ref ty,
+ ref item_ids) => {
// Don't duplicate impls when inlining, we'll pick them up
// regardless of where they're located.
if !self.inlining {
let i = Impl {
unsafety: unsafety,
polarity: polarity,
+ defaultness: defaultness,
generics: gen.clone(),
trait_: tr.clone(),
for_: ty.clone(),
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
Impl(Unsafety,
ImplPolarity,
+ Defaultness,
Generics,
Option<TraitRef>, // (optional) trait this impl implements
P<Ty>, // self
and possibly buggy");
}
- ast::ItemKind::Impl(_, polarity, _, _, _, _) => {
+ ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
match polarity {
ast::ImplPolarity::Negative => {
gate_feature_post!(&self, optin_builtin_traits,
},
_ => {}
}
+
+ if let ast::Defaultness::Default = defaultness {
+ gate_feature_post!(&self, specialization,
+ i.span,
+ "specialization is unstable");
+ }
}
_ => {}
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
ItemKind::DefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
}
- ItemKind::Impl(unsafety, polarity, generics, ifce, ty, impl_items) => ItemKind::Impl(
+ ItemKind::Impl(unsafety,
+ polarity,
+ defaultness,
+ generics,
+ ifce,
+ ty,
+ impl_items) => ItemKind::Impl(
unsafety,
polarity,
+ defaultness,
folder.fold_generics(generics),
ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref.clone())),
folder.fold_ty(ty),
/// impl<T> Foo { ... }
/// impl<T> ToString for &'static T { ... }
/// impl Send for .. {}
- fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> PResult<'a, ItemInfo> {
+ fn parse_item_impl(&mut self,
+ unsafety: ast::Unsafety,
+ defaultness: Defaultness) -> PResult<'a, ItemInfo> {
let impl_span = self.span;
// First, parse type parameters if necessary.
allowed to have generics");
}
+ if let ast::Defaultness::Default = defaultness {
+ self.span_err(impl_span, "`default impl` is not allowed for \
+ default trait implementations");
+ }
+
self.expect(&token::OpenDelim(token::Brace))?;
self.expect(&token::CloseDelim(token::Brace))?;
Ok((keywords::Invalid.ident(),
}
Ok((keywords::Invalid.ident(),
- ItemKind::Impl(unsafety, polarity, generics, opt_trait, ty, impl_items),
+ ItemKind::Impl(unsafety, polarity, defaultness, generics, opt_trait, ty, impl_items),
Some(attrs)))
}
}
maybe_append(attrs, extra_attrs));
return Ok(Some(item));
}
- if self.check_keyword(keywords::Unsafe) &&
- self.look_ahead(1, |t| t.is_keyword(keywords::Impl))
+ if (self.check_keyword(keywords::Unsafe) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
+ (self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
+ self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
{
// IMPL ITEM
+ let defaultness = self.parse_defaultness()?;
self.expect_keyword(keywords::Unsafe)?;
self.expect_keyword(keywords::Impl)?;
- let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe)?;
+ let (ident,
+ item_,
+ extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe, defaultness)?;
let prev_span = self.prev_span;
let item = self.mk_item(lo.to(prev_span),
ident,
maybe_append(attrs, extra_attrs));
return Ok(Some(item));
}
- if self.eat_keyword(keywords::Impl) {
+ if (self.check_keyword(keywords::Impl)) ||
+ (self.check_keyword(keywords::Default) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Impl)))
+ {
// IMPL ITEM
- let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal)?;
+ let defaultness = self.parse_defaultness()?;
+ self.expect_keyword(keywords::Impl)?;
+ let (ident,
+ item_,
+ extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal, defaultness)?;
let prev_span = self.prev_span;
let item = self.mk_item(lo.to(prev_span),
ident,
}
ast::ItemKind::Impl(unsafety,
polarity,
+ defaultness,
ref generics,
ref opt_trait,
ref ty,
ref impl_items) => {
self.head("")?;
self.print_visibility(&item.vis)?;
+ self.print_defaultness(defaultness)?;
self.print_unsafety(unsafety)?;
self.word_nbsp("impl")?;
}
}
+ pub fn print_defaultness(&mut self, defatulness: ast::Defaultness) -> io::Result<()> {
+ if let ast::Defaultness::Default = defatulness {
+ try!(self.word_nbsp("default"));
+ }
+ Ok(())
+ }
+
pub fn print_struct(&mut self,
struct_def: &ast::VariantData,
generics: &ast::Generics,
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(ii.span.lo)?;
self.print_outer_attributes(&ii.attrs)?;
- if let ast::Defaultness::Default = ii.defaultness {
- self.word_nbsp("default")?;
- }
+ self.print_defaultness(ii.defaultness)?;
match ii.node {
ast::ImplItemKind::Const(ref ty, ref expr) => {
self.print_associated_const(ii.ident, &ty, Some(&expr), &ii.vis)?;
ItemKind::DefaultImpl(_, ref trait_ref) => {
visitor.visit_trait_ref(trait_ref)
}
- ItemKind::Impl(_, _,
+ ItemKind::Impl(_, _, _,
ref type_parameters,
ref opt_trait_reference,
ref typ,
a,
ast::ItemKind::Impl(unsafety,
ast::ImplPolarity::Positive,
+ ast::Defaultness::Final,
trait_generics,
opt_trait_ref,
self_type,
--- /dev/null
+// 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.
+
+#![feature(specialization)]
+
+// Make sure we can't project defaulted associated types
+
+trait Foo {
+ type Assoc;
+}
+
+default impl<T> Foo for T {
+ type Assoc = ();
+}
+
+impl Foo for u8 {
+ type Assoc = String;
+}
+
+fn generic<T>() -> <T as Foo>::Assoc {
+ // `T` could be some downstream crate type that specializes (or,
+ // for that matter, `u8`).
+
+ () //~ ERROR mismatched types
+}
+
+fn monomorphic() -> () {
+ // Even though we know that `()` is not specialized in a
+ // downstream crate, typeck refuses to project here.
+
+ generic::<()>() //~ ERROR mismatched types
+}
+
+fn main() {
+ // No error here, we CAN project from `u8`, as there is no `default`
+ // in that impl.
+ let s: String = generic::<u8>();
+ println!("{}", s); // bad news if this all compiles
+}
--- /dev/null
+// 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.
+
+// It should not be possible to use the concrete value of a defaulted
+// associated type in the impl defining it -- otherwise, what happens
+// if it's overridden?
+
+#![feature(specialization)]
+
+trait Example {
+ type Output;
+ fn generate(self) -> Self::Output;
+}
+
+default impl<T> Example for T {
+ type Output = Box<T>;
+ fn generate(self) -> Self::Output {
+ Box::new(self) //~ ERROR mismatched types
+ }
+}
+
+impl Example for bool {
+ type Output = bool;
+ fn generate(self) -> bool { self }
+}
+
+fn trouble<T>(t: T) -> Box<T> {
+ Example::generate(t) //~ ERROR mismatched types
+}
+
+fn weaponize() -> bool {
+ let b: Box<bool> = trouble(true);
+ *b
+}
+
+fn main() {
+ weaponize();
+}
--- /dev/null
+// 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.
+
+// Check that specialization must be ungated to use the `default` keyword
+
+trait Foo {
+ fn foo(&self);
+}
+
+default impl<T> Foo for T { //~ ERROR specialization is unstable
+ fn foo(&self) {}
+}
+
+fn main() {}
--- /dev/null
+// 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.
+
+#![feature(specialization)]
+#![feature(optin_builtin_traits)]
+
+trait Foo {}
+
+default impl Foo for .. {}
+//~^ ERROR `default impl` is not allowed for default trait implementations
+
+fn main() {}
--- /dev/null
+// 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.
+
+#![feature(specialization)]
+
+// Check a number of scenarios in which one impl tries to override another,
+// without correctly using `default`.
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 1: one layer of specialization, multiple methods, missing `default`
+////////////////////////////////////////////////////////////////////////////////
+
+trait Foo {
+ fn foo(&self);
+ fn bar(&self);
+}
+
+impl<T> Foo for T {
+ fn foo(&self) {}
+ fn bar(&self) {}
+}
+
+impl Foo for u8 {}
+impl Foo for u16 {
+ fn foo(&self) {} //~ ERROR E0520
+}
+impl Foo for u32 {
+ fn bar(&self) {} //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 2: one layer of specialization, missing `default` on associated type
+////////////////////////////////////////////////////////////////////////////////
+
+trait Bar {
+ type T;
+}
+
+impl<T> Bar for T {
+ type T = u8;
+}
+
+impl Bar for u8 {
+ type T = (); //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 3a: multiple layers of specialization, missing interior `default`
+////////////////////////////////////////////////////////////////////////////////
+
+trait Baz {
+ fn baz(&self);
+}
+
+default impl<T> Baz for T {
+ fn baz(&self) {}
+}
+
+impl<T: Clone> Baz for T {
+ fn baz(&self) {}
+}
+
+impl Baz for i32 {
+ fn baz(&self) {} //~ ERROR E0520
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 3b: multiple layers of specialization, missing interior `default`,
+// redundant `default` in bottom layer.
+////////////////////////////////////////////////////////////////////////////////
+
+trait Redundant {
+ fn redundant(&self);
+}
+
+default impl<T> Redundant for T {
+ fn redundant(&self) {}
+}
+
+impl<T: Clone> Redundant for T {
+ fn redundant(&self) {}
+}
+
+default impl Redundant for i32 {
+ fn redundant(&self) {} //~ ERROR E0520
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2014 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.
+
+#![feature(specialization)]
+
+// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy.
+
+pub trait Go {
+ fn go(&self, arg: isize);
+}
+
+pub fn go<G:Go>(this: &G, arg: isize) {
+ this.go(arg)
+}
+
+pub trait GoMut {
+ fn go_mut(&mut self, arg: isize);
+}
+
+pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) {
+ this.go_mut(arg)
+}
+
+pub trait GoOnce {
+ fn go_once(self, arg: isize);
+}
+
+pub fn go_once<G:GoOnce>(this: G, arg: isize) {
+ this.go_once(arg)
+}
+
+default impl<G> GoMut for G
+ where G : Go
+{
+ fn go_mut(&mut self, arg: isize) {
+ go(&*self, arg)
+ }
+}
+
+default impl<G> GoOnce for G
+ where G : GoMut
+{
+ fn go_once(mut self, arg: isize) {
+ go_mut(&mut self, arg)
+ }
+}
--- /dev/null
+// 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.
+
+#![feature(specialization)]
+
+pub trait Foo {
+ fn foo(&self) -> &'static str;
+}
+
+default impl<T> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic"
+ }
+}
+
+default impl<T: Clone> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone"
+ }
+}
+
+default impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
+ fn foo(&self) -> &'static str {
+ "generic pair"
+ }
+}
+
+default impl<T: Clone> Foo for (T, T) {
+ fn foo(&self) -> &'static str {
+ "generic uniform pair"
+ }
+}
+
+default impl Foo for (u8, u32) {
+ fn foo(&self) -> &'static str {
+ "(u8, u32)"
+ }
+}
+
+default impl Foo for (u8, u8) {
+ fn foo(&self) -> &'static str {
+ "(u8, u8)"
+ }
+}
+
+default impl<T: Clone> Foo for Vec<T> {
+ fn foo(&self) -> &'static str {
+ "generic Vec"
+ }
+}
+
+impl Foo for Vec<i32> {
+ fn foo(&self) -> &'static str {
+ "Vec<i32>"
+ }
+}
+
+impl Foo for String {
+ fn foo(&self) -> &'static str {
+ "String"
+ }
+}
+
+impl Foo for i32 {
+ fn foo(&self) -> &'static str {
+ "i32"
+ }
+}
+
+pub trait MyMarker {}
+default impl<T: Clone + MyMarker> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone + MyMarker"
+ }
+}
--- /dev/null
+// 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.
+
+
+#![feature(specialization)]
+
+// First, test only use of explicit `default` items:
+
+pub trait Foo {
+ fn foo(&self) -> bool;
+}
+
+default impl<T> Foo for T {
+ fn foo(&self) -> bool { false }
+}
+
+impl Foo for i32 {}
+
+impl Foo for i64 {
+ fn foo(&self) -> bool { true }
+}
+
+// Next, test mixture of explicit `default` and provided methods:
+
+pub trait Bar {
+ fn bar(&self) -> i32 { 0 }
+}
+
+impl<T> Bar for T {} // use the provided method
+
+impl Bar for i32 {
+ fn bar(&self) -> i32 { 1 }
+}
+impl<'a> Bar for &'a str {}
+
+default impl<T> Bar for Vec<T> {
+ fn bar(&self) -> i32 { 2 }
+}
+impl Bar for Vec<i32> {}
+impl Bar for Vec<i64> {
+ fn bar(&self) -> i32 { 3 }
+}
--- /dev/null
+// Copyright 2014 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.
+
+// aux-build:go_trait.rs
+
+#![feature(specialization)]
+
+extern crate go_trait;
+
+use go_trait::{Go,GoMut};
+use std::fmt::Debug;
+use std::default::Default;
+
+struct MyThingy;
+
+impl Go for MyThingy {
+ fn go(&self, arg: isize) { }
+}
+
+impl GoMut for MyThingy {
+ fn go_mut(&mut self, arg: isize) { }
+}
+
+fn main() { }
--- /dev/null
+// 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 non-method associated functions can be specialized
+
+#![feature(specialization)]
+
+trait Foo {
+ fn mk() -> Self;
+}
+
+default impl<T: Default> Foo for T {
+ fn mk() -> T {
+ T::default()
+ }
+}
+
+impl Foo for Vec<u8> {
+ fn mk() -> Vec<u8> {
+ vec![0]
+ }
+}
+
+fn main() {
+ let v1: Vec<i32> = Foo::mk();
+ let v2: Vec<u8> = Foo::mk();
+
+ assert!(v1.len() == 0);
+ assert!(v2.len() == 1);
+}
--- /dev/null
+// Copyright 2014 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.
+
+#![feature(specialization)]
+
+// Tests a variety of basic specialization scenarios and method
+// dispatch for them.
+
+unsafe trait Foo {
+ fn foo(&self) -> &'static str;
+}
+
+default unsafe impl<T> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic"
+ }
+}
+
+default unsafe impl<T: Clone> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone"
+ }
+}
+
+default unsafe impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
+ fn foo(&self) -> &'static str {
+ "generic pair"
+ }
+}
+
+default unsafe impl<T: Clone> Foo for (T, T) {
+ fn foo(&self) -> &'static str {
+ "generic uniform pair"
+ }
+}
+
+default unsafe impl Foo for (u8, u32) {
+ fn foo(&self) -> &'static str {
+ "(u8, u32)"
+ }
+}
+
+default unsafe impl Foo for (u8, u8) {
+ fn foo(&self) -> &'static str {
+ "(u8, u8)"
+ }
+}
+
+default unsafe impl<T: Clone> Foo for Vec<T> {
+ fn foo(&self) -> &'static str {
+ "generic Vec"
+ }
+}
+
+default unsafe impl Foo for Vec<i32> {
+ fn foo(&self) -> &'static str {
+ "Vec<i32>"
+ }
+}
+
+default unsafe impl Foo for String {
+ fn foo(&self) -> &'static str {
+ "String"
+ }
+}
+
+default unsafe impl Foo for i32 {
+ fn foo(&self) -> &'static str {
+ "i32"
+ }
+}
+
+struct NotClone;
+
+unsafe trait MyMarker {}
+default unsafe impl<T: Clone + MyMarker> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone + MyMarker"
+ }
+}
+
+#[derive(Clone)]
+struct MarkedAndClone;
+unsafe impl MyMarker for MarkedAndClone {}
+
+fn main() {
+ assert!(NotClone.foo() == "generic");
+ assert!(0u8.foo() == "generic Clone");
+ assert!(vec![NotClone].foo() == "generic");
+ assert!(vec![0u8].foo() == "generic Vec");
+ assert!(vec![0i32].foo() == "Vec<i32>");
+ assert!(0i32.foo() == "i32");
+ assert!(String::new().foo() == "String");
+ assert!(((), 0).foo() == "generic pair");
+ assert!(((), ()).foo() == "generic uniform pair");
+ assert!((0u8, 0u32).foo() == "(u8, u32)");
+ assert!((0u8, 0u8).foo() == "(u8, u8)");
+ assert!(MarkedAndClone.foo() == "generic Clone + MyMarker");
+}
--- /dev/null
+// Copyright 2014 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.
+
+#![feature(specialization)]
+
+// Tests a variety of basic specialization scenarios and method
+// dispatch for them.
+
+trait Foo {
+ fn foo(&self) -> &'static str;
+}
+
+default impl<T> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic"
+ }
+}
+
+default impl<T: Clone> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone"
+ }
+}
+
+default impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
+ fn foo(&self) -> &'static str {
+ "generic pair"
+ }
+}
+
+default impl<T: Clone> Foo for (T, T) {
+ fn foo(&self) -> &'static str {
+ "generic uniform pair"
+ }
+}
+
+default impl Foo for (u8, u32) {
+ fn foo(&self) -> &'static str {
+ "(u8, u32)"
+ }
+}
+
+default impl Foo for (u8, u8) {
+ fn foo(&self) -> &'static str {
+ "(u8, u8)"
+ }
+}
+
+default impl<T: Clone> Foo for Vec<T> {
+ fn foo(&self) -> &'static str {
+ "generic Vec"
+ }
+}
+
+impl Foo for Vec<i32> {
+ fn foo(&self) -> &'static str {
+ "Vec<i32>"
+ }
+}
+
+impl Foo for String {
+ fn foo(&self) -> &'static str {
+ "String"
+ }
+}
+
+impl Foo for i32 {
+ fn foo(&self) -> &'static str {
+ "i32"
+ }
+}
+
+struct NotClone;
+
+trait MyMarker {}
+default impl<T: Clone + MyMarker> Foo for T {
+ fn foo(&self) -> &'static str {
+ "generic Clone + MyMarker"
+ }
+}
+
+#[derive(Clone)]
+struct MarkedAndClone;
+impl MyMarker for MarkedAndClone {}
+
+fn main() {
+ assert!(NotClone.foo() == "generic");
+ assert!(0u8.foo() == "generic Clone");
+ assert!(vec![NotClone].foo() == "generic");
+ assert!(vec![0u8].foo() == "generic Vec");
+ assert!(vec![0i32].foo() == "Vec<i32>");
+ assert!(0i32.foo() == "i32");
+ assert!(String::new().foo() == "String");
+ assert!(((), 0).foo() == "generic pair");
+ assert!(((), ()).foo() == "generic uniform pair");
+ assert!((0u8, 0u32).foo() == "(u8, u32)");
+ assert!((0u8, 0u8).foo() == "(u8, u8)");
+ assert!(MarkedAndClone.foo() == "generic Clone + MyMarker");
+}
--- /dev/null
+// 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.
+
+// aux-build:specialization_cross_crate_defaults.rs
+
+#![feature(specialization)]
+
+extern crate specialization_cross_crate_defaults;
+
+use specialization_cross_crate_defaults::*;
+
+struct LocalDefault;
+struct LocalOverride;
+
+impl Foo for LocalDefault {}
+
+impl Foo for LocalOverride {
+ fn foo(&self) -> bool { true }
+}
+
+fn test_foo() {
+ assert!(!0i8.foo());
+ assert!(!0i32.foo());
+ assert!(0i64.foo());
+
+ assert!(!LocalDefault.foo());
+ assert!(LocalOverride.foo());
+}
+
+fn test_bar() {
+ assert!(0u8.bar() == 0);
+ assert!(0i32.bar() == 1);
+ assert!("hello".bar() == 0);
+ assert!(vec![()].bar() == 2);
+ assert!(vec![0i32].bar() == 2);
+ assert!(vec![0i64].bar() == 3);
+}
+
+fn main() {
+ test_foo();
+ test_bar();
+}
--- /dev/null
+// 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 specialization works even if only the upstream crate enables it
+
+// aux-build:specialization_cross_crate.rs
+
+extern crate specialization_cross_crate;
+
+use specialization_cross_crate::*;
+
+fn main() {
+ assert!(0u8.foo() == "generic Clone");
+ assert!(vec![0u8].foo() == "generic Vec");
+ assert!(vec![0i32].foo() == "Vec<i32>");
+ assert!(0i32.foo() == "i32");
+ assert!(String::new().foo() == "String");
+ assert!(((), 0).foo() == "generic pair");
+ assert!(((), ()).foo() == "generic uniform pair");
+ assert!((0u8, 0u32).foo() == "(u8, u32)");
+ assert!((0u8, 0u8).foo() == "(u8, u8)");
+}
--- /dev/null
+// 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.
+
+// aux-build:specialization_cross_crate.rs
+
+#![feature(specialization)]
+
+extern crate specialization_cross_crate;
+
+use specialization_cross_crate::*;
+
+struct NotClone;
+
+#[derive(Clone)]
+struct MarkedAndClone;
+impl MyMarker for MarkedAndClone {}
+
+struct MyType<T>(T);
+default impl<T> Foo for MyType<T> {
+ fn foo(&self) -> &'static str {
+ "generic MyType"
+ }
+}
+
+impl Foo for MyType<u8> {
+ fn foo(&self) -> &'static str {
+ "MyType<u8>"
+ }
+}
+
+struct MyOtherType;
+impl Foo for MyOtherType {}
+
+fn main() {
+ assert!(NotClone.foo() == "generic");
+ assert!(0u8.foo() == "generic Clone");
+ assert!(vec![NotClone].foo() == "generic");
+ assert!(vec![0u8].foo() == "generic Vec");
+ assert!(vec![0i32].foo() == "Vec<i32>");
+ assert!(0i32.foo() == "i32");
+ assert!(String::new().foo() == "String");
+ assert!(((), 0).foo() == "generic pair");
+ assert!(((), ()).foo() == "generic uniform pair");
+ assert!((0u8, 0u32).foo() == "(u8, u32)");
+ assert!((0u8, 0u8).foo() == "(u8, u8)");
+ assert!(MarkedAndClone.foo() == "generic Clone + MyMarker");
+
+ assert!(MyType(()).foo() == "generic MyType");
+ assert!(MyType(0u8).foo() == "MyType<u8>");
+ assert!(MyOtherType.foo() == "generic");
+}
--- /dev/null
+// 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.
+
+#![feature(specialization)]
+
+// Test that default methods are cascaded correctly
+
+// First, test only use of explicit `default` items:
+
+trait Foo {
+ fn foo(&self) -> bool;
+}
+
+// Specialization tree for Foo:
+//
+// T
+// / \
+// i32 i64
+
+default impl<T> Foo for T {
+ fn foo(&self) -> bool { false }
+}
+
+impl Foo for i32 {}
+
+impl Foo for i64 {
+ fn foo(&self) -> bool { true }
+}
+
+fn test_foo() {
+ assert!(!0i8.foo());
+ assert!(!0i32.foo());
+ assert!(0i64.foo());
+}
+
+// Next, test mixture of explicit `default` and provided methods:
+
+trait Bar {
+ fn bar(&self) -> i32 { 0 }
+}
+
+// Specialization tree for Bar.
+// Uses of $ designate that method is provided
+//
+// $Bar (the trait)
+// |
+// T
+// /|\
+// / | \
+// / | \
+// / | \
+// / | \
+// / | \
+// $i32 &str $Vec<T>
+// /\
+// / \
+// Vec<i32> $Vec<i64>
+
+// use the provided method
+impl<T> Bar for T {}
+
+impl Bar for i32 {
+ fn bar(&self) -> i32 { 1 }
+}
+impl<'a> Bar for &'a str {}
+
+default impl<T> Bar for Vec<T> {
+ fn bar(&self) -> i32 { 2 }
+}
+impl Bar for Vec<i32> {}
+impl Bar for Vec<i64> {
+ fn bar(&self) -> i32 { 3 }
+}
+
+fn test_bar() {
+ assert!(0u8.bar() == 0);
+ assert!(0i32.bar() == 1);
+ assert!("hello".bar() == 0);
+ assert!(vec![()].bar() == 2);
+ assert!(vec![0i32].bar() == 2);
+ assert!(vec![0i64].bar() == 3);
+}
+
+fn main() {
+ test_foo();
+ test_bar();
+}
--- /dev/null
+// Copyright 2016 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 you can list the more specific impl before the more general one.
+
+#![feature(specialization)]
+
+trait Foo {
+ type Out;
+}
+
+impl Foo for bool {
+ type Out = ();
+}
+
+default impl<T> Foo for T {
+ type Out = bool;
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2016 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 impls on projected self types can resolve overlap, even when the
+// projections involve specialization, so long as the associated type is
+// provided by the most specialized impl.
+
+#![feature(specialization)]
+
+trait Assoc {
+ type Output;
+}
+
+default impl<T> Assoc for T {
+ type Output = bool;
+}
+
+impl Assoc for u8 { type Output = u8; }
+impl Assoc for u16 { type Output = u16; }
+
+trait Foo {}
+impl Foo for u32 {}
+impl Foo for <u8 as Assoc>::Output {}
+impl Foo for <u16 as Assoc>::Output {}
+
+fn main() {}
--- /dev/null
+// Copyright 2016 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.
+
+#![feature(specialization)]
+
+// Regression test for ICE when combining specialized associated types and type
+// aliases
+
+trait Id_ {
+ type Out;
+}
+
+type Id<T> = <T as Id_>::Out;
+
+default impl<T> Id_ for T {
+ type Out = T;
+}
+
+fn test_proection() {
+ let x: Id<bool> = panic!();
+}
+
+fn main() {
+
+}
--- /dev/null
+// 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.
+
+#![feature(specialization)]
+
+// Make sure we *can* project non-defaulted associated types
+// cf compile-fail/specialization-default-projection.rs
+
+// First, do so without any use of specialization
+
+trait Foo {
+ type Assoc;
+}
+
+impl<T> Foo for T {
+ type Assoc = ();
+}
+
+fn generic_foo<T>() -> <T as Foo>::Assoc {
+ ()
+}
+
+// Next, allow for one layer of specialization
+
+trait Bar {
+ type Assoc;
+}
+
+default impl<T> Bar for T {
+ type Assoc = ();
+}
+
+impl<T: Clone> Bar for T {
+ type Assoc = u8;
+}
+
+fn generic_bar_clone<T: Clone>() -> <T as Bar>::Assoc {
+ 0u8
+}
+
+fn main() {
+}