support default impl
for specialization
this commit implements the first step of the `default impl` feature: all items in a `default impl` are (implicitly) `default` and hence specializable. In order to test this feature I've copied all the tests provided for the `default` method implementation (in run-pass/specialization and compile-fail/specialization directories) and moved the `default` keyword from the item to the impl. See referenced issue for further info
This commit is contained in:
parent
15ce54096a
commit
116e9831a5
50 changed files with 1078 additions and 41 deletions
2
cargo
2
cargo
|
@ -1 +1 @@
|
||||||
Subproject commit 8326a3683a9045d825e4fdc4021af340ee3b3755
|
Subproject commit c416fb60b11ecfd2a1ba0fb8567c9a92590b5d28
|
2
rls
2
rls
|
@ -1 +1 @@
|
||||||
Subproject commit 6ecff95fdc3ee7ceed2b9b0cc1a3a64876860bce
|
Subproject commit 016cbc514cf44a2bd3fe806e8afa6b9c50287373
|
|
@ -1 +1 @@
|
||||||
Subproject commit d30da544a8afc5d78391dee270bdf40e74a215d3
|
Subproject commit a8fc4c169fac43a5dc204d4fd56ddb1739f8c178
|
|
@ -1 +1 @@
|
||||||
Subproject commit ad7de198561b3a12217ea2da76d796d9c7fc0ed3
|
Subproject commit beea82b9230cd641dd1ca263cf31025ace4aebb5
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6b0de90d87dda15e323ef24cdf7ed873ac5cf4d3
|
Subproject commit b060f732145f2fa16df84c74e511df08a3a47c5d
|
|
@ -1 +1 @@
|
||||||
Subproject commit 11bfb0dcf85f7aa92abd30524bb1e42e18d108c6
|
Subproject commit e058ca661692a8d01f8cf9d35939dfe3105ce968
|
|
@ -1 +1 @@
|
||||||
Subproject commit c34a802d1eb037b44c5252078c7270b5472e0f65
|
Subproject commit 05a2d197356ef253dfd985166576619ac9b6947f
|
|
@ -1326,7 +1326,13 @@ impl<'a> LoweringContext<'a> {
|
||||||
hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
|
hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
|
||||||
trait_ref)
|
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()
|
let new_impl_items = impl_items.iter()
|
||||||
.map(|item| self.lower_impl_item_ref(item))
|
.map(|item| self.lower_impl_item_ref(item))
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -1340,6 +1346,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
hir::ItemImpl(self.lower_unsafety(unsafety),
|
hir::ItemImpl(self.lower_unsafety(unsafety),
|
||||||
self.lower_impl_polarity(polarity),
|
self.lower_impl_polarity(polarity),
|
||||||
|
self.lower_defaultness(defaultness),
|
||||||
self.lower_generics(generics),
|
self.lower_generics(generics),
|
||||||
ifce,
|
ifce,
|
||||||
self.lower_ty(ty),
|
self.lower_ty(ty),
|
||||||
|
|
|
@ -1712,6 +1712,7 @@ pub enum Item_ {
|
||||||
/// An implementation, eg `impl<A> Trait for Foo { .. }`
|
/// An implementation, eg `impl<A> Trait for Foo { .. }`
|
||||||
ItemImpl(Unsafety,
|
ItemImpl(Unsafety,
|
||||||
ImplPolarity,
|
ImplPolarity,
|
||||||
|
Defaultness,
|
||||||
Generics,
|
Generics,
|
||||||
Option<TraitRef>, // (optional) trait this impl implements
|
Option<TraitRef>, // (optional) trait this impl implements
|
||||||
P<Ty>, // self
|
P<Ty>, // self
|
||||||
|
|
|
@ -678,12 +678,14 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
hir::ItemImpl(unsafety,
|
hir::ItemImpl(unsafety,
|
||||||
polarity,
|
polarity,
|
||||||
|
defaultness,
|
||||||
ref generics,
|
ref generics,
|
||||||
ref opt_trait,
|
ref opt_trait,
|
||||||
ref ty,
|
ref ty,
|
||||||
ref impl_items) => {
|
ref impl_items) => {
|
||||||
self.head("")?;
|
self.head("")?;
|
||||||
self.print_visibility(&item.vis)?;
|
self.print_visibility(&item.vis)?;
|
||||||
|
self.print_defaultness(defaultness)?;
|
||||||
self.print_unsafety(unsafety)?;
|
self.print_unsafety(unsafety)?;
|
||||||
self.word_nbsp("impl")?;
|
self.word_nbsp("impl")?;
|
||||||
|
|
||||||
|
@ -820,6 +822,13 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) -> io::Result<()> {
|
||||||
|
if let hir::Defaultness::Default = defaultness {
|
||||||
|
self.word_nbsp("default")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_struct(&mut self,
|
pub fn print_struct(&mut self,
|
||||||
struct_def: &hir::VariantData,
|
struct_def: &hir::VariantData,
|
||||||
generics: &hir::Generics,
|
generics: &hir::Generics,
|
||||||
|
@ -931,11 +940,7 @@ impl<'a> State<'a> {
|
||||||
self.hardbreak_if_not_bol()?;
|
self.hardbreak_if_not_bol()?;
|
||||||
self.maybe_print_comment(ii.span.lo)?;
|
self.maybe_print_comment(ii.span.lo)?;
|
||||||
self.print_outer_attributes(&ii.attrs)?;
|
self.print_outer_attributes(&ii.attrs)?;
|
||||||
|
self.print_defaultness(ii.defaultness)?;
|
||||||
match ii.defaultness {
|
|
||||||
hir::Defaultness::Default { .. } => self.word_nbsp("default")?,
|
|
||||||
hir::Defaultness::Final => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
match ii.node {
|
match ii.node {
|
||||||
hir::ImplItemKind::Const(ref ty, expr) => {
|
hir::ImplItemKind::Const(ref ty, expr) => {
|
||||||
|
|
|
@ -50,7 +50,7 @@ fn item_might_be_inlined(item: &hir::Item) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
match item.node {
|
match item.node {
|
||||||
hir::ItemImpl(_, _, ref generics, ..) |
|
hir::ItemImpl(_, _, _, ref generics, ..) |
|
||||||
hir::ItemFn(.., ref generics, _) => {
|
hir::ItemFn(.., ref generics, _) => {
|
||||||
generics_require_inlining(generics)
|
generics_require_inlining(generics)
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||||
// does too.
|
// does too.
|
||||||
let impl_node_id = self.tcx.hir.as_local_node_id(impl_did).unwrap();
|
let impl_node_id = self.tcx.hir.as_local_node_id(impl_did).unwrap();
|
||||||
match self.tcx.hir.expect_item(impl_node_id).node {
|
match self.tcx.hir.expect_item(impl_node_id).node {
|
||||||
hir::ItemImpl(_, _, ref generics, ..) => {
|
hir::ItemImpl(_, _, _, ref generics, ..) => {
|
||||||
generics_require_inlining(generics)
|
generics_require_inlining(generics)
|
||||||
}
|
}
|
||||||
_ => false
|
_ => false
|
||||||
|
|
|
@ -331,7 +331,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
hir::ItemStruct(_, ref generics) |
|
hir::ItemStruct(_, ref generics) |
|
||||||
hir::ItemUnion(_, ref generics) |
|
hir::ItemUnion(_, ref generics) |
|
||||||
hir::ItemTrait(_, ref generics, ..) |
|
hir::ItemTrait(_, ref generics, ..) |
|
||||||
hir::ItemImpl(_, _, ref generics, ..) => {
|
hir::ItemImpl(_, _, _, ref generics, ..) => {
|
||||||
// These kinds of items have only early bound lifetime parameters.
|
// These kinds of items have only early bound lifetime parameters.
|
||||||
let mut index = if let hir::ItemTrait(..) = item.node {
|
let mut index = if let hir::ItemTrait(..) = item.node {
|
||||||
1 // Self comes before lifetimes
|
1 // Self comes before lifetimes
|
||||||
|
@ -834,7 +834,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
match parent.node {
|
match parent.node {
|
||||||
hir::ItemTrait(_, ref generics, ..) |
|
hir::ItemTrait(_, ref generics, ..) |
|
||||||
hir::ItemImpl(_, _, ref generics, ..) => {
|
hir::ItemImpl(_, _, _, ref generics, ..) => {
|
||||||
index += (generics.lifetimes.len() + generics.ty_params.len()) as u32;
|
index += (generics.lifetimes.len() + generics.ty_params.len()) as u32;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -33,6 +33,7 @@ use ty::subst::Subst;
|
||||||
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
|
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
|
||||||
use ty::fold::{TypeFoldable, TypeFolder};
|
use ty::fold::{TypeFoldable, TypeFolder};
|
||||||
use util::common::FN_OUTPUT_NAME;
|
use util::common::FN_OUTPUT_NAME;
|
||||||
|
use hir::{self};
|
||||||
|
|
||||||
/// Depending on the stage of compilation, we want projection to be
|
/// Depending on the stage of compilation, we want projection to be
|
||||||
/// more or less conservative.
|
/// more or less conservative.
|
||||||
|
@ -923,7 +924,28 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
|
||||||
// being invoked).
|
// being invoked).
|
||||||
node_item.item.defaultness.has_value()
|
node_item.item.defaultness.has_value()
|
||||||
} else {
|
} else {
|
||||||
node_item.item.defaultness.is_default()
|
let is_default = match selcx.tcx()
|
||||||
|
.map
|
||||||
|
.as_local_node_id(node_item.node.def_id()) {
|
||||||
|
Some(node_id) => {
|
||||||
|
let item = selcx.tcx().map.expect_item(node_id);
|
||||||
|
if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
|
||||||
|
defaultness.is_default()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
selcx.tcx()
|
||||||
|
.global_tcx()
|
||||||
|
.sess
|
||||||
|
.cstore
|
||||||
|
.impl_defaultness(node_item.node.def_id())
|
||||||
|
.is_default()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
node_item.item.defaultness.is_default() || is_default
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only reveal a specializable default if we're past type-checking
|
// Only reveal a specializable default if we're past type-checking
|
||||||
|
|
|
@ -90,6 +90,7 @@ provide! { <'tcx> tcx, def_id, cdata
|
||||||
associated_item => { cdata.get_associated_item(def_id.index) }
|
associated_item => { cdata.get_associated_item(def_id.index) }
|
||||||
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
|
impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
|
||||||
impl_polarity => { cdata.get_impl_polarity(def_id.index) }
|
impl_polarity => { cdata.get_impl_polarity(def_id.index) }
|
||||||
|
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
|
||||||
coerce_unsized_info => {
|
coerce_unsized_info => {
|
||||||
cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
|
cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
|
||||||
bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
|
bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
|
||||||
|
|
|
@ -629,6 +629,10 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
self.get_impl_data(id).polarity
|
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,
|
pub fn get_coerce_unsized_info(&self,
|
||||||
id: DefIndex)
|
id: DefIndex)
|
||||||
-> Option<ty::adjustment::CoerceUnsizedInfo> {
|
-> Option<ty::adjustment::CoerceUnsizedInfo> {
|
||||||
|
|
|
@ -706,6 +706,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
||||||
hir::ItemDefaultImpl(..) => {
|
hir::ItemDefaultImpl(..) => {
|
||||||
let data = ImplData {
|
let data = ImplData {
|
||||||
polarity: hir::ImplPolarity::Positive,
|
polarity: hir::ImplPolarity::Positive,
|
||||||
|
defaultness: hir::Defaultness::Final,
|
||||||
parent_impl: None,
|
parent_impl: None,
|
||||||
coerce_unsized_info: None,
|
coerce_unsized_info: None,
|
||||||
trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
|
trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
|
||||||
|
@ -713,7 +714,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
||||||
|
|
||||||
EntryKind::DefaultImpl(self.lazy(&data))
|
EntryKind::DefaultImpl(self.lazy(&data))
|
||||||
}
|
}
|
||||||
hir::ItemImpl(_, polarity, ..) => {
|
hir::ItemImpl(_, polarity, defaultness, ..) => {
|
||||||
let trait_ref = tcx.impl_trait_ref(def_id);
|
let trait_ref = tcx.impl_trait_ref(def_id);
|
||||||
let parent = if let Some(trait_ref) = trait_ref {
|
let parent = if let Some(trait_ref) = trait_ref {
|
||||||
let trait_def = tcx.lookup_trait_def(trait_ref.def_id);
|
let trait_def = tcx.lookup_trait_def(trait_ref.def_id);
|
||||||
|
@ -740,6 +741,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> {
|
||||||
|
|
||||||
let data = ImplData {
|
let data = ImplData {
|
||||||
polarity: polarity,
|
polarity: polarity,
|
||||||
|
defaultness: defaultness,
|
||||||
parent_impl: parent,
|
parent_impl: parent,
|
||||||
coerce_unsized_info: coerce_unsized_info,
|
coerce_unsized_info: coerce_unsized_info,
|
||||||
trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
|
trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
|
||||||
|
|
|
@ -406,6 +406,7 @@ impl_stable_hash_for!(struct TraitData<'tcx> {
|
||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct ImplData<'tcx> {
|
pub struct ImplData<'tcx> {
|
||||||
pub polarity: hir::ImplPolarity,
|
pub polarity: hir::ImplPolarity,
|
||||||
|
pub defaultness: hir::Defaultness,
|
||||||
pub parent_impl: Option<DefId>,
|
pub parent_impl: Option<DefId>,
|
||||||
|
|
||||||
/// This is `Some` only for impls of `CoerceUnsized`.
|
/// This is `Some` only for impls of `CoerceUnsized`.
|
||||||
|
|
|
@ -429,8 +429,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let Some(NodeItem(item)) = self.tcx.hir.get_if_local(id) {
|
if let Some(NodeItem(item)) = self.tcx.map.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);
|
trait_id = self.lookup_def_id(ty.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -880,7 +880,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||||
let parent_node_id = hir_map.get_parent_node(ii.id);
|
let parent_node_id = hir_map.get_parent_node(ii.id);
|
||||||
let is_impl_generic = match hir_map.expect_item(parent_node_id) {
|
let is_impl_generic = match hir_map.expect_item(parent_node_id) {
|
||||||
&hir::Item {
|
&hir::Item {
|
||||||
node: hir::ItemImpl(_, _, ref generics, ..),
|
node: hir::ItemImpl(_, _, _, ref generics, ..),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
generics.is_type_parameterized()
|
generics.is_type_parameterized()
|
||||||
|
@ -911,6 +911,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
|
||||||
let tcx = scx.tcx();
|
let tcx = scx.tcx();
|
||||||
match item.node {
|
match item.node {
|
||||||
hir::ItemImpl(_,
|
hir::ItemImpl(_,
|
||||||
|
_,
|
||||||
_,
|
_,
|
||||||
ref generics,
|
ref generics,
|
||||||
..,
|
..,
|
||||||
|
|
|
@ -1142,7 +1142,23 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
if let Some(parent) = parent {
|
if let Some(parent) = parent {
|
||||||
if parent.item.is_final() {
|
if parent.item.is_final() {
|
||||||
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
|
let is_final = match tcx.map.as_local_node_id(parent.node.def_id()) {
|
||||||
|
Some(node_id) => {
|
||||||
|
let item = tcx.map.expect_item(node_id);
|
||||||
|
if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
|
||||||
|
defaultness.is_final()
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
tcx.global_tcx().sess.cstore.impl_defaultness(parent.node.def_id()).is_final()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_final {
|
||||||
|
report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,11 +105,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
||||||
///
|
///
|
||||||
/// won't be allowed unless there's an *explicit* implementation of `Send`
|
/// won't be allowed unless there's an *explicit* implementation of `Send`
|
||||||
/// for `T`
|
/// for `T`
|
||||||
hir::ItemImpl(_, hir::ImplPolarity::Positive, _,
|
hir::ItemImpl(_, hir::ImplPolarity::Positive, _, _,
|
||||||
ref trait_ref, ref self_ty, _) => {
|
ref trait_ref, ref self_ty, _) => {
|
||||||
self.check_impl(item, self_ty, trait_ref);
|
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?
|
// 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();
|
let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();
|
||||||
|
|
|
@ -87,7 +87,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> {
|
||||||
hir::ItemDefaultImpl(unsafety, _) => {
|
hir::ItemDefaultImpl(unsafety, _) => {
|
||||||
self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive);
|
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);
|
self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -214,6 +214,7 @@ pub struct Trait {
|
||||||
pub struct Impl {
|
pub struct Impl {
|
||||||
pub unsafety: hir::Unsafety,
|
pub unsafety: hir::Unsafety,
|
||||||
pub polarity: hir::ImplPolarity,
|
pub polarity: hir::ImplPolarity,
|
||||||
|
pub defaultness: hir::Defaultness,
|
||||||
pub generics: hir::Generics,
|
pub generics: hir::Generics,
|
||||||
pub trait_: Option<hir::TraitRef>,
|
pub trait_: Option<hir::TraitRef>,
|
||||||
pub for_: P<hir::Ty>,
|
pub for_: P<hir::Ty>,
|
||||||
|
|
|
@ -502,7 +502,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
om.traits.push(t);
|
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
|
// Don't duplicate impls when inlining, we'll pick them up
|
||||||
// regardless of where they're located.
|
// regardless of where they're located.
|
||||||
if !self.inlining {
|
if !self.inlining {
|
||||||
|
@ -512,6 +512,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
let i = Impl {
|
let i = Impl {
|
||||||
unsafety: unsafety,
|
unsafety: unsafety,
|
||||||
polarity: polarity,
|
polarity: polarity,
|
||||||
|
defaultness: defaultness,
|
||||||
generics: gen.clone(),
|
generics: gen.clone(),
|
||||||
trait_: tr.clone(),
|
trait_: tr.clone(),
|
||||||
for_: ty.clone(),
|
for_: ty.clone(),
|
||||||
|
|
|
@ -1852,6 +1852,7 @@ pub enum ItemKind {
|
||||||
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
|
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
|
||||||
Impl(Unsafety,
|
Impl(Unsafety,
|
||||||
ImplPolarity,
|
ImplPolarity,
|
||||||
|
Defaultness,
|
||||||
Generics,
|
Generics,
|
||||||
Option<TraitRef>, // (optional) trait this impl implements
|
Option<TraitRef>, // (optional) trait this impl implements
|
||||||
P<Ty>, // self
|
P<Ty>, // self
|
||||||
|
|
|
@ -1215,7 +1215,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
and possibly buggy");
|
and possibly buggy");
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ItemKind::Impl(_, polarity, _, _, _, _) => {
|
ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
|
||||||
match polarity {
|
match polarity {
|
||||||
ast::ImplPolarity::Negative => {
|
ast::ImplPolarity::Negative => {
|
||||||
gate_feature_post!(&self, optin_builtin_traits,
|
gate_feature_post!(&self, optin_builtin_traits,
|
||||||
|
@ -1225,6 +1225,15 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match defaultness {
|
||||||
|
ast::Defaultness::Default => {
|
||||||
|
gate_feature_post!(&self, specialization,
|
||||||
|
i.span,
|
||||||
|
"specialization is unstable");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -897,9 +897,16 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
|
||||||
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
|
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
|
||||||
ItemKind::DefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
|
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,
|
unsafety,
|
||||||
polarity,
|
polarity,
|
||||||
|
defaultness,
|
||||||
folder.fold_generics(generics),
|
folder.fold_generics(generics),
|
||||||
ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref.clone())),
|
ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref.clone())),
|
||||||
folder.fold_ty(ty),
|
folder.fold_ty(ty),
|
||||||
|
|
|
@ -4863,7 +4863,9 @@ impl<'a> Parser<'a> {
|
||||||
/// impl<T> Foo { ... }
|
/// impl<T> Foo { ... }
|
||||||
/// impl<T> ToString for &'static T { ... }
|
/// impl<T> ToString for &'static T { ... }
|
||||||
/// impl Send for .. {}
|
/// 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;
|
let impl_span = self.span;
|
||||||
|
|
||||||
// First, parse type parameters if necessary.
|
// First, parse type parameters if necessary.
|
||||||
|
@ -4944,7 +4946,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
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)))
|
Some(attrs)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5756,13 +5758,19 @@ impl<'a> Parser<'a> {
|
||||||
maybe_append(attrs, extra_attrs));
|
maybe_append(attrs, extra_attrs));
|
||||||
return Ok(Some(item));
|
return Ok(Some(item));
|
||||||
}
|
}
|
||||||
if self.check_keyword(keywords::Unsafe) &&
|
if (self.check_keyword(keywords::Unsafe) &&
|
||||||
self.look_ahead(1, |t| t.is_keyword(keywords::Impl))
|
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
|
// IMPL ITEM
|
||||||
|
let defaultness = self.parse_defaultness()?;
|
||||||
self.expect_keyword(keywords::Unsafe)?;
|
self.expect_keyword(keywords::Unsafe)?;
|
||||||
self.expect_keyword(keywords::Impl)?;
|
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 prev_span = self.prev_span;
|
||||||
let item = self.mk_item(lo.to(prev_span),
|
let item = self.mk_item(lo.to(prev_span),
|
||||||
ident,
|
ident,
|
||||||
|
@ -5856,9 +5864,16 @@ impl<'a> Parser<'a> {
|
||||||
maybe_append(attrs, extra_attrs));
|
maybe_append(attrs, extra_attrs));
|
||||||
return Ok(Some(item));
|
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
|
// 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 prev_span = self.prev_span;
|
||||||
let item = self.mk_item(lo.to(prev_span),
|
let item = self.mk_item(lo.to(prev_span),
|
||||||
ident,
|
ident,
|
||||||
|
|
|
@ -1317,12 +1317,14 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
ast::ItemKind::Impl(unsafety,
|
ast::ItemKind::Impl(unsafety,
|
||||||
polarity,
|
polarity,
|
||||||
|
defaultness,
|
||||||
ref generics,
|
ref generics,
|
||||||
ref opt_trait,
|
ref opt_trait,
|
||||||
ref ty,
|
ref ty,
|
||||||
ref impl_items) => {
|
ref impl_items) => {
|
||||||
self.head("")?;
|
self.head("")?;
|
||||||
self.print_visibility(&item.vis)?;
|
self.print_visibility(&item.vis)?;
|
||||||
|
self.print_defaultness(defaultness)?;
|
||||||
self.print_unsafety(unsafety)?;
|
self.print_unsafety(unsafety)?;
|
||||||
self.word_nbsp("impl")?;
|
self.word_nbsp("impl")?;
|
||||||
|
|
||||||
|
@ -1477,6 +1479,13 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
pub fn print_struct(&mut self,
|
||||||
struct_def: &ast::VariantData,
|
struct_def: &ast::VariantData,
|
||||||
generics: &ast::Generics,
|
generics: &ast::Generics,
|
||||||
|
@ -1602,9 +1611,7 @@ impl<'a> State<'a> {
|
||||||
self.hardbreak_if_not_bol()?;
|
self.hardbreak_if_not_bol()?;
|
||||||
self.maybe_print_comment(ii.span.lo)?;
|
self.maybe_print_comment(ii.span.lo)?;
|
||||||
self.print_outer_attributes(&ii.attrs)?;
|
self.print_outer_attributes(&ii.attrs)?;
|
||||||
if let ast::Defaultness::Default = ii.defaultness {
|
self.print_defaultness(ii.defaultness)?;
|
||||||
self.word_nbsp("default")?;
|
|
||||||
}
|
|
||||||
match ii.node {
|
match ii.node {
|
||||||
ast::ImplItemKind::Const(ref ty, ref expr) => {
|
ast::ImplItemKind::Const(ref ty, ref expr) => {
|
||||||
self.print_associated_const(ii.ident, &ty, Some(&expr), &ii.vis)?;
|
self.print_associated_const(ii.ident, &ty, Some(&expr), &ii.vis)?;
|
||||||
|
|
|
@ -266,7 +266,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
||||||
ItemKind::DefaultImpl(_, ref trait_ref) => {
|
ItemKind::DefaultImpl(_, ref trait_ref) => {
|
||||||
visitor.visit_trait_ref(trait_ref)
|
visitor.visit_trait_ref(trait_ref)
|
||||||
}
|
}
|
||||||
ItemKind::Impl(_, _,
|
ItemKind::Impl(_, _, _,
|
||||||
ref type_parameters,
|
ref type_parameters,
|
||||||
ref opt_trait_reference,
|
ref opt_trait_reference,
|
||||||
ref typ,
|
ref typ,
|
||||||
|
|
|
@ -658,6 +658,7 @@ impl<'a> TraitDef<'a> {
|
||||||
a,
|
a,
|
||||||
ast::ItemKind::Impl(unsafety,
|
ast::ItemKind::Impl(unsafety,
|
||||||
ast::ImplPolarity::Positive,
|
ast::ImplPolarity::Positive,
|
||||||
|
ast::Defaultness::Final,
|
||||||
trait_generics,
|
trait_generics,
|
||||||
opt_trait_ref,
|
opt_trait_ref,
|
||||||
self_type,
|
self_type,
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit da282f1bb7277b4d30fa1599ee29ad8eb4dd2a92
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
// 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
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
// 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();
|
||||||
|
}
|
|
@ -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.
|
||||||
|
|
||||||
|
// 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() {}
|
|
@ -0,0 +1,95 @@
|
||||||
|
// 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() {}
|
|
@ -0,0 +1,53 @@
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
// 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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
// 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 }
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
// 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() { }
|
|
@ -0,0 +1,37 @@
|
||||||
|
// 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);
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
// 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");
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
// 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();
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// 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)");
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
// 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");
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
// 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();
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
// 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() {}
|
|
@ -0,0 +1,33 @@
|
||||||
|
// 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() {}
|
|
@ -0,0 +1,32 @@
|
||||||
|
// 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() {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
// 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() {
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue