});
impl_stable_hash_for!(struct ty::TraitRef<'tcx> { def_id, substs });
-impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
+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!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 });
impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b });
}
// Treat negative impls as unimplemented
- fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>)
- -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
+ fn filter_negative_and_default_impls<'o>(&self,
+ candidate: SelectionCandidate<'tcx>,
+ stack: &TraitObligationStack<'o, '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))
}
// Instead, we select the right impl now but report `Bar does
// not implement Clone`.
if candidates.len() == 1 {
- return self.filter_negative_impls(candidates.pop().unwrap());
+ return self.filter_negative_and_default_impls(candidates.pop().unwrap(), stack);
}
-
// Winnow, but record the exact outcome of evaluation, which
// is needed for specialization.
let mut candidates: Vec<_> = candidates.into_iter().filter_map(|c| {
}
// Just one candidate left.
- self.filter_negative_impls(candidates.pop().unwrap().candidate)
+ self.filter_negative_and_default_impls(candidates.pop().unwrap().candidate, stack)
}
fn is_knowable<'o>(&mut self,
pred: &ty::Predicate<'tcx>)
-> ty::Predicate<'tcx> {
match *pred {
- ty::Predicate::Trait(ref data) =>
- ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data)),
+ 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::Equate(ref data) =>
ty::Predicate::Equate(tcx.anonymize_late_bound_regions(data)),
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 }
// except according to those terms.
use hir::def_id::DefId;
-use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
-use ty::subst::Kind;
+use ty::{self, Ty, TypeFoldable, Substs, TyCtxt, AssociatedKind, AssociatedItemContainer};
+use ty::subst::{Kind, Subst};
use traits;
use syntax::abi::Abi;
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>,
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))
}
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
}
}
+#[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 trait_ref: TraitRef<'tcx>,
+ pub default_impl_check: DefaultImplCheck
}
pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>;
assert!(!self.has_escaping_regions());
ty::Predicate::Trait(ty::Binder(ty::TraitPredicate {
- trait_ref: self.clone()
+ trait_ref: self.clone(),
+ default_impl_check: DefaultImplCheck::No
}))
}
}
}
}
}
+
+ 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
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: trait_ref,
+ default_impl_check: self.default_impl_check
})
}
}
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)
+ trait_ref: self.trait_ref.fold_with(folder),
+ default_impl_check: self.default_impl_check
}
}
pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
// Note that we preserve binding levels
- Binder(ty::TraitPredicate { trait_ref: self.0.clone() })
+ Binder(ty::TraitPredicate {
+ trait_ref: self.0.clone(),
+ default_impl_check: ty::DefaultImplCheck::No
+ })
}
}
define_print! {
('tcx) ty::TraitPredicate<'tcx>, (self, f, cx) {
debug {
- write!(f, "TraitPredicate({:?})",
- self.trait_ref)
+ 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)
}
display {
print!(f, cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
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, .. } |
ty::ParamEnv::empty(traits::Reveal::All),
def_id,
substs).unwrap();
- visit_instance_use(tcx, instance, is_direct_call, output);
+ if !tcx.sess.has_errors() {
+ // continue only if no errors are encountered during monomorphization
+ visit_instance_use(tcx, instance, is_direct_call, output);
+ }
}
}
}
impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
- pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
+ pub fn predicates(&self,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ param_ty: Ty<'tcx>,
+ default_impl_check: ty::DefaultImplCheck)
-> Vec<ty::Predicate<'tcx>>
{
let mut vec = Vec::new();
}
for bound_trait_ref in &self.trait_bounds {
- vec.push(bound_trait_ref.to_predicate());
+ 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()
+ }
+ );
}
for projection in &self.projection_bounds {
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 = assumptions_in_impl_context.predicates;
+ 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();
// An earlier version of this code attempted to do this checking
// via the traits::fulfill machinery. However, it ran into trouble
// the analysis together via the fulfill , rather than the
// repeated `contains` calls.
- if !assumptions_in_impl_context.contains(&predicate) {
+ if !assumptions_in_impl_context.contains(
+ &predicate.change_default_impl_check(ty::DefaultImplCheck::No)
+ .unwrap_or(predicate.clone())) {
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)
.map(|node_item| !node_item.node.is_from_trait())
.unwrap_or(false);
- if !is_implemented {
+ if !is_implemented && !tcx.impl_is_default(impl_id) {
if !trait_item.defaultness.has_value() {
missing_items.push(trait_item);
} else if associated_type_overridden {
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>,
fcx.body_id,
&trait_ref,
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
+ };
+
for obligation in obligations {
- fcx.register_predicate(obligation);
+ let register = match obligation.predicate {
+ ty::Predicate::Trait(..) => {
+ if impl_not_implement_trait &&
+ !obligation.predicate.has_param_types() {
+ false
+ } else {
+ true
+ }
+ }
+ _ => true
+ };
+
+ if register {
+ fcx.register_predicate(obligation);
+ }
}
}
None => {
SizedByDefault::No,
item.span);
- let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
+ let superbounds1 = superbounds1.predicates(tcx, self_param_ty, ty::DefaultImplCheck::No);
// Convert any explicit superbounds in the where clause,
// e.g. `trait Foo where Self : Bar`:
ty::GenericPredicates {
parent: None,
- predicates: superbounds
+ predicates: superbounds.iter()
+ .map(|predicate| {
+ predicate.change_default_impl_check(ty::DefaultImplCheck::Yes)
+ .unwrap_or(predicate.clone())
+ }).collect()
}
}
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) => &item.generics,
- NodeImplItem(item) => &item.generics,
+ 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
+ }
+ }
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) |
debug!("explicit_predicates_of: bounds={:?}", bounds);
- let predicates = bounds.predicates(tcx, anon_ty);
+ let predicates = bounds.predicates(tcx, anon_ty, ty::DefaultImplCheck::No);
debug!("explicit_predicates_of: predicates={:?}", predicates);
¶m.bounds,
SizedByDefault::Yes,
param.span);
- predicates.extend(bounds.predicates(tcx, param_ty));
+ predicates.extend(bounds.predicates(tcx, param_ty, default_impl_check));
}
// Add in the bounds that appear in the where-clause
poly_trait_ref,
ty,
&mut projections);
-
- predicates.push(trait_ref.to_predicate());
+ 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()
+ }
+ );
for projection in &projections {
predicates.push(projection.to_predicate());
SizedByDefault::Yes,
trait_item.span);
- bounds.predicates(tcx, assoc_ty).into_iter()
+ bounds.predicates(tcx, assoc_ty, ty::DefaultImplCheck::No).into_iter()
}))
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+pub trait Foo {
+ fn foo_one(&self) -> &'static str;
+ fn foo_two(&self) -> &'static str;
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+pub 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"
+ }
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build: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
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build: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
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+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
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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();
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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"
+ }
+}
+
+fn foo<T: Foo>(x: T) -> &'static str {
+ x.foo_one()
+}
+
+struct MyStruct;
+
+fn main() {
+ println!("{:?}", foo(MyStruct));
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+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
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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();
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+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
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+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");
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build: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");
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+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");
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(specialization)]
+
+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"
+ }
+}
+
+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");
+}