changes to libs
This commit is contained in:
@@ -53,7 +53,6 @@ register_diagnostics!(
|
|||||||
E0035,
|
E0035,
|
||||||
E0036,
|
E0036,
|
||||||
E0038,
|
E0038,
|
||||||
E0039,
|
|
||||||
E0040,
|
E0040,
|
||||||
E0044,
|
E0044,
|
||||||
E0045,
|
E0045,
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ use middle::typeck::infer;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use util::ppaux::UserString;
|
use util::ppaux::{UserString, Repr, ty_to_string};
|
||||||
use util::ppaux::Repr;
|
|
||||||
|
|
||||||
pub fn check_object_cast(fcx: &FnCtxt,
|
pub fn check_object_cast(fcx: &FnCtxt,
|
||||||
cast_expr: &ast::Expr,
|
cast_expr: &ast::Expr,
|
||||||
@@ -131,18 +130,46 @@ pub fn check_object_cast(fcx: &FnCtxt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO comment
|
// Check that a trait is 'object-safe'. This should be checked whenever a trait object
|
||||||
|
// is created (by casting or coercion, etc.). A trait is object-safe if all its
|
||||||
|
// methods are object-safe. A trait method is object-safe if it does not take
|
||||||
|
// self by value, has no type parameters and does not use the `Self` type, except
|
||||||
|
// in self position.
|
||||||
pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Span) {
|
pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Span) {
|
||||||
|
// Skip the fn_once lang item trait since only the compiler should call
|
||||||
|
// `call_once` which is the method which takes self by value. What could go
|
||||||
|
// wrong?
|
||||||
|
match tcx.lang_items.fn_once_trait() {
|
||||||
|
Some(def_id) if def_id == object_trait.def_id => return,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let trait_items = ty::trait_items(tcx, object_trait.def_id);
|
let trait_items = ty::trait_items(tcx, object_trait.def_id);
|
||||||
|
|
||||||
|
let mut errors = Vec::new();
|
||||||
for item in trait_items.iter() {
|
for item in trait_items.iter() {
|
||||||
match *item {
|
match *item {
|
||||||
ty::MethodTraitItem(ref m) => check_object_safety_of_method(tcx, &**m, span),
|
ty::MethodTraitItem(ref m) => {
|
||||||
|
errors.push(check_object_safety_of_method(tcx, &**m))
|
||||||
|
}
|
||||||
ty::TypeTraitItem(_) => {}
|
ty::TypeTraitItem(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO error messages
|
let mut errors = errors.iter().flat_map(|x| x.iter()).peekable();
|
||||||
fn check_object_safety_of_method(tcx: &ty::ctxt, method: &ty::Method, span: Span) {
|
if errors.peek().is_some() {
|
||||||
|
let trait_name = ty::item_path_str(tcx, object_trait.def_id);
|
||||||
|
span_err!(tcx.sess, span, E0038,
|
||||||
|
"cannot convert to a trait object because trait `{}` is not object-safe",
|
||||||
|
trait_name);
|
||||||
|
|
||||||
|
for msg in errors {
|
||||||
|
tcx.sess.note(msg.as_slice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a vec of error messages. If hte vec is empty - no errors!
|
||||||
|
fn check_object_safety_of_method(tcx: &ty::ctxt, method: &ty::Method) -> Vec<String> {
|
||||||
/*!
|
/*!
|
||||||
* There are some limitations to calling functions through an
|
* There are some limitations to calling functions through an
|
||||||
* object, because (a) the self type is not known
|
* object, because (a) the self type is not known
|
||||||
@@ -150,13 +177,14 @@ pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Spa
|
|||||||
* obscure the self type) and (b) the call must go through a
|
* obscure the self type) and (b) the call must go through a
|
||||||
* vtable and hence cannot be monomorphized.
|
* vtable and hence cannot be monomorphized.
|
||||||
*/
|
*/
|
||||||
|
let mut msgs = Vec::new();
|
||||||
|
|
||||||
|
let method_name = method.ident.repr(tcx);
|
||||||
|
|
||||||
match method.explicit_self {
|
match method.explicit_self {
|
||||||
ty::ByValueExplicitSelfCategory => { // reason (a) above
|
ty::ByValueExplicitSelfCategory => { // reason (a) above
|
||||||
tcx.sess.span_err(
|
msgs.push(format!("cannot call a method (`{}`) with a by-value \
|
||||||
span,
|
receiver through a trait object", method_name))
|
||||||
"cannot call a method with a by-value receiver \
|
|
||||||
through a trait object");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::StaticExplicitSelfCategory |
|
ty::StaticExplicitSelfCategory |
|
||||||
@@ -167,31 +195,29 @@ pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Spa
|
|||||||
// reason (a) above
|
// reason (a) above
|
||||||
let check_for_self_ty = |ty| {
|
let check_for_self_ty = |ty| {
|
||||||
if ty::type_has_self(ty) {
|
if ty::type_has_self(ty) {
|
||||||
span_err!(tcx.sess, span, E0038,
|
Some(format!(
|
||||||
"cannot call a method whose type contains a \
|
"cannot call a method (`{}`) whose type (`{}`) contains \
|
||||||
self-type through an object: {}", ::util::ppaux::ty_to_string(tcx, ty));
|
a self-type through a trait object",
|
||||||
true
|
method_name, ty_to_string(tcx, ty)))
|
||||||
} else {
|
} else {
|
||||||
false
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let ref sig = method.fty.sig;
|
let ref sig = method.fty.sig;
|
||||||
let mut found_self_ty = false;
|
for &input_ty in sig.inputs.tail().iter().chain([sig.output].iter()) {
|
||||||
for &input_ty in sig.inputs.tail().iter() {
|
match check_for_self_ty(input_ty) {
|
||||||
if check_for_self_ty(input_ty) {
|
Some(msg) => msgs.push(msg),
|
||||||
found_self_ty = true;
|
_ => {}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found_self_ty {
|
|
||||||
check_for_self_ty(sig.output);
|
|
||||||
}
|
|
||||||
|
|
||||||
if method.generics.has_type_params(FnSpace) {
|
if method.generics.has_type_params(FnSpace) {
|
||||||
// reason (b) above
|
// reason (b) above
|
||||||
span_err!(tcx.sess, span, E0039,
|
msgs.push(format!("cannot call a generic method (`{}`) through a trait object",
|
||||||
"cannot call a generic method through an object");
|
method_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msgs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
use cmp;
|
use cmp;
|
||||||
use collections::Collection;
|
use collections::Collection;
|
||||||
use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult};
|
use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult, AsRefReader};
|
||||||
use iter::ExactSize;
|
use iter::ExactSize;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
use option::{Some, None, Option};
|
use option::{Some, None, Option};
|
||||||
@@ -118,6 +118,8 @@ impl<R: Reader> Reader for BufferedReader<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<R: Reader> AsRefReader for BufferedReader<R> {}
|
||||||
|
|
||||||
/// Wraps a Writer and buffers output to it
|
/// Wraps a Writer and buffers output to it
|
||||||
///
|
///
|
||||||
/// It can be excessively inefficient to work directly with a `Writer`. For
|
/// It can be excessively inefficient to work directly with a `Writer`. For
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use collections::Collection;
|
|||||||
use option::None;
|
use option::None;
|
||||||
use result::{Err, Ok};
|
use result::{Err, Ok};
|
||||||
use io;
|
use io;
|
||||||
use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult};
|
use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult, AsRefReader, AsRefWriter};
|
||||||
use slice;
|
use slice;
|
||||||
use slice::AsSlice;
|
use slice::AsSlice;
|
||||||
use vec::Vec;
|
use vec::Vec;
|
||||||
@@ -97,6 +97,8 @@ impl Writer for MemWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRefWriter for MemWriter {}
|
||||||
|
|
||||||
/// Reads from an owned byte vector
|
/// Reads from an owned byte vector
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@@ -163,6 +165,8 @@ impl Reader for MemReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRefReader for MemReader {}
|
||||||
|
|
||||||
impl Seek for MemReader {
|
impl Seek for MemReader {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
|
fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
|
||||||
@@ -309,6 +313,8 @@ impl<'a> Reader for BufReader<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> AsRefReader for BufReader<'a> {}
|
||||||
|
|
||||||
impl<'a> Seek for BufReader<'a> {
|
impl<'a> Seek for BufReader<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
|
fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
|
||||||
|
|||||||
@@ -712,17 +712,6 @@ pub trait Reader {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an iterator that reads a single byte on
|
|
||||||
/// each iteration, until EOF.
|
|
||||||
///
|
|
||||||
/// # Error
|
|
||||||
///
|
|
||||||
/// Any error other than `EndOfFile` that is produced by the underlying Reader
|
|
||||||
/// is returned by the iterator and should be handled by the caller.
|
|
||||||
fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self> {
|
|
||||||
extensions::Bytes::new(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Byte conversion helpers
|
// Byte conversion helpers
|
||||||
|
|
||||||
/// Reads `n` little-endian unsigned integer bytes.
|
/// Reads `n` little-endian unsigned integer bytes.
|
||||||
@@ -932,7 +921,10 @@ pub trait Reader {
|
|||||||
fn read_i8(&mut self) -> IoResult<i8> {
|
fn read_i8(&mut self) -> IoResult<i8> {
|
||||||
self.read_byte().map(|i| i as i8)
|
self.read_byte().map(|i| i as i8)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A reader which can be converted to a RefReader.
|
||||||
|
pub trait AsRefReader {
|
||||||
/// Creates a wrapper around a mutable reference to the reader.
|
/// Creates a wrapper around a mutable reference to the reader.
|
||||||
///
|
///
|
||||||
/// This is useful to allow applying adaptors while still
|
/// This is useful to allow applying adaptors while still
|
||||||
@@ -942,6 +934,20 @@ pub trait Reader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A reader which can be converted to bytes.
|
||||||
|
pub trait BytesReader: Reader {
|
||||||
|
/// Create an iterator that reads a single byte on
|
||||||
|
/// each iteration, until EOF.
|
||||||
|
///
|
||||||
|
/// # Error
|
||||||
|
///
|
||||||
|
/// Any error other than `EndOfFile` that is produced by the underlying Reader
|
||||||
|
/// is returned by the iterator and should be handled by the caller.
|
||||||
|
fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self> {
|
||||||
|
extensions::Bytes::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Reader for Box<Reader+'a> {
|
impl<'a> Reader for Box<Reader+'a> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||||
let reader: &mut Reader = &mut **self;
|
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) -
|
|||||||
/// # fn process_input<R: Reader>(r: R) {}
|
/// # fn process_input<R: Reader>(r: R) {}
|
||||||
/// # fn foo() {
|
/// # fn foo() {
|
||||||
/// use std::io;
|
/// use std::io;
|
||||||
|
/// use std::io::AsRefReader;
|
||||||
/// use std::io::util::LimitReader;
|
/// use std::io::util::LimitReader;
|
||||||
///
|
///
|
||||||
/// let mut stream = io::stdin();
|
/// let mut stream = io::stdin();
|
||||||
@@ -1268,7 +1275,10 @@ pub trait Writer {
|
|||||||
fn write_i8(&mut self, n: i8) -> IoResult<()> {
|
fn write_i8(&mut self, n: i8) -> IoResult<()> {
|
||||||
self.write([n as u8])
|
self.write([n as u8])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A writer which can be converted to a RefWriter.
|
||||||
|
pub trait AsRefWriter {
|
||||||
/// Creates a wrapper around a mutable reference to the writer.
|
/// Creates a wrapper around a mutable reference to the writer.
|
||||||
///
|
///
|
||||||
/// This is useful to allow applying wrappers while still
|
/// This is useful to allow applying wrappers while still
|
||||||
@@ -1309,7 +1319,7 @@ impl<'a> Writer for &'a mut Writer+'a {
|
|||||||
/// # fn process_input<R: Reader>(r: R) {}
|
/// # fn process_input<R: Reader>(r: R) {}
|
||||||
/// # fn foo () {
|
/// # fn foo () {
|
||||||
/// use std::io::util::TeeReader;
|
/// use std::io::util::TeeReader;
|
||||||
/// use std::io::{stdin, MemWriter};
|
/// use std::io::{stdin, MemWriter, AsRefWriter};
|
||||||
///
|
///
|
||||||
/// let mut output = MemWriter::new();
|
/// let mut output = MemWriter::new();
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -89,11 +89,9 @@ impl Writer for WriterWrapper {
|
|||||||
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
|
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
|
||||||
/// opened.
|
/// opened.
|
||||||
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
|
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
|
||||||
let ti: Option<TerminfoTerminal<WriterWrapper>>
|
TerminfoTerminal::new(WriterWrapper {
|
||||||
= Terminal::new(WriterWrapper {
|
wrapped: box std::io::stdout() as Box<Writer + Send>,
|
||||||
wrapped: box std::io::stdout() as Box<Writer + Send>,
|
})
|
||||||
});
|
|
||||||
ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@@ -121,11 +119,9 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
|
|||||||
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
|
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
|
||||||
/// opened.
|
/// opened.
|
||||||
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
|
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
|
||||||
let ti: Option<TerminfoTerminal<WriterWrapper>>
|
TerminfoTerminal::new(WriterWrapper {
|
||||||
= Terminal::new(WriterWrapper {
|
wrapped: box std::io::stderr() as Box<Writer + Send>,
|
||||||
wrapped: box std::io::stderr() as Box<Writer + Send>,
|
})
|
||||||
});
|
|
||||||
ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@@ -208,10 +204,6 @@ pub mod attr {
|
|||||||
/// A terminal with similar capabilities to an ANSI Terminal
|
/// A terminal with similar capabilities to an ANSI Terminal
|
||||||
/// (foreground/background colors etc).
|
/// (foreground/background colors etc).
|
||||||
pub trait Terminal<T: Writer>: Writer {
|
pub trait Terminal<T: Writer>: Writer {
|
||||||
/// Returns `None` whenever the terminal cannot be created for some
|
|
||||||
/// reason.
|
|
||||||
fn new(out: T) -> Option<Self>;
|
|
||||||
|
|
||||||
/// Sets the foreground color to the given color.
|
/// Sets the foreground color to the given color.
|
||||||
///
|
///
|
||||||
/// If the color is a bright color, but the terminal only supports 8 colors,
|
/// If the color is a bright color, but the terminal only supports 8 colors,
|
||||||
@@ -242,12 +234,15 @@ pub trait Terminal<T: Writer>: Writer {
|
|||||||
/// Returns `Ok()`.
|
/// Returns `Ok()`.
|
||||||
fn reset(&mut self) -> IoResult<()>;
|
fn reset(&mut self) -> IoResult<()>;
|
||||||
|
|
||||||
/// Returns the contained stream, destroying the `Terminal`
|
|
||||||
fn unwrap(self) -> T;
|
|
||||||
|
|
||||||
/// Gets an immutable reference to the stream inside
|
/// Gets an immutable reference to the stream inside
|
||||||
fn get_ref<'a>(&'a self) -> &'a T;
|
fn get_ref<'a>(&'a self) -> &'a T;
|
||||||
|
|
||||||
/// Gets a mutable reference to the stream inside
|
/// Gets a mutable reference to the stream inside
|
||||||
fn get_mut<'a>(&'a mut self) -> &'a mut T;
|
fn get_mut<'a>(&'a mut self) -> &'a mut T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A terminal which can be unwrapped.
|
||||||
|
pub trait UnwrappableTerminal<T: Writer>: Terminal<T> {
|
||||||
|
/// Returns the contained stream, destroying the `Terminal`
|
||||||
|
fn unwrap(self) -> T;
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use std::os;
|
|||||||
use attr;
|
use attr;
|
||||||
use color;
|
use color;
|
||||||
use Terminal;
|
use Terminal;
|
||||||
|
use UnwrappableTerminal;
|
||||||
use self::searcher::open;
|
use self::searcher::open;
|
||||||
use self::parser::compiled::{parse, msys_terminfo};
|
use self::parser::compiled::{parse, msys_terminfo};
|
||||||
use self::parm::{expand, Number, Variables};
|
use self::parm::{expand, Number, Variables};
|
||||||
@@ -71,44 +72,7 @@ pub struct TerminfoTerminal<T> {
|
|||||||
ti: Box<TermInfo>
|
ti: Box<TermInfo>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Writer> Terminal<T> for TerminfoTerminal<T> {
|
impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
|
||||||
fn new(out: T) -> Option<TerminfoTerminal<T>> {
|
|
||||||
let term = match os::getenv("TERM") {
|
|
||||||
Some(t) => t,
|
|
||||||
None => {
|
|
||||||
debug!("TERM environment variable not defined");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let entry = open(term.as_slice());
|
|
||||||
if entry.is_err() {
|
|
||||||
if os::getenv("MSYSCON").map_or(false, |s| {
|
|
||||||
"mintty.exe" == s.as_slice()
|
|
||||||
}) {
|
|
||||||
// msys terminal
|
|
||||||
return Some(TerminfoTerminal {out: out, ti: msys_terminfo(), num_colors: 8});
|
|
||||||
}
|
|
||||||
debug!("error finding terminfo entry: {}", entry.err().unwrap());
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut file = entry.unwrap();
|
|
||||||
let ti = parse(&mut file, false);
|
|
||||||
if ti.is_err() {
|
|
||||||
debug!("error parsing terminfo entry: {}", ti.unwrap_err());
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let inf = ti.unwrap();
|
|
||||||
let nc = if inf.strings.find_equiv(&("setaf")).is_some()
|
|
||||||
&& inf.strings.find_equiv(&("setab")).is_some() {
|
|
||||||
inf.numbers.find_equiv(&("colors")).map_or(0, |&n| n)
|
|
||||||
} else { 0 };
|
|
||||||
|
|
||||||
return Some(TerminfoTerminal {out: out, ti: inf, num_colors: nc});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fg(&mut self, color: color::Color) -> IoResult<bool> {
|
fn fg(&mut self, color: color::Color) -> IoResult<bool> {
|
||||||
let color = self.dim_if_necessary(color);
|
let color = self.dim_if_necessary(color);
|
||||||
if self.num_colors > color {
|
if self.num_colors > color {
|
||||||
@@ -195,14 +159,59 @@ impl<T: Writer> Terminal<T> for TerminfoTerminal<T> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unwrap(self) -> T { self.out }
|
|
||||||
|
|
||||||
fn get_ref<'a>(&'a self) -> &'a T { &self.out }
|
fn get_ref<'a>(&'a self) -> &'a T { &self.out }
|
||||||
|
|
||||||
fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out }
|
fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Writer> TerminfoTerminal<T> {
|
impl<T: Writer+Send> UnwrappableTerminal<T> for TerminfoTerminal<T> {
|
||||||
|
fn unwrap(self) -> T { self.out }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Writer+Send> TerminfoTerminal<T> {
|
||||||
|
/// Returns `None` whenever the terminal cannot be created for some
|
||||||
|
/// reason.
|
||||||
|
pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
|
||||||
|
let term = match os::getenv("TERM") {
|
||||||
|
Some(t) => t,
|
||||||
|
None => {
|
||||||
|
debug!("TERM environment variable not defined");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let entry = open(term.as_slice());
|
||||||
|
if entry.is_err() {
|
||||||
|
if os::getenv("MSYSCON").map_or(false, |s| {
|
||||||
|
"mintty.exe" == s.as_slice()
|
||||||
|
}) {
|
||||||
|
// msys terminal
|
||||||
|
return Some(box TerminfoTerminal {out: out,
|
||||||
|
ti: msys_terminfo(),
|
||||||
|
num_colors: 8} as Box<Terminal<T>+Send>);
|
||||||
|
}
|
||||||
|
debug!("error finding terminfo entry: {}", entry.err().unwrap());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut file = entry.unwrap();
|
||||||
|
let ti = parse(&mut file, false);
|
||||||
|
if ti.is_err() {
|
||||||
|
debug!("error parsing terminfo entry: {}", ti.unwrap_err());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let inf = ti.unwrap();
|
||||||
|
let nc = if inf.strings.find_equiv(&("setaf")).is_some()
|
||||||
|
&& inf.strings.find_equiv(&("setab")).is_some() {
|
||||||
|
inf.numbers.find_equiv(&("colors")).map_or(0, |&n| n)
|
||||||
|
} else { 0 };
|
||||||
|
|
||||||
|
return Some(box TerminfoTerminal {out: out,
|
||||||
|
ti: inf,
|
||||||
|
num_colors: nc} as Box<Terminal<T>+Send>);
|
||||||
|
}
|
||||||
|
|
||||||
fn dim_if_necessary(&self, color: color::Color) -> color::Color {
|
fn dim_if_necessary(&self, color: color::Color) -> color::Color {
|
||||||
if color >= self.num_colors && color >= 8 && color < 16 {
|
if color >= self.num_colors && color >= 8 && color < 16 {
|
||||||
color-8
|
color-8
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
// error-pattern:explicit panic
|
|
||||||
|
|
||||||
trait Foo {
|
|
||||||
fn foo(self, x: int);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct S {
|
|
||||||
x: int,
|
|
||||||
y: int,
|
|
||||||
z: int,
|
|
||||||
s: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Foo for S {
|
|
||||||
fn foo(self, x: int) {
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for S {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
println!("bye 1!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn f() {
|
|
||||||
let s = S {
|
|
||||||
x: 2,
|
|
||||||
y: 3,
|
|
||||||
z: 4,
|
|
||||||
s: "hello".to_string(),
|
|
||||||
};
|
|
||||||
let st = box s as Box<Foo>;
|
|
||||||
st.foo(5);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
f();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user