diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 45890cd3d8139..8a9f662bf83aa 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -192,11 +192,8 @@ extern "rust-intrinsic" { /// The size of a type in bytes. /// - /// This is the exact number of bytes in memory taken up by a - /// value of the given type. In other words, a memset of this size - /// would *exactly* overwrite a value. When laid out in vectors - /// and structures there may be additional padding between - /// elements. + /// More specifically, this is the offset in bytes between successive + /// items of the same type, including alignment padding. pub fn size_of() -> usize; /// Moves a value to an uninitialized memory location. diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 2c648d1516bff..56d268bf37c66 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -117,6 +117,9 @@ pub fn forget(t: T) { /// Returns the size of a type in bytes. /// +/// More specifically, this is the offset in bytes between successive +/// items of the same type, including alignment padding. +/// /// # Examples /// /// ``` diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index efef259dcad9b..5ee8a79f621de 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -635,7 +635,17 @@ fn foo(x: u8) -> u8 { ``` It is advisable to find out what the unhandled cases are and check for them, -returning an appropriate value or panicking if necessary. +returning an appropriate value or panicking if necessary. Check if you need +to remove a semicolon from the last expression, like in this case: + +```ignore +fn foo(x: u8) -> u8 { + inner(2*x + 1); +} +``` + +The semicolon discards the return value of `inner`, instead of returning +it from `foo`. "##, E0270: r##" diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index ead6ab099a88b..0207fa52d8de5 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -341,7 +341,15 @@ fn check_arms(cx: &MatchCheckCtxt, }, hir::MatchSource::Normal => { - span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern") + let mut err = struct_span_err!(cx.tcx.sess, pat.span, E0001, + "unreachable pattern"); + // if we had a catchall pattern, hint at that + for row in &seen.0 { + if pat_is_catchall(&cx.tcx.def_map.borrow(), row[0]) { + span_note!(err, row[0].span, "this pattern matches any value"); + } + } + err.emit(); }, hir::MatchSource::TryDesugar => { @@ -361,7 +369,18 @@ fn check_arms(cx: &MatchCheckCtxt, } } -fn raw_pat<'a>(p: &'a Pat) -> &'a Pat { +/// Checks for common cases of "catchall" patterns that may not be intended as such. +fn pat_is_catchall(dm: &DefMap, p: &Pat) -> bool { + match p.node { + PatKind::Ident(_, _, None) => pat_is_binding(dm, p), + PatKind::Ident(_, _, Some(ref s)) => pat_is_catchall(dm, &s), + PatKind::Ref(ref s, _) => pat_is_catchall(dm, &s), + PatKind::Tup(ref v) => v.iter().all(|p| pat_is_catchall(dm, &p)), + _ => false + } +} + +fn raw_pat(p: &Pat) -> &Pat { match p.node { PatKind::Ident(_, _, Some(ref s)) => raw_pat(&s), _ => p diff --git a/src/librustc_incremental/persist/util.rs b/src/librustc_incremental/persist/util.rs index 9b4e5997efe42..5b4e88def018b 100644 --- a/src/librustc_incremental/persist/util.rs +++ b/src/librustc_incremental/persist/util.rs @@ -9,14 +9,16 @@ // except according to those terms. use rustc::ty; + use std::fs; -use std::path::PathBuf; +use std::io; +use std::path::{PathBuf, Path}; pub fn dep_graph_path<'tcx>(tcx: &ty::TyCtxt<'tcx>) -> Option { // For now, just save/load dep-graph from // directory/dep_graph.rbml tcx.sess.opts.incremental.as_ref().and_then(|incr_dir| { - match fs::create_dir_all(&incr_dir){ + match create_dir_racy(&incr_dir) { Ok(()) => {} Err(err) => { tcx.sess.err( @@ -30,3 +32,23 @@ pub fn dep_graph_path<'tcx>(tcx: &ty::TyCtxt<'tcx>) -> Option { }) } +// Like std::fs::create_dir_all, except handles concurrent calls among multiple +// threads or processes. +fn create_dir_racy(path: &Path) -> io::Result<()> { + match fs::create_dir(path) { + Ok(()) => return Ok(()), + Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => return Ok(()), + Err(ref e) if e.kind() == io::ErrorKind::NotFound => {} + Err(e) => return Err(e), + } + match path.parent() { + Some(p) => try!(create_dir_racy(p)), + None => return Err(io::Error::new(io::ErrorKind::Other, + "failed to create whole tree")), + } + match fs::create_dir(path) { + Ok(()) => Ok(()), + Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()), + Err(e) => Err(e), + } +} diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 0a8fce49ebbaf..56d3b927dc592 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -916,11 +916,14 @@ An import was unresolved. Erroneous code example: use something::Foo; // error: unresolved import `something::Foo`. ``` -Please verify you didn't misspell the import name or the import does exist -in the module from where you tried to import it. Example: +Paths in `use` statements are relative to the crate root. To import items +relative to the current and parent modules, use the `self::` and `super::` +prefixes, respectively. Also verify that you didn't misspell the import +name and that the import exists in the module from where you tried to +import it. Example: ```ignore -use something::Foo; // ok! +use self::something::Foo; // ok! mod something { pub struct Foo; @@ -928,7 +931,7 @@ mod something { ``` Or, if you tried to use a module from an external crate, you may have missed -the `extern crate` declaration: +the `extern crate` declaration (which is usually placed in the crate root): ```ignore extern crate homura; // Required to use the `homura` crate diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index b541ca151c856..4ba8f2c9d6251 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -156,10 +156,6 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, if let Some(expr) = rcvr_expr { if let Ok (expr_string) = cx.sess.codemap().span_to_snippet(expr.span) { report_function!(expr.span, expr_string); - err.span_suggestion(expr.span, - "try calling the base function:", - format!("{}()", - expr_string)); } else if let Expr_::ExprPath(_, path) = expr.node.clone() { if let Some(segment) = path.segments.last() { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index d914d143e7011..ca15aa2d56c49 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -195,7 +195,7 @@ //! //! ## Functions //! -//! There are a number of [functions][functions] that offer access to various +//! There are a number of [functions][functions-list] that offer access to various //! features. For example, we can use three of these functions to copy everything //! from standard input to standard output: //! @@ -208,7 +208,7 @@ //! # } //! ``` //! -//! [functions]: #functions +//! [functions-list]: #functions-1 //! //! ## io::Result //! diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 881663a056c78..da62e5286d4e7 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -931,11 +931,10 @@ impl<'a> StringReader<'a> { _ => { if ascii_only && first_source_char > '\x7F' { let last_pos = self.last_pos; - self.err_span_char(start, - last_pos, - "byte constant must be ASCII. Use a \\xHH escape for a \ - non-ASCII byte", - first_source_char); + self.err_span_(start, + last_pos, + "byte constant must be ASCII. Use a \\xHH escape for a \ + non-ASCII byte"); return false; } } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index c381a3a8437de..4a92ad8ddb26d 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -61,8 +61,9 @@ //! line (which it can't) and so naturally place the content on its own line to //! avoid combining it with other lines and making matters even worse. +use std::collections::VecDeque; +use std::fmt; use std::io; -use std::string; #[derive(Clone, Copy, PartialEq)] pub enum Breaks { @@ -112,35 +113,30 @@ impl Token { } } -pub fn tok_str(token: &Token) -> String { - match *token { - Token::String(ref s, len) => format!("STR({},{})", s, len), - Token::Break(_) => "BREAK".to_string(), - Token::Begin(_) => "BEGIN".to_string(), - Token::End => "END".to_string(), - Token::Eof => "EOF".to_string() +impl fmt::Display for Token { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Token::String(ref s, len) => write!(f, "STR({},{})", s, len), + Token::Break(_) => f.write_str("BREAK"), + Token::Begin(_) => f.write_str("BEGIN"), + Token::End => f.write_str("END"), + Token::Eof => f.write_str("EOF"), + } } } -pub fn buf_str(toks: &[Token], - szs: &[isize], - left: usize, - right: usize, - lim: usize) - -> String { +fn buf_str(toks: &[Token], szs: &[isize], left: usize, right: usize, lim: usize) -> String { let n = toks.len(); assert_eq!(n, szs.len()); let mut i = left; let mut l = lim; - let mut s = string::String::from("["); + let mut s = String::from("["); while i != right && l != 0 { l -= 1; if i != left { s.push_str(", "); } - s.push_str(&format!("{}={}", - szs[i], - tok_str(&toks[i]))); + s.push_str(&format!("{}={}", szs[i], &toks[i])); i += 1; i %= n; } @@ -169,7 +165,7 @@ pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { debug!("mk_printer {}", linewidth); let token = vec![Token::Eof; n]; let size = vec![0; n]; - let scan_stack = vec![0; n]; + let scan_stack = VecDeque::with_capacity(n); Printer { out: out, buf_len: n, @@ -182,9 +178,6 @@ pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { left_total: 0, right_total: 0, scan_stack: scan_stack, - scan_stack_empty: true, - top: 0, - bottom: 0, print_stack: Vec::new(), pending_indentation: 0 } @@ -246,9 +239,8 @@ pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { /// approximation for purposes of line breaking). /// /// The "input side" of the printer is managed as an abstract process called -/// SCAN, which uses 'scan_stack', 'scan_stack_empty', 'top' and 'bottom', to -/// manage calculating 'size'. SCAN is, in other words, the process of -/// calculating 'size' entries. +/// SCAN, which uses 'scan_stack', to manage calculating 'size'. SCAN is, in +/// other words, the process of calculating 'size' entries. /// /// The "output side" of the printer is managed by an abstract process called /// PRINT, which uses 'print_stack', 'margin' and 'space' to figure out what to @@ -291,13 +283,7 @@ pub struct Printer<'a> { /// Begin (if there is any) on top of it. Stuff is flushed off the /// bottom as it becomes irrelevant due to the primary ring-buffer /// advancing. - scan_stack: Vec , - /// Top==bottom disambiguator - scan_stack_empty: bool, - /// Index of top of scan_stack - top: usize, - /// Index of bottom of scan_stack - bottom: usize, + scan_stack: VecDeque , /// Stack of blocks-in-progress being flushed by print print_stack: Vec , /// Buffered indentation to avoid writing trailing whitespace @@ -316,7 +302,7 @@ impl<'a> Printer<'a> { debug!("pp Vec<{},{}>", self.left, self.right); match token { Token::Eof => { - if !self.scan_stack_empty { + if !self.scan_stack.is_empty() { self.check_stack(0); self.advance_left()?; } @@ -324,7 +310,7 @@ impl<'a> Printer<'a> { Ok(()) } Token::Begin(b) => { - if self.scan_stack_empty { + if self.scan_stack.is_empty() { self.left_total = 1; self.right_total = 1; self.left = 0; @@ -339,7 +325,7 @@ impl<'a> Printer<'a> { Ok(()) } Token::End => { - if self.scan_stack_empty { + if self.scan_stack.is_empty() { debug!("pp End/print Vec<{},{}>", self.left, self.right); self.print(token, 0) } else { @@ -353,7 +339,7 @@ impl<'a> Printer<'a> { } } Token::Break(b) => { - if self.scan_stack_empty { + if self.scan_stack.is_empty() { self.left_total = 1; self.right_total = 1; self.left = 0; @@ -370,7 +356,7 @@ impl<'a> Printer<'a> { Ok(()) } Token::String(s, len) => { - if self.scan_stack_empty { + if self.scan_stack.is_empty() { debug!("pp String('{}')/print Vec<{},{}>", s, self.left, self.right); self.print(Token::String(s, len), len) @@ -392,12 +378,10 @@ impl<'a> Printer<'a> { if self.right_total - self.left_total > self.space { debug!("scan window is {}, longer than space on line ({})", self.right_total - self.left_total, self.space); - if !self.scan_stack_empty { - if self.left == self.scan_stack[self.bottom] { - debug!("setting {} to infinity and popping", self.left); - let scanned = self.scan_pop_bottom(); - self.size[scanned] = SIZE_INFINITY; - } + if Some(&self.left) == self.scan_stack.back() { + debug!("setting {} to infinity and popping", self.left); + let scanned = self.scan_pop_bottom(); + self.size[scanned] = SIZE_INFINITY; } self.advance_left()?; if self.left != self.right { @@ -408,43 +392,21 @@ impl<'a> Printer<'a> { } pub fn scan_push(&mut self, x: usize) { debug!("scan_push {}", x); - if self.scan_stack_empty { - self.scan_stack_empty = false; - } else { - self.top += 1; - self.top %= self.buf_len; - assert!((self.top != self.bottom)); - } - self.scan_stack[self.top] = x; + self.scan_stack.push_front(x); } pub fn scan_pop(&mut self) -> usize { - assert!((!self.scan_stack_empty)); - let x = self.scan_stack[self.top]; - if self.top == self.bottom { - self.scan_stack_empty = true; - } else { - self.top += self.buf_len - 1; self.top %= self.buf_len; - } - return x; + self.scan_stack.pop_front().unwrap() } pub fn scan_top(&mut self) -> usize { - assert!((!self.scan_stack_empty)); - return self.scan_stack[self.top]; + *self.scan_stack.front().unwrap() } pub fn scan_pop_bottom(&mut self) -> usize { - assert!((!self.scan_stack_empty)); - let x = self.scan_stack[self.bottom]; - if self.top == self.bottom { - self.scan_stack_empty = true; - } else { - self.bottom += 1; self.bottom %= self.buf_len; - } - return x; + self.scan_stack.pop_back().unwrap() } pub fn advance_right(&mut self) { self.right += 1; self.right %= self.buf_len; - assert!((self.right != self.left)); + assert!(self.right != self.left); } pub fn advance_left(&mut self) -> io::Result<()> { debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right, @@ -481,7 +443,7 @@ impl<'a> Printer<'a> { Ok(()) } pub fn check_stack(&mut self, k: isize) { - if !self.scan_stack_empty { + if !self.scan_stack.is_empty() { let x = self.scan_top(); match self.token[x] { Token::Begin(_) => { @@ -512,19 +474,16 @@ impl<'a> Printer<'a> { let ret = write!(self.out, "\n"); self.pending_indentation = 0; self.indent(amount); - return ret; + ret } pub fn indent(&mut self, amount: isize) { debug!("INDENT {}", amount); self.pending_indentation += amount; } pub fn get_top(&mut self) -> PrintStackElem { - let print_stack = &mut self.print_stack; - let n = print_stack.len(); - if n != 0 { - (*print_stack)[n - 1] - } else { - PrintStackElem { + match self.print_stack.last() { + Some(el) => *el, + None => PrintStackElem { offset: 0, pbreak: PrintStackBreak::Broken(Breaks::Inconsistent) } @@ -538,7 +497,7 @@ impl<'a> Printer<'a> { write!(self.out, "{}", s) } pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> { - debug!("print {} {} (remaining line space={})", tok_str(&token), l, + debug!("print {} {} (remaining line space={})", token, l, self.space); debug!("{}", buf_str(&self.token, &self.size, @@ -566,7 +525,7 @@ impl<'a> Printer<'a> { Token::End => { debug!("print End -> pop End"); let print_stack = &mut self.print_stack; - assert!((!print_stack.is_empty())); + assert!(!print_stack.is_empty()); print_stack.pop().unwrap(); Ok(()) } @@ -603,12 +562,12 @@ impl<'a> Printer<'a> { } } } - Token::String(s, len) => { + Token::String(ref s, len) => { debug!("print String({})", s); assert_eq!(l, len); // assert!(l <= space); self.space -= len; - self.print_str(&s[..]) + self.print_str(s) } Token::Eof => { // Eof should never get here. @@ -652,15 +611,15 @@ pub fn eof(p: &mut Printer) -> io::Result<()> { } pub fn word(p: &mut Printer, wrd: &str) -> io::Result<()> { - p.pretty_print(Token::String(/* bad */ wrd.to_string(), wrd.len() as isize)) + p.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize)) } pub fn huge_word(p: &mut Printer, wrd: &str) -> io::Result<()> { - p.pretty_print(Token::String(/* bad */ wrd.to_string(), SIZE_INFINITY)) + p.pretty_print(Token::String(wrd.to_string(), SIZE_INFINITY)) } pub fn zero_word(p: &mut Printer, wrd: &str) -> io::Result<()> { - p.pretty_print(Token::String(/* bad */ wrd.to_string(), 0)) + p.pretty_print(Token::String(wrd.to_string(), 0)) } pub fn spaces(p: &mut Printer, n: usize) -> io::Result<()> { diff --git a/src/test/compile-fail/issue-29124.rs b/src/test/compile-fail/issue-29124.rs index b3dc043f502fc..a72dac0d5dd68 100644 --- a/src/test/compile-fail/issue-29124.rs +++ b/src/test/compile-fail/issue-29124.rs @@ -25,11 +25,7 @@ fn main() { obj::func.x(); //~^ ERROR no method named `x` found for type `fn() -> ret {obj::func}` in the current scope //~^^ NOTE obj::func is a function, perhaps you wish to call it - //~^^^ HELP try calling the base function: - //~| SUGGESTION obj::func().x(); func.x(); //~^ ERROR no method named `x` found for type `fn() -> ret {func}` in the current scope //~^^ NOTE func is a function, perhaps you wish to call it - //~^^^ HELP try calling the base function: - //~| SUGGESTION func().x(); } diff --git a/src/test/compile-fail/issue-31221.rs b/src/test/compile-fail/issue-31221.rs new file mode 100644 index 0000000000000..2b3df9ad1d83b --- /dev/null +++ b/src/test/compile-fail/issue-31221.rs @@ -0,0 +1,49 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Enum { + Var1, + Var2, +} + +fn main() { + use Enum::*; + let s = Var1; + match s { + Var1 => (), + Var3 => (), + //~^ NOTE this pattern matches any value + Var2 => (), + //~^ ERROR unreachable pattern + }; + match &s { + &Var1 => (), + &Var3 => (), + //~^ NOTE this pattern matches any value + &Var2 => (), + //~^ ERROR unreachable pattern + }; + let t = (Var1, Var1); + match t { + (Var1, b) => (), + (c, d) => (), + //~^ NOTE this pattern matches any value + anything => () + //~^ ERROR unreachable pattern + }; + // `_` need not emit a note, it is pretty obvious already. + let t = (Var1, Var1); + match t { + (Var1, b) => (), + _ => (), + anything => () + //~^ ERROR unreachable pattern + }; +}