Skip to content

Commit 1d500cf

Browse files
committed
changes to libs
1 parent 8d8d8d4 commit 1d500cf

File tree

8 files changed

+145
-149
lines changed

8 files changed

+145
-149
lines changed

src/librustc/diagnostics.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ register_diagnostics!(
5353
E0035,
5454
E0036,
5555
E0038,
56-
E0039,
5756
E0040,
5857
E0044,
5958
E0045,

src/librustc/middle/typeck/check/vtable.rs

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ use middle::typeck::infer;
2121
use std::rc::Rc;
2222
use syntax::ast;
2323
use syntax::codemap::Span;
24-
use util::ppaux::UserString;
25-
use util::ppaux::Repr;
24+
use util::ppaux::{UserString, Repr, ty_to_string};
2625

2726
pub fn check_object_cast(fcx: &FnCtxt,
2827
cast_expr: &ast::Expr,
@@ -131,32 +130,61 @@ pub fn check_object_cast(fcx: &FnCtxt,
131130
}
132131
}
133132

134-
// TODO comment
133+
// Check that a trait is 'object-safe'. This should be checked whenever a trait object
134+
// is created (by casting or coercion, etc.). A trait is object-safe if all its
135+
// methods are object-safe. A trait method is object-safe if it does not take
136+
// self by value, has no type parameters and does not use the `Self` type, except
137+
// in self position.
135138
pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Span) {
139+
// Skip the fn_once lang item trait since only the compiler should call
140+
// `call_once` which is the method which takes self by value. What could go
141+
// wrong?
142+
match tcx.lang_items.fn_once_trait() {
143+
Some(def_id) if def_id == object_trait.def_id => return,
144+
_ => {}
145+
}
146+
136147
let trait_items = ty::trait_items(tcx, object_trait.def_id);
148+
149+
let mut errors = Vec::new();
137150
for item in trait_items.iter() {
138151
match *item {
139-
ty::MethodTraitItem(ref m) => check_object_safety_of_method(tcx, &**m, span),
152+
ty::MethodTraitItem(ref m) => {
153+
errors.push(check_object_safety_of_method(tcx, &**m))
154+
}
140155
ty::TypeTraitItem(_) => {}
141156
}
142157
}
143158

144-
// TODO error messages
145-
fn check_object_safety_of_method(tcx: &ty::ctxt, method: &ty::Method, span: Span) {
159+
let mut errors = errors.iter().flat_map(|x| x.iter()).peekable();
160+
if errors.peek().is_some() {
161+
let trait_name = ty::item_path_str(tcx, object_trait.def_id);
162+
span_err!(tcx.sess, span, E0038,
163+
"cannot convert to a trait object because trait `{}` is not object-safe",
164+
trait_name);
165+
166+
for msg in errors {
167+
tcx.sess.note(msg.as_slice());
168+
}
169+
}
170+
171+
// Returns a vec of error messages. If hte vec is empty - no errors!
172+
fn check_object_safety_of_method(tcx: &ty::ctxt, method: &ty::Method) -> Vec<String> {
146173
/*!
147174
* There are some limitations to calling functions through an
148175
* object, because (a) the self type is not known
149176
* (that's the whole point of a trait instance, after all, to
150177
* obscure the self type) and (b) the call must go through a
151178
* vtable and hence cannot be monomorphized.
152179
*/
180+
let mut msgs = Vec::new();
181+
182+
let method_name = method.ident.repr(tcx);
153183

154184
match method.explicit_self {
155185
ty::ByValueExplicitSelfCategory => { // reason (a) above
156-
tcx.sess.span_err(
157-
span,
158-
"cannot call a method with a by-value receiver \
159-
through a trait object");
186+
msgs.push(format!("cannot call a method (`{}`) with a by-value \
187+
receiver through a trait object", method_name))
160188
}
161189

162190
ty::StaticExplicitSelfCategory |
@@ -167,31 +195,29 @@ pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Spa
167195
// reason (a) above
168196
let check_for_self_ty = |ty| {
169197
if ty::type_has_self(ty) {
170-
span_err!(tcx.sess, span, E0038,
171-
"cannot call a method whose type contains a \
172-
self-type through an object: {}", ::util::ppaux::ty_to_string(tcx, ty));
173-
true
198+
Some(format!(
199+
"cannot call a method (`{}`) whose type (`{}`) contains \
200+
a self-type through a trait object",
201+
method_name, ty_to_string(tcx, ty)))
174202
} else {
175-
false
203+
None
176204
}
177205
};
178206
let ref sig = method.fty.sig;
179-
let mut found_self_ty = false;
180-
for &input_ty in sig.inputs.tail().iter() {
181-
if check_for_self_ty(input_ty) {
182-
found_self_ty = true;
183-
break;
207+
for &input_ty in sig.inputs.tail().iter().chain([sig.output].iter()) {
208+
match check_for_self_ty(input_ty) {
209+
Some(msg) => msgs.push(msg),
210+
_ => {}
184211
}
185212
}
186-
if !found_self_ty {
187-
check_for_self_ty(sig.output);
188-
}
189213

190214
if method.generics.has_type_params(FnSpace) {
191215
// reason (b) above
192-
span_err!(tcx.sess, span, E0039,
193-
"cannot call a generic method through an object");
216+
msgs.push(format!("cannot call a generic method (`{}`) through a trait object",
217+
method_name));
194218
}
219+
220+
msgs
195221
}
196222
}
197223

src/libstd/io/buffered.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
1515
use cmp;
1616
use collections::Collection;
17-
use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult};
17+
use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult, AsRefReader};
1818
use iter::ExactSize;
1919
use ops::Drop;
2020
use option::{Some, None, Option};
@@ -118,6 +118,8 @@ impl<R: Reader> Reader for BufferedReader<R> {
118118
}
119119
}
120120

121+
impl<R: Reader> AsRefReader for BufferedReader<R> {}
122+
121123
/// Wraps a Writer and buffers output to it
122124
///
123125
/// It can be excessively inefficient to work directly with a `Writer`. For

src/libstd/io/mem.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use collections::Collection;
1717
use option::None;
1818
use result::{Err, Ok};
1919
use io;
20-
use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult};
20+
use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult, AsRefReader, AsRefWriter};
2121
use slice;
2222
use slice::AsSlice;
2323
use vec::Vec;
@@ -97,6 +97,8 @@ impl Writer for MemWriter {
9797
}
9898
}
9999

100+
impl AsRefWriter for MemWriter {}
101+
100102
/// Reads from an owned byte vector
101103
///
102104
/// # Example
@@ -163,6 +165,8 @@ impl Reader for MemReader {
163165
}
164166
}
165167

168+
impl AsRefReader for MemReader {}
169+
166170
impl Seek for MemReader {
167171
#[inline]
168172
fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
@@ -309,6 +313,8 @@ impl<'a> Reader for BufReader<'a> {
309313
}
310314
}
311315

316+
impl<'a> AsRefReader for BufReader<'a> {}
317+
312318
impl<'a> Seek for BufReader<'a> {
313319
#[inline]
314320
fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }

src/libstd/io/mod.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -712,17 +712,6 @@ pub trait Reader {
712712
})
713713
}
714714

715-
/// Create an iterator that reads a single byte on
716-
/// each iteration, until EOF.
717-
///
718-
/// # Error
719-
///
720-
/// Any error other than `EndOfFile` that is produced by the underlying Reader
721-
/// is returned by the iterator and should be handled by the caller.
722-
fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self> {
723-
extensions::Bytes::new(self)
724-
}
725-
726715
// Byte conversion helpers
727716

728717
/// Reads `n` little-endian unsigned integer bytes.
@@ -932,7 +921,10 @@ pub trait Reader {
932921
fn read_i8(&mut self) -> IoResult<i8> {
933922
self.read_byte().map(|i| i as i8)
934923
}
924+
}
935925

926+
/// A reader which can be converted to a RefReader.
927+
pub trait AsRefReader {
936928
/// Creates a wrapper around a mutable reference to the reader.
937929
///
938930
/// This is useful to allow applying adaptors while still
@@ -942,6 +934,20 @@ pub trait Reader {
942934
}
943935
}
944936

937+
/// A reader which can be converted to bytes.
938+
pub trait BytesReader: Reader {
939+
/// Create an iterator that reads a single byte on
940+
/// each iteration, until EOF.
941+
///
942+
/// # Error
943+
///
944+
/// Any error other than `EndOfFile` that is produced by the underlying Reader
945+
/// is returned by the iterator and should be handled by the caller.
946+
fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self> {
947+
extensions::Bytes::new(self)
948+
}
949+
}
950+
945951
impl<'a> Reader for Box<Reader+'a> {
946952
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
947953
let reader: &mut Reader = &mut **self;
@@ -986,6 +992,7 @@ unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -
986992
/// # fn process_input<R: Reader>(r: R) {}
987993
/// # fn foo() {
988994
/// use std::io;
995+
/// use std::io::AsRefReader;
989996
/// use std::io::util::LimitReader;
990997
///
991998
/// let mut stream = io::stdin();
@@ -1268,7 +1275,10 @@ pub trait Writer {
12681275
fn write_i8(&mut self, n: i8) -> IoResult<()> {
12691276
self.write([n as u8])
12701277
}
1278+
}
12711279

1280+
/// A writer which can be converted to a RefWriter.
1281+
pub trait AsRefWriter {
12721282
/// Creates a wrapper around a mutable reference to the writer.
12731283
///
12741284
/// This is useful to allow applying wrappers while still
@@ -1309,7 +1319,7 @@ impl<'a> Writer for &'a mut Writer+'a {
13091319
/// # fn process_input<R: Reader>(r: R) {}
13101320
/// # fn foo () {
13111321
/// use std::io::util::TeeReader;
1312-
/// use std::io::{stdin, MemWriter};
1322+
/// use std::io::{stdin, MemWriter, AsRefWriter};
13131323
///
13141324
/// let mut output = MemWriter::new();
13151325
///

src/libterm/lib.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,9 @@ impl Writer for WriterWrapper {
8989
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
9090
/// opened.
9191
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
92-
let ti: Option<TerminfoTerminal<WriterWrapper>>
93-
= Terminal::new(WriterWrapper {
94-
wrapped: box std::io::stdout() as Box<Writer + Send>,
95-
});
96-
ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
92+
TerminfoTerminal::new(WriterWrapper {
93+
wrapped: box std::io::stdout() as Box<Writer + Send>,
94+
})
9795
}
9896

9997
#[cfg(windows)]
@@ -121,11 +119,9 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
121119
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
122120
/// opened.
123121
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
124-
let ti: Option<TerminfoTerminal<WriterWrapper>>
125-
= Terminal::new(WriterWrapper {
126-
wrapped: box std::io::stderr() as Box<Writer + Send>,
127-
});
128-
ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
122+
TerminfoTerminal::new(WriterWrapper {
123+
wrapped: box std::io::stderr() as Box<Writer + Send>,
124+
})
129125
}
130126

131127
#[cfg(windows)]
@@ -208,10 +204,6 @@ pub mod attr {
208204
/// A terminal with similar capabilities to an ANSI Terminal
209205
/// (foreground/background colors etc).
210206
pub trait Terminal<T: Writer>: Writer {
211-
/// Returns `None` whenever the terminal cannot be created for some
212-
/// reason.
213-
fn new(out: T) -> Option<Self>;
214-
215207
/// Sets the foreground color to the given color.
216208
///
217209
/// If the color is a bright color, but the terminal only supports 8 colors,
@@ -242,12 +234,15 @@ pub trait Terminal<T: Writer>: Writer {
242234
/// Returns `Ok()`.
243235
fn reset(&mut self) -> IoResult<()>;
244236

245-
/// Returns the contained stream, destroying the `Terminal`
246-
fn unwrap(self) -> T;
247-
248237
/// Gets an immutable reference to the stream inside
249238
fn get_ref<'a>(&'a self) -> &'a T;
250239

251240
/// Gets a mutable reference to the stream inside
252241
fn get_mut<'a>(&'a mut self) -> &'a mut T;
253242
}
243+
244+
/// A terminal which can be unwrapped.
245+
pub trait UnwrappableTerminal<T: Writer>: Terminal<T> {
246+
/// Returns the contained stream, destroying the `Terminal`
247+
fn unwrap(self) -> T;
248+
}

0 commit comments

Comments
 (0)