1
Fork 0

Auto merge of #29039 - Manishearth:rollup, r=Manishearth

- Successful merges: #28991, #29004, #29006, #29013, #29016, #29024, #29027, #29028, #29029, #29032, #29035
- Failed merges:
This commit is contained in:
bors 2015-10-14 07:24:36 +00:00
commit 294ef5b158
13 changed files with 516 additions and 273 deletions

View file

@ -1435,11 +1435,11 @@ struct Foo;
trait Shape { fn area(&self) -> f64; } trait Shape { fn area(&self) -> f64; }
trait Circle : Shape { fn radius(&self) -> f64; } trait Circle : Shape { fn radius(&self) -> f64; }
# impl Shape for Foo { impl Shape for Foo {
# fn area(&self) -> f64 { fn area(&self) -> f64 {
# 0.0 0.0
# } }
# } }
impl Circle for Foo { impl Circle for Foo {
fn radius(&self) -> f64 { fn radius(&self) -> f64 {
println!("calling area: {}", self.area()); println!("calling area: {}", self.area());

View file

@ -74,7 +74,7 @@ associated with it, but the compiler lets you elide (i.e. omit, see
["Lifetime Elision"][lifetime-elision] below) them in common cases. ["Lifetime Elision"][lifetime-elision] below) them in common cases.
Before we get to that, though, lets break the explicit example down: Before we get to that, though, lets break the explicit example down:
[lifetime-elision]: #user-content-lifetime-elision [lifetime-elision]: #lifetime-elision
```rust,ignore ```rust,ignore
fn bar<'a>(...) fn bar<'a>(...)

View file

@ -3032,7 +3032,52 @@ impl<A: Clone> DoubleEndedIterator for Repeat<A> {
fn next_back(&mut self) -> Option<A> { Some(self.element.clone()) } fn next_back(&mut self) -> Option<A> { Some(self.element.clone()) }
} }
/// Creates a new iterator that endlessly repeats the element `elt`. /// Creates a new iterator that endlessly repeats a single element.
///
/// The `repeat()` function repeats a single value over and over and over and
/// over and over and 🔁.
///
/// Infinite iterators like `repeat()` are often used with adapters like
/// [`take()`], in order to make them finite.
///
/// [`take()`]: trait.Iterator.html#method.take
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::iter;
///
/// // the number four 4ever:
/// let mut fours = iter::repeat(4);
///
/// assert_eq!(Some(4), fours.next());
/// assert_eq!(Some(4), fours.next());
/// assert_eq!(Some(4), fours.next());
/// assert_eq!(Some(4), fours.next());
/// assert_eq!(Some(4), fours.next());
///
/// // yup, still four
/// assert_eq!(Some(4), fours.next());
/// ```
///
/// Going finite with [`take()`]:
///
/// ```
/// use std::iter;
///
/// // that last example was too many fours. Let's only have four fours.
/// let mut four_fours = iter::repeat(4).take(4);
///
/// assert_eq!(Some(4), four_fours.next());
/// assert_eq!(Some(4), four_fours.next());
/// assert_eq!(Some(4), four_fours.next());
/// assert_eq!(Some(4), four_fours.next());
///
/// // ... and now we're done
/// assert_eq!(None, four_fours.next());
/// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat<T: Clone>(elt: T) -> Repeat<T> { pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
@ -3089,6 +3134,19 @@ impl<T> Default for Empty<T> {
} }
/// Creates an iterator that yields nothing. /// Creates an iterator that yields nothing.
///
/// # Exampes
///
/// Basic usage:
///
/// ```
/// use std::iter;
///
/// // this could have been an iterator over i32, but alas, it's just not.
/// let mut nope = iter::empty::<i32>();
///
/// assert_eq!(None, nope.next());
/// ```
#[stable(feature = "iter_empty", since = "1.2.0")] #[stable(feature = "iter_empty", since = "1.2.0")]
pub fn empty<T>() -> Empty<T> { pub fn empty<T>() -> Empty<T> {
Empty(marker::PhantomData) Empty(marker::PhantomData)
@ -3129,6 +3187,56 @@ impl<T> ExactSizeIterator for Once<T> {
} }
/// Creates an iterator that yields an element exactly once. /// Creates an iterator that yields an element exactly once.
///
/// This is commonly used to adapt a single value into a [`chain()`] of other
/// kinds of iteration. Maybe you have an iterator that covers almost
/// everything, but you need an extra special case. Maybe you have a function
/// which works on iterators, but you only need to process one value.
///
/// [`chain()`]: trait.Iterator.html#method.chain
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::iter;
///
/// // one is the loneliest number
/// let mut one = iter::once(1);
///
/// assert_eq!(Some(1), one.next());
///
/// // just one, that's all we get
/// assert_eq!(None, one.next());
/// ```
///
/// Chaining together with another iterator. Let's say that we want to iterate
/// over each file of the `.foo` directory, but also a configuration file,
/// `.foorc`:
///
/// ```no_run
/// use std::iter;
/// use std::fs;
/// use std::path::PathBuf;
///
/// let dirs = fs::read_dir(".foo").unwrap();
///
/// // we need to convert from an iterator of DirEntry-s to an iterator of
/// // PathBufs, so we use map
/// let dirs = dirs.map(|file| file.unwrap().path());
///
/// // now, our iterator just for our config file
/// let config = iter::once(PathBuf::from(".foorc"));
///
/// // chain the two iterators together into one big iterator
/// let files = dirs.chain(config);
///
/// // this will give us all of the files in .foo as well as .foorc
/// for f in files {
/// println!("{:?}", f);
/// }
/// ```
#[stable(feature = "iter_once", since = "1.2.0")] #[stable(feature = "iter_once", since = "1.2.0")]
pub fn once<T>(value: T) -> Once<T> { pub fn once<T>(value: T) -> Once<T> {
Once { inner: Some(value).into_iter() } Once { inner: Some(value).into_iter() }

View file

@ -75,7 +75,7 @@ pub struct FormatSpec<'a> {
/// The descriptor string representing the name of the format desired for /// The descriptor string representing the name of the format desired for
/// this argument, this can be empty or any number of characters, although /// this argument, this can be empty or any number of characters, although
/// it is required to be one word. /// it is required to be one word.
pub ty: &'a str pub ty: &'a str,
} }
/// Enum describing where an argument for a format can be located. /// Enum describing where an argument for a format can be located.
@ -202,7 +202,12 @@ impl<'a> Parser<'a> {
/// returned, otherwise the character is consumed and true is returned. /// returned, otherwise the character is consumed and true is returned.
fn consume(&mut self, c: char) -> bool { fn consume(&mut self, c: char) -> bool {
if let Some(&(_, maybe)) = self.cur.peek() { if let Some(&(_, maybe)) = self.cur.peek() {
if c == maybe { self.cur.next(); true } else { false } if c == maybe {
self.cur.next();
true
} else {
false
}
} else { } else {
false false
} }
@ -227,7 +232,11 @@ impl<'a> Parser<'a> {
/// character /// character
fn ws(&mut self) { fn ws(&mut self) {
while let Some(&(_, c)) = self.cur.peek() { while let Some(&(_, c)) = self.cur.peek() {
if c.is_whitespace() { self.cur.next(); } else { break } if c.is_whitespace() {
self.cur.next();
} else {
break
}
} }
} }
@ -237,8 +246,12 @@ impl<'a> Parser<'a> {
// we may not consume the character, peek the iterator // we may not consume the character, peek the iterator
while let Some(&(pos, c)) = self.cur.peek() { while let Some(&(pos, c)) = self.cur.peek() {
match c { match c {
'{' | '}' => { return &self.input[start..pos]; } '{' | '}' => {
_ => { self.cur.next(); } return &self.input[start..pos];
}
_ => {
self.cur.next();
}
} }
} }
&self.input[start..self.input.len()] &self.input[start..self.input.len()]
@ -263,7 +276,7 @@ impl<'a> Parser<'a> {
Some(&(_, c)) if c.is_alphabetic() => { Some(&(_, c)) if c.is_alphabetic() => {
ArgumentNamed(self.word()) ArgumentNamed(self.word())
} }
_ => ArgumentNext _ => ArgumentNext,
} }
} }
} }
@ -279,7 +292,9 @@ impl<'a> Parser<'a> {
width: CountImplied, width: CountImplied,
ty: &self.input[..0], ty: &self.input[..0],
}; };
if !self.consume(':') { return spec } if !self.consume(':') {
return spec
}
// fill character // fill character
if let Some(&(_, c)) = self.cur.peek() { if let Some(&(_, c)) = self.cur.peek() {
@ -347,7 +362,11 @@ impl<'a> Parser<'a> {
/// width. /// width.
fn count(&mut self) -> Count<'a> { fn count(&mut self) -> Count<'a> {
if let Some(i) = self.integer() { if let Some(i) = self.integer() {
if self.consume('$') { CountIsParam(i) } else { CountIs(i) } if self.consume('$') {
CountIsParam(i)
} else {
CountIs(i)
}
} else { } else {
let tmp = self.cur.clone(); let tmp = self.cur.clone();
let word = self.word(); let word = self.word();
@ -370,8 +389,13 @@ impl<'a> Parser<'a> {
/// characters. /// characters.
fn word(&mut self) -> &'a str { fn word(&mut self) -> &'a str {
let start = match self.cur.peek() { let start = match self.cur.peek() {
Some(&(pos, c)) if c.is_xid_start() => { self.cur.next(); pos } Some(&(pos, c)) if c.is_xid_start() => {
_ => { return &self.input[..0]; } self.cur.next();
pos
}
_ => {
return &self.input[..0];
}
}; };
while let Some(&(pos, c)) = self.cur.peek() { while let Some(&(pos, c)) = self.cur.peek() {
if c.is_xid_continue() { if c.is_xid_continue() {
@ -397,7 +421,11 @@ impl<'a> Parser<'a> {
break break
} }
} }
if found { Some(cur) } else { None } if found {
Some(cur)
} else {
None
}
} }
} }
@ -437,178 +465,210 @@ mod tests {
same("\\}}", &[String("\\"), String("}")]); same("\\}}", &[String("\\"), String("}")]);
} }
#[test] fn invalid01() { musterr("{") } #[test]
#[test] fn invalid02() { musterr("}") } fn invalid01() {
#[test] fn invalid04() { musterr("{3a}") } musterr("{")
#[test] fn invalid05() { musterr("{:|}") } }
#[test] fn invalid06() { musterr("{:>>>}") } #[test]
fn invalid02() {
musterr("}")
}
#[test]
fn invalid04() {
musterr("{3a}")
}
#[test]
fn invalid05() {
musterr("{:|}")
}
#[test]
fn invalid06() {
musterr("{:>>>}")
}
#[test] #[test]
fn format_nothing() { fn format_nothing() {
same("{}", &[NextArgument(Argument { same("{}",
position: ArgumentNext, &[NextArgument(Argument {
format: fmtdflt(), position: ArgumentNext,
})]); format: fmtdflt(),
})]);
} }
#[test] #[test]
fn format_position() { fn format_position() {
same("{3}", &[NextArgument(Argument { same("{3}",
position: ArgumentIs(3), &[NextArgument(Argument {
format: fmtdflt(), position: ArgumentIs(3),
})]); format: fmtdflt(),
})]);
} }
#[test] #[test]
fn format_position_nothing_else() { fn format_position_nothing_else() {
same("{3:}", &[NextArgument(Argument { same("{3:}",
position: ArgumentIs(3), &[NextArgument(Argument {
format: fmtdflt(), position: ArgumentIs(3),
})]); format: fmtdflt(),
})]);
} }
#[test] #[test]
fn format_type() { fn format_type() {
same("{3:a}", &[NextArgument(Argument { same("{3:a}",
position: ArgumentIs(3), &[NextArgument(Argument {
format: FormatSpec { position: ArgumentIs(3),
fill: None, format: FormatSpec {
align: AlignUnknown, fill: None,
flags: 0, align: AlignUnknown,
precision: CountImplied, flags: 0,
width: CountImplied, precision: CountImplied,
ty: "a", width: CountImplied,
}, ty: "a",
})]); },
})]);
} }
#[test] #[test]
fn format_align_fill() { fn format_align_fill() {
same("{3:>}", &[NextArgument(Argument { same("{3:>}",
position: ArgumentIs(3), &[NextArgument(Argument {
format: FormatSpec { position: ArgumentIs(3),
fill: None, format: FormatSpec {
align: AlignRight, fill: None,
flags: 0, align: AlignRight,
precision: CountImplied, flags: 0,
width: CountImplied, precision: CountImplied,
ty: "", width: CountImplied,
}, ty: "",
})]); },
same("{3:0<}", &[NextArgument(Argument { })]);
position: ArgumentIs(3), same("{3:0<}",
format: FormatSpec { &[NextArgument(Argument {
fill: Some('0'), position: ArgumentIs(3),
align: AlignLeft, format: FormatSpec {
flags: 0, fill: Some('0'),
precision: CountImplied, align: AlignLeft,
width: CountImplied, flags: 0,
ty: "", precision: CountImplied,
}, width: CountImplied,
})]); ty: "",
same("{3:*<abcd}", &[NextArgument(Argument { },
position: ArgumentIs(3), })]);
format: FormatSpec { same("{3:*<abcd}",
fill: Some('*'), &[NextArgument(Argument {
align: AlignLeft, position: ArgumentIs(3),
flags: 0, format: FormatSpec {
precision: CountImplied, fill: Some('*'),
width: CountImplied, align: AlignLeft,
ty: "abcd", flags: 0,
}, precision: CountImplied,
})]); width: CountImplied,
ty: "abcd",
},
})]);
} }
#[test] #[test]
fn format_counts() { fn format_counts() {
same("{:10s}", &[NextArgument(Argument { same("{:10s}",
position: ArgumentNext, &[NextArgument(Argument {
format: FormatSpec { position: ArgumentNext,
fill: None, format: FormatSpec {
align: AlignUnknown, fill: None,
flags: 0, align: AlignUnknown,
precision: CountImplied, flags: 0,
width: CountIs(10), precision: CountImplied,
ty: "s", width: CountIs(10),
}, ty: "s",
})]); },
same("{:10$.10s}", &[NextArgument(Argument { })]);
position: ArgumentNext, same("{:10$.10s}",
format: FormatSpec { &[NextArgument(Argument {
fill: None, position: ArgumentNext,
align: AlignUnknown, format: FormatSpec {
flags: 0, fill: None,
precision: CountIs(10), align: AlignUnknown,
width: CountIsParam(10), flags: 0,
ty: "s", precision: CountIs(10),
}, width: CountIsParam(10),
})]); ty: "s",
same("{:.*s}", &[NextArgument(Argument { },
position: ArgumentNext, })]);
format: FormatSpec { same("{:.*s}",
fill: None, &[NextArgument(Argument {
align: AlignUnknown, position: ArgumentNext,
flags: 0, format: FormatSpec {
precision: CountIsNextParam, fill: None,
width: CountImplied, align: AlignUnknown,
ty: "s", flags: 0,
}, precision: CountIsNextParam,
})]); width: CountImplied,
same("{:.10$s}", &[NextArgument(Argument { ty: "s",
position: ArgumentNext, },
format: FormatSpec { })]);
fill: None, same("{:.10$s}",
align: AlignUnknown, &[NextArgument(Argument {
flags: 0, position: ArgumentNext,
precision: CountIsParam(10), format: FormatSpec {
width: CountImplied, fill: None,
ty: "s", align: AlignUnknown,
}, flags: 0,
})]); precision: CountIsParam(10),
same("{:a$.b$s}", &[NextArgument(Argument { width: CountImplied,
position: ArgumentNext, ty: "s",
format: FormatSpec { },
fill: None, })]);
align: AlignUnknown, same("{:a$.b$s}",
flags: 0, &[NextArgument(Argument {
precision: CountIsName("b"), position: ArgumentNext,
width: CountIsName("a"), format: FormatSpec {
ty: "s", fill: None,
}, align: AlignUnknown,
})]); flags: 0,
precision: CountIsName("b"),
width: CountIsName("a"),
ty: "s",
},
})]);
} }
#[test] #[test]
fn format_flags() { fn format_flags() {
same("{:-}", &[NextArgument(Argument { same("{:-}",
position: ArgumentNext, &[NextArgument(Argument {
format: FormatSpec { position: ArgumentNext,
fill: None, format: FormatSpec {
align: AlignUnknown, fill: None,
flags: (1 << FlagSignMinus as u32), align: AlignUnknown,
precision: CountImplied, flags: (1 << FlagSignMinus as u32),
width: CountImplied, precision: CountImplied,
ty: "", width: CountImplied,
}, ty: "",
})]); },
same("{:+#}", &[NextArgument(Argument { })]);
position: ArgumentNext, same("{:+#}",
format: FormatSpec { &[NextArgument(Argument {
fill: None, position: ArgumentNext,
align: AlignUnknown, format: FormatSpec {
flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32), fill: None,
precision: CountImplied, align: AlignUnknown,
width: CountImplied, flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32),
ty: "", precision: CountImplied,
}, width: CountImplied,
})]); ty: "",
},
})]);
} }
#[test] #[test]
fn format_mixture() { fn format_mixture() {
same("abcd {3:a} efg", &[String("abcd "), NextArgument(Argument { same("abcd {3:a} efg",
position: ArgumentIs(3), &[String("abcd "),
format: FormatSpec { NextArgument(Argument {
fill: None, position: ArgumentIs(3),
align: AlignUnknown, format: FormatSpec {
flags: 0, fill: None,
precision: CountImplied, align: AlignUnknown,
width: CountImplied, flags: 0,
ty: "a", precision: CountImplied,
}, width: CountImplied,
}), String(" efg")]); ty: "a",
},
}),
String(" efg")]);
} }
} }

View file

@ -17,15 +17,17 @@ pub struct LogDirective {
pub level: u32, pub level: u32,
} }
pub const LOG_LEVEL_NAMES: [&'static str; 4] = ["ERROR", "WARN", "INFO", pub const LOG_LEVEL_NAMES: [&'static str; 4] = ["ERROR", "WARN", "INFO", "DEBUG"];
"DEBUG"];
/// Parse an individual log level that is either a number or a symbolic log level /// Parse an individual log level that is either a number or a symbolic log level
fn parse_log_level(level: &str) -> Option<u32> { fn parse_log_level(level: &str) -> Option<u32> {
level.parse::<u32>().ok().or_else(|| { level.parse::<u32>()
let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level)); .ok()
pos.map(|p| p as u32 + 1) .or_else(|| {
}).map(|p| cmp::min(p, ::MAX_LOG_LEVEL)) let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
pos.map(|p| p as u32 + 1)
})
.map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
} }
/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo") /// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo")
@ -40,44 +42,48 @@ pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<String>) {
let mods = parts.next(); let mods = parts.next();
let filter = parts.next(); let filter = parts.next();
if parts.next().is_some() { if parts.next().is_some() {
println!("warning: invalid logging spec '{}', \ println!("warning: invalid logging spec '{}', ignoring it (too many '/'s)",
ignoring it (too many '/'s)", spec); spec);
return (dirs, None); return (dirs, None);
} }
mods.map(|m| { for s in m.split(',') { mods.map(|m| {
if s.is_empty() { continue } for s in m.split(',') {
let mut parts = s.split('='); if s.is_empty() {
let (log_level, name) = match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
(Some(part0), None, None) => {
// if the single argument is a log-level string or number,
// treat that as a global fallback
match parse_log_level(part0) {
Some(num) => (num, None),
None => (::MAX_LOG_LEVEL, Some(part0)),
}
}
(Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
(Some(part0), Some(part1), None) => {
match parse_log_level(part1) {
Some(num) => (num, Some(part0)),
_ => {
println!("warning: invalid logging spec '{}', \
ignoring it", part1);
continue
}
}
},
_ => {
println!("warning: invalid logging spec '{}', \
ignoring it", s);
continue continue
} }
}; let mut parts = s.split('=');
dirs.push(LogDirective { let (log_level, name) = match (parts.next(),
name: name.map(str::to_owned), parts.next().map(|s| s.trim()),
level: log_level, parts.next()) {
}); (Some(part0), None, None) => {
}}); // if the single argument is a log-level string or number,
// treat that as a global fallback
match parse_log_level(part0) {
Some(num) => (num, None),
None => (::MAX_LOG_LEVEL, Some(part0)),
}
}
(Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
(Some(part0), Some(part1), None) => {
match parse_log_level(part1) {
Some(num) => (num, Some(part0)),
_ => {
println!("warning: invalid logging spec '{}', ignoring it", part1);
continue
}
}
}
_ => {
println!("warning: invalid logging spec '{}', ignoring it", s);
continue
}
};
dirs.push(LogDirective {
name: name.map(str::to_owned),
level: log_level,
});
}
});
(dirs, filter.map(str::to_owned)) (dirs, filter.map(str::to_owned))
} }

View file

@ -235,7 +235,9 @@ pub trait Logger {
fn log(&mut self, record: &LogRecord); fn log(&mut self, record: &LogRecord);
} }
struct DefaultLogger { handle: Stderr } struct DefaultLogger {
handle: Stderr,
}
/// Wraps the log level with fmt implementations. /// Wraps the log level with fmt implementations.
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
@ -246,7 +248,7 @@ impl fmt::Display for LogLevel {
let LogLevel(level) = *self; let LogLevel(level) = *self;
match LOG_LEVEL_NAMES.get(level as usize - 1) { match LOG_LEVEL_NAMES.get(level as usize - 1) {
Some(ref name) => fmt::Display::fmt(name, fmt), Some(ref name) => fmt::Display::fmt(name, fmt),
None => fmt::Display::fmt(&level, fmt) None => fmt::Display::fmt(&level, fmt),
} }
} }
} }
@ -301,11 +303,10 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
// Completely remove the local logger from TLS in case anyone attempts to // Completely remove the local logger from TLS in case anyone attempts to
// frob the slot while we're doing the logging. This will destroy any logger // frob the slot while we're doing the logging. This will destroy any logger
// set during logging. // set during logging.
let mut logger: Box<Logger + Send> = LOCAL_LOGGER.with(|s| { let mut logger: Box<Logger + Send> = LOCAL_LOGGER.with(|s| s.borrow_mut().take())
s.borrow_mut().take() .unwrap_or_else(|| {
}).unwrap_or_else(|| { box DefaultLogger { handle: io::stderr() }
box DefaultLogger { handle: io::stderr() } });
});
logger.log(&LogRecord { logger.log(&LogRecord {
level: LogLevel(level), level: LogLevel(level),
args: args, args: args,
@ -320,22 +321,21 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
/// safely /// safely
#[doc(hidden)] #[doc(hidden)]
#[inline(always)] #[inline(always)]
pub fn log_level() -> u32 { unsafe { LOG_LEVEL } } pub fn log_level() -> u32 {
unsafe { LOG_LEVEL }
}
/// Replaces the thread-local logger with the specified logger, returning the old /// Replaces the thread-local logger with the specified logger, returning the old
/// logger. /// logger.
pub fn set_logger(logger: Box<Logger + Send>) -> Option<Box<Logger + Send>> { pub fn set_logger(logger: Box<Logger + Send>) -> Option<Box<Logger + Send>> {
let mut l = Some(logger); let mut l = Some(logger);
LOCAL_LOGGER.with(|slot| { LOCAL_LOGGER.with(|slot| mem::replace(&mut *slot.borrow_mut(), l.take()))
mem::replace(&mut *slot.borrow_mut(), l.take())
})
} }
/// A LogRecord is created by the logging macros, and passed as the only /// A LogRecord is created by the logging macros, and passed as the only
/// argument to Loggers. /// argument to Loggers.
#[derive(Debug)] #[derive(Debug)]
pub struct LogRecord<'a> { pub struct LogRecord<'a> {
/// The module path of where the LogRecord originated. /// The module path of where the LogRecord originated.
pub module_path: &'a str, pub module_path: &'a str,
@ -373,7 +373,9 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
// again to whether they should really be here or not. Hence, despite this // again to whether they should really be here or not. Hence, despite this
// check being expanded manually in the logging macro, this function checks // check being expanded manually in the logging macro, this function checks
// the log level again. // the log level again.
if level > unsafe { LOG_LEVEL } { return false } if level > unsafe { LOG_LEVEL } {
return false
}
// This assertion should never get tripped unless we're in an at_exit // This assertion should never get tripped unless we're in an at_exit
// handler after logging has been torn down and a logging attempt was made. // handler after logging has been torn down and a logging attempt was made.
@ -385,14 +387,11 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
} }
} }
fn enabled(level: u32, fn enabled(level: u32, module: &str, iter: slice::Iter<directive::LogDirective>) -> bool {
module: &str,
iter: slice::Iter<directive::LogDirective>)
-> bool {
// Search for the longest match, the vector is assumed to be pre-sorted. // Search for the longest match, the vector is assumed to be pre-sorted.
for directive in iter.rev() { for directive in iter.rev() {
match directive.name { match directive.name {
Some(ref name) if !module.starts_with(&name[..]) => {}, Some(ref name) if !module.starts_with(&name[..]) => {}
Some(..) | None => { Some(..) | None => {
return level <= directive.level return level <= directive.level
} }
@ -445,16 +444,14 @@ mod tests {
#[test] #[test]
fn match_full_path() { fn match_full_path() {
let dirs = [ let dirs = [LogDirective {
LogDirective { name: Some("crate2".to_string()),
name: Some("crate2".to_string()), level: 3,
level: 3 },
}, LogDirective {
LogDirective { name: Some("crate1::mod1".to_string()),
name: Some("crate1::mod1".to_string()), level: 2,
level: 2 }];
}
];
assert!(enabled(2, "crate1::mod1", dirs.iter())); assert!(enabled(2, "crate1::mod1", dirs.iter()));
assert!(!enabled(3, "crate1::mod1", dirs.iter())); assert!(!enabled(3, "crate1::mod1", dirs.iter()));
assert!(enabled(3, "crate2", dirs.iter())); assert!(enabled(3, "crate2", dirs.iter()));
@ -463,49 +460,72 @@ mod tests {
#[test] #[test]
fn no_match() { fn no_match() {
let dirs = [ let dirs = [LogDirective {
LogDirective { name: Some("crate2".to_string()), level: 3 }, name: Some("crate2".to_string()),
LogDirective { name: Some("crate1::mod1".to_string()), level: 2 } level: 3,
]; },
LogDirective {
name: Some("crate1::mod1".to_string()),
level: 2,
}];
assert!(!enabled(2, "crate3", dirs.iter())); assert!(!enabled(2, "crate3", dirs.iter()));
} }
#[test] #[test]
fn match_beginning() { fn match_beginning() {
let dirs = [ let dirs = [LogDirective {
LogDirective { name: Some("crate2".to_string()), level: 3 }, name: Some("crate2".to_string()),
LogDirective { name: Some("crate1::mod1".to_string()), level: 2 } level: 3,
]; },
LogDirective {
name: Some("crate1::mod1".to_string()),
level: 2,
}];
assert!(enabled(3, "crate2::mod1", dirs.iter())); assert!(enabled(3, "crate2::mod1", dirs.iter()));
} }
#[test] #[test]
fn match_beginning_longest_match() { fn match_beginning_longest_match() {
let dirs = [ let dirs = [LogDirective {
LogDirective { name: Some("crate2".to_string()), level: 3 }, name: Some("crate2".to_string()),
LogDirective { name: Some("crate2::mod".to_string()), level: 4 }, level: 3,
LogDirective { name: Some("crate1::mod1".to_string()), level: 2 } },
]; LogDirective {
name: Some("crate2::mod".to_string()),
level: 4,
},
LogDirective {
name: Some("crate1::mod1".to_string()),
level: 2,
}];
assert!(enabled(4, "crate2::mod1", dirs.iter())); assert!(enabled(4, "crate2::mod1", dirs.iter()));
assert!(!enabled(4, "crate2", dirs.iter())); assert!(!enabled(4, "crate2", dirs.iter()));
} }
#[test] #[test]
fn match_default() { fn match_default() {
let dirs = [ let dirs = [LogDirective {
LogDirective { name: None, level: 3 }, name: None,
LogDirective { name: Some("crate1::mod1".to_string()), level: 2 } level: 3,
]; },
LogDirective {
name: Some("crate1::mod1".to_string()),
level: 2,
}];
assert!(enabled(2, "crate1::mod1", dirs.iter())); assert!(enabled(2, "crate1::mod1", dirs.iter()));
assert!(enabled(3, "crate2::mod2", dirs.iter())); assert!(enabled(3, "crate2::mod2", dirs.iter()));
} }
#[test] #[test]
fn zero_level() { fn zero_level() {
let dirs = [ let dirs = [LogDirective {
LogDirective { name: None, level: 3 }, name: None,
LogDirective { name: Some("crate1::mod1".to_string()), level: 0 } level: 3,
]; },
LogDirective {
name: Some("crate1::mod1".to_string()),
level: 0,
}];
assert!(!enabled(1, "crate1::mod1", dirs.iter())); assert!(!enabled(1, "crate1::mod1", dirs.iter()));
assert!(enabled(3, "crate2::mod2", dirs.iter())); assert!(enabled(3, "crate2::mod2", dirs.iter()));
} }

View file

@ -528,6 +528,10 @@ impl<'ast> Map<'ast> {
NodeTraitItem(ti) => PathName(ti.name), NodeTraitItem(ti) => PathName(ti.name),
NodeVariant(v) => PathName(v.node.name), NodeVariant(v) => PathName(v.node.name),
NodeLifetime(lt) => PathName(lt.name), NodeLifetime(lt) => PathName(lt.name),
NodeTyParam(tp) => PathName(tp.name),
NodeLocal(&Pat { node: PatIdent(_,l,_), .. }) => {
PathName(l.node.name)
},
_ => panic!("no path elem for {:?}", node) _ => panic!("no path elem for {:?}", node)
} }
} }
@ -988,4 +992,3 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
} }
} }
} }

View file

@ -22,7 +22,9 @@
//! A typesafe bitmask flag generator. //! A typesafe bitmask flag generator.
#[cfg(test)] #[macro_use] extern crate std; #[cfg(test)]
#[macro_use]
extern crate std;
/// The `bitflags!` macro generates a `struct` that holds a set of C-style /// The `bitflags!` macro generates a `struct` that holds a set of C-style
/// bitmask flags. It is useful for creating typesafe wrappers for C APIs. /// bitmask flags. It is useful for creating typesafe wrappers for C APIs.
@ -321,7 +323,7 @@ mod tests {
} }
#[test] #[test]
fn test_bits(){ fn test_bits() {
assert_eq!(Flags::empty().bits(), 0b00000000); assert_eq!(Flags::empty().bits(), 0b00000000);
assert_eq!(Flags::FlagA.bits(), 0b00000001); assert_eq!(Flags::FlagA.bits(), 0b00000001);
assert_eq!(Flags::FlagABC.bits(), 0b00000111); assert_eq!(Flags::FlagABC.bits(), 0b00000111);
@ -354,7 +356,7 @@ mod tests {
} }
#[test] #[test]
fn test_is_empty(){ fn test_is_empty() {
assert!(Flags::empty().is_empty()); assert!(Flags::empty().is_empty());
assert!(!Flags::FlagA.is_empty()); assert!(!Flags::FlagA.is_empty());
assert!(!Flags::FlagABC.is_empty()); assert!(!Flags::FlagABC.is_empty());
@ -413,7 +415,7 @@ mod tests {
} }
#[test] #[test]
fn test_insert(){ fn test_insert() {
let mut e1 = Flags::FlagA; let mut e1 = Flags::FlagA;
let e2 = Flags::FlagA | Flags::FlagB; let e2 = Flags::FlagA | Flags::FlagB;
e1.insert(e2); e1.insert(e2);
@ -425,7 +427,7 @@ mod tests {
} }
#[test] #[test]
fn test_remove(){ fn test_remove() {
let mut e1 = Flags::FlagA | Flags::FlagB; let mut e1 = Flags::FlagA | Flags::FlagB;
let e2 = Flags::FlagA | Flags::FlagC; let e2 = Flags::FlagA | Flags::FlagC;
e1.remove(e2); e1.remove(e2);
@ -484,12 +486,12 @@ mod tests {
#[test] #[test]
fn test_hash() { fn test_hash() {
let mut x = Flags::empty(); let mut x = Flags::empty();
let mut y = Flags::empty(); let mut y = Flags::empty();
assert!(hash(&x) == hash(&y)); assert!(hash(&x) == hash(&y));
x = Flags::all(); x = Flags::all();
y = Flags::FlagABC; y = Flags::FlagABC;
assert!(hash(&x) == hash(&y)); assert!(hash(&x) == hash(&y));
} }
fn hash<T: Hash>(t: &T) -> u64 { fn hash<T: Hash>(t: &T) -> u64 {

View file

@ -592,6 +592,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &hir::Expr) {
}; };
substs_wf_in_scope(rcx, origin, &callee.substs, expr.span, expr_region); substs_wf_in_scope(rcx, origin, &callee.substs, expr.span, expr_region);
type_must_outlive(rcx, infer::ExprTypeIsNotInScope(callee.ty, expr.span),
callee.ty, expr_region);
} }
// Check any autoderefs or autorefs that appear. // Check any autoderefs or autorefs that appear.
@ -664,6 +666,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &hir::Expr) {
} }
} }
debug!("regionck::visit_expr(e={:?}, repeating_scope={}) - visiting subexprs",
expr, rcx.repeating_scope);
match expr.node { match expr.node {
hir::ExprPath(..) => { hir::ExprPath(..) => {
rcx.fcx.opt_node_ty_substs(expr.id, |item_substs| { rcx.fcx.opt_node_ty_substs(expr.id, |item_substs| {

View file

@ -17,9 +17,8 @@ use option::Option::{self, Some, None};
use result; use result;
use sys; use sys;
/// A specialized [`Result`][result] type for I/O operations. /// A specialized [`Result`](../result/enum.Result.html) type for I/O
/// /// operations.
/// [result]: ../result/enum.Result.html
/// ///
/// This type is broadly used across `std::io` for any operation which may /// This type is broadly used across `std::io` for any operation which may
/// produce an error. /// produce an error.

View file

@ -335,8 +335,7 @@ LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
LLVMTargetMachineRef TMR) { LLVMTargetMachineRef TMR) {
TargetMachine *Target = unwrap(TMR); TargetMachine *Target = unwrap(TMR);
#if LLVM_VERSION_MINOR >= 7 #if LLVM_VERSION_MINOR >= 7
if (const DataLayout *DL = Target->getDataLayout()) unwrap(Module)->setDataLayout(Target->createDataLayout());
unwrap(Module)->setDataLayout(*DL);
#elif LLVM_VERSION_MINOR >= 6 #elif LLVM_VERSION_MINOR >= 6
if (const DataLayout *DL = Target->getSubtargetImpl()->getDataLayout()) if (const DataLayout *DL = Target->getSubtargetImpl()->getDataLayout())
unwrap(Module)->setDataLayout(DL); unwrap(Module)->setDataLayout(DL);

View file

@ -0,0 +1,22 @@
// Copyright 2015 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.
trait Test {}
macro_rules! test {
( $($name:ident)+) => (
impl<$($name: Test),*> Test for ($($name,)*) {
}
)
}
test!(A B C);
fn main() {}

View file

@ -0,0 +1,20 @@
// Copyright 2015 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.
pub struct Xyz<'a, V> {
pub v: (V, &'a u32),
}
pub fn eq<'a, 's, 't, V>(this: &'s Xyz<'a, V>, other: &'t Xyz<'a, V>) -> bool
where V: PartialEq {
this.v == other.v
}
fn main() {}