1
Fork 0

auto merge of #5252 : nikomatsakis/rust/issue-5087-make-trait-not-impl-self, r=pcwalton

Two changes:

- The first fixes an inconsistency in coherence whereby extension methods were added to the inherent methods table, but only in cross-crate scenarios.  This causes some minor fallout in tests and so forth.  In one case (comm) I added inherent and trait methods so as to avoid the need to import traits like `GenericPort` just to use a port.

- The second makes objects not implement the associated trait, as discussed in #5087.

r? @pcwalton
This commit is contained in:
bors 2013-03-06 09:27:59 -08:00
commit 4b79a58d9d
33 changed files with 345 additions and 421 deletions

View file

@ -104,64 +104,98 @@ pub fn stream<T:Owned>() -> (Port<T>, Chan<T>) {
(Port_(Port_ { endp: Some(s) }), Chan_(Chan_{ endp: Some(c) })) (Port_(Port_ { endp: Some(s) }), Chan_(Chan_{ endp: Some(c) }))
} }
// Add an inherent method so that imports of GenericChan are not
// required.
#[cfg(stage1)]
#[cfg(stage2)]
pub impl<T: Owned> Chan<T> {
fn send(&self, x: T) { chan_send(self, x) }
fn try_send(&self, x: T) -> bool { chan_try_send(self, x) }
}
impl<T: Owned> GenericChan<T> for Chan<T> { impl<T: Owned> GenericChan<T> for Chan<T> {
fn send(&self, x: T) { fn send(&self, x: T) { chan_send(self, x) }
let mut endp = None; }
endp <-> self.endp;
self.endp = Some( #[inline(always)]
streamp::client::data(unwrap(endp), x)) fn chan_send<T:Owned>(self: &Chan<T>, x: T) {
} let mut endp = None;
endp <-> self.endp;
self.endp = Some(
streamp::client::data(unwrap(endp), x))
} }
impl<T: Owned> GenericSmartChan<T> for Chan<T> { impl<T: Owned> GenericSmartChan<T> for Chan<T> {
fn try_send(&self, x: T) -> bool { fn try_send(&self, x: T) -> bool {
let mut endp = None; chan_try_send(self, x)
endp <-> self.endp;
match streamp::client::try_data(unwrap(endp), x) {
Some(next) => {
self.endp = Some(next);
true
}
None => false
}
} }
} }
impl<T: Owned> GenericPort<T> for Port<T> { #[inline(always)]
fn recv(&self) -> T { fn chan_try_send<T:Owned>(self: &Chan<T>, x: T) -> bool {
let mut endp = None; let mut endp = None;
endp <-> self.endp; endp <-> self.endp;
let streamp::data(x, endp) = recv(unwrap(endp)); match streamp::client::try_data(unwrap(endp), x) {
self.endp = Some(endp); Some(next) => {
x self.endp = Some(next);
true
}
None => false
} }
}
fn try_recv(&self) -> Option<T> { // Use an inherent impl so that imports are not required:
let mut endp = None; #[cfg(stage1)]
endp <-> self.endp; #[cfg(stage2)]
match try_recv(unwrap(endp)) { pub impl<T: Owned> Port<T> {
Some(streamp::data(x, endp)) => { fn recv(&self) -> T { port_recv(self) }
fn try_recv(&self) -> Option<T> { port_try_recv(self) }
pure fn peek(&self) -> bool { port_peek(self) }
}
impl<T: Owned> GenericPort<T> for Port<T> {
// These two calls will prefer the inherent versions above:
fn recv(&self) -> T { port_recv(self) }
fn try_recv(&self) -> Option<T> { port_try_recv(self) }
}
#[inline(always)]
fn port_recv<T:Owned>(self: &Port<T>) -> T {
let mut endp = None;
endp <-> self.endp;
let streamp::data(x, endp) = recv(unwrap(endp));
self.endp = Some(endp);
x
}
#[inline(always)]
fn port_try_recv<T:Owned>(self: &Port<T>) -> Option<T> {
let mut endp = None;
endp <-> self.endp;
match try_recv(unwrap(endp)) {
Some(streamp::data(x, endp)) => {
self.endp = Some(endp); self.endp = Some(endp);
Some(x) Some(x)
}
None => None
} }
None => None
} }
} }
impl<T: Owned> Peekable<T> for Port<T> { impl<T: Owned> Peekable<T> for Port<T> {
pure fn peek(&self) -> bool { pure fn peek(&self) -> bool { port_peek(self) }
unsafe { }
let mut endp = None;
endp <-> self.endp; #[inline(always)]
let peek = match &endp { pure fn port_peek<T:Owned>(self: &Port<T>) -> bool {
&Some(ref endp) => peek(endp), unsafe {
&None => fail!(~"peeking empty stream") let mut endp = None;
}; endp <-> self.endp;
self.endp <-> endp; let peek = match &endp {
peek &Some(ref endp) => peek(endp),
} &None => fail!(~"peeking empty stream")
};
self.endp <-> endp;
peek
} }
} }
@ -187,8 +221,16 @@ pub fn PortSet<T: Owned>() -> PortSet<T>{
} }
} }
pub impl<T: Owned> PortSet<T> { // Use an inherent impl so that imports are not required:
#[cfg(stage1)]
#[cfg(stage2)]
pub impl<T:Owned> PortSet<T> {
fn recv(&self) -> T { port_set_recv(self) }
fn try_recv(&self) -> Option<T> { port_set_try_recv(self) }
pure fn peek(&self) -> bool { port_set_peek(self) }
}
pub impl<T: Owned> PortSet<T> {
fn add(&self, port: Port<T>) { fn add(&self, port: Port<T>) {
self.ports.push(port) self.ports.push(port)
} }
@ -200,69 +242,89 @@ pub impl<T: Owned> PortSet<T> {
} }
} }
impl<T: Owned> GenericPort<T> for PortSet<T> { impl<T:Owned> GenericPort<T> for PortSet<T> {
fn try_recv(&self) -> Option<T> { port_set_try_recv(self) }
fn recv(&self) -> T { port_set_recv(self) }
}
fn try_recv(&self) -> Option<T> { #[inline(always)]
let mut result = None; fn port_set_recv<T:Owned>(self: &PortSet<T>) -> T {
// we have to swap the ports array so we aren't borrowing port_set_try_recv(self).expect("port_set: endpoints closed")
// aliasable mutable memory. }
let mut ports = ~[];
ports <-> self.ports; #[inline(always)]
while result.is_none() && ports.len() > 0 { fn port_set_try_recv<T:Owned>(self: &PortSet<T>) -> Option<T> {
let i = wait_many(ports); let mut result = None;
match ports[i].try_recv() { // we have to swap the ports array so we aren't borrowing
Some(m) => { // aliasable mutable memory.
result = Some(m); let mut ports = ~[];
} ports <-> self.ports;
None => { while result.is_none() && ports.len() > 0 {
// Remove this port. let i = wait_many(ports);
let _ = ports.swap_remove(i); match ports[i].try_recv() {
} Some(m) => {
result = Some(m);
}
None => {
// Remove this port.
let _ = ports.swap_remove(i);
} }
} }
ports <-> self.ports;
result
} }
ports <-> self.ports;
fn recv(&self) -> T { result
self.try_recv().expect("port_set: endpoints closed")
}
} }
impl<T: Owned> Peekable<T> for PortSet<T> { impl<T: Owned> Peekable<T> for PortSet<T> {
pure fn peek(&self) -> bool { pure fn peek(&self) -> bool { port_set_peek(self) }
// It'd be nice to use self.port.each, but that version isn't
// pure.
for vec::each(self.ports) |p| {
if p.peek() { return true }
}
false
}
} }
#[inline(always)]
pure fn port_set_peek<T:Owned>(self: &PortSet<T>) -> bool {
// It'd be nice to use self.port.each, but that version isn't
// pure.
for vec::each(self.ports) |p| {
if p.peek() { return true }
}
false
}
/// A channel that can be shared between many senders. /// A channel that can be shared between many senders.
pub type SharedChan<T> = unstable::Exclusive<Chan<T>>; pub type SharedChan<T> = unstable::Exclusive<Chan<T>>;
#[cfg(stage1)]
#[cfg(stage2)]
pub impl<T: Owned> SharedChan<T> {
fn send(&self, x: T) { shared_chan_send(self, x) }
fn try_send(&self, x: T) -> bool { shared_chan_try_send(self, x) }
}
impl<T: Owned> GenericChan<T> for SharedChan<T> { impl<T: Owned> GenericChan<T> for SharedChan<T> {
fn send(&self, x: T) { fn send(&self, x: T) { shared_chan_send(self, x) }
let mut xx = Some(x); }
do self.with_imm |chan| {
let mut x = None; #[inline(always)]
x <-> xx; fn shared_chan_send<T:Owned>(self: &SharedChan<T>, x: T) {
chan.send(option::unwrap(x)) let mut xx = Some(x);
} do self.with_imm |chan| {
let mut x = None;
x <-> xx;
chan.send(option::unwrap(x))
} }
} }
impl<T: Owned> GenericSmartChan<T> for SharedChan<T> { impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
fn try_send(&self, x: T) -> bool { fn try_send(&self, x: T) -> bool { shared_chan_try_send(self, x) }
let mut xx = Some(x); }
do self.with_imm |chan| {
let mut x = None; #[inline(always)]
x <-> xx; fn shared_chan_try_send<T:Owned>(self: &SharedChan<T>, x: T) -> bool {
chan.try_send(option::unwrap(x)) let mut xx = Some(x);
} do self.with_imm |chan| {
let mut x = None;
x <-> xx;
chan.try_send(option::unwrap(x))
} }
} }

