Skip to content

Commit 37abf4b

Browse files
committed
librustc: Forbid type implementations on typedefs.
1 parent 670ab8a commit 37abf4b

File tree

8 files changed

+193
-84
lines changed

8 files changed

+193
-84
lines changed

src/libcore/comm.rs

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -395,58 +395,103 @@ pub mod oneshot {
395395
}
396396
397397
/// The send end of a oneshot pipe.
398-
pub type ChanOne<T> = oneshot::client::Oneshot<T>;
398+
pub struct ChanOne<T> {
399+
contents: oneshot::client::Oneshot<T>
400+
}
401+
402+
impl<T> ChanOne<T> {
403+
pub fn new(contents: oneshot::client::Oneshot<T>) -> ChanOne<T> {
404+
ChanOne {
405+
contents: contents
406+
}
407+
}
408+
}
409+
399410
/// The receive end of a oneshot pipe.
400-
pub type PortOne<T> = oneshot::server::Oneshot<T>;
411+
pub struct PortOne<T> {
412+
contents: oneshot::server::Oneshot<T>
413+
}
414+
415+
impl<T> PortOne<T> {
416+
pub fn new(contents: oneshot::server::Oneshot<T>) -> PortOne<T> {
417+
PortOne {
418+
contents: contents
419+
}
420+
}
421+
}
401422
402423
/// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair.
403424
pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
404425
let (chan, port) = oneshot::init();
405-
(port, chan)
426+
(PortOne::new(port), ChanOne::new(chan))
406427
}
407428
408429
pub impl<T: Owned> PortOne<T> {
409430
fn recv(self) -> T { recv_one(self) }
410431
fn try_recv(self) -> Option<T> { try_recv_one(self) }
432+
fn unwrap(self) -> oneshot::server::Oneshot<T> {
433+
match self {
434+
PortOne { contents: s } => s
435+
}
436+
}
411437
}
412438
413439
pub impl<T: Owned> ChanOne<T> {
414440
fn send(self, data: T) { send_one(self, data) }
415441
fn try_send(self, data: T) -> bool { try_send_one(self, data) }
442+
fn unwrap(self) -> oneshot::client::Oneshot<T> {
443+
match self {
444+
ChanOne { contents: s } => s
445+
}
446+
}
416447
}
417448
418449
/**
419450
* Receive a message from a oneshot pipe, failing if the connection was
420451
* closed.
421452
*/
422453
pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
423-
let oneshot::send(message) = recv(port);
424-
message
454+
match port {
455+
PortOne { contents: port } => {
456+
let oneshot::send(message) = recv(port);
457+
message
458+
}
459+
}
425460
}
426461
427462
/// Receive a message from a oneshot pipe unless the connection was closed.
428463
pub fn try_recv_one<T: Owned> (port: PortOne<T>) -> Option<T> {
429-
let message = try_recv(port);
430-
431-
if message.is_none() { None }
432-
else {
433-
let oneshot::send(message) = message.unwrap();
434-
Some(message)
464+
match port {
465+
PortOne { contents: port } => {
466+
let message = try_recv(port);
467+
468+
if message.is_none() {
469+
None
470+
} else {
471+
let oneshot::send(message) = message.unwrap();
472+
Some(message)
473+
}
474+
}
435475
}
436476
}
437477
438478
/// Send a message on a oneshot pipe, failing if the connection was closed.
439479
pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
440-
oneshot::client::send(chan, data);
480+
match chan {
481+
ChanOne { contents: chan } => oneshot::client::send(chan, data),
482+
}
441483
}
442484
443485
/**
444486
* Send a message on a oneshot pipe, or return false if the connection was
445487
* closed.
446488
*/
447-
pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T)
448-
-> bool {
449-
oneshot::client::try_send(chan, data).is_some()
489+
pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
490+
match chan {
491+
ChanOne { contents: chan } => {
492+
oneshot::client::try_send(chan, data).is_some()
493+
}
494+
}
450495
}
451496
452497

src/libcore/path.rs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ use str;
2121
use to_str::ToStr;
2222
use ascii::{AsciiCast, AsciiStr};
2323

