Skip to content

Commit

Permalink
auto merge of #5252 : nikomatsakis/rust/issue-5087-make-trait-not-imp…
Browse files Browse the repository at this point in the history
…l-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
  • Loading branch information
bors committed Mar 6, 2013
2 parents 67100dd + 5653fe6 commit 4b79a58
Show file tree
Hide file tree
Showing 33 changed files with 344 additions and 420 deletions.
238 changes: 150 additions & 88 deletions src/libcore/comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,64 +104,98 @@ pub fn stream<T:Owned>() -> (Port<T>, Chan<T>) {
(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> {
fn send(&self, x: T) {
let mut endp = None;
endp <-> self.endp;
self.endp = Some(
streamp::client::data(unwrap(endp), x))
}
fn send(&self, x: T) { chan_send(self, x) }
}
impl<T: Owned> GenericSmartChan<T> for Chan<T> {
#[inline(always)]
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> {
fn try_send(&self, x: T) -> bool {
let mut endp = None;
endp <-> self.endp;
match streamp::client::try_data(unwrap(endp), x) {
Some(next) => {
self.endp = Some(next);
true
}
None => false
}
chan_try_send(self, x)
}
}
impl<T: Owned> GenericPort<T> for Port<T> {
fn recv(&self) -> T {
let mut endp = None;
endp <-> self.endp;
let streamp::data(x, endp) = recv(unwrap(endp));
self.endp = Some(endp);
x
#[inline(always)]
fn chan_try_send<T:Owned>(self: &Chan<T>, x: T) -> bool {
let mut endp = None;
endp <-> self.endp;
match streamp::client::try_data(unwrap(endp), x) {
Some(next) => {
self.endp = Some(next);
true
}
None => false
}
}
fn try_recv(&self) -> Option<T> {
let mut endp = None;
endp <-> self.endp;
match try_recv(unwrap(endp)) {
Some(streamp::data(x, endp)) => {
// Use an inherent impl so that imports are not required:
#[cfg(stage1)]
#[cfg(stage2)]
pub impl<T: Owned> Port<T> {
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);
Some(x)
}
None => None
}
None => None
}
}
impl<T: Owned> Peekable<T> for Port<T> {
pure fn peek(&self) -> bool {
unsafe {
let mut endp = None;
endp <-> self.endp;
let peek = match &endp {
&Some(ref endp) => peek(endp),
&None => fail!(~"peeking empty stream")
};
self.endp <-> endp;
peek
}
pure fn peek(&self) -> bool { port_peek(self) }
}
#[inline(always)]
pure fn port_peek<T:Owned>(self: &Port<T>) -> bool {
unsafe {
let mut endp = None;
endp <-> self.endp;
let peek = match &endp {
&Some(ref endp) => peek(endp),
&None => fail!(~"peeking empty stream")
};
self.endp <-> endp;
peek
}
}
Expand All @@ -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>) {
self.ports.push(port)
}
Expand All @@ -200,69 +242,89 @@ pub impl<T: Owned> PortSet<T> {
}
}
impl<T: Owned> GenericPort<T> for PortSet<T> {
fn try_recv(&self) -> Option<T> {
let mut result = None;
// we have to swap the ports array so we aren't borrowing
// aliasable mutable memory.
let mut ports = ~[];
ports <-> self.ports;
while result.is_none() && ports.len() > 0 {
let i = wait_many(ports);
match ports[i].try_recv() {
Some(m) => {
result = Some(m);
}
None => {
// Remove this port.
let _ = ports.swap_remove(i);
}
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) }
}
#[inline(always)]
fn port_set_recv<T:Owned>(self: &PortSet<T>) -> T {
port_set_try_recv(self).expect("port_set: endpoints closed")
}
#[inline(always)]
fn port_set_try_recv<T:Owned>(self: &PortSet<T>) -> Option<T> {
let mut result = None;
// we have to swap the ports array so we aren't borrowing
// aliasable mutable memory.
let mut ports = ~[];
ports <-> self.ports;
while result.is_none() && ports.len() > 0 {
let i = wait_many(ports);
match ports[i].try_recv() {
Some(m) => {
result = Some(m);
}
None => {
// Remove this port.
let _ = ports.swap_remove(i);
}
}
ports <-> self.ports;
result
}
fn recv(&self) -> T {
self.try_recv().expect("port_set: endpoints closed")
}
ports <-> self.ports;
result
}
impl<T: Owned> Peekable<T> for PortSet<T> {
pure fn peek(&self) -> 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
pure fn peek(&self) -> bool { port_set_peek(self) }
}
#[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.
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> {
fn send(&self, x: T) {
let mut xx = Some(x);
do self.with_imm |chan| {
let mut x = None;
x <-> xx;
chan.send(option::unwrap(x))
}
fn send(&self, x: T) { shared_chan_send(self, x) }
}
#[inline(always)]
fn shared_chan_send<T:Owned>(self: &SharedChan<T>, x: T) {
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> {
fn try_send(&self, x: T) -> bool {
let mut xx = Some(x);
do self.with_imm |chan| {
let mut x = None;
x <-> xx;
chan.try_send(option::unwrap(x))
}
fn try_send(&self, x: T) -> bool { shared_chan_try_send(self, x) }
}
#[inline(always)]
fn shared_chan_try_send<T:Owned>(self: &SharedChan<T>, x: T) -> bool {
let mut xx = Some(x);
do self.with_imm |chan| {
let mut x = None;
x <-> xx;
chan.try_send(option::unwrap(x))
}
}
Expand Down
34 changes: 32 additions & 2 deletions src/libcore/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,26 @@ pub trait Reader {
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.
pub trait ReaderUtil {

Expand Down Expand Up @@ -631,6 +651,16 @@ pub trait Writer {
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> {
fn write(&self, bs: &[const u8]) { self.base.write(bs); }
fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
Expand Down Expand Up @@ -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) why are these different from the way stdin() is
// implemented?
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 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 print(s: &str) { stdout().write_str(s); }
pub fn println(s: &str) { stdout().write_line(s); }
Expand Down
1 change: 1 addition & 0 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use middle::ty;
use util::ppaux;

use core::char;
use core::hash::Streaming;
use core::hash;
use core::io::{Writer, WriterUtil};
use core::libc::{c_int, c_uint, c_char};
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use core::dvec;
use core::flate;
use core::hash::{Hash, HashUtil};
use core::int;
use core::io::WriterUtil;
use core::io::{Writer, WriterUtil};
use core::io;
use core::str;
use core::to_bytes::IterBytes;
Expand Down
Loading

0 comments on commit 4b79a58

Please sign in to comment.