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:
commit
4b79a58d9d
33 changed files with 345 additions and 421 deletions
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1405,7 +1405,6 @@ pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, +vt: typeck::vtable_origin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vt => vt
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
45
src/test/compile-fail/coherence_inherent.rs
Normal file
45
src/test/compile-fail/coherence_inherent.rs
Normal 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() {}
|
38
src/test/compile-fail/coherence_inherent_cc.rs
Normal file
38
src/test/compile-fail/coherence_inherent_cc.rs
Normal 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() {}
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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() {}
|
|
|
@ -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);
|
||||||
|
|
|
@ -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(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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!");
|
||||||
|
|
|
@ -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 (
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue