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
This commit is contained in:
parent
f5c55ff379
commit
13e80af159
src
librustc
ich
traits
ty
util
librustc_mir/monomorphize
librustc_typeck
test
compile-fail/specialization/defaultimpl
auxiliary
specialization-default-projection.rsspecialization-default-types.rsspecialization-method-not-implemented-cross-crate-impl.rsspecialization-method-not-implemented-cross-crate.rsspecialization-method-not-implemented.rsspecialization-trait-bounds-casting.rsspecialization-trait-bounds-impl-item.rsspecialization-trait-bounds-super-trait.rsspecialization-trait-bounds-trait-item.rsspecialization-trait-bounds-vec.rsspecialization-trait-item-not-implemented.rsspecialization-trait-not-implemented.rsrun-pass/specialization/defaultimpl
assoc-fns.rs
auxiliary
basics-unsafe.rsbasics.rscross-crate-defaults.rscross-crate-no-gate.rscross-crate.rsdefault-methods.rsprojection-alias.rsspecialization-trait-bounds.rsspecialization-trait-item-not-implemented.rsspecialization-traits-impl-default-method-cross-crate.rsspecialization-traits-impl-default-method.rs@ -218,8 +218,7 @@ impl_stable_hash_for!(enum ty::Visibility {
|
||||
});
|
||||
|
||||
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 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// 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 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
// 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 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// 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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
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 util::ppaux;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
@ -1070,13 +1070,9 @@ impl<'a, 'gcx, 'tcx> Predicate<'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 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'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 @@ impl<'tcx> Predicate<'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 @@ impl<'tcx> TypeFoldable<'tcx> for ty::SubtypePredicate<'tcx> {
|
||||
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 @@ impl<'tcx> PolyTraitRef<'tcx> {
|
||||
|
||||
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
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 @@ define_print! {
|
||||
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 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
|
||||
}
|
||||
|
||||
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 errors::{DiagnosticBuilder, DiagnosticId};
|
||||
|
||||
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 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
||||
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>,
|
||||
¶m.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()
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
// 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;
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
// 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();
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
// 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();
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// 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));
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// 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());
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
// 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();
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// 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());
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// 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
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
// 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);
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
// 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"
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
// 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 }
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// 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"
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
// 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");
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
// 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");
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
// 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();
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// 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)");
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
// 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");
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
// 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();
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
// 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() {
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// 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");
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// 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");
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// 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");
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// 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");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user