librustc: Forbid type implementations on typedefs.
This commit is contained in:
parent
670ab8ac36
commit
37abf4bad0
@ -395,24 +395,55 @@ pub mod server {
|
||||
}
|
||||
|
||||
/// The send end of a oneshot pipe.
|
||||
pub type ChanOne<T> = oneshot::client::Oneshot<T>;
|
||||
pub struct ChanOne<T> {
|
||||
contents: oneshot::client::Oneshot<T>
|
||||
}
|
||||
|
||||
impl<T> ChanOne<T> {
|
||||
pub fn new(contents: oneshot::client::Oneshot<T>) -> ChanOne<T> {
|
||||
ChanOne {
|
||||
contents: contents
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The receive end of a oneshot pipe.
|
||||
pub type PortOne<T> = oneshot::server::Oneshot<T>;
|
||||
pub struct PortOne<T> {
|
||||
contents: oneshot::server::Oneshot<T>
|
||||
}
|
||||
|
||||
impl<T> PortOne<T> {
|
||||
pub fn new(contents: oneshot::server::Oneshot<T>) -> PortOne<T> {
|
||||
PortOne {
|
||||
contents: contents
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair.
|
||||
pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
|
||||
let (chan, port) = oneshot::init();
|
||||
(port, chan)
|
||||
(PortOne::new(port), ChanOne::new(chan))
|
||||
}
|
||||
|
||||
pub impl<T: Owned> PortOne<T> {
|
||||
fn recv(self) -> T { recv_one(self) }
|
||||
fn try_recv(self) -> Option<T> { try_recv_one(self) }
|
||||
fn unwrap(self) -> oneshot::server::Oneshot<T> {
|
||||
match self {
|
||||
PortOne { contents: s } => s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub impl<T: Owned> ChanOne<T> {
|
||||
fn send(self, data: T) { send_one(self, data) }
|
||||
fn try_send(self, data: T) -> bool { try_send_one(self, data) }
|
||||
fn unwrap(self) -> oneshot::client::Oneshot<T> {
|
||||
match self {
|
||||
ChanOne { contents: s } => s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -420,33 +451,47 @@ fn try_send(self, data: T) -> bool { try_send_one(self, data) }
|
||||
* closed.
|
||||
*/
|
||||
pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
|
||||
let oneshot::send(message) = recv(port);
|
||||
message
|
||||
match port {
|
||||
PortOne { contents: port } => {
|
||||
let oneshot::send(message) = recv(port);
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Receive a message from a oneshot pipe unless the connection was closed.
|
||||
pub fn try_recv_one<T: Owned> (port: PortOne<T>) -> Option<T> {
|
||||
let message = try_recv(port);
|
||||
match port {
|
||||
PortOne { contents: port } => {
|
||||
let message = try_recv(port);
|
||||
|
||||
if message.is_none() { None }
|
||||
else {
|
||||
let oneshot::send(message) = message.unwrap();
|
||||
Some(message)
|
||||
if message.is_none() {
|
||||
None
|
||||
} else {
|
||||
let oneshot::send(message) = message.unwrap();
|
||||
Some(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a message on a oneshot pipe, failing if the connection was closed.
|
||||
pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
|
||||
oneshot::client::send(chan, data);
|
||||
match chan {
|
||||
ChanOne { contents: chan } => oneshot::client::send(chan, data),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message on a oneshot pipe, or return false if the connection was
|
||||
* closed.
|
||||
*/
|
||||
pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T)
|
||||
-> bool {
|
||||
oneshot::client::try_send(chan, data).is_some()
|
||||
pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
|
||||
match chan {
|
||||
ChanOne { contents: chan } => {
|
||||
oneshot::client::try_send(chan, data).is_some()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,6 +21,11 @@
|
||||
use to_str::ToStr;
|
||||
use ascii::{AsciiCast, AsciiStr};
|
||||
|
||||
#[cfg(windows)]
|
||||
pub use Path = self::WindowsPath;
|
||||
#[cfg(unix)]
|
||||
pub use Path = self::PosixPath;
|
||||
|
||||
#[deriving(Clone, Eq)]
|
||||
pub struct WindowsPath {
|
||||
host: Option<~str>,
|
||||
@ -72,22 +77,6 @@ pub trait GenericPath {
|
||||
fn is_absolute(&self) -> bool;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub type Path = WindowsPath;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn Path(s: &str) -> Path {
|
||||
WindowsPath(s)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub type Path = PosixPath;
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn Path(s: &str) -> Path {
|
||||
PosixPath(s)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(target_os = "android")]
|
||||
mod stat {
|
||||
|
@ -38,8 +38,9 @@
|
||||
use middle::typeck::infer::InferCtxt;
|
||||
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar};
|
||||
use middle::typeck::infer::{resolve_nested_tvar, resolve_type};
|
||||
use syntax::ast::{crate, def_id, def_mod, def_trait};
|
||||
use syntax::ast::{item, item_impl, item_mod, local_crate, method, trait_ref};
|
||||
use syntax::ast::{crate, def_id, def_mod, def_struct, def_trait, def_ty};
|
||||
use syntax::ast::{item, item_enum, item_impl, item_mod, item_struct};
|
||||
use syntax::ast::{local_crate, method, trait_ref, ty_path};
|
||||
use syntax::ast;
|
||||
use syntax::ast_map::node_item;
|
||||
use syntax::ast_map;
|
||||
@ -661,7 +662,19 @@ fn check_privileged_scopes(self, crate: @crate) {
|
||||
// Then visit the module items.
|
||||
visit_mod(module_, item.span, item.id, (), visitor);
|
||||
}
|
||||
item_impl(_, opt_trait, _, _) => {
|
||||
item_impl(_, None, ast_ty, _) => {
|
||||
if !self.ast_type_is_defined_in_local_crate(ast_ty) {
|
||||
// This is an error.
|
||||
let session = self.crate_context.tcx.sess;
|
||||
session.span_err(item.span,
|
||||
~"cannot associate methods with \
|
||||
a type outside the crate the \
|
||||
type is defined in; define \
|
||||
and implement a trait or new \
|
||||
type instead");
|
||||
}
|
||||
}
|
||||
item_impl(_, Some(trait_ref), _, _) => {
|
||||
// `for_ty` is `Type` in `impl Trait for Type`
|
||||
let for_ty =
|
||||
ty::node_id_to_type(self.crate_context.tcx,
|
||||
@ -671,40 +684,16 @@ fn check_privileged_scopes(self, crate: @crate) {
|
||||
// type. This still might be OK if the trait is
|
||||
// defined in the same crate.
|
||||
|
||||
match opt_trait {
|
||||
None => {
|
||||
// There is no trait to implement, so
|
||||
// this is an error.
|
||||
let trait_def_id =
|
||||
self.trait_ref_to_trait_def_id(trait_ref);
|
||||
|
||||
let session = self.crate_context.tcx.sess;
|
||||
session.span_err(item.span,
|
||||
~"cannot implement \
|
||||
inherent methods for a \
|
||||
type outside the crate \
|
||||
the type was defined \
|
||||
in; define and \
|
||||
implement a trait or \
|
||||
new type instead");
|
||||
}
|
||||
|
||||
Some(trait_ref) => {
|
||||
// This is OK if and only if the trait was
|
||||
// defined in this crate.
|
||||
|
||||
let trait_def_id =
|
||||
self.trait_ref_to_trait_def_id(
|
||||
trait_ref);
|
||||
|
||||
if trait_def_id.crate != local_crate {
|
||||
let session = self.crate_context.tcx.sess;
|
||||
session.span_err(item.span,
|
||||
~"cannot provide an \
|
||||
extension \
|
||||
implementation for a \
|
||||
trait not defined in \
|
||||
this crate");
|
||||
}
|
||||
}
|
||||
if trait_def_id.crate != local_crate {
|
||||
let session = self.crate_context.tcx.sess;
|
||||
session.span_err(item.span,
|
||||
~"cannot provide an \
|
||||
extension implementation \
|
||||
for a trait not defined \
|
||||
in this crate");
|
||||
}
|
||||
}
|
||||
|
||||
@ -754,6 +743,46 @@ fn please_check_that_trait_methods_are_implemented(&self,
|
||||
}
|
||||
}
|
||||
|
||||
/// For coherence, when we have `impl Type`, we need to guarantee that
|
||||
/// `Type` is "local" to the crate. For our purposes, this means that it
|
||||
/// must precisely name some nominal type defined in this crate.
|
||||
pub fn ast_type_is_defined_in_local_crate(&self, original_type: @ast::Ty)
|
||||
-> bool {
|
||||
match original_type.node {
|
||||
ty_path(_, path_id) => {
|
||||
match *self.crate_context.tcx.def_map.get(&path_id) {
|
||||
def_ty(def_id) | def_struct(def_id) => {
|
||||
if def_id.crate != local_crate {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that this type precisely names a nominal
|
||||
// type.
|
||||
match self.crate_context
|
||||
.tcx
|
||||
.items
|
||||
.find(&def_id.node) {
|
||||
None => {
|
||||
self.crate_context.tcx.sess.span_bug(
|
||||
original_type.span,
|
||||
~"resolve didn't resolve this type?!");
|
||||
}
|
||||
Some(&node_item(item, _)) => {
|
||||
match item.node {
|
||||
item_struct(*) | item_enum(*) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
Some(_) => false,
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
// Converts an implementation in the AST to an Impl structure.
|
||||
fn create_impl_from_item(&self, item: @item) -> @Impl {
|
||||
fn add_provided_methods(all_methods: &mut ~[@MethodInfo],
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
use core::cast;
|
||||
use core::cell::Cell;
|
||||
use core::comm::{oneshot, PortOne, send_one};
|
||||
use core::comm::{ChanOne, PortOne, oneshot, send_one};
|
||||
use core::pipes::recv;
|
||||
use core::task;
|
||||
|
||||
@ -120,8 +120,7 @@ pub fn from_value<A>(val: A) -> Future<A> {
|
||||
Future {state: Forced(val)}
|
||||
}
|
||||
|
||||
pub fn from_port<A:Owned>(port: PortOne<A>) ->
|
||||
Future<A> {
|
||||
pub fn from_port<A:Owned>(port: PortOne<A>) -> Future<A> {
|
||||
/*!
|
||||
* Create a future from a port
|
||||
*
|
||||
@ -131,7 +130,7 @@ pub fn from_port<A:Owned>(port: PortOne<A>) ->
|
||||
|
||||
let port = Cell(port);
|
||||
do from_fn || {
|
||||
let port = port.take();
|
||||
let port = port.take().unwrap();
|
||||
match recv(port) {
|
||||
oneshot::send(data) => data
|
||||
}
|
||||
@ -158,10 +157,10 @@ pub fn spawn<A:Owned>(blk: ~fn() -> A) -> Future<A> {
|
||||
* value of the future.
|
||||
*/
|
||||
|
||||
let (chan, port) = oneshot::init();
|
||||
let (port, chan) = oneshot();
|
||||
|
||||
let chan = Cell(chan);
|
||||
do task::spawn || {
|
||||
do task::spawn {
|
||||
let chan = chan.take();
|
||||
send_one(chan, blk());
|
||||
}
|
||||
@ -186,7 +185,7 @@ fn test_from_value() {
|
||||
|
||||
#[test]
|
||||
fn test_from_port() {
|
||||
let (ch, po) = oneshot::init();
|
||||
let (ch, po) = oneshot();
|
||||
send_one(ch, ~"whale");
|
||||
let f = from_port(po);
|
||||
assert!(f.get() == ~"whale");
|
||||
|
@ -16,10 +16,13 @@
|
||||
use sort;
|
||||
|
||||
use core::cell::Cell;
|
||||
use core::comm::{oneshot, PortOne, send_one};
|
||||
use core::cmp;
|
||||
use core::comm::{ChanOne, PortOne, oneshot, send_one};
|
||||
use core::either::{Either, Left, Right};
|
||||
use core::hashmap::HashMap;
|
||||
use core::io;
|
||||
use core::pipes::recv;
|
||||
use core::run;
|
||||
use core::hashmap::HashMap;
|
||||
use core::to_bytes;
|
||||
|
||||
/**
|
||||
@ -340,13 +343,13 @@ fn exec<T:Owned +
|
||||
}
|
||||
|
||||
_ => {
|
||||
let (chan, port) = oneshot::init();
|
||||
let (port, chan) = oneshot();
|
||||
let mut blk = None;
|
||||
blk <-> bo;
|
||||
let blk = blk.unwrap();
|
||||
let chan = Cell(chan);
|
||||
|
||||
do task::spawn || {
|
||||
do task::spawn {
|
||||
let exe = Exec {
|
||||
discovered_inputs: WorkMap::new(),
|
||||
discovered_outputs: WorkMap::new(),
|
||||
@ -383,7 +386,7 @@ fn unwrap<T:Owned +
|
||||
None => fail!(),
|
||||
Some(Left(v)) => v,
|
||||
Some(Right(port)) => {
|
||||
let (exe, v) = match recv(port) {
|
||||
let (exe, v) = match recv(port.unwrap()) {
|
||||
oneshot::send(data) => data
|
||||
};
|
||||
|
||||
|
@ -215,7 +215,50 @@ fn filter_attrs(item: @ast::item) -> @ast::item {
|
||||
}
|
||||
}
|
||||
|
||||
priv impl @ext_ctxt {
|
||||
trait ExtCtxtMethods {
|
||||
fn bind_path(&self,
|
||||
span: span,
|
||||
ident: ast::ident,
|
||||
path: @ast::Path,
|
||||
bounds: @OptVec<ast::TyParamBound>)
|
||||
-> ast::TyParam;
|
||||
fn expr(&self, span: span, node: ast::expr_) -> @ast::expr;
|
||||
fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path;
|
||||
fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path;
|
||||
fn path_tps(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty])
|
||||
-> @ast::Path;
|
||||
fn path_tps_global(&self,
|
||||
span: span,
|
||||
strs: ~[ast::ident],
|
||||
tps: ~[@ast::Ty])
|
||||
-> @ast::Path;
|
||||
fn ty_path(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty])
|
||||
-> @ast::Ty;
|
||||
fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat;
|
||||
fn stmt(&self, expr: @ast::expr) -> @ast::stmt;
|
||||
fn lit_str(&self, span: span, s: @~str) -> @ast::expr;
|
||||
fn lit_uint(&self, span: span, i: uint) -> @ast::expr;
|
||||
fn lambda(&self, blk: ast::blk) -> @ast::expr;
|
||||
fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk;
|
||||
fn expr_blk(&self, expr: @ast::expr) -> ast::blk;
|
||||
fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
|
||||
fn expr_path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
|
||||
fn expr_var(&self, span: span, var: ~str) -> @ast::expr;
|
||||
fn expr_field(&self, span: span, expr: @ast::expr, ident: ast::ident)
|
||||
-> @ast::expr;
|
||||
fn expr_call(&self, span: span, expr: @ast::expr, args: ~[@ast::expr])
|
||||
-> @ast::expr;
|
||||
fn expr_method_call(&self,
|
||||
span: span,
|
||||
expr: @ast::expr,
|
||||
ident: ast::ident,
|
||||
args: ~[@ast::expr])
|
||||
-> @ast::expr;
|
||||
fn lambda_expr(&self, expr: @ast::expr) -> @ast::expr;
|
||||
fn lambda_stmts(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr;
|
||||
}
|
||||
|
||||
impl ExtCtxtMethods for @ext_ctxt {
|
||||
fn bind_path(
|
||||
&self,
|
||||
_span: span,
|
||||
|
@ -867,7 +867,11 @@ fn new_span(@self, span: span) -> span {
|
||||
}
|
||||
}
|
||||
|
||||
pub impl @ast_fold {
|
||||
pub trait AstFoldExtensions {
|
||||
fn fold_attributes(&self, attrs: ~[attribute]) -> ~[attribute];
|
||||
}
|
||||
|
||||
impl AstFoldExtensions for @ast_fold {
|
||||
fn fold_attributes(&self, attrs: ~[attribute]) -> ~[attribute] {
|
||||
attrs.map(|x| fold_attribute_(*x, *self))
|
||||
}
|
||||
|
@ -56,6 +56,3 @@ fn context_res() -> context_res {
|
||||
|
||||
pub type context = arc_destruct<context_res>;
|
||||
|
||||
pub impl context {
|
||||
fn socket(&self) { }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user