提交 13e80af1 编写于 作者: G Gianni Ciccarelli

support `default impl` for specialization

a default impl should never be considered as implementing the
trait on its own -- regardless of whether it contains all items
or not
上级 f5c55ff3
......@@ -218,8 +218,7 @@ fn hash_stable<W: StableHasherResult>(&self,
});
impl_stable_hash_for!(struct ty::TraitRef<'tcx> { def_id, substs });
impl_stable_hash_for!(enum ty::DefaultImplCheck { Yes, No });
impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref, default_impl_check });
impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 });
impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b });
......
......@@ -1083,39 +1083,12 @@ fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
}
// Treat negative impls as unimplemented
fn filter_negative_and_default_impls<'o>(&self,
candidate: SelectionCandidate<'tcx>,
stack: &TraitObligationStack<'o, 'tcx>)
-> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>)
-> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
if let ImplCandidate(def_id) = candidate {
if self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative {
return Err(Unimplemented)
}
// if def_id is a default impl and it doesn't implement all the trait items,
// the impl doesn't implement the trait.
// An `Unimplemented` error is returned only if the default_impl_check is
// applicable to the trait predicate or the cause of the predicate is an
// `ObjectCastObligation`
if self.tcx().impl_is_default(def_id) &&
!self.tcx().default_impl_implement_all_methods(def_id){
match stack.obligation.cause.code {
ObligationCauseCode::ObjectCastObligation(_) => {
return Err(Unimplemented)
},
ObligationCauseCode::ItemObligation(..) |
ObligationCauseCode::MiscObligation => {
if let ty::DefaultImplCheck::Yes = stack.obligation
.predicate
.skip_binder()
.default_impl_check {
return Err(Unimplemented)
}
},
_ => {}
}
}
}
Ok(Some(candidate))
}
......@@ -1205,8 +1178,9 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
// Instead, we select the right impl now but report `Bar does
// not implement Clone`.
if candidates.len() == 1 {
return self.filter_negative_and_default_impls(candidates.pop().unwrap(), stack);
return self.filter_negative_impls(candidates.pop().unwrap());
}
// Winnow, but record the exact outcome of evaluation, which
// is needed for specialization.
let mut candidates: Vec<_> = candidates.into_iter().filter_map(|c| {
......@@ -1265,7 +1239,7 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
}
// Just one candidate left.
self.filter_negative_and_default_impls(candidates.pop().unwrap().candidate, stack)
self.filter_negative_impls(candidates.pop().unwrap().candidate)
}
fn is_knowable<'o>(&mut self,
......
......@@ -22,11 +22,8 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
pred: &ty::Predicate<'tcx>)
-> ty::Predicate<'tcx> {
match *pred {
ty::Predicate::Trait(ref data) => {
let anonymized_pred = ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data));
anonymized_pred.change_default_impl_check(ty::DefaultImplCheck::No)
.unwrap_or(anonymized_pred)
}
ty::Predicate::Trait(ref data) =>
ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data)),
ty::Predicate::Equate(ref data) =>
ty::Predicate::Equate(tcx.anonymize_late_bound_regions(data)),
......@@ -557,24 +554,6 @@ pub fn impl_is_default(self, node_item_def_id: DefId) -> bool {
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 fn default_impl_implement_all_methods(self, node_item_def_id: DefId) -> bool {
if let Some(impl_trait_ref) = self.impl_trait_ref(node_item_def_id) {
let trait_def = self.trait_def(impl_trait_ref.def_id);
for trait_item in self.associated_items(impl_trait_ref.def_id) {
let is_implemented = trait_def.ancestors(self, node_item_def_id)
.defs(self, trait_item.name, trait_item.kind, impl_trait_ref.def_id)
.next()
.map(|node_item| !node_item.node.is_from_trait())
.unwrap_or(false);
if !is_implemented {
return false;
}
}
}
true
}
}
pub enum TupleArgumentsFlag { Yes, No }
......@@ -9,7 +9,7 @@
// except according to those terms.
use hir::def_id::DefId;
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt, AssociatedKind, AssociatedItemContainer};
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
use ty::subst::{Kind, Subst};
use traits;
use syntax::abi::Abi;
......@@ -17,11 +17,6 @@
use std::fmt;
use syntax_pos::{BytePos, Span};
use syntax::ext::hygiene::SyntaxContext;
use hir::map::Node::NodeTraitItem;
use hir;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Instance<'tcx> {
pub def: InstanceDef<'tcx>,
......@@ -265,13 +260,6 @@ fn resolve_associated_item<'a, 'tcx>(
traits::VtableImpl(impl_data) => {
let (def_id, substs) = traits::find_associated_item(
tcx, trait_item, rcvr_substs, &impl_data);
check_unimplemented_trait_item(tcx,
impl_data.impl_def_id,
def_id,
trait_id,
trait_item);
let substs = tcx.erase_regions(&substs);
Some(ty::Instance::new(def_id, substs))
}
......@@ -375,108 +363,3 @@ fn fn_once_adapter_instance<'a, 'tcx>(
debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
Instance { def, substs }
}
fn check_unimplemented_trait_item<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_def_id: DefId,
trait_item_def_id: DefId,
trait_id: DefId,
trait_item: &ty::AssociatedItem)
{
// if trait_item_def_id is a trait item and it doesn't have a default trait implementation
// the resolution has found an unimplemented trait item inside a default impl
if tcx.impl_is_default(impl_def_id) {
let is_unimplemented_trait_item = match tcx.hir.as_local_node_id(trait_item_def_id) {
Some(node_id) =>
match tcx.hir.find(node_id) {
Some(NodeTraitItem(item)) => {
if let hir::TraitItemKind::Method(_,
hir::TraitMethod::Provided(_))
= item.node {
false
} else {
true
}
},
_ => false
}
None => {
let item = tcx.global_tcx().associated_item(trait_item_def_id);
match item.kind {
AssociatedKind::Method => match item.container {
AssociatedItemContainer::TraitContainer(_) => {
!item.defaultness.has_value()
}
_ => false
}
_ => false
}
}
};
if is_unimplemented_trait_item {
let mut err = tcx.sess.struct_err(&format!("the trait method `{}` \
is not implemented",
trait_item.name));
let mut help_messages = Vec::new();
help_messages.push(
if impl_def_id.is_local() {
let item = tcx.hir
.expect_item(
tcx.hir
.as_local_node_id(impl_def_id).unwrap()
);
(item.span, format!("implement it inside this `default impl`"))
} else {
(Span::new (
BytePos(0),
BytePos(0),
SyntaxContext::empty()
),
format!("implement it inside the {} `default impl`",
tcx.item_path_str(impl_def_id)))
}
);
help_messages.push(
if trait_id.is_local() {
let trait_item = tcx.hir
.expect_item(
tcx.hir
.as_local_node_id(trait_id).unwrap()
);
(trait_item.span, format!("provide a default method implementation \
inside this `trait`"))
} else {
(Span::new (
BytePos(0),
BytePos(0),
SyntaxContext::empty()
),
format!("provide a default method implementation \
inside the {} `trait`",
tcx.item_path_str(trait_id)))
}
);
help_messages.sort_by(|&(a,_), &(b,_)| a.partial_cmp(&b).unwrap());
let mut cnjs = vec!["or ", "either "];
help_messages.iter().for_each(|&(span, ref msg)| {
let mut help_msg = String::from(cnjs.pop().unwrap_or(""));
help_msg.push_str(&msg);
if span.data().lo == BytePos(0) && span.data().hi == BytePos(0) {
err.help(&help_msg);
} else {
err.span_help(span, &help_msg);
}
});
err.note(&format!("a `default impl` doesn't need to include all \
items from the trait"));
err.emit();
}
}
}
\ No newline at end of file
......@@ -1070,13 +1070,9 @@ pub fn subst_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum DefaultImplCheck { Yes, No, }
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct TraitPredicate<'tcx> {
pub trait_ref: TraitRef<'tcx>,
pub default_impl_check: DefaultImplCheck
pub trait_ref: TraitRef<'tcx>
}
pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>;
......@@ -1184,8 +1180,7 @@ fn to_predicate(&self) -> Predicate<'tcx> {
assert!(!self.has_escaping_regions());
ty::Predicate::Trait(ty::Binder(ty::TraitPredicate {
trait_ref: self.clone(),
default_impl_check: DefaultImplCheck::No
trait_ref: self.clone()
}))
}
}
......@@ -1303,36 +1298,6 @@ pub fn to_opt_type_outlives(&self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
}
}
}
pub fn change_default_impl_check(&self, default_impl_check: ty::DefaultImplCheck)
-> Option<Predicate<'tcx>> {
match *self {
Predicate::Trait(ref t) => {
if t.skip_binder().default_impl_check != default_impl_check {
Some(
Predicate::Trait(ty::Binder(ty::TraitPredicate {
trait_ref: t.skip_binder().trait_ref,
default_impl_check: default_impl_check
}))
)
} else {
None
}
}
Predicate::Trait(..) |
Predicate::Projection(..) |
Predicate::Equate(..) |
Predicate::Subtype(..) |
Predicate::RegionOutlives(..) |
Predicate::WellFormed(..) |
Predicate::ObjectSafe(..) |
Predicate::ClosureKind(..) |
Predicate::TypeOutlives(..) |
Predicate::ConstEvaluatable(..) => {
None
}
}
}
}
/// Represents the bounds declared on a particular set of type
......
......@@ -278,8 +278,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
-> Option<ty::TraitPredicate<'tcx>> {
tcx.lift(&self.trait_ref).map(|trait_ref| ty::TraitPredicate {
trait_ref: trait_ref,
default_impl_check: self.default_impl_check
trait_ref,
})
}
}
......@@ -1128,8 +1127,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::TraitPredicate {
trait_ref: self.trait_ref.fold_with(folder),
default_impl_check: self.default_impl_check
trait_ref: self.trait_ref.fold_with(folder)
}
}
......
......@@ -582,10 +582,7 @@ pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a
pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
// Note that we preserve binding levels
Binder(ty::TraitPredicate {
trait_ref: self.0.clone(),
default_impl_check: ty::DefaultImplCheck::No
})
Binder(ty::TraitPredicate { trait_ref: self.0.clone() })
}
}
......
......@@ -92,10 +92,16 @@ pub fn for_each_relevant_impl<F: FnMut(DefId)>(self,
self_ty: Ty<'tcx>,
mut f: F)
{
let mut emit_impl = |impl_def_id: DefId| {
if !self.impl_is_default(impl_def_id) {
f(impl_def_id);
}
};
let impls = self.trait_impls_of(def_id);
for &impl_def_id in impls.blanket_impls.iter() {
f(impl_def_id);
emit_impl(impl_def_id);
}
// simplify_type(.., false) basically replaces type parameters and
......@@ -126,13 +132,13 @@ pub fn for_each_relevant_impl<F: FnMut(DefId)>(self,
if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
f(impl_def_id);
emit_impl(impl_def_id);
}
}
} else {
for v in impls.non_blanket_impls.values() {
for &impl_def_id in v {
f(impl_def_id);
emit_impl(impl_def_id);
}
}
}
......
......@@ -1230,12 +1230,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
define_print! {
('tcx) ty::TraitPredicate<'tcx>, (self, f, cx) {
debug {
let default_impl_check_value = match self.default_impl_check {
ty::DefaultImplCheck::Yes => "default_impl_check: yes",
ty::DefaultImplCheck::No => "default_impl_check: no",
};
write!(f, "TraitPredicate({:?}, {})",
self.trait_ref, default_impl_check_value)
write!(f, "TraitPredicate({:?})",
self.trait_ref)
}
display {
print!(f, cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
......
......@@ -618,18 +618,6 @@ fn visit_terminator_kind(&mut self,
self.output);
} else {
visit_fn_use(self.tcx, callee_ty, true, &mut self.output);
if tcx.sess.has_errors() {
match func {
&mir::Operand::Consume(_) => {}
&mir::Operand::Constant(ref cst) => {
tcx.sess
.span_note_without_error(cst.span,
"the function call is here");
}
}
tcx.sess.abort_if_errors();
}
}
}
mir::TerminatorKind::Drop { ref location, .. } |
......@@ -690,10 +678,7 @@ fn visit_fn_use<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ty::ParamEnv::empty(traits::Reveal::All),
def_id,
substs).unwrap();
if !tcx.sess.has_errors() {
// continue only if no errors are encountered during monomorphization
visit_instance_use(tcx, instance, is_direct_call, output);
}
visit_instance_use(tcx, instance, is_direct_call, output);
}
}
......
......@@ -1378,10 +1378,7 @@ pub struct Bounds<'tcx> {
}
impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
pub fn predicates(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
param_ty: Ty<'tcx>,
default_impl_check: ty::DefaultImplCheck)
pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
-> Vec<ty::Predicate<'tcx>>
{
let mut vec = Vec::new();
......@@ -1405,16 +1402,7 @@ pub fn predicates(&self,
}
for bound_trait_ref in &self.trait_bounds {
vec.push(
if bound_trait_ref.skip_binder().def_id !=
tcx.lang_items().sized_trait().unwrap() {
bound_trait_ref.to_predicate()
.change_default_impl_check(default_impl_check)
.unwrap_or(bound_trait_ref.to_predicate())
} else {
bound_trait_ref.to_predicate()
}
);
vec.push(bound_trait_ref.to_predicate());
}
for projection in &self.projection_bounds {
......
......@@ -189,13 +189,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
let generic_assumptions = tcx.predicates_of(self_type_did);
let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
let assumptions_in_impl_context: Vec<ty::Predicate> =
assumptions_in_impl_context.predicates
.iter()
.map(|predicate| {
predicate.change_default_impl_check(ty::DefaultImplCheck::No)
.unwrap_or(predicate.clone())
}).collect();
let assumptions_in_impl_context = assumptions_in_impl_context.predicates;
// An earlier version of this code attempted to do this checking
// via the traits::fulfill machinery. However, it ran into trouble
......@@ -217,9 +211,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
// the analysis together via the fulfill , rather than the
// repeated `contains` calls.
if !assumptions_in_impl_context.contains(
&predicate.change_default_impl_check(ty::DefaultImplCheck::No)
.unwrap_or(predicate.clone())) {
if !assumptions_in_impl_context.contains(&predicate) {
let item_span = tcx.hir.span(self_type_node_id);
struct_span_err!(tcx.sess, drop_impl_span, E0367,
"The requirement `{}` is added only by the Drop impl.", predicate)
......
......@@ -25,7 +25,6 @@
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir;
use rustc::ty::TypeFoldable;
pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
......@@ -346,28 +345,10 @@ fn check_impl(&mut self,
ast_trait_ref.path.span);
// not registering predicates associcated with a `default impl`
// that doesn't implement all the trait items.
// it's left to the trait selection to select those trait predicates
// and trigger an `Unimplemented` error in case the defaul_impl_check
// is applicable
let impl_not_implement_trait =
if fcx.tcx.impl_is_default(item_def_id) &&
!fcx.tcx.default_impl_implement_all_methods(item_def_id) {
true
} else {
false
};
let impl_is_default = fcx.tcx.impl_is_default(item_def_id);
for obligation in obligations {
let register = match obligation.predicate {
ty::Predicate::Trait(..) => {
if impl_not_implement_trait &&
!obligation.predicate.has_param_types() {
false
} else {
true
}
}
ty::Predicate::Trait(..) => !impl_is_default,
_ => true
};
......
......@@ -677,7 +677,7 @@ fn super_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
SizedByDefault::No,
item.span);
let superbounds1 = superbounds1.predicates(tcx, self_param_ty, ty::DefaultImplCheck::No);
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
// Convert any explicit superbounds in the where clause,
// e.g. `trait Foo where Self : Bar`:
......@@ -694,11 +694,7 @@ fn super_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ty::GenericPredicates {
parent: None,
predicates: superbounds.iter()
.map(|predicate| {
predicate.change_default_impl_check(ty::DefaultImplCheck::Yes)
.unwrap_or(predicate.clone())
}).collect()
predicates: superbounds
}
}
......@@ -1368,39 +1364,17 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let node = tcx.hir.get(node_id);
let mut is_trait = None;
let mut default_impl_check = ty::DefaultImplCheck::No;
let icx = ItemCtxt::new(tcx, def_id);
let no_generics = hir::Generics::empty();
let ast_generics = match node {
NodeTraitItem(item) => {
match item.node {
TraitItemKind::Method(ref sig, _) => {
default_impl_check = ty::DefaultImplCheck::Yes;
&item.generics
},
_ => &item.generics
}
}
NodeImplItem(item) => {
match item.node {
ImplItemKind::Method(ref sig, _) => {
default_impl_check = ty::DefaultImplCheck::Yes;
&item.generics
},
_ => &item.generics
}
}
NodeTraitItem(item) => &item.generics,
NodeImplItem(item) => &item.generics,
NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
ItemImpl(_, _, _, ref generics, ..) |
ItemStruct(_, ref generics) => {
default_impl_check = ty::DefaultImplCheck::Yes;
generics
}
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
......@@ -1441,7 +1415,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
debug!("explicit_predicates_of: bounds={:?}", bounds);
let predicates = bounds.predicates(tcx, anon_ty, ty::DefaultImplCheck::No);
let predicates = bounds.predicates(tcx, anon_ty);
debug!("explicit_predicates_of: predicates={:?}", predicates);
......@@ -1502,7 +1476,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
&param.bounds,
SizedByDefault::Yes,
param.span);
predicates.extend(bounds.predicates(tcx, param_ty, default_impl_check));
predicates.extend(bounds.predicates(tcx, param_ty));
}
// Add in the bounds that appear in the where-clause
......@@ -1522,16 +1496,8 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
poly_trait_ref,
ty,
&mut projections);
predicates.push(
if trait_ref.skip_binder().def_id !=
tcx.lang_items().sized_trait().unwrap() {
trait_ref.to_predicate()
.change_default_impl_check(default_impl_check)
.unwrap_or(trait_ref.to_predicate())
} else {
trait_ref.to_predicate()
}
);
predicates.push(trait_ref.to_predicate());
for projection in &projections {
predicates.push(projection.to_predicate());
......@@ -1586,7 +1552,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
SizedByDefault::Yes,
trait_item.span);
bounds.predicates(tcx, assoc_ty, ty::DefaultImplCheck::No).into_iter()
bounds.predicates(tcx, assoc_ty).into_iter()
}))
}
......
// 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)]
pub trait Foo {
fn foo_one(&self) -> &'static str;
fn foo_two(&self) -> &'static str;
}
// 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
}
// 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();
}
// 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:foo_trait_default_impl.rs
#![feature(specialization)]
extern crate foo_trait_default_impl;
use foo_trait_default_impl::*;
struct MyStruct;
fn main() {
MyStruct.foo_two(); //~ NOTE the function call is here
}
// 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:foo_trait.rs
#![feature(specialization)]
extern crate foo_trait;
use foo_trait::{Foo};
struct MyStruct;
default impl Foo for MyStruct {
fn foo_one(&self) -> &'static str {
"generic"
}
}
//~^^^^^ HELP implement it inside this `default impl`
fn main() {
MyStruct.foo_two(); //~ NOTE the function call is here
}
// 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)]
trait Foo {
fn foo_one(&self) -> &'static str;
fn foo_two(&self) -> &'static str;
}
//~^^^^ HELP provide a default method implementation inside this `trait`
default impl<T> Foo for T {
fn foo_one(&self) -> &'static str {
"generic"
}
}
//~^^^^^ HELP implement it inside this `default impl`
struct MyStruct;
fn main() {
MyStruct.foo_two(); //~ NOTE the function call is here
}
// 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.
// error-pattern: the trait bound `MyStruct: Draw` is not satisfied
#![feature(specialization)]
trait Draw {
fn draw(&self);
fn draw2(&self);
}
struct Screen {
pub components: Vec<Box<Draw>>,
}
impl Screen {
pub fn run(&self) {
for component in self.components.iter() {
component.draw();
}
}
}
default impl<T> Draw for T {
fn draw(&self) {
println!("draw");
}
}
struct MyStruct;
fn main() {
let screen = Screen {
components: vec![
Box::new(MyStruct)
]
};
screen.run();
}
// 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.
// error-pattern: the trait bound `MyStruct: Foo` is not satisfied
#![feature(specialization)]
trait Foo {
fn foo_one(&self) -> &'static str;
fn foo_two(&self) -> &'static str;
}
default impl<T> Foo for T {
fn foo_one(&self) -> &'static str {
"generic"
}
}
struct FooS;
impl FooS{
fn foo<T: Foo>(&self, x: T) -> &'static str{
x.foo_one()
}
}
struct MyStruct;
fn main() {
println!("{:?}", FooS.foo(MyStruct));
}
\ No newline at end of file
// 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.
// error-pattern: the trait bound `MyStruct: SuperFoo` is not satisfied
#![feature(specialization)]
trait SuperFoo {
fn super_foo_one(&self) -> &'static str;
fn super_foo_two(&self) -> &'static str;
}
trait Foo: SuperFoo {
fn foo(&self) -> &'static str;
}
default impl<T> SuperFoo for T {
fn super_foo_one(&self) -> &'static str {
"generic"
}
}
struct MyStruct;
impl Foo for MyStruct {
fn foo(&self) -> &'static str {
"foo"
}
}
fn main() {
println!("{:?}", MyStruct.foo());
}
\ No newline at end of file
// 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)]
trait Foo<T> {
fn dummy(&self, t: T);
}
trait Bar<A> {
fn method<B>(&self) where A: Foo<B>;
}
struct S;
struct X;
default impl Foo<X> for X {}
impl Bar<X> for isize {
fn method<U>(&self) where X: Foo<U> {
}
}
fn main() {
1.method::<X>();
//~^ ERROR the trait bound `X: Foo<X>` is not satisfied
}
// 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.
// error-pattern: the trait bound `MyStruct: Draw` is not satisfied
#![feature(specialization)]
trait Draw {
fn draw(&self);
fn draw2(&self);
}
struct Screen<T: Draw> {
pub components: Vec<T>,
}
impl<T> Screen<T>
where T: Draw {
pub fn run(&self) {
for component in self.components.iter() {
component.draw();
}
}
}
default impl Draw for MyStruct {
fn draw(&self) {
println!("draw");
}
}
struct MyStruct;
fn main() {
let screen = Screen {
components: vec![
MyStruct
]
};
screen.run();
}
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// 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.
//
......@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: the trait bound `MyStruct: Foo` is not satisfied
#![feature(specialization)]
trait Foo {
......@@ -17,18 +15,17 @@ trait Foo {
fn foo_two(&self) -> &'static str;
}
struct MyStruct;
default impl<T> Foo for T {
fn foo_one(&self) -> &'static str {
"generic"
}
}
fn foo<T: Foo>(x: T) -> &'static str {
x.foo_one()
}
struct MyStruct;
impl Foo for MyStruct {}
//~^ ERROR not all trait items implemented, missing: `foo_two` [E0046]
fn main() {
println!("{:?}", foo(MyStruct));
}
println!("{}", MyStruct.foo_one());
}
\ No newline at end of file
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// 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.
//
......@@ -10,13 +10,21 @@
#![feature(specialization)]
pub trait Foo {
trait Foo {
fn foo_one(&self) -> &'static str;
fn foo_two(&self) -> &'static str;
}
struct MyStruct;
default impl<T> Foo for T {
fn foo_one(&self) -> &'static str {
"generic"
}
}
fn main() {
println!("{}", MyStruct.foo_one());
//~^ ERROR no method named `foo_one` found for type `MyStruct` in the current scope
}
\ No newline at end of file
// 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);
}
// 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"
}
}
// 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 }
}
// 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)]
pub trait Foo {
fn foo_one(&self) -> &'static str;
fn foo_two(&self) -> &'static str {
"generic Trait"
}
}
default impl<T> Foo for T {
fn foo_one(&self) -> &'static str {
"generic"
}
}
default impl<T: Clone> Foo for T {
fn foo_two(&self) -> &'static str {
"generic Clone"
}
}
\ No newline at end of file
// 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");
}
// 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");
}
// 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:cross_crate_defaults.rs
#![feature(specialization)]
extern crate cross_crate_defaults;
use 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();
}
// 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:cross_crate.rs
extern crate cross_crate;
use 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)");
}
// 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:cross_crate.rs
#![feature(specialization)]
extern crate cross_crate;
use 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");
}
// 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();
}
// 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() {
}
// 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)]
trait Foo {
fn foo_one(&self) -> &'static str;
fn foo_two(&self) -> &'static str;
}
default impl<T> Foo for T {
fn foo_one(&self) -> &'static str {
"generic one"
}
fn foo_two(&self) -> &'static str {
"generic two"
}
}
fn foo_one<T: Foo>(x: T) -> &'static str {
x.foo_one()
}
fn foo_two<T: Foo>(x: T) -> &'static str {
x.foo_two()
}
struct MyStruct;
fn main() {
assert!(foo_one(MyStruct) == "generic one");
assert!(foo_two(MyStruct) == "generic two");
}
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// 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.
//
......@@ -15,21 +15,20 @@ trait Foo {
fn foo_two(&self) -> &'static str;
}
struct MyStruct;
default impl<T> Foo for T {
fn foo_one(&self) -> &'static str {
"generic"
}
}
default impl<T: Clone> Foo for T {
impl Foo for MyStruct {
fn foo_two(&self) -> &'static str {
"generic Clone"
self.foo_one()
}
}
struct MyStruct;
fn main() {
assert!(MyStruct.foo_one() == "generic");
assert!(0u8.foo_two() == "generic Clone");
}
fn main() {
assert!(MyStruct.foo_two() == "generic");
}
\ No newline at end of file
// 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:foo_trait.rs
#![feature(specialization)]
extern crate foo_trait;
use foo_trait::*;
struct MyStruct;
fn main() {
assert!(MyStruct.foo_one() == "generic");
assert!(0u8.foo_two() == "generic Clone");
assert!(MyStruct.foo_two() == "generic Trait");
}
// 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)]
trait Foo {
fn foo_one(&self) -> &'static str;
fn foo_two(&self) -> &'static str {
"generic Trait"
}
}
default impl<T> Foo for T {
fn foo_one(&self) -> &'static str {
"generic"
}
}
default impl<T: Clone> Foo for T {
fn foo_two(&self) -> &'static str {
"generic Clone"
}
}
struct MyStruct;
fn main() {
assert!(MyStruct.foo_one() == "generic");
assert!(0u8.foo_two() == "generic Clone");
assert!(MyStruct.foo_two() == "generic Trait");
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册