24+
#[cfg(windows)]
25+
pub use Path = self::WindowsPath;
26+
#[cfg(unix)]
27+
pub use Path = self::PosixPath;
28+
2429
#[deriving(Clone, Eq)]
2530
pub struct WindowsPath {
2631
host: Option<~str>,
@@ -72,22 +77,6 @@ pub trait GenericPath {
7277
fn is_absolute(&self) -> bool;
7378
}
7479

75-
#[cfg(windows)]
76-
pub type Path = WindowsPath;
77-
78-
#[cfg(windows)]
79-
pub fn Path(s: &str) -> Path {
80-
WindowsPath(s)
81-
}
82-
83-
#[cfg(unix)]
84-
pub type Path = PosixPath;
85-
86-
#[cfg(unix)]
87-
pub fn Path(s: &str) -> Path {
88-
PosixPath(s)
89-
}
90-
9180
#[cfg(target_os = "linux")]
9281
#[cfg(target_os = "android")]
9382
mod stat {

src/librustc/middle/typeck/coherence.rs

Lines changed: 65 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ use middle::typeck::infer::combine::Combine;
3838
use middle::typeck::infer::InferCtxt;
3939
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar};
4040
use middle::typeck::infer::{resolve_nested_tvar, resolve_type};
41-
use syntax::ast::{crate, def_id, def_mod, def_trait};
42-
use syntax::ast::{item, item_impl, item_mod, local_crate, method, trait_ref};
41+
use syntax::ast::{crate, def_id, def_mod, def_struct, def_trait, def_ty};
42+
use syntax::ast::{item, item_enum, item_impl, item_mod, item_struct};
43+
use syntax::ast::{local_crate, method, trait_ref, ty_path};
4344
use syntax::ast;
4445
use syntax::ast_map::node_item;
4546
use syntax::ast_map;
@@ -661,7 +662,19 @@ pub impl CoherenceChecker {
661662
// Then visit the module items.
662663
visit_mod(module_, item.span, item.id, (), visitor);
663664
}
664-
item_impl(_, opt_trait, _, _) => {
665+
item_impl(_, None, ast_ty, _) => {
666+
if !self.ast_type_is_defined_in_local_crate(ast_ty) {
667+
// This is an error.
668+
let session = self.crate_context.tcx.sess;
669+
session.span_err(item.span,
670+
~"cannot associate methods with \
671+
a type outside the crate the \
672+
type is defined in; define \
673+
and implement a trait or new \
674+
type instead");
675+
}
676+
}
677+
item_impl(_, Some(trait_ref), _, _) => {
665678
// `for_ty` is `Type` in `impl Trait for Type`
666679
let for_ty =
667680
ty::node_id_to_type(self.crate_context.tcx,
@@ -671,40 +684,16 @@ pub impl CoherenceChecker {
671684
// type. This still might be OK if the trait is
672685
// defined in the same crate.
673686

674-
match opt_trait {
675-
None => {
676-
// There is no trait to implement, so
677-
// this is an error.
678-
679-
let session = self.crate_context.tcx.sess;
680-
session.span_err(item.span,
681-
~"cannot implement \
682-
inherent methods for a \
683-
type outside the crate \
684-
the type was defined \
685-
in; define and \
686-
implement a trait or \
687-
new type instead");
688-
}
687+
let trait_def_id =
688+
self.trait_ref_to_trait_def_id(trait_ref);
689689

690-
Some(trait_ref) => {
691-
// This is OK if and only if the trait was
692-
// defined in this crate.
693-
694-
let trait_def_id =
695-
self.trait_ref_to_trait_def_id(
696-
trait_ref);
697-
698-
if trait_def_id.crate != local_crate {
699-
let session = self.crate_context.tcx.sess;
700-
session.span_err(item.span,
701-
~"cannot provide an \
702-
extension \
703-
implementation for a \
704-
trait not defined in \
705-
this crate");
706-
}
707-
}
690+
if trait_def_id.crate != local_crate {
691+
let session = self.crate_context.tcx.sess;
692+
session.span_err(item.span,
693+
~"cannot provide an \
694+
extension implementation \
695+
for a trait not defined \
696+
in this crate");
708697
}
709698
}
710699
@@ -754,6 +743,46 @@ pub impl CoherenceChecker {
754743
}
755744
}
756745

746+
/// For coherence, when we have `impl Type`, we need to guarantee that
747+
/// `Type` is "local" to the crate. For our purposes, this means that it
748+
/// must precisely name some nominal type defined in this crate.
749+
pub fn ast_type_is_defined_in_local_crate(&self, original_type: @ast::Ty)
750+
-> bool {
751+
match original_type.node {
752+
ty_path(_, path_id) => {
753+
match *self.crate_context.tcx.def_map.get(&path_id) {
754+
def_ty(def_id) | def_struct(def_id) => {
755+
if def_id.crate != local_crate {
756+
return false;
757+
}
758+
759+
// Make sure that this type precisely names a nominal
760+
// type.
761+
match self.crate_context
762+
.tcx
763+
.items
764+
.find(&def_id.node) {
765+
None => {
766+
self.crate_context.tcx.sess.span_bug(
767+
original_type.span,
768+
~"resolve didn't resolve this type?!");
769+
}
770+
Some(&node_item(item, _)) => {
771+
match item.node {
772+
item_struct(*) | item_enum(*) => true,
773+
_ => false,
774+
}
775+
}
776+
Some(_) => false,
777+
}
778+
}
779+
_ => false
780+
}
781+
}
782+
_ => false
783+
}
784+
}
785+
757786
// Converts an implementation in the AST to an Impl structure.
758787
fn create_impl_from_item(&self, item: @item) -> @Impl {
759788
fn add_provided_methods(all_methods: &mut ~[@MethodInfo],

src/libstd/future.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
use core::cast;
2525
use core::cell::Cell;
26-
use core::comm::{oneshot, PortOne, send_one};
26+
use core::comm::{ChanOne, PortOne, oneshot, send_one};
2727
use core::pipes::recv;
2828
use core::task;
2929

@@ -120,8 +120,7 @@ pub fn from_value<A>(val: A) -> Future<A> {
120120
Future {state: Forced(val)}
121121
}
122122
123-
pub fn from_port<A:Owned>(port: PortOne<A>) ->
124-
Future<A> {
123+
pub fn from_port<A:Owned>(port: PortOne<A>) -> Future<A> {
125124
/*!
126125
* Create a future from a port
127126
*
@@ -131,7 +130,7 @@ pub fn from_port<A:Owned>(port: PortOne<A>) ->
131130
132131
let port = Cell(port);
133132
do from_fn || {
134-
let port = port.take();
133+
let port = port.take().unwrap();
135134
match recv(port) {
136135
oneshot::send(data) => data
137136
}
@@ -158,10 +157,10 @@ pub fn spawn<A:Owned>(blk: ~fn() -> A) -> Future<A> {
158157
* value of the future.
159158
*/
160159
161-
let (chan, port) = oneshot::init();
160+
let (port, chan) = oneshot();
162161
163162
let chan = Cell(chan);
164-
do task::spawn || {
163+
do task::spawn {
165164
let chan = chan.take();
166165
send_one(chan, blk());
167166
}
@@ -186,7 +185,7 @@ mod test {
186185
187186
#[test]
188187
fn test_from_port() {
189-
let (ch, po) = oneshot::init();
188+
let (ch, po) = oneshot();
190189
send_one(ch, ~"whale");
191190
let f = from_port(po);
192191
assert!(f.get() == ~"whale");

src/libstd/workcache.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ use serialize::{Encoder, Encodable, Decoder, Decodable};
1616
use sort;
1717

1818
use core::cell::Cell;
19-
use core::comm::{oneshot, PortOne, send_one};
19+
use core::cmp;
20+
use core::comm::{ChanOne, PortOne, oneshot, send_one};
21+
use core::either::{Either, Left, Right};
22+
use core::hashmap::HashMap;
23+
use core::io;
2024
use core::pipes::recv;
2125
use core::run;
22-
use core::hashmap::HashMap;
2326
use core::to_bytes;
2427

2528
/**
@@ -340,13 +343,13 @@ impl TPrep for Prep {
340343
}
341344

342345
_ => {
343-
let (chan, port) = oneshot::init();
346+
let (port, chan) = oneshot();
344347
let mut blk = None;
345348
blk <-> bo;
346349
let blk = blk.unwrap();
347350
let chan = Cell(chan);
348351

349-
do task::spawn || {
352+
do task::spawn {
350353
let exe = Exec {
351354
discovered_inputs: WorkMap::new(),
352355
discovered_outputs: WorkMap::new(),
@@ -383,7 +386,7 @@ fn unwrap<T:Owned +
383386
None => fail!(),
384387
Some(Left(v)) => v,
385388
Some(Right(port)) => {
386-
let (exe, v) = match recv(port) {
389+
let (exe, v) = match recv(port.unwrap()) {
387390
oneshot::send(data) => data
388391
};
389392

0 commit comments

Comments
 (0)