View file

@ -69,6 +69,26 @@ pub trait Reader {
fn tell(&self) -> uint; fn tell(&self) -> uint;
} }
#[cfg(stage1)]
#[cfg(stage2)]
impl Reader for @Reader {
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
self.read(bytes, len)
}
fn read_byte(&self) -> int {
self.read_byte()
}
fn eof(&self) -> bool {
self.eof()
}
fn seek(&self, position: int, style: SeekStyle) {
self.seek(position, style)
}
fn tell(&self) -> uint {
self.tell()
}
}
/// Generic utility functions defined on readers. /// Generic utility functions defined on readers.
pub trait ReaderUtil { pub trait ReaderUtil {
@ -631,6 +651,16 @@ pub trait Writer {
fn get_type(&self) -> WriterType; fn get_type(&self) -> WriterType;
} }
#[cfg(stage1)]
#[cfg(stage2)]
impl Writer for @Writer {
fn write(&self, v: &[const u8]) { self.write(v) }
fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
fn tell(&self) -> uint { self.tell() }
fn flush(&self) -> int { self.flush() }
fn get_type(&self) -> WriterType { self.get_type() }
}
impl<W:Writer,C> Writer for Wrapper<W, C> { impl<W:Writer,C> Writer for Wrapper<W, C> {
fn write(&self, bs: &[const u8]) { self.base.write(bs); } fn write(&self, bs: &[const u8]) { self.base.write(bs); }
fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); } fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
@ -1067,8 +1097,8 @@ pub fn buffered_file_writer(path: &Path) -> Result<Writer, ~str> {
// FIXME (#2004) it would be great if this could be a const // FIXME (#2004) it would be great if this could be a const
// FIXME (#2004) why are these different from the way stdin() is // FIXME (#2004) why are these different from the way stdin() is
// implemented? // implemented?
pub fn stdout() -> Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) } pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
pub fn stderr() -> Writer { fd_writer(libc::STDERR_FILENO as c_int, false) } pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
pub fn print(s: &str) { stdout().write_str(s); } pub fn print(s: &str) { stdout().write_str(s); }
pub fn println(s: &str) { stdout().write_line(s); } pub fn println(s: &str) { stdout().write_line(s); }

View file

@ -23,6 +23,7 @@ use middle::ty;
use util::ppaux; use util::ppaux;
use core::char; use core::char;
use core::hash::Streaming;
use core::hash; use core::hash;
use core::io::{Writer, WriterUtil}; use core::io::{Writer, WriterUtil};
use core::libc::{c_int, c_uint, c_char}; use core::libc::{c_int, c_uint, c_char};

View file

@ -26,7 +26,7 @@ use core::dvec;
use core::flate; use core::flate;
use core::hash::{Hash, HashUtil}; use core::hash::{Hash, HashUtil};
use core::int; use core::int;
use core::io::WriterUtil; use core::io::{Writer, WriterUtil};
use core::io; use core::io;
use core::str; use core::str;
use core::to_bytes::IterBytes; use core::to_bytes::IterBytes;

View file

@ -29,10 +29,11 @@ use core::{dvec, io, option, vec};
use std::ebml::reader; use std::ebml::reader;
use std::ebml; use std::ebml;
use std::serialize; use std::serialize;
use std::serialize::{Encodable, EncoderHelpers, DecoderHelpers}; use std::serialize::{Encoder, Encodable, EncoderHelpers, DecoderHelpers};
use std::serialize::Decodable; use std::serialize::{Decoder, Decodable};
use syntax::ast; use syntax::ast;
use syntax::ast_map; use syntax::ast_map;
use syntax::ast_util::inlined_item_utils;
use syntax::ast_util; use syntax::ast_util;
use syntax::codemap::span; use syntax::codemap::span;
use syntax::codemap; use syntax::codemap;
@ -663,16 +664,6 @@ fn encode_vtable_origin(ecx: @e::EncodeContext,
} }
} }
} }
typeck::vtable_trait(def_id, tys) => {
do ebml_w.emit_enum_variant(~"vtable_trait", 1u, 3u) {
do ebml_w.emit_enum_variant_arg(0u) {
ebml_w.emit_def_id(def_id)
}
do ebml_w.emit_enum_variant_arg(1u) {
ebml_w.emit_tys(ecx, /*bad*/copy tys);
}
}
}
} }
} }
@ -719,16 +710,6 @@ impl vtable_decoder_helpers for reader::Decoder {
} }
) )
} }
2 => {
typeck::vtable_trait(
do self.read_enum_variant_arg(0u) {
self.read_def_id(xcx)
},
do self.read_enum_variant_arg(1u) {
self.read_tys(xcx)
}
)
}
// hard to avoid - user input // hard to avoid - user input
_ => fail!(~"bad enum variant") _ => fail!(~"bad enum variant")
} }

View file

@ -1405,7 +1405,6 @@ pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, +vt: typeck::vtable_origin)
} }
} }
} }
vt => vt
} }
} }

View file

@ -478,14 +478,6 @@ pub fn trans_monomorphized_callee(bcx: block,
}) })
} }
} }
typeck::vtable_trait(_, _) => {
trans_trait_callee(bcx,
callee_id,
n_method,
base,
ty::vstore_box,
mentry.explicit_self)
}
typeck::vtable_param(*) => { typeck::vtable_param(*) => {
fail!(~"vtable_param left in monomorphized function's " + fail!(~"vtable_param left in monomorphized function's " +
"vtable substs"); "vtable substs");
@ -756,13 +748,7 @@ pub fn vtable_id(ccx: @CrateContext,
None, None,
None) None)
} }
typeck::vtable_trait(trait_id, substs) => {
@mono_id_ {
def: trait_id,
params: vec::map(substs, |t| mono_precise(*t, None)),
impl_did_opt: None
}
}
// can't this be checked at the callee? // can't this be checked at the callee?
_ => fail!(~"vtable_id") _ => fail!(~"vtable_id")
} }

View file

@ -30,7 +30,7 @@ itself (note that inherent impls can only be defined in the same
module as the type itself). module as the type itself).
Inherent candidates are not always derived from impls. If you have a Inherent candidates are not always derived from impls. If you have a
trait instance, such as a value of type `ToStr`, then the trait trait instance, such as a value of type `@ToStr`, then the trait
methods (`to_str()`, in this case) are inherently associated with it. methods (`to_str()`, in this case) are inherently associated with it.
Another case is type parameters, in which case the methods of their Another case is type parameters, in which case the methods of their
bounds are inherent. bounds are inherent.
@ -1221,7 +1221,7 @@ pub impl LookupContext {
} }
method_trait(trait_did, _, _) | method_self(trait_did, _) method_trait(trait_did, _, _) | method_self(trait_did, _)
| method_super(trait_did, _) => { | method_super(trait_did, _) => {
self.report_param_candidate(idx, trait_did) self.report_trait_candidate(idx, trait_did)
} }
} }
} }

View file

@ -18,7 +18,7 @@ use middle::typeck::infer::{fixup_err_to_str, InferCtxt};
use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type}; use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
use middle::typeck::infer; use middle::typeck::infer;
use middle::typeck::{CrateCtxt, vtable_origin, vtable_param, vtable_res}; use middle::typeck::{CrateCtxt, vtable_origin, vtable_param, vtable_res};
use middle::typeck::{vtable_static, vtable_trait}; use middle::typeck::{vtable_static};
use util::common::indenter; use util::common::indenter;
use util::ppaux::tys_to_str; use util::ppaux::tys_to_str;
use util::ppaux; use util::ppaux;
@ -81,7 +81,6 @@ pub fn lookup_vtables(vcx: &VtableContext,
location_info: &LocationInfo, location_info: &LocationInfo,
bounds: @~[ty::param_bounds], bounds: @~[ty::param_bounds],
substs: &ty::substs, substs: &ty::substs,
allow_unsafe: bool,
is_early: bool) -> vtable_res { is_early: bool) -> vtable_res {
debug!("lookup_vtables(location_info=%?, debug!("lookup_vtables(location_info=%?,
# bounds=%?, \ # bounds=%?, \
@ -110,8 +109,7 @@ pub fn lookup_vtables(vcx: &VtableContext,
debug!("after subst: %?", debug!("after subst: %?",
ppaux::ty_to_str(tcx, trait_ty)); ppaux::ty_to_str(tcx, trait_ty));
match lookup_vtable(vcx, location_info, *ty, trait_ty, match lookup_vtable(vcx, location_info, *ty, trait_ty, is_early) {
allow_unsafe, is_early) {
Some(vtable) => result.push(vtable), Some(vtable) => result.push(vtable),
None => { None => {
vcx.tcx().sess.span_fatal( vcx.tcx().sess.span_fatal(
@ -162,7 +160,6 @@ pub fn lookup_vtable(vcx: &VtableContext,
location_info: &LocationInfo, location_info: &LocationInfo,
ty: ty::t, ty: ty::t,
trait_ty: ty::t, trait_ty: ty::t,
allow_unsafe: bool,
is_early: bool) is_early: bool)
-> Option<vtable_origin> { -> Option<vtable_origin> {
debug!("lookup_vtable(ty=%s, trait_ty=%s)", debug!("lookup_vtable(ty=%s, trait_ty=%s)",
@ -224,30 +221,6 @@ pub fn lookup_vtable(vcx: &VtableContext,
} }
} }
ty::ty_trait(did, ref substs, _) if trait_id == did => {
debug!("(checking vtable) @1 relating ty to trait ty with did %?",
did);
relate_trait_tys(vcx, location_info, trait_ty, ty);
if !allow_unsafe && !is_early {
for vec::each(*ty::trait_methods(tcx, did)) |m| {
if ty::type_has_self(ty::mk_bare_fn(tcx, copy m.fty)) {
tcx.sess.span_err(
location_info.span,
~"a boxed trait with self types may not be \
passed as a bounded type");
} else if (*m.tps).len() > 0u {
tcx.sess.span_err(
location_info.span,
~"a boxed trait with generic methods may not \
be passed as a bounded type");
}
}
}
return Some(vtable_trait(did, /*bad*/copy (*substs).tps));
}
_ => { _ => {
let mut found = ~[]; let mut found = ~[];
@ -411,7 +384,7 @@ pub fn lookup_vtable(vcx: &VtableContext,
trait_vstore); trait_vstore);
let subres = lookup_vtables( let subres = lookup_vtables(
vcx, location_info, im_bs, &substs_f, vcx, location_info, im_bs, &substs_f,
false, is_early); is_early);
// Finally, we register that we found a // Finally, we register that we found a
// matching impl, and record the def ID of // matching impl, and record the def ID of
@ -542,8 +515,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
} }
let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() }; let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() };
let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex), let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
item_ty.bounds, substs, false, item_ty.bounds, substs, is_early);
is_early);
if !is_early { if !is_early {
let vtable_map = cx.vtable_map; let vtable_map = cx.vtable_map;
vtable_map.insert(ex.id, vtbls); vtable_map.insert(ex.id, vtbls);
@ -573,7 +545,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
let substs = fcx.node_ty_substs(callee_id); let substs = fcx.node_ty_substs(callee_id);
let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() }; let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() };
let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex), let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
bounds, &substs, false, is_early); bounds, &substs, is_early);
if !is_early { if !is_early {
insert_vtables(cx, callee_id, vtbls); insert_vtables(cx, callee_id, vtbls);
} }
@ -607,7 +579,6 @@ pub fn early_resolve_expr(ex: @ast::expr,
location_info, location_info,
mt.ty, mt.ty,
target_ty, target_ty,
true,
is_early); is_early);
match vtable_opt { match vtable_opt {
Some(vtable) => { Some(vtable) => {

View file

@ -22,7 +22,7 @@ use middle::typeck::infer::{force_all, resolve_all, resolve_region};
use middle::typeck::infer::{resolve_type}; use middle::typeck::infer::{resolve_type};
use middle::typeck::infer; use middle::typeck::infer;
use middle::typeck::method_map_entry; use middle::typeck::method_map_entry;
use middle::typeck::{vtable_param, vtable_trait, write_substs_to_tcx}; use middle::typeck::{vtable_param, write_substs_to_tcx};
use middle::typeck::{write_ty_to_tcx}; use middle::typeck::{write_ty_to_tcx};
use util::ppaux; use util::ppaux;

View file

@ -902,8 +902,12 @@ pub impl CoherenceChecker {
// Nothing to do. // Nothing to do.
} }
Some(base_type_def_id) => { Some(base_type_def_id) => {
self.add_inherent_method(base_type_def_id, // inherent methods apply to `impl Type` but not
*implementation); // `impl Trait for Type`:
if associated_traits.len() == 0 {
self.add_inherent_method(base_type_def_id,
*implementation);
}
self.base_type_def_ids.insert(implementation.did, self.base_type_def_ids.insert(implementation.did,
base_type_def_id); base_type_def_id);

View file

@ -150,12 +150,7 @@ pub enum vtable_origin {
The first uint is the param number (identifying T in the example), The first uint is the param number (identifying T in the example),
and the second is the bound number (identifying baz) and the second is the bound number (identifying baz)
*/ */
vtable_param(uint, uint), vtable_param(uint, uint)
/*
Dynamic vtable, comes from something known to have a trait
type. def_id refers to the trait item, tys are the substs
*/
vtable_trait(ast::def_id, ~[ty::t]),
} }
pub impl vtable_origin { pub impl vtable_origin {
@ -171,12 +166,6 @@ pub impl vtable_origin {
vtable_param(x, y) => { vtable_param(x, y) => {
fmt!("vtable_param(%?, %?)", x, y) fmt!("vtable_param(%?, %?)", x, y)
} }
vtable_trait(def_id, ref tys) => {
fmt!("vtable_trait(%?:%s, %?)",
def_id, ty::item_path_str(tcx, def_id),
tys.map(|t| ppaux::ty_to_str(tcx, *t)))
}
} }
} }
} }

View file

@ -35,6 +35,7 @@ use std::net::url;
use std::{json, semver, getopts}; use std::{json, semver, getopts};
use syntax::codemap::spanned; use syntax::codemap::spanned;
use syntax::{ast, attr, codemap, diagnostic, parse, visit}; use syntax::{ast, attr, codemap, diagnostic, parse, visit};
use core::container::Map;
mod usage; mod usage;
mod util; mod util;

View file

@ -9,6 +9,7 @@
// except according to those terms. // except according to those terms.
use core::*; use core::*;
use core::hash::{Hash, HashUtil, Streaming};
use core::hashmap::linear::LinearMap; use core::hashmap::linear::LinearMap;
use rustc::driver::{driver, session}; use rustc::driver::{driver, session};
use rustc::metadata::filesearch; use rustc::metadata::filesearch;

View file

@ -25,6 +25,27 @@ pub struct DuplexStream<T, U> {
priv port: Port<U>, priv port: Port<U>,
} }
// Allow these methods to be used without import:
#[cfg(stage1)]
#[cfg(stage2)]
pub impl<T:Owned,U:Owned> DuplexStream<T, U> {
fn send(x: T) {
self.chan.send(x)
}
fn try_send(x: T) -> bool {
self.chan.try_send(x)
}
fn recv() -> U {
self.port.recv()
}
fn try_recv() -> Option<U> {
self.port.try_recv()
}
pure fn peek() -> bool {
self.port.peek()
}
}
impl<T:Owned,U:Owned> GenericChan<T> for DuplexStream<T, U> { impl<T:Owned,U:Owned> GenericChan<T> for DuplexStream<T, U> {
fn send(&self, x: T) { fn send(&self, x: T) {
self.chan.send(x) self.chan.send(x)

View file

@ -8,19 +8,14 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
trait double { // See coherence_inherent_cc.rs
fn double() -> uint;
pub trait TheTrait {
fn the_fn(&self);
} }
impl double for uint { pub struct TheStruct;
fn double() -> uint { self * 2u }
}
fn is_equal<D:double>(x: @D, exp: uint) { impl TheTrait for TheStruct {
assert x.double() == exp; fn the_fn(&self) {}
}
pub fn main() {
let x = @(@3u as @double);
is_equal(x, 6);
} }

View file

@ -0,0 +1,45 @@
// Copyright 2012 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.
// Tests that methods that implement a trait cannot be invoked
// unless the trait is imported.
mod Lib {
pub trait TheTrait {
fn the_fn(&self);
}
pub struct TheStruct;
impl TheTrait for TheStruct {
fn the_fn(&self) {}
}
}
mod Import {
// Trait is in scope here:
use Lib::TheStruct;
use Lib::TheTrait;
fn call_the_fn(s: &TheStruct) {
s.the_fn();
}
}
mod NoImport {
// Trait is not in scope here:
use Lib::TheStruct;
fn call_the_fn(s: &TheStruct) {
s.the_fn(); //~ ERROR does not implement any method in scope named `the_fn`
}
}
fn main() {}

View file

@ -0,0 +1,38 @@
// Copyright 2012 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.
// xfail-fast
// aux-build:coherence_inherent_cc_lib.rs
// Tests that methods that implement a trait cannot be invoked
// unless the trait is imported.
extern mod coherence_inherent_cc_lib;
mod Import {
// Trait is in scope here:
use coherence_inherent_cc_lib::TheStruct;
use coherence_inherent_cc_lib::TheTrait;
fn call_the_fn(s: &TheStruct) {
s.the_fn();
}
}
mod NoImport {
// Trait is not in scope here:
use coherence_inherent_cc_lib::TheStruct;
fn call_the_fn(s: &TheStruct) {
s.the_fn(); //~ ERROR does not implement any method in scope named `the_fn`
}
}
fn main() {}

View file

@ -8,19 +8,10 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
trait double { // Test that an object type `@Foo` is not considered to implement the
fn double() -> uint; // trait `Foo`. Issue #5087.
}
impl double for uint { trait Foo {}
fn double() -> uint { self * 2u } fn take_foo<F:Foo>(f: F) {}
} fn take_object(f: @Foo) { take_foo(f); } //~ ERROR failed to find an implementation of trait
fn main() {}
fn is_equal<D:double>(x: @D, exp: uint) {
assert x.double() == exp;
}
pub fn main() {
let x = @(@3u as @double);
is_equal(x, 6);
}

View file

@ -16,8 +16,16 @@ fn make_gc1(gc: get_ctxt/&a) -> get_ctxt/&b {
return gc; //~ ERROR mismatched types: expected `@get_ctxt/&b` but found `@get_ctxt/&a` return gc; //~ ERROR mismatched types: expected `@get_ctxt/&b` but found `@get_ctxt/&a`
} }
fn make_gc2(gc: get_ctxt/&a) -> get_ctxt/&b { struct Foo {
return @gc as get_ctxt; //~ ERROR cannot infer an appropriate lifetime r: &'self uint
}
impl get_ctxt/&self for Foo/&self {
fn get_ctxt() -> &self/uint { self.r }
}
fn make_gc2(foo: Foo/&a) -> get_ctxt/&b {
return @foo as get_ctxt; //~ ERROR cannot infer an appropriate lifetime
} }
fn main() { fn main() {

View file

@ -1,25 +0,0 @@
// Copyright 2012 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.
trait add {
fn plus(++x: Self) -> Self;
}
impl add for int {
fn plus(++x: int) -> int { self + x }
}
fn do_add<A:add>(x: A, y: A) -> A { x.plus(y) }
fn main() {
let x = @3 as @add;
let y = @4 as @add;
do_add(x, y); //~ ERROR a boxed trait with self types may not be passed as a bounded type
}

View file

@ -1,21 +0,0 @@
// Copyright 2012 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.
trait foo<T> { }
fn bar(x: foo<uint>) -> foo<int> {
return (@x as foo::<int>);
//~^ ERROR mismatched types: expected `@foo<int>` but found `@foo<uint>`
//~^^ ERROR mismatched types: expected `@foo<int>` but found `@foo<uint>`
// This is unfortunate -- new handling of parens means the error message
// gets printed twice
}
fn main() {}

View file

@ -14,7 +14,7 @@ extern mod cci_class_cast;
use core::to_str::ToStr; use core::to_str::ToStr;
use cci_class_cast::kitty::*; use cci_class_cast::kitty::*;
fn print_out<T:ToStr>(thing: T, expected: ~str) { fn print_out(thing: @ToStr, expected: ~str) {
let actual = thing.to_str(); let actual = thing.to_str();
debug!("%s", actual); debug!("%s", actual);
assert(actual == expected); assert(actual == expected);

View file

@ -79,7 +79,7 @@ fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat {
} }
fn annoy_neighbors<T:noisy>(critter: T) { fn annoy_neighbors(critter: @noisy) {
for uint::range(0u, 10u) |i| { critter.speak(); } for uint::range(0u, 10u) |i| { critter.speak(); }
} }

View file

@ -56,7 +56,7 @@ impl ToStr for cat {
pure fn to_str(&self) -> ~str { copy self.name } pure fn to_str(&self) -> ~str { copy self.name }
} }
fn print_out<T:ToStr>(thing: T, expected: ~str) { fn print_out(thing: @ToStr, expected: ~str) {
let actual = thing.to_str(); let actual = thing.to_str();
debug!("%s", actual); debug!("%s", actual);
assert(actual == expected); assert(actual == expected);

View file

@ -1,39 +0,0 @@
pub trait Reader {
// FIXME (#2004): Seekable really should be orthogonal.
/// Read up to len bytes (or EOF) and put them into bytes (which
/// must be at least len bytes long). Return number of bytes read.
// FIXME (#2982): This should probably return an error.
fn read(&self, bytes: &mut [u8], len: uint) -> uint;
}
pub trait ReaderUtil {
/// Read len bytes into a new vec.
fn read_bytes(&self, len: uint);
}
impl<T:Reader> ReaderUtil for T {
fn read_bytes(&self, len: uint) {
let mut count = self.read(&mut [0], len);
}
}
struct S {
x: int,
y: int
}
impl Reader for S {
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
0
}
}
pub fn main() {
let x = S { x: 1, y: 2 };
let x = @x as @Reader;
x.read_bytes(0);
}

View file

@ -1,39 +0,0 @@
pub trait Reader {
// FIXME (#2004): Seekable really should be orthogonal.
/// Read up to len bytes (or EOF) and put them into bytes (which
/// must be at least len bytes long). Return number of bytes read.
// FIXME (#2982): This should probably return an error.
fn read(&self, bytes: &mut [u8], len: uint) -> uint;
}
pub trait ReaderUtil {
/// Read len bytes into a new vec.
fn read_bytes(&self, len: uint);
}
impl<T:Reader> ReaderUtil for T {
fn read_bytes(&self, len: uint) {
let mut count = self.read(&mut [0], len);
}
}
struct S {
x: int,
y: int
}
impl Reader for S {
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
0
}
}
pub fn main() {
let x = S { x: 1, y: 2 };
let x = @x as @Reader;
x.read_bytes(0);
}

View file

@ -1,39 +0,0 @@
pub trait Reader {
// FIXME (#2004): Seekable really should be orthogonal.
/// Read up to len bytes (or EOF) and put them into bytes (which
/// must be at least len bytes long). Return number of bytes read.
// FIXME (#2982): This should probably return an error.
fn read(&self, bytes: &mut [u8], len: uint) -> uint;
}
pub trait ReaderUtil {
/// Read len bytes into a new vec.
fn read_bytes(len: uint);
}
impl<T:Reader> ReaderUtil for T {
fn read_bytes(len: uint) {
let mut count = self.read(&mut [0], len);
}
}
struct S {
x: int,
y: int
}
impl Reader for S {
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
0
}
}
pub fn main() {
let x = S { x: 1, y: 2 };
let x = @x as @Reader;
x.read_bytes(0);
}

View file

@ -1,39 +0,0 @@
pub trait Reader {
// FIXME (#2004): Seekable really should be orthogonal.
/// Read up to len bytes (or EOF) and put them into bytes (which
/// must be at least len bytes long). Return number of bytes read.
// FIXME (#2982): This should probably return an error.
fn read(bytes: &mut [u8], len: uint) -> uint;
}
pub trait ReaderUtil {
/// Read len bytes into a new vec.
fn read_bytes(len: uint);
}
impl<T:Reader> ReaderUtil for T {
fn read_bytes(len: uint) {
let mut count = self.read(&mut [0], len);
}
}
struct S {
x: int,
y: int
}
impl Reader for S {
fn read(bytes: &mut [u8], len: uint) -> uint {
0
}
}
pub fn main() {
let x = S { x: 1, y: 2 };
let x = @x as @Reader;
x.read_bytes(0);
}

View file

@ -11,12 +11,12 @@
use core::iter::BaseIter; use core::iter::BaseIter;
trait FlatMapToVec<A> { trait FlatMapToVec<A> {
fn flat_map_to_vec<B, IB:BaseIter<B>>(op: fn(&A) -> IB) -> ~[B]; fn flat_map_to_vec<B, IB:BaseIter<B>>(&self, op: fn(&A) -> IB) -> ~[B];
} }
impl<A:Copy> FlatMapToVec<A> for BaseIter<A> { impl<A:Copy> FlatMapToVec<A> for ~[A] {
fn flat_map_to_vec<B, IB:BaseIter<B>>(op: fn(&A) -> IB) -> ~[B] { fn flat_map_to_vec<B, IB:BaseIter<B>>(&self, op: fn(&A) -> IB) -> ~[B] {
iter::flat_map_to_vec(&self, op) iter::flat_map_to_vec(self, op)
} }
} }

View file

@ -18,13 +18,13 @@ pub fn main() {
p2.recv(); p2.recv();
error!("sibling fails"); error!("sibling fails");
fail!(); fail!();
} }
let (p3,c3) = comm::stream(); let (p3,c3) = comm::stream();
c.send(c3); c.send(c3);
c2.send(()); c2.send(());
error!("child blocks"); error!("child blocks");
p3.recv(); p3.recv();
}; };
error!("parent tries"); error!("parent tries");
assert !p.recv().try_send(()); assert !p.recv().try_send(());
error!("all done!"); error!("all done!");

View file

@ -17,6 +17,7 @@
use double_buffer::client::*; use double_buffer::client::*;
use double_buffer::give_buffer; use double_buffer::give_buffer;
use core::comm::Selectable;
macro_rules! select_if ( macro_rules! select_if (
{ {

View file

@ -13,7 +13,9 @@
extern mod aux(name = "trait_inheritance_cross_trait_call_xc_aux"); extern mod aux(name = "trait_inheritance_cross_trait_call_xc_aux");
trait Bar : aux::Foo { use aux::Foo;
trait Bar : Foo {
fn g() -> int; fn g() -> int;
} }