Skip to content

Make object not impl associated trait, fix cross-crate coherence inconsistency #5252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could also be done by adding GenericChan to the prelude, couldn't it?

#[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