From b85aa7800de4a0f9c0b1ac2546b33afc5effced3 Mon Sep 17 00:00:00 2001 From: Vladimir Rutsky Date: Wed, 1 Jul 2015 01:57:54 +0300 Subject: [PATCH 01/47] fix typo: "requests function in the same [way] as other" --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0bcb3219858c9..d558e2f8840a6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -114,8 +114,8 @@ Documentation improvements are very welcome. The source of `doc.rust-lang.org` is located in `src/doc` in the tree, and standard API documentation is generated from the source code itself. -Documentation pull requests function in the same as other pull requests, though -you may see a slightly different form of `r+`: +Documentation pull requests function in the same way as other pull requests, +though you may see a slightly different form of `r+`: @bors: r+ 38fe8d2 rollup From aacb5f68bf224ecfa5adc6f3f0701f619010b3b1 Mon Sep 17 00:00:00 2001 From: Vladimir Rutsky Date: Wed, 1 Jul 2015 02:31:49 +0300 Subject: [PATCH 02/47] add missing colon --- src/doc/trpl/the-stack-and-the-heap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/the-stack-and-the-heap.md b/src/doc/trpl/the-stack-and-the-heap.md index 2c5f5927fd15a..d3f36427e3b6b 100644 --- a/src/doc/trpl/the-stack-and-the-heap.md +++ b/src/doc/trpl/the-stack-and-the-heap.md @@ -176,7 +176,7 @@ After `bar()` is over, its frame is deallocated, leaving just `foo()` and | 1 | a | 5 | | 0 | x | 42 | -And then `foo()` ends, leaving just `main()` +And then `foo()` ends, leaving just `main()`: | Address | Name | Value | |---------|------|-------| From dbaaa2c6a4036f821cafd06a3691e6bcb15bc4cb Mon Sep 17 00:00:00 2001 From: Vladimir Rutsky Date: Wed, 1 Jul 2015 02:34:01 +0300 Subject: [PATCH 03/47] remove terminating dot from caption --- src/doc/trpl/the-stack-and-the-heap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/trpl/the-stack-and-the-heap.md b/src/doc/trpl/the-stack-and-the-heap.md index d3f36427e3b6b..ff81590cc03b9 100644 --- a/src/doc/trpl/the-stack-and-the-heap.md +++ b/src/doc/trpl/the-stack-and-the-heap.md @@ -537,7 +537,7 @@ Generally, you should prefer stack allocation, and so, Rust stack-allocates by default. The LIFO model of the stack is simpler, at a fundamental level. This has two big impacts: runtime efficiency and semantic impact. -## Runtime Efficiency. +## Runtime Efficiency Managing the memory for the stack is trivial: The machine just increments or decrements a single value, the so-called “stack pointer”. From 36882a00074b0a444041f5348146ad66343c3e59 Mon Sep 17 00:00:00 2001 From: Nick Howell Date: Wed, 1 Jul 2015 23:28:54 -0400 Subject: [PATCH 04/47] rustdoc: Reset the title when pressing the back button Fixes #26673 --- src/librustdoc/html/static/main.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 4a03345277466..31fe043b79098 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -697,6 +697,9 @@ // Push and pop states are used to add search results to the browser // history. if (browserSupportsHistoryApi()) { + // Store the previous so we can revert back to it later. + var previousTitle = $(document).prop("title"); + $(window).on('popstate', function(e) { var params = getQueryStringParams(); // When browsing back from search results the main page @@ -705,6 +708,9 @@ $('#main.content').removeClass('hidden'); $('#search.content').addClass('hidden'); } + // Revert to the previous title manually since the History + // API ignores the title parameter. + $(document).prop("title", previousTitle); // When browsing forward to search results the previous // search will be repeated, so the currentResults are // cleared to ensure the search is successful. From 0d3954f4c574cda5f1bc63a915ff4d4f5e6e14ac Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe <tshepang@gmail.com> Date: Sun, 5 Jul 2015 17:49:06 +0200 Subject: [PATCH 05/47] reference: improve coercions section --- src/doc/reference.md | 107 ++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 41 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index a3e13acccae28..7946a4071c33e 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3652,47 +3652,71 @@ sites are: * `let` statements where an explicit type is given. - In `let _: U = e;`, `e` is coerced to have type `U`. + For example, `128` is coerced to have type `i8` in the following: + + ```rust + let _: i8 = 128; + ``` * `static` and `const` statements (similar to `let` statements). -* arguments for function calls. +* Arguments for function calls + + The value being coerced is the actual parameter, and it is coerced to + the type of the formal parameter. + + For example, `128` is coerced to have type `i8` in the following: + + ```rust + fn bar(_: i8) { } - The value being coerced is the - actual parameter and it is coerced to the type of the formal parameter. For - example, let `foo` be defined as `fn foo(x: U) { ... }` and call it as - `foo(e);`. Then `e` is coerced to have type `U`; + fn main() { + bar(128); + } + ``` -* instantiations of struct or variant fields. +* Instantiations of struct or variant fields - Assume we have a `struct - Foo { x: U }` and instantiate it as `Foo { x: e }`. Then `e` is coerced to - have type `U`. + For example, `128` is coerced to have type `i8` in the following: -* function results (either the final line of a block if it is not semicolon -terminated or any expression in a `return` statement). + ```rust + struct Foo { x: i8 } - In `fn foo() -> U { e }`, `e` is coerced to to have type `U`. + fn main() { + Foo { x: 128 }; + } + ``` + +* Function results, either the final line of a block if it is not + semicolon-terminated or any expression in a `return` statement + + For example, `128` is coerced to have type `i8` in the following: + + ```rust + fn foo() -> i8 { + 128 + } + ``` If the expression in one of these coercion sites is a coercion-propagating expression, then the relevant sub-expressions in that expression are also coercion sites. Propagation recurses from these new coercion sites. Propagating expressions and their relevant sub-expressions are: -* array literals, where the array has type `[U; n]`. Each sub-expression in +* Array literals, where the array has type `[U; n]`. Each sub-expression in the array literal is a coercion site for coercion to type `U`. -* array literals with repeating syntax, where the array has type `[U; n]`. The +* Array literals with repeating syntax, where the array has type `[U; n]`. The repeated sub-expression is a coercion site for coercion to type `U`. -* tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`. +* Tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`. Each sub-expression is a coercion site to the respective type, e.g. the zeroth sub-expression is a coercion site to type `U_0`. -* parenthesised sub-expressions (`(e)`). If the expression has type `U`, then +* Parenthesised sub-expressions (`(e)`): if the expression has type `U`, then the sub-expression is a coercion site to `U`. -* blocks. If a block has type `U`, then the last expression in the block (if +* Blocks: if a block has type `U`, then the last expression in the block (if it is not semicolon-terminated) is a coercion site to `U`. This includes blocks which are part of control flow statements, such as `if`/`else`, if the block has a known type. @@ -3701,45 +3725,46 @@ the block has a known type. Coercion is allowed between the following types: -* `T` to `U` if `T` is a subtype of `U` (*reflexive case*). +* `T` to `U` if `T` is a subtype of `U` (*reflexive case*) * `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` -(*transitive case*). +(*transitive case*) Note that this is not fully supported yet -* `&mut T` to `&T`. +* `&mut T` to `&T` -* `*mut T` to `*const T`. +* `*mut T` to `*const T` -* `&T` to `*const T`. +* `&T` to `*const T` -* `&mut T` to `*mut T`. +* `&mut T` to `*mut T` * `&T` to `&U` if `T` implements `Deref<Target = U>`. For example: -```rust -use std::ops::Deref; + ```rust + use std::ops::Deref; -struct CharContainer { - value: char -} + struct CharContainer { + value: char + } -impl Deref for CharContainer { - type Target = char; + impl Deref for CharContainer { + type Target = char; - fn deref<'a>(&'a self) -> &'a char { - &self.value - } -} + fn deref<'a>(&'a self) -> &'a char { + &self.value + } + } -fn foo(arg: &char) {} + fn foo(arg: &char) {} + + fn main() { + let x = &mut CharContainer { value: 'y' }; + foo(x); //&mut CharContainer is coerced to &char. + } + ``` -fn main() { - let x = &mut CharContainer { value: 'y' }; - foo(x); //&mut CharContainer is coerced to &char. -} -``` * `&mut T` to `&mut U` if `T` implements `DerefMut<Target = U>`. * TyCtor(`T`) to TyCtor(coerce_inner(`T`)), where TyCtor(`T`) is one of From 4ee704703444a23133e0c196e3a3fa75b8b7c5e3 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe <tshepang@gmail.com> Date: Sun, 5 Jul 2015 16:49:02 +0200 Subject: [PATCH 06/47] reference: miscellaneous fixes --- src/doc/reference.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 060f954274a9d..af02fc7a5bb36 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -343,10 +343,10 @@ The type of an _unsuffixed_ integer literal is determined by type inference: * If an integer type can be _uniquely_ determined from the surrounding program context, the unsuffixed integer literal has that type. -* If the program context underconstrains the type, it defaults to the +* If the program context under-constrains the type, it defaults to the signed 32-bit integer `i32`. -* If the program context overconstrains the type, it is considered a +* If the program context over-constrains the type, it is considered a static type error. Examples of integer literals of various forms: @@ -382,9 +382,9 @@ type inference: surrounding program context, the unsuffixed floating-point literal has that type. -* If the program context underconstrains the type, it defaults to `f64`. +* If the program context under-constrains the type, it defaults to `f64`. -* If the program context overconstrains the type, it is considered a +* If the program context over-constrains the type, it is considered a static type error. Examples of floating-point literals of various forms: @@ -1292,7 +1292,7 @@ All access to a static is safe, but there are a number of restrictions on statics: * Statics may not contain any destructors. -* The types of static values must ascribe to `Sync` to allow threadsafe access. +* The types of static values must ascribe to `Sync` to allow thread-safe access. * Statics may not refer to other statics by value, only by reference. * Constants cannot refer to statics. @@ -1694,7 +1694,7 @@ explain, here's a few use cases and what they would entail: * A crate needs a global available "helper module" to itself, but it doesn't want to expose the helper module as a public API. To accomplish this, the root of the crate's hierarchy would have a private module which then - internally has a "public api". Because the entire crate is a descendant of + internally has a "public API". Because the entire crate is a descendant of the root, then the entire local crate can access this private module through the second case. @@ -3964,7 +3964,7 @@ In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for all compilation needs, and the other options are just available if more fine-grained control is desired over the output format of a Rust crate. -# Appendix: Rationales and design tradeoffs +# Appendix: Rationales and design trade-offs *TODO*. @@ -3974,7 +3974,7 @@ Rust is not a particularly original language, with design elements coming from a wide range of sources. Some of these are listed below (including elements that have since been removed): -* SML, OCaml: algebraic datatypes, pattern matching, type inference, +* SML, OCaml: algebraic data types, pattern matching, type inference, semicolon statement separation * C++: references, RAII, smart pointers, move semantics, monomorphisation, memory model From e08c5f751578520c013d4838f0e288af937caf0d Mon Sep 17 00:00:00 2001 From: P1start <rewi-github@whanau.org> Date: Tue, 7 Jul 2015 11:11:20 +1200 Subject: [PATCH 07/47] Change some free functions into methods in libsyntax/diagnostic.rs --- src/libsyntax/diagnostic.rs | 788 ++++++++++++++++++------------------ 1 file changed, 392 insertions(+), 396 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index ec93d2c553627..fbf015169f858 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -308,63 +308,6 @@ impl Level { } } -fn print_maybe_styled(w: &mut EmitterWriter, - msg: &str, - color: term::attr::Attr) -> io::Result<()> { - match w.dst { - Terminal(ref mut t) => { - try!(t.attr(color)); - // If `msg` ends in a newline, we need to reset the color before - // the newline. We're making the assumption that we end up writing - // to a `LineBufferedWriter`, which means that emitting the reset - // after the newline ends up buffering the reset until we print - // another line or exit. Buffering the reset is a problem if we're - // sharing the terminal with any other programs (e.g. other rustc - // instances via `make -jN`). - // - // Note that if `msg` contains any internal newlines, this will - // result in the `LineBufferedWriter` flushing twice instead of - // once, which still leaves the opportunity for interleaved output - // to be miscolored. We assume this is rare enough that we don't - // have to worry about it. - if msg.ends_with("\n") { - try!(t.write_all(msg[..msg.len()-1].as_bytes())); - try!(t.reset()); - try!(t.write_all(b"\n")); - } else { - try!(t.write_all(msg.as_bytes())); - try!(t.reset()); - } - Ok(()) - } - Raw(ref mut w) => w.write_all(msg.as_bytes()), - } -} - -fn print_diagnostic(dst: &mut EmitterWriter, topic: &str, lvl: Level, - msg: &str, code: Option<&str>) -> io::Result<()> { - if !topic.is_empty() { - try!(write!(&mut dst.dst, "{} ", topic)); - } - - try!(print_maybe_styled(dst, - &format!("{}: ", lvl.to_string()), - term::attr::ForegroundColor(lvl.color()))); - try!(print_maybe_styled(dst, - &format!("{}", msg), - term::attr::Bold)); - - match code { - Some(code) => { - let style = term::attr::ForegroundColor(term::color::BRIGHT_MAGENTA); - try!(print_maybe_styled(dst, &format!(" [{}]", code.clone()), style)); - } - None => () - } - try!(write!(&mut dst.dst, "\n")); - Ok(()) -} - pub struct EmitterWriter { dst: Destination, registry: Option<diagnostics::registry::Registry> @@ -401,6 +344,392 @@ impl EmitterWriter { registry: Option<diagnostics::registry::Registry>) -> EmitterWriter { EmitterWriter { dst: Raw(dst), registry: registry } } + + fn print_maybe_styled(&mut self, + msg: &str, + color: term::attr::Attr) -> io::Result<()> { + match self.dst { + Terminal(ref mut t) => { + try!(t.attr(color)); + // If `msg` ends in a newline, we need to reset the color before + // the newline. We're making the assumption that we end up writing + // to a `LineBufferedWriter`, which means that emitting the reset + // after the newline ends up buffering the reset until we print + // another line or exit. Buffering the reset is a problem if we're + // sharing the terminal with any other programs (e.g. other rustc + // instances via `make -jN`). + // + // Note that if `msg` contains any internal newlines, this will + // result in the `LineBufferedWriter` flushing twice instead of + // once, which still leaves the opportunity for interleaved output + // to be miscolored. We assume this is rare enough that we don't + // have to worry about it. + if msg.ends_with("\n") { + try!(t.write_all(msg[..msg.len()-1].as_bytes())); + try!(t.reset()); + try!(t.write_all(b"\n")); + } else { + try!(t.write_all(msg.as_bytes())); + try!(t.reset()); + } + Ok(()) + } + Raw(ref mut w) => w.write_all(msg.as_bytes()), + } + } + + fn print_diagnostic(&mut self, topic: &str, lvl: Level, + msg: &str, code: Option<&str>) -> io::Result<()> { + if !topic.is_empty() { + try!(write!(&mut self.dst, "{} ", topic)); + } + + try!(self.print_maybe_styled(&format!("{}: ", lvl.to_string()), + term::attr::ForegroundColor(lvl.color()))); + try!(self.print_maybe_styled(&format!("{}", msg), + term::attr::Bold)); + + match code { + Some(code) => { + let style = term::attr::ForegroundColor(term::color::BRIGHT_MAGENTA); + try!(self.print_maybe_styled(&format!(" [{}]", code.clone()), style)); + } + None => () + } + try!(write!(&mut self.dst, "\n")); + Ok(()) + } + + fn emit_(&mut self, cm: &codemap::CodeMap, rsp: RenderSpan, + msg: &str, code: Option<&str>, lvl: Level) -> io::Result<()> { + let sp = rsp.span(); + + // We cannot check equality directly with COMMAND_LINE_SP + // since PartialEq is manually implemented to ignore the ExpnId + let ss = if sp.expn_id == COMMAND_LINE_EXPN { + "<command line option>".to_string() + } else if let EndSpan(_) = rsp { + let span_end = Span { lo: sp.hi, hi: sp.hi, expn_id: sp.expn_id}; + cm.span_to_string(span_end) + } else { + cm.span_to_string(sp) + }; + + try!(self.print_diagnostic(&ss[..], lvl, msg, code)); + + match rsp { + FullSpan(_) => { + try!(self.highlight_lines(cm, sp, lvl, cm.span_to_lines(sp))); + try!(self.print_macro_backtrace(cm, sp)); + } + EndSpan(_) => { + try!(self.end_highlight_lines(cm, sp, lvl, cm.span_to_lines(sp))); + try!(self.print_macro_backtrace(cm, sp)); + } + Suggestion(_, ref suggestion) => { + try!(self.highlight_suggestion(cm, sp, suggestion)); + try!(self.print_macro_backtrace(cm, sp)); + } + FileLine(..) => { + // no source text in this case! + } + } + + match code { + Some(code) => + match self.registry.as_ref().and_then(|registry| registry.find_description(code)) { + Some(_) => { + try!(self.print_diagnostic(&ss[..], Help, + &format!("run `rustc --explain {}` to see a \ + detailed explanation", code), None)); + } + None => () + }, + None => (), + } + Ok(()) + } + + fn highlight_suggestion(&mut self, + cm: &codemap::CodeMap, + sp: Span, + suggestion: &str) + -> io::Result<()> + { + let lines = cm.span_to_lines(sp).unwrap(); + assert!(!lines.lines.is_empty()); + + // To build up the result, we want to take the snippet from the first + // line that precedes the span, prepend that with the suggestion, and + // then append the snippet from the last line that trails the span. + let fm = &lines.file; + + let first_line = &lines.lines[0]; + let prefix = fm.get_line(first_line.line_index) + .map(|l| &l[..first_line.start_col.0]) + .unwrap_or(""); + + let last_line = lines.lines.last().unwrap(); + let suffix = fm.get_line(last_line.line_index) + .map(|l| &l[last_line.end_col.0..]) + .unwrap_or(""); + + let complete = format!("{}{}{}", prefix, suggestion, suffix); + + // print the suggestion without any line numbers, but leave + // space for them. This helps with lining up with previous + // snippets from the actual error being reported. + let fm = &*lines.file; + let mut lines = complete.lines(); + for (line, line_index) in lines.by_ref().take(MAX_LINES).zip(first_line.line_index..) { + let elided_line_num = format!("{}", line_index+1); + try!(write!(&mut self.dst, "{0}:{1:2$} {3}\n", + fm.name, "", elided_line_num.len(), line)); + } + + // if we elided some lines, add an ellipsis + if lines.next().is_some() { + let elided_line_num = format!("{}", first_line.line_index + MAX_LINES + 1); + try!(write!(&mut self.dst, "{0:1$} {0:2$} ...\n", + "", fm.name.len(), elided_line_num.len())); + } + + Ok(()) + } + + fn highlight_lines(&mut self, + cm: &codemap::CodeMap, + sp: Span, + lvl: Level, + lines: codemap::FileLinesResult) + -> io::Result<()> + { + let lines = match lines { + Ok(lines) => lines, + Err(_) => { + try!(write!(&mut self.dst, "(internal compiler error: unprintable span)\n")); + return Ok(()); + } + }; + + let fm = &*lines.file; + + let line_strings: Option<Vec<&str>> = + lines.lines.iter() + .map(|info| fm.get_line(info.line_index)) + .collect(); + + let line_strings = match line_strings { + None => { return Ok(()); } + Some(line_strings) => line_strings + }; + + // Display only the first MAX_LINES lines. + let all_lines = lines.lines.len(); + let display_lines = cmp::min(all_lines, MAX_LINES); + let display_line_infos = &lines.lines[..display_lines]; + let display_line_strings = &line_strings[..display_lines]; + + // Calculate the widest number to format evenly and fix #11715 + assert!(display_line_infos.len() > 0); + let mut max_line_num = display_line_infos[display_line_infos.len() - 1].line_index + 1; + let mut digits = 0; + while max_line_num > 0 { + max_line_num /= 10; + digits += 1; + } + + // Print the offending lines + for (line_info, line) in display_line_infos.iter().zip(display_line_strings) { + try!(write!(&mut self.dst, "{}:{:>width$} {}\n", + fm.name, + line_info.line_index + 1, + line, + width=digits)); + } + + // If we elided something, put an ellipsis. + if display_lines < all_lines { + let last_line_index = display_line_infos.last().unwrap().line_index; + let s = format!("{}:{} ", fm.name, last_line_index + 1); + try!(write!(&mut self.dst, "{0:1$}...\n", "", s.len())); + } + + // FIXME (#3260) + // If there's one line at fault we can easily point to the problem + if lines.lines.len() == 1 { + let lo = cm.lookup_char_pos(sp.lo); + let mut digits = 0; + let mut num = (lines.lines[0].line_index + 1) / 10; + + // how many digits must be indent past? + while num > 0 { num /= 10; digits += 1; } + + let mut s = String::new(); + // Skip is the number of characters we need to skip because they are + // part of the 'filename:line ' part of the previous line. + let skip = fm.name.chars().count() + digits + 3; + for _ in 0..skip { + s.push(' '); + } + if let Some(orig) = fm.get_line(lines.lines[0].line_index) { + let mut col = skip; + let mut lastc = ' '; + let mut iter = orig.chars().enumerate(); + for (pos, ch) in iter.by_ref() { + lastc = ch; + if pos >= lo.col.to_usize() { break; } + // Whenever a tab occurs on the previous line, we insert one on + // the error-point-squiggly-line as well (instead of a space). + // That way the squiggly line will usually appear in the correct + // position. + match ch { + '\t' => { + col += 8 - col%8; + s.push('\t'); + }, + _ => { + col += 1; + s.push(' '); + }, + } + } + + try!(write!(&mut self.dst, "{}", s)); + let mut s = String::from("^"); + let count = match lastc { + // Most terminals have a tab stop every eight columns by default + '\t' => 8 - col%8, + _ => 1, + }; + col += count; + s.extend(::std::iter::repeat('~').take(count)); + + let hi = cm.lookup_char_pos(sp.hi); + if hi.col != lo.col { + for (pos, ch) in iter { + if pos >= hi.col.to_usize() { break; } + let count = match ch { + '\t' => 8 - col%8, + _ => 1, + }; + col += count; + s.extend(::std::iter::repeat('~').take(count)); + } + } + + if s.len() > 1 { + // One extra squiggly is replaced by a "^" + s.pop(); + } + + try!(self.print_maybe_styled(&format!("{}\n", s), + term::attr::ForegroundColor(lvl.color()))); + } + } + Ok(()) + } + + /// Here are the differences between this and the normal `highlight_lines`: + /// `end_highlight_lines` will always put arrow on the last byte of the + /// span (instead of the first byte). Also, when the span is too long (more + /// than 6 lines), `end_highlight_lines` will print the first line, then + /// dot dot dot, then last line, whereas `highlight_lines` prints the first + /// six lines. + #[allow(deprecated)] + fn end_highlight_lines(&mut self, + cm: &codemap::CodeMap, + sp: Span, + lvl: Level, + lines: codemap::FileLinesResult) + -> io::Result<()> { + let lines = match lines { + Ok(lines) => lines, + Err(_) => { + try!(write!(&mut self.dst, "(internal compiler error: unprintable span)\n")); + return Ok(()); + } + }; + + let fm = &*lines.file; + + let lines = &lines.lines[..]; + if lines.len() > MAX_LINES { + if let Some(line) = fm.get_line(lines[0].line_index) { + try!(write!(&mut self.dst, "{}:{} {}\n", fm.name, + lines[0].line_index + 1, line)); + } + try!(write!(&mut self.dst, "...\n")); + let last_line_index = lines[lines.len() - 1].line_index; + if let Some(last_line) = fm.get_line(last_line_index) { + try!(write!(&mut self.dst, "{}:{} {}\n", fm.name, + last_line_index + 1, last_line)); + } + } else { + for line_info in lines { + if let Some(line) = fm.get_line(line_info.line_index) { + try!(write!(&mut self.dst, "{}:{} {}\n", fm.name, + line_info.line_index + 1, line)); + } + } + } + let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1].line_index + 1); + let hi = cm.lookup_char_pos(sp.hi); + let skip = last_line_start.chars().count(); + let mut s = String::new(); + for _ in 0..skip { + s.push(' '); + } + if let Some(orig) = fm.get_line(lines[0].line_index) { + let iter = orig.chars().enumerate(); + for (pos, ch) in iter { + // Span seems to use half-opened interval, so subtract 1 + if pos >= hi.col.to_usize() - 1 { break; } + // Whenever a tab occurs on the previous line, we insert one on + // the error-point-squiggly-line as well (instead of a space). + // That way the squiggly line will usually appear in the correct + // position. + match ch { + '\t' => s.push('\t'), + _ => s.push(' '), + } + } + } + s.push('^'); + s.push('\n'); + self.print_maybe_styled(&s[..], + term::attr::ForegroundColor(lvl.color())) + } + + fn print_macro_backtrace(&mut self, + cm: &codemap::CodeMap, + sp: Span) + -> io::Result<()> { + let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> { + match expn_info { + Some(ei) => { + let ss = ei.callee.span.map_or(String::new(), + |span| cm.span_to_string(span)); + let (pre, post) = match ei.callee.format { + codemap::MacroAttribute => ("#[", "]"), + codemap::MacroBang => ("", "!"), + codemap::CompilerExpansion => ("", ""), + }; + try!(self.print_diagnostic(&ss, Note, + &format!("in expansion of {}{}{}", + pre, + ei.callee.name, + post), + None)); + let ss = cm.span_to_string(ei.call_site); + try!(self.print_diagnostic(&ss, Note, "expansion site", None)); + Ok(Some(ei.call_site)) + } + None => Ok(None) + } + })); + cs.map_or(Ok(()), |call_site| self.print_macro_backtrace(cm, call_site)) + } } #[cfg(unix)] @@ -442,11 +771,11 @@ impl Emitter for EmitterWriter { cmsp: Option<(&codemap::CodeMap, Span)>, msg: &str, code: Option<&str>, lvl: Level) { let error = match cmsp { - Some((cm, COMMAND_LINE_SP)) => emit(self, cm, + Some((cm, COMMAND_LINE_SP)) => self.emit_(cm, FileLine(COMMAND_LINE_SP), msg, code, lvl), - Some((cm, sp)) => emit(self, cm, FullSpan(sp), msg, code, lvl), - None => print_diagnostic(self, "", lvl, msg, code), + Some((cm, sp)) => self.emit_(cm, FullSpan(sp), msg, code, lvl), + None => self.print_diagnostic("", lvl, msg, code), }; match error { @@ -457,346 +786,13 @@ impl Emitter for EmitterWriter { fn custom_emit(&mut self, cm: &codemap::CodeMap, sp: RenderSpan, msg: &str, lvl: Level) { - match emit(self, cm, sp, msg, None, lvl) { + match self.emit_(cm, sp, msg, None, lvl) { Ok(()) => {} Err(e) => panic!("failed to print diagnostics: {:?}", e), } } } -fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, - msg: &str, code: Option<&str>, lvl: Level) -> io::Result<()> { - let sp = rsp.span(); - - // We cannot check equality directly with COMMAND_LINE_SP - // since PartialEq is manually implemented to ignore the ExpnId - let ss = if sp.expn_id == COMMAND_LINE_EXPN { - "<command line option>".to_string() - } else if let EndSpan(_) = rsp { - let span_end = Span { lo: sp.hi, hi: sp.hi, expn_id: sp.expn_id}; - cm.span_to_string(span_end) - } else { - cm.span_to_string(sp) - }; - - try!(print_diagnostic(dst, &ss[..], lvl, msg, code)); - - match rsp { - FullSpan(_) => { - try!(highlight_lines(dst, cm, sp, lvl, cm.span_to_lines(sp))); - try!(print_macro_backtrace(dst, cm, sp)); - } - EndSpan(_) => { - try!(end_highlight_lines(dst, cm, sp, lvl, cm.span_to_lines(sp))); - try!(print_macro_backtrace(dst, cm, sp)); - } - Suggestion(_, ref suggestion) => { - try!(highlight_suggestion(dst, cm, sp, suggestion)); - try!(print_macro_backtrace(dst, cm, sp)); - } - FileLine(..) => { - // no source text in this case! - } - } - - match code { - Some(code) => - match dst.registry.as_ref().and_then(|registry| registry.find_description(code)) { - Some(_) => { - try!(print_diagnostic(dst, &ss[..], Help, - &format!("run `rustc --explain {}` to see a detailed \ - explanation", code), None)); - } - None => () - }, - None => (), - } - Ok(()) -} - -fn highlight_suggestion(err: &mut EmitterWriter, - cm: &codemap::CodeMap, - sp: Span, - suggestion: &str) - -> io::Result<()> -{ - let lines = cm.span_to_lines(sp).unwrap(); - assert!(!lines.lines.is_empty()); - - // To build up the result, we want to take the snippet from the first - // line that precedes the span, prepend that with the suggestion, and - // then append the snippet from the last line that trails the span. - let fm = &lines.file; - - let first_line = &lines.lines[0]; - let prefix = fm.get_line(first_line.line_index) - .map(|l| &l[..first_line.start_col.0]) - .unwrap_or(""); - - let last_line = lines.lines.last().unwrap(); - let suffix = fm.get_line(last_line.line_index) - .map(|l| &l[last_line.end_col.0..]) - .unwrap_or(""); - - let complete = format!("{}{}{}", prefix, suggestion, suffix); - - // print the suggestion without any line numbers, but leave - // space for them. This helps with lining up with previous - // snippets from the actual error being reported. - let fm = &*lines.file; - let mut lines = complete.lines(); - for (line, line_index) in lines.by_ref().take(MAX_LINES).zip(first_line.line_index..) { - let elided_line_num = format!("{}", line_index+1); - try!(write!(&mut err.dst, "{0}:{1:2$} {3}\n", - fm.name, "", elided_line_num.len(), line)); - } - - // if we elided some lines, add an ellipsis - if lines.next().is_some() { - let elided_line_num = format!("{}", first_line.line_index + MAX_LINES + 1); - try!(write!(&mut err.dst, "{0:1$} {0:2$} ...\n", - "", fm.name.len(), elided_line_num.len())); - } - - Ok(()) -} - -fn highlight_lines(err: &mut EmitterWriter, - cm: &codemap::CodeMap, - sp: Span, - lvl: Level, - lines: codemap::FileLinesResult) - -> io::Result<()> -{ - let lines = match lines { - Ok(lines) => lines, - Err(_) => { - try!(write!(&mut err.dst, "(internal compiler error: unprintable span)\n")); - return Ok(()); - } - }; - - let fm = &*lines.file; - - let line_strings: Option<Vec<&str>> = - lines.lines.iter() - .map(|info| fm.get_line(info.line_index)) - .collect(); - - let line_strings = match line_strings { - None => { return Ok(()); } - Some(line_strings) => line_strings - }; - - // Display only the first MAX_LINES lines. - let all_lines = lines.lines.len(); - let display_lines = cmp::min(all_lines, MAX_LINES); - let display_line_infos = &lines.lines[..display_lines]; - let display_line_strings = &line_strings[..display_lines]; - - // Calculate the widest number to format evenly and fix #11715 - assert!(display_line_infos.len() > 0); - let mut max_line_num = display_line_infos[display_line_infos.len() - 1].line_index + 1; - let mut digits = 0; - while max_line_num > 0 { - max_line_num /= 10; - digits += 1; - } - - // Print the offending lines - for (line_info, line) in display_line_infos.iter().zip(display_line_strings) { - try!(write!(&mut err.dst, "{}:{:>width$} {}\n", - fm.name, - line_info.line_index + 1, - line, - width=digits)); - } - - // If we elided something, put an ellipsis. - if display_lines < all_lines { - let last_line_index = display_line_infos.last().unwrap().line_index; - let s = format!("{}:{} ", fm.name, last_line_index + 1); - try!(write!(&mut err.dst, "{0:1$}...\n", "", s.len())); - } - - // FIXME (#3260) - // If there's one line at fault we can easily point to the problem - if lines.lines.len() == 1 { - let lo = cm.lookup_char_pos(sp.lo); - let mut digits = 0; - let mut num = (lines.lines[0].line_index + 1) / 10; - - // how many digits must be indent past? - while num > 0 { num /= 10; digits += 1; } - - let mut s = String::new(); - // Skip is the number of characters we need to skip because they are - // part of the 'filename:line ' part of the previous line. - let skip = fm.name.chars().count() + digits + 3; - for _ in 0..skip { - s.push(' '); - } - if let Some(orig) = fm.get_line(lines.lines[0].line_index) { - let mut col = skip; - let mut lastc = ' '; - let mut iter = orig.chars().enumerate(); - for (pos, ch) in iter.by_ref() { - lastc = ch; - if pos >= lo.col.to_usize() { break; } - // Whenever a tab occurs on the previous line, we insert one on - // the error-point-squiggly-line as well (instead of a space). - // That way the squiggly line will usually appear in the correct - // position. - match ch { - '\t' => { - col += 8 - col%8; - s.push('\t'); - }, - _ => { - col += 1; - s.push(' '); - }, - } - } - - try!(write!(&mut err.dst, "{}", s)); - let mut s = String::from("^"); - let count = match lastc { - // Most terminals have a tab stop every eight columns by default - '\t' => 8 - col%8, - _ => 1, - }; - col += count; - s.extend(::std::iter::repeat('~').take(count)); - - let hi = cm.lookup_char_pos(sp.hi); - if hi.col != lo.col { - for (pos, ch) in iter { - if pos >= hi.col.to_usize() { break; } - let count = match ch { - '\t' => 8 - col%8, - _ => 1, - }; - col += count; - s.extend(::std::iter::repeat('~').take(count)); - } - } - - if s.len() > 1 { - // One extra squiggly is replaced by a "^" - s.pop(); - } - - try!(print_maybe_styled(err, - &format!("{}\n", s), - term::attr::ForegroundColor(lvl.color()))); - } - } - Ok(()) -} - -/// Here are the differences between this and the normal `highlight_lines`: -/// `end_highlight_lines` will always put arrow on the last byte of the -/// span (instead of the first byte). Also, when the span is too long (more -/// than 6 lines), `end_highlight_lines` will print the first line, then -/// dot dot dot, then last line, whereas `highlight_lines` prints the first -/// six lines. -#[allow(deprecated)] -fn end_highlight_lines(w: &mut EmitterWriter, - cm: &codemap::CodeMap, - sp: Span, - lvl: Level, - lines: codemap::FileLinesResult) - -> io::Result<()> { - let lines = match lines { - Ok(lines) => lines, - Err(_) => { - try!(write!(&mut w.dst, "(internal compiler error: unprintable span)\n")); - return Ok(()); - } - }; - - let fm = &*lines.file; - - let lines = &lines.lines[..]; - if lines.len() > MAX_LINES { - if let Some(line) = fm.get_line(lines[0].line_index) { - try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, - lines[0].line_index + 1, line)); - } - try!(write!(&mut w.dst, "...\n")); - let last_line_index = lines[lines.len() - 1].line_index; - if let Some(last_line) = fm.get_line(last_line_index) { - try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, - last_line_index + 1, last_line)); - } - } else { - for line_info in lines { - if let Some(line) = fm.get_line(line_info.line_index) { - try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, - line_info.line_index + 1, line)); - } - } - } - let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1].line_index + 1); - let hi = cm.lookup_char_pos(sp.hi); - let skip = last_line_start.chars().count(); - let mut s = String::new(); - for _ in 0..skip { - s.push(' '); - } - if let Some(orig) = fm.get_line(lines[0].line_index) { - let iter = orig.chars().enumerate(); - for (pos, ch) in iter { - // Span seems to use half-opened interval, so subtract 1 - if pos >= hi.col.to_usize() - 1 { break; } - // Whenever a tab occurs on the previous line, we insert one on - // the error-point-squiggly-line as well (instead of a space). - // That way the squiggly line will usually appear in the correct - // position. - match ch { - '\t' => s.push('\t'), - _ => s.push(' '), - } - } - } - s.push('^'); - s.push('\n'); - print_maybe_styled(w, - &s[..], - term::attr::ForegroundColor(lvl.color())) -} - -fn print_macro_backtrace(w: &mut EmitterWriter, - cm: &codemap::CodeMap, - sp: Span) - -> io::Result<()> { - let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> { - match expn_info { - Some(ei) => { - let ss = ei.callee.span.map_or(String::new(), - |span| cm.span_to_string(span)); - let (pre, post) = match ei.callee.format { - codemap::MacroAttribute => ("#[", "]"), - codemap::MacroBang => ("", "!"), - codemap::CompilerExpansion => ("", ""), - }; - try!(print_diagnostic(w, &ss, Note, - &format!("in expansion of {}{}{}", - pre, - ei.callee.name, - post), - None)); - let ss = cm.span_to_string(ei.call_site); - try!(print_diagnostic(w, &ss, Note, "expansion site", None)); - Ok(Some(ei.call_site)) - } - None => Ok(None) - } - })); - cs.map_or(Ok(()), |call_site| print_macro_backtrace(w, cm, call_site)) -} - pub fn expect<T, M>(diag: &SpanHandler, opt: Option<T>, msg: M) -> T where M: FnOnce() -> String, { @@ -808,7 +804,7 @@ pub fn expect<T, M>(diag: &SpanHandler, opt: Option<T>, msg: M) -> T where #[cfg(test)] mod test { - use super::{EmitterWriter, highlight_lines, Level}; + use super::{EmitterWriter, Level}; use codemap::{mk_sp, CodeMap, BytePos}; use std::sync::{Arc, Mutex}; use std::io::{self, Write}; @@ -854,7 +850,7 @@ mod test { println!("span_to_lines"); let lines = cm.span_to_lines(sp); println!("highlight_lines"); - highlight_lines(&mut ew, &cm, sp, lvl, lines).unwrap(); + ew.highlight_lines(&cm, sp, lvl, lines).unwrap(); println!("done"); let vec = data.lock().unwrap().clone(); let vec: &[u8] = &vec; From c3fd0e12297d9e535f8e8e70eb942babfc11901d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Wed, 8 Jul 2015 22:55:22 +0200 Subject: [PATCH 08/47] Remove token::get_name when unneeded --- src/librustc_resolve/lib.rs | 80 ++++++++++++++----------- src/librustc_resolve/resolve_imports.rs | 30 +++++----- 2 files changed, 60 insertions(+), 50 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5d10b0d9a57b8..f879f1c09f68a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -109,6 +109,14 @@ mod record_exports; mod build_reduced_graph; mod resolve_imports; +macro_rules! resolve_err { + ($this:expr, $($rest:tt)*) => { + if $this.emit_errors { + span_err!($this.session, $($rest)*); + } + } +} + #[derive(Copy, Clone)] struct BindingInfo { span: Span, @@ -947,8 +955,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if module.external_module_children.borrow().contains_key(&name) { span_err!(self.session, span, E0259, "an external crate named `{}` has already \ - been imported into this module", - &token::get_name(name)); + been imported into this module", + name); } } @@ -960,9 +968,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if module.external_module_children.borrow().contains_key(&name) { span_err!(self.session, span, E0260, "the name `{}` conflicts with an external \ - crate that has been imported into this \ - module", - &token::get_name(name)); + crate that has been imported into this \ + module", + name); } } @@ -1041,7 +1049,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Indeterminate => { debug!("(resolving module path for import) module \ resolution is indeterminate: {}", - token::get_name(name)); + name); return Indeterminate; } Success((target, used_proxy)) => { @@ -1052,7 +1060,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match type_def.module_def { None => { let msg = format!("Not a module `{}`", - token::get_name(name)); + name); return Failed(Some((span, msg))); } @@ -1078,7 +1086,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { // There are no type bindings at all. let msg = format!("Not a module `{}`", - token::get_name(name)); + name); return Failed(Some((span, msg))); } } @@ -1200,7 +1208,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { -> ResolveResult<(Target, bool)> { debug!("(resolving item in lexical scope) resolving `{}` in \ namespace {:?} in `{}`", - token::get_name(name), + name, namespace, module_to_string(&*module_)); @@ -1302,9 +1310,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { namespace, PathSearch, true) { - Failed(Some((span, msg))) => - self.resolve_error(span, &format!("failed to resolve. {}", - msg)), + Failed(Some((span, msg))) => { + self.resolve_error(span, + &format!("failed to resolve. {}", + msg)); + }, Failed(None) => (), // Continue up the search chain. Indeterminate => { // We couldn't see through the higher scope because of an @@ -1469,7 +1479,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { allow_private_imports: bool) -> ResolveResult<(Target, bool)> { debug!("(resolving name in module) resolving `{}` in `{}`", - &token::get_name(name), + name, module_to_string(&*module_)); // First, check the direct children of the module. @@ -1547,7 +1557,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // We're out of luck. debug!("(resolving name in module) failed to resolve `{}`", - &token::get_name(name)); + name); return Failed(None); } @@ -1623,7 +1633,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match orig_module.children.borrow().get(&name) { None => { debug!("!!! (with scope) didn't find `{}` in `{}`", - token::get_name(name), + name, module_to_string(&*orig_module)); } Some(name_bindings) => { @@ -1631,7 +1641,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { debug!("!!! (with scope) didn't find module \ for `{}` in `{}`", - token::get_name(name), + name, module_to_string(&*orig_module)); } Some(module_) => { @@ -1795,7 +1805,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let name = item.ident.name; debug!("(resolving item) resolving {}", - token::get_name(name)); + name); match item.node { ItemEnum(_, ref generics) | @@ -1931,7 +1941,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { used for a type \ parameter in this type \ parameter list", - token::get_name(name))) + name)) } seen_bindings.insert(name); @@ -2177,7 +2187,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let path_str = path_names_to_string(&trait_ref.path, 0); self.resolve_error(span, &format!("method `{}` is not a member of trait `{}`", - token::get_name(name), + name, path_str)); } } @@ -2229,7 +2239,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { p.span, &format!("variable `{}` from pattern #1 is \ not bound in pattern #{}", - token::get_name(key), + key, i + 1)); } Some(binding_i) => { @@ -2238,7 +2248,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { binding_i.span, &format!("variable `{}` is bound with different \ mode in pattern #{} than in pattern #1", - token::get_name(key), + key, i + 1)); } } @@ -2251,7 +2261,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { binding.span, &format!("variable `{}` from pattern {}{} is \ not bound in pattern {}1", - token::get_name(key), + key, "#", i + 1, "#")); } } @@ -2410,7 +2420,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ struct or enum variant", - token::get_name(renamed)); + renamed); self.enforce_default_binding_mode( pattern, @@ -2428,12 +2438,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &format!("declaration of `{}` shadows an enum \ variant or unit-like struct in \ scope", - token::get_name(renamed))); + renamed)); } FoundConst(def, lp) if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ constant", - token::get_name(renamed)); + renamed); self.enforce_default_binding_mode( pattern, @@ -2452,7 +2462,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } BareIdentifierPatternUnresolved => { debug!("(resolving pattern) binding `{}`", - token::get_name(renamed)); + renamed); let def = DefLocal(pattern.id); @@ -2639,7 +2649,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Success((target, _)) => { debug!("(resolve bare identifier pattern) succeeded in \ finding {} at {:?}", - token::get_name(name), + name, target.bindings.value_def.borrow()); match *target.bindings.value_def.borrow() { None => { @@ -2685,7 +2695,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } debug!("(resolve bare identifier pattern) failed to find {}", - token::get_name(name)); + name); return BareIdentifierPatternUnresolved; } } @@ -3043,13 +3053,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // found a module instead. Modules don't have defs. debug!("(resolving item path by identifier in lexical \ scope) failed to resolve {} after success...", - token::get_name(name)); + name); return None; } Some(def) => { debug!("(resolving item path in lexical scope) \ resolved `{}` to item", - token::get_name(name)); + name); // This lookup is "all public" because it only searched // for one identifier in the current module (couldn't // have passed through reexports or anything like that. @@ -3062,7 +3072,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Failed(err) => { debug!("(resolving item path by identifier in lexical scope) \ - failed to resolve {}", token::get_name(name)); + failed to resolve {}", name); if let Some((span, msg)) = err { self.resolve_error(span, &format!("failed to resolve. {}", msg)) @@ -3472,7 +3482,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn get_traits_containing_item(&mut self, name: Name) -> Vec<DefId> { debug!("(getting traits containing item) looking for '{}'", - token::get_name(name)); + name); fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, @@ -3480,7 +3490,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(adding trait info) found trait {}:{} for method '{}'", trait_def_id.krate, trait_def_id.node, - token::get_name(name)); + name); found_traits.push(trait_def_id); } @@ -3591,7 +3601,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("Children:"); build_reduced_graph::populate_module_if_necessary(self, &module_); for (&name, _) in module_.children.borrow().iter() { - debug!("* {}", token::get_name(name)); + debug!("* {}", name); } debug!("Import resolutions:"); @@ -3615,7 +3625,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - debug!("* {}:{}{}", token::get_name(name), value_repr, type_repr); + debug!("* {}:{}{}", name, value_repr, type_repr); } } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e77e7116b9fea..a08d022ffcd7e 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -394,9 +394,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { -> ResolveResult<()> { debug!("(resolving single import) resolving `{}` = `{}::{}` from \ `{}` id {}, last private {:?}", - token::get_name(target), + target, module_to_string(&*target_module), - token::get_name(source), + source, module_to_string(module_), directive.id, lp); @@ -431,7 +431,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { value_result = BoundResult(target_module.clone(), (*child_name_bindings).clone()); if directive.is_public && !child_name_bindings.is_public(ValueNS) { - let msg = format!("`{}` is private", token::get_name(source)); + let msg = format!("`{}` is private", source); span_err!(self.resolver.session, directive.span, E0364, "{}", &msg); pub_err = true; } @@ -441,7 +441,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { type_result = BoundResult(target_module.clone(), (*child_name_bindings).clone()); if !pub_err && directive.is_public && !child_name_bindings.is_public(TypeNS) { - let msg = format!("`{}` is private", token::get_name(source)); + let msg = format!("`{}` is private", source); span_err!(self.resolver.session, directive.span, E0365, "{}", &msg); } } @@ -655,7 +655,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { if value_result.is_unbound() && type_result.is_unbound() { let msg = format!("There is no `{}` in `{}`", - token::get_name(source), + source, module_to_string(&target_module)); return ResolveResult::Failed(Some((directive.span, msg))); } @@ -736,7 +736,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { for (ident, target_import_resolution) in import_resolutions.iter() { debug!("(resolving glob import) writing module resolution \ {} into `{}`", - token::get_name(*ident), + *ident, module_to_string(module_)); if !target_import_resolution.is_public { @@ -842,7 +842,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { debug!("(resolving glob import) writing resolution `{}` in `{}` \ to `{}`", - &token::get_name(name), + name, module_to_string(&*containing_module), module_to_string(module_)); @@ -861,7 +861,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let msg = format!("a {} named `{}` has already been imported \ in this module", namespace_name, - &token::get_name(name)); + name); span_err!(self.resolver.session, import_directive.span, E0251, "{}", msg); } else { let target = Target::new(containing_module.clone(), @@ -894,7 +894,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { namespace: Namespace) { let target = import_resolution.target_for_namespace(namespace); debug!("check_for_conflicting_import: {}; target exists: {}", - &token::get_name(name), + name, target.is_some()); match target { @@ -918,13 +918,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { span_err!(self.resolver.session, import_span, E0252, "a {} named `{}` has already been imported \ in this module", ns_word, - &token::get_name(name)); + name); let use_id = import_resolution.id(namespace); let item = self.resolver.ast_map.expect_item(use_id); // item is syntax::ast::Item; span_note!(self.resolver.session, item.span, "previous import of `{}` here", - token::get_name(name)); + name); } Some(_) | None => {} } @@ -938,7 +938,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { namespace: Namespace) { if !name_bindings.defined_in_namespace_with(namespace, DefModifiers::IMPORTABLE) { let msg = format!("`{}` is not directly importable", - token::get_name(name)); + name); span_err!(self.resolver.session, import_span, E0253, "{}", &msg[..]); } } @@ -959,7 +959,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { let msg = format!("import `{0}` conflicts with imported \ crate in this module \ (maybe you meant `use {0}::*`?)", - &token::get_name(name)); + name); span_err!(self.resolver.session, import_span, E0254, "{}", &msg[..]); } Some(_) | None => {} @@ -981,7 +981,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { if let Some(ref value) = *name_bindings.value_def.borrow() { span_err!(self.resolver.session, import_span, E0255, "import `{}` conflicts with value in this module", - &token::get_name(name)); + name); if let Some(span) = value.value_span { self.resolver.session.span_note(span, "conflicting value here"); } @@ -1004,7 +1004,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { }; span_err!(self.resolver.session, import_span, E0256, "import `{}` conflicts with {}", - &token::get_name(name), what); + name, what); if let Some(span) = ty.type_span { self.resolver.session.span_note(span, note); } From 0bf9fbb6dd8d9762e8248aa3b61916547e59b5dd Mon Sep 17 00:00:00 2001 From: P1start <rewi-github@whanau.org> Date: Mon, 6 Jul 2015 18:16:46 +1200 Subject: [PATCH 09/47] Suggest using `ref` inline in an error --- src/librustc_borrowck/borrowck/mod.rs | 15 +++++++++-- src/test/compile-fail/ref-suggestion.rs | 33 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/ref-suggestion.rs diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 0d475e1257141..8f2e5deb92c7d 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -705,8 +705,19 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { ol, moved_lp_msg, pat_ty)); - self.tcx.sess.fileline_help(span, - "use `ref` to override"); + match self.tcx.sess.codemap().span_to_snippet(span) { + Ok(string) => { + self.tcx.sess.span_suggestion( + span, + &format!("if you would like to borrow the value instead, \ + use a `ref` binding as shown:"), + format!("ref {}", string)); + }, + Err(_) => { + self.tcx.sess.fileline_help(span, + "use `ref` to override"); + }, + } } move_data::Captured => { diff --git a/src/test/compile-fail/ref-suggestion.rs b/src/test/compile-fail/ref-suggestion.rs new file mode 100644 index 0000000000000..815f752663223 --- /dev/null +++ b/src/test/compile-fail/ref-suggestion.rs @@ -0,0 +1,33 @@ +// 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. + +fn main() { + let x = vec![1]; + let y = x; + //~^ HELP use a `ref` binding as shown + //~| SUGGESTION let ref y = x; + x; //~ ERROR use of moved value + + let x = vec![1]; + let mut y = x; + //~^ HELP use a `ref` binding as shown + //~| SUGGESTION let ref mut y = x; + x; //~ ERROR use of moved value + + let x = (Some(vec![1]), ()); + + match x { + (Some(y), ()) => {}, + //~^ HELP use a `ref` binding as shown + //~| SUGGESTION (Some(ref y), ()) => {}, + _ => {}, + } + x; //~ ERROR use of partially moved value +} From 2e00b3177001dd8281038930f4a5d0f214420bc4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Sat, 11 Jul 2015 21:46:06 +0200 Subject: [PATCH 10/47] We just have to replace error codes but code is good now --- src/librustc_resolve/diagnostics.rs | 4 +- src/librustc_resolve/lib.rs | 295 +++++++++++++++++++++------- 2 files changed, 222 insertions(+), 77 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 15ddcbc80749c..06019b96f6f5f 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -202,8 +202,8 @@ http://doc.rust-lang.org/reference.html#types } register_diagnostics! { - E0157, - E0153, + E0153, // called no where + E0157, // called from no where E0253, // not directly importable E0254, // import conflicts with imported crate in this module E0257, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f879f1c09f68a..b314772c8cb15 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -109,10 +109,17 @@ mod record_exports; mod build_reduced_graph; mod resolve_imports; +macro_rules! span_err { + ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ + __diagnostic_used!($code); + $session.span_err_with_code($span, &format!($($message)*), stringify!($code)) + }) +} + macro_rules! resolve_err { - ($this:expr, $($rest:tt)*) => { + ($this:expr, $span:expr, $code:ident, $($rest:tt)*) => { if $this.emit_errors { - span_err!($this.session, $($rest)*); + span_err!($this.session, $span, $code, $($rest)*); } } } @@ -1311,9 +1318,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathSearch, true) { Failed(Some((span, msg))) => { - self.resolve_error(span, + /*self.resolve_error(span, &format!("failed to resolve. {}", - msg)); + msg));*/ + resolve_err!(self, span, E0253, "failed to resolve. {}", msg); }, Failed(None) => (), // Continue up the search chain. Indeterminate => { @@ -1571,12 +1579,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .span_to_snippet((*imports)[index].span) .unwrap(); if sn.contains("::") { - self.resolve_error((*imports)[index].span, - "unresolved import"); + /*self.resolve_error((*imports)[index].span, + "unresolved import");*/ + resolve_err!(self, (*imports)[index].span, E0253, + "{}", "unresolved import"); } else { - let err = format!("unresolved import (maybe you meant `{}::*`?)", + /*let err = format!("unresolved import (maybe you meant `{}::*`?)", sn); - self.resolve_error((*imports)[index].span, &err[..]); + self.resolve_error((*imports)[index].span, &err[..]);*/ + resolve_err!(self, (*imports)[index].span, E0253, + "unresolved import (maybe you meant `{}::*`?)", sn); } } @@ -1703,16 +1715,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // named function item. This is not allowed, so we // report an error. - self.resolve_error(span, + /*self.resolve_error(span, "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); + use the || { ... } closure form instead");*/ + resolve_err!(self, span, E0253, "{}", + "can't capture dynamic environment in a fn item; \ + use the || { ... } closure form instead"); return None; } ConstantItemRibKind => { // Still doesn't deal with upvars - self.resolve_error(span, + /*self.resolve_error(span, "attempt to use a non-constant \ - value in a constant"); + value in a constant");*/ + resolve_err!(self, span, E0253, "{}", + "attempt to use a non-constant \ + value in a constant"); return None; } } @@ -1728,17 +1746,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This was an attempt to use a type parameter outside // its scope. - self.resolve_error(span, + /*self.resolve_error(span, "can't use type parameters from \ outer function; try using a local \ - type parameter instead"); + type parameter instead");*/ + resolve_err!(self, span, E0253, "{}", + "can't use type parameters from \ + outer function; try using a local \ + type parameter instead"); return None; } ConstantItemRibKind => { // see #9186 - self.resolve_error(span, + /*self.resolve_error(span, "cannot use an outer type \ - parameter in this context"); + parameter in this context");*/ + resolve_err!(self, span, E0253, "{}", + "cannot use an outer type \ + parameter in this context"); return None; } } @@ -1936,12 +1961,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("with_type_parameter_rib: {}", type_parameter.id); if seen_bindings.contains(&name) { - self.resolve_error(type_parameter.span, + /*self.resolve_error(type_parameter.span, &format!("the name `{}` is already \ used for a type \ parameter in this type \ parameter list", - name)) + name))*/ + resolve_err!(self, type_parameter.span, E0253, + "the name `{}` is already \ + used for a type \ + parameter in this type \ + parameter list", + name) } seen_bindings.insert(name); @@ -2028,9 +2059,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving trait) found trait def: {:?}", path_res); Ok(path_res) } else { - self.resolve_error(trait_path.span, + /*self.resolve_error(trait_path.span, &format!("`{}` is not a trait", - path_names_to_string(trait_path, path_depth))); + path_names_to_string(trait_path, path_depth)));*/ + resolve_err!(self, trait_path.span, E0253, + "`{}` is not a trait", + path_names_to_string(trait_path, path_depth)); // If it's a typedef, give a note if let DefTy(..) = path_res.base_def { @@ -2040,9 +2074,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Err(()) } } else { - let msg = format!("use of undeclared trait name `{}`", + /*let msg = format!("use of undeclared trait name `{}`", path_names_to_string(trait_path, path_depth)); - self.resolve_error(trait_path.span, &msg); + self.resolve_error(trait_path.span, &msg);*/ + resolve_err!(self, trait_path.span, E0253, + "use of undeclared trait name `{}`", + path_names_to_string(trait_path, path_depth)); Err(()) } } @@ -2060,7 +2097,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res { self.record_def(eq_pred.id, path_res.unwrap()); } else { - self.resolve_error(eq_pred.path.span, "undeclared associated type"); + //self.resolve_error(eq_pred.path.span, "undeclared associated type"); + resolve_err!(self, eq_pred.span, E0253, "{}", + "undeclared associated type"); } } } @@ -2185,10 +2224,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some((did, ref trait_ref)) = self.current_trait_ref { if !self.trait_item_map.contains_key(&(name, did)) { let path_str = path_names_to_string(&trait_ref.path, 0); - self.resolve_error(span, + /*self.resolve_error(span, &format!("method `{}` is not a member of trait `{}`", name, - path_str)); + path_str));*/ + resolve_err!(self, span, E0253, "method `{}` is not a member of trait `{}`", + name, path_str); } } } @@ -2235,21 +2276,31 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&key, &binding_0) in &map_0 { match map_i.get(&key) { None => { - self.resolve_error( + /*self.resolve_error( p.span, &format!("variable `{}` from pattern #1 is \ not bound in pattern #{}", key, - i + 1)); + i + 1));*/ + resolve_err!(self, p.span, E0253, + "variable `{}` from pattern #1 is \ + not bound in pattern #{}", + key, + i + 1); } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { - self.resolve_error( + /*self.resolve_error( binding_i.span, &format!("variable `{}` is bound with different \ mode in pattern #{} than in pattern #1", key, - i + 1)); + i + 1));*/ + resolve_err!(self, binding_i.span, E0253, + "variable `{}` is bound with different \ + mode in pattern #{} than in pattern #1", + key, + i + 1); } } } @@ -2257,12 +2308,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&key, &binding) in &map_i { if !map_0.contains_key(&key) { - self.resolve_error( + /*self.resolve_error( binding.span, &format!("variable `{}` from pattern {}{} is \ not bound in pattern {}1", key, - "#", i + 1, "#")); + "#", i + 1, "#"));*/ + resolve_err!(self, binding.span, E0253, + "variable `{}` from pattern {}{} is \ + not bound in pattern {}1", + key, + "#", i + 1, "#"); } } } @@ -2382,7 +2438,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { kind, path_names_to_string(path, 0)) }; - self.resolve_error(ty.span, &msg[..]); + //self.resolve_error(ty.span, &msg[..]); + resolve_err!(self, ty.span, E0253, + "{}", msg); } } } @@ -2433,12 +2491,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } FoundStructOrEnumVariant(..) => { - self.resolve_error( + /*self.resolve_error( pattern.span, &format!("declaration of `{}` shadows an enum \ variant or unit-like struct in \ scope", - renamed)); + renamed));*/ + resolve_err!(self, pattern.span, E0253, + "declaration of `{}` shadows an enum \ + variant or unit-like struct in \ + scope", + renamed); } FoundConst(def, lp) if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ @@ -2456,9 +2519,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } FoundConst(..) => { - self.resolve_error(pattern.span, + /*self.resolve_error(pattern.span, "only irrefutable patterns \ - allowed here"); + allowed here");*/ + resolve_err!(self, pattern.span, E0253, + "{}", + "only irrefutable patterns \ + allowed here"); } BareIdentifierPatternUnresolved => { debug!("(resolving pattern) binding `{}`", @@ -2490,7 +2557,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { bindings_list.contains_key(&renamed) { // Forbid duplicate bindings in the same // parameter list. - self.resolve_error(pattern.span, + /*self.resolve_error(pattern.span, &format!("identifier `{}` \ is bound more \ than once in \ @@ -2498,16 +2565,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { list", token::get_ident( ident)) - ) + )*/ + resolve_err!(self, pattern.span, E0253, + "identifier `{}` \ + is bound more \ + than once in \ + this parameter \ + list", + token::get_ident(ident)); } else if bindings_list.get(&renamed) == Some(&pat_id) { // Then this is a duplicate variable in the // same disjunction, which is an error. - self.resolve_error(pattern.span, + /*self.resolve_error(pattern.span, &format!("identifier `{}` is bound \ more than once in the same \ pattern", - token::get_ident(ident))); + token::get_ident(ident)));*/ + resolve_err!(self, pattern.span, E0253, + "identifier `{}` is bound \ + more than once in the same \ + pattern", + token::get_ident(ident)); } // Else, not bound in the same pattern: do // nothing. @@ -2538,10 +2617,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, path_res); } DefStatic(..) => { - self.resolve_error(path.span, + /*self.resolve_error(path.span, "static variables cannot be \ referenced in a pattern, \ - use a `const` instead"); + use a `const` instead");*/ + resolve_err!(self, path.span, E0253, "{}", + "static variables cannot be \ + referenced in a pattern, \ + use a `const` instead"); } _ => { // If anything ends up here entirely resolved, @@ -2549,11 +2632,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // partially resolved, that's OK, because it may // be a `T::CONST` that typeck will resolve. if path_res.depth == 0 { - self.resolve_error( + /*self.resolve_error( path.span, &format!("`{}` is not an enum variant, struct or const", token::get_ident( - path.segments.last().unwrap().identifier))); + path.segments.last().unwrap().identifier)));*/ + resolve_err!(self, path.span, E0253, + "`{}` is not an enum variant, struct or const", + token::get_ident( + path.segments.last().unwrap().identifier)); } else { let const_name = path.segments.last().unwrap() .identifier.name; @@ -2564,9 +2651,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } else { - self.resolve_error(path.span, + /*self.resolve_error(path.span, &format!("unresolved enum variant, struct or const `{}`", - token::get_ident(path.segments.last().unwrap().identifier))); + token::get_ident(path.segments.last().unwrap().identifier)));*/ + resolve_err!(self, path.span, E0253, + "unresolved enum variant, struct or const `{}`", + token::get_ident(path.segments.last().unwrap().identifier)); } visit::walk_path(self, path); } @@ -2598,16 +2688,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, path_res); } _ => { - self.resolve_error(path.span, + /*self.resolve_error(path.span, &format!("`{}` is not an associated const", token::get_ident( - path.segments.last().unwrap().identifier))); + path.segments.last().unwrap().identifier)));*/ + resolve_err!(self, path.span, E0253, + "`{}` is not an associated const", + token::get_ident( + path.segments.last().unwrap().identifier)); } } } else { - self.resolve_error(path.span, + /*self.resolve_error(path.span, &format!("unresolved associated const `{}`", - token::get_ident(path.segments.last().unwrap().identifier))); + token::get_ident(path.segments.last().unwrap().identifier)));*/ + resolve_err!(self, path.span, E0253, + "unresolved associated const `{}`", + token::get_ident(path.segments.last().unwrap().identifier)); } visit::walk_pat(self, pattern); } @@ -2620,9 +2717,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result => { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); - let msg = format!("`{}` does not name a structure", + /*let msg = format!("`{}` does not name a structure", path_names_to_string(path, 0)); - self.resolve_error(path.span, &msg[..]); + self.resolve_error(path.span, &msg[..]);*/ + resolve_err!(self, path.span, E0253, + "`{}` does not name a structure", + path_names_to_string(path, 0)); } } visit::walk_path(self, path); @@ -2668,10 +2768,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return FoundConst(def, LastMod(AllPublic)); } DefStatic(..) => { - self.resolve_error(span, + /*self.resolve_error(span, "static variables cannot be \ referenced in a pattern, \ - use a `const` instead"); + use a `const` instead");*/ + resolve_err!(self, span, E0253, + "{}", + "static variables cannot be \ + referenced in a pattern, \ + use a `const` instead"); return BareIdentifierPatternUnresolved; } _ => { @@ -2688,8 +2793,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Failed(err) => { match err { Some((span, msg)) => { - self.resolve_error(span, &format!("failed to resolve: {}", - msg)); + /*self.resolve_error(span, &format!("failed to resolve: {}", + msg));*/ + resolve_err!(self, span, E0253, + "failed to resolve: {}", + msg); } None => () } @@ -2918,8 +3026,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - self.resolve_error(span, &format!("failed to resolve. {}", - msg)); + /*self.resolve_error(span, &format!("failed to resolve. {}", + msg));*/ + resolve_err!(self, span, E0253, + "failed to resolve: {}", + msg); return None; } Indeterminate => panic!("indeterminate unexpected"), @@ -2978,8 +3089,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - self.resolve_error(span, &format!("failed to resolve. {}", - msg)); + /*self.resolve_error(span, &format!("failed to resolve. {}", + msg));*/ + resolve_err!(self, span, E0253, + "failed to resolve: {}", + msg); return None; } @@ -3075,7 +3189,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { failed to resolve {}", name); if let Some((span, msg)) = err { - self.resolve_error(span, &format!("failed to resolve. {}", msg)) + //self.resolve_error(span, &format!("failed to resolve. {}", msg)) + resolve_err!(self, span, E0253, + "failed to resolve: {}", + msg) } return None; @@ -3283,11 +3400,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Check if struct variant if let DefVariant(_, _, true) = path_res.base_def { let path_name = path_names_to_string(path, 0); - self.resolve_error(expr.span, + /*self.resolve_error(expr.span, &format!("`{}` is a struct variant name, but \ this expression \ uses it like a function name", - path_name)); + path_name));*/ + resolve_err!(self, expr.span, E0253, + "`{}` is a struct variant name, but \ + this expression \ + uses it like a function name", + path_name); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3324,11 +3446,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match type_res.map(|r| r.base_def) { Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => { - self.resolve_error(expr.span, + /*self.resolve_error(expr.span, &format!("`{}` is a structure name, but \ this expression \ uses it like a function name", - path_name)); + path_name));*/ + resolve_err!(self, expr.span, E0253, + "{}` is a structure name, but \ + this expression \ + uses it like a function name", + path_name); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3355,11 +3482,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if method_scope && &token::get_name(special_names::self_)[..] == path_name { - self.resolve_error( + /*self.resolve_error( expr.span, "`self` is not available \ in a static method. Maybe a \ - `self` argument is missing?"); + `self` argument is missing?");*/ + resolve_err!(self, expr.span, E0253, + "{}", + "`self` is not available \ + in a static method. Maybe a \ + `self` argument is missing?"); } else { let last_name = path.segments.last().unwrap().identifier.name; let mut msg = match self.find_fallback_in_self_type(last_name) { @@ -3383,10 +3515,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { msg = format!(". Did you mean {}?", msg) } - self.resolve_error( + /*self.resolve_error( expr.span, &format!("unresolved name `{}`{}", - path_name, msg)); + path_name, msg));*/ + resolve_err!(self, expr.span, E0253, + "unresolved name `{}`{}", + path_name, + msg); } } } @@ -3403,9 +3539,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(definition) => self.record_def(expr.id, definition), None => { debug!("(resolving expression) didn't find struct def",); - let msg = format!("`{}` does not name a structure", + /*let msg = format!("`{}` does not name a structure", path_names_to_string(path, 0)); - self.resolve_error(path.span, &msg[..]); + self.resolve_error(path.span, &msg[..]);*/ + resolve_err!(self, path.span, E0253, + "`{}` does not name a structure", + path_names_to_string(path, 0)); } } @@ -3430,10 +3569,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let renamed = mtwt::resolve(label); match self.search_label(renamed) { None => { - self.resolve_error( + /*self.resolve_error( expr.span, &format!("use of undeclared label `{}`", - token::get_ident(label))) + token::get_ident(label)))*/ + resolve_err!(self, expr.span, E0253, + "use of undeclared label `{}`", + token::get_ident(label)) } Some(DlDef(def @ DefLabel(_))) => { // Since this def is a label, it is never read. @@ -3579,10 +3721,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match pat_binding_mode { BindByValue(_) => {} BindByRef(..) => { - self.resolve_error(pat.span, + /*self.resolve_error(pat.span, &format!("cannot use `ref` binding mode \ with {}", - descr)); + descr));*/ + resolve_err!(self, pat.span, E0253, + "cannot use `ref` binding mode with {}", + descr); } } } From 8b731a5cac22f37d3709c889e4de342ca851e3ff Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Mon, 13 Jul 2015 00:31:09 +0200 Subject: [PATCH 11/47] Add error codes --- src/librustc_resolve/build_reduced_graph.rs | 21 +- src/librustc_resolve/diagnostics.rs | 42 +++- src/librustc_resolve/lib.rs | 258 +++++--------------- src/librustc_resolve/resolve_imports.rs | 8 +- 4 files changed, 113 insertions(+), 216 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 30d5a4f111ba4..00745136eef22 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -208,10 +208,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // Return an error here by looking up the namespace that // had the duplicate. let ns = ns.unwrap(); - self.resolve_error(sp, - &format!("duplicate definition of {} `{}`", - namespace_error_to_string(duplicate_type), - token::get_name(name))); + resolve_err!(self, sp, E0428, + "duplicate definition of {} `{}`", + namespace_error_to_string(duplicate_type), + token::get_name(name)); { let r = child.span_for_namespace(ns); if let Some(sp) = r { @@ -304,8 +304,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { full_path.segments.last().unwrap().identifier.name; if &token::get_name(source_name)[..] == "mod" || &token::get_name(source_name)[..] == "self" { - self.resolve_error(view_path.span, - "`self` imports are only allowed within a { } list"); + resolve_err!(self, view_path.span, E0429, + "{}", + "`self` imports are only allowed within a { } list"); } let subclass = SingleImport(binding.name, @@ -325,8 +326,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { _ => None }).collect::<Vec<Span>>(); if mod_spans.len() > 1 { - self.resolve_error(mod_spans[0], - "`self` import can only appear once in the list"); + resolve_err!(self, mod_spans[0], E0430, + "{}", + "`self` import can only appear once in the list"); for other_span in mod_spans.iter().skip(1) { self.session.span_note(*other_span, "another `self` import appears here"); @@ -341,7 +343,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let name = match module_path.last() { Some(name) => *name, None => { - self.resolve_error(source_item.span, + resolve_err!(self, source_item.span, E0431, + "{}", "`self` import can only appear in an import list \ with a non-empty prefix"); continue; diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 06019b96f6f5f..34cd6ef002ec8 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -209,5 +209,45 @@ register_diagnostics! { E0257, E0258, E0364, // item is private - E0365 // item is private + E0365, // item is private + E0397, // failed to resolve + E0398, // unresolved import + E0399, // can't capture dynamic environment in a fn item + E0400, // attempt to use a non-constant value in a constant + E0401, // can't use type parameters from outer function + E0402, // cannot use an outer type parameter in this context + E0403, // the name `{}` is already used + E0404, // is not a trait + E0405, // use of undeclared trait name + E0406, // undeclared associated type + E0407, // method is not a member of trait + E0408, // variable from pattern #1 is not bound in pattern # + E0409, // variable is bound with different mode in pattern # than in + // pattern #1 + E0410, // variable from pattern is not bound in pattern 1 + E0411, // use of `Self` outside of an impl or trait + E0412, // use of undeclared + E0413, // declaration of shadows an enum variant or unit-like struct in + // scope + E0414, // only irrefutable patterns allowed here + E0415, // identifier is bound more than once in this parameter list + E0416, // identifier is bound more than once in the same pattern + E0417, // static variables cannot be referenced in a pattern, use a + // `const` instead + E0418, // is not an enum variant, struct or const + E0419, // unresolved enum variant, struct or const + E0420, // is not an associated const + E0421, // unresolved associated const + E0422, // does not name a structure + E0423, // is a struct variant name, but this expression uses it like a + // function name + E0424, // `self` is not available in a static method. + E0425, // unresolved name + E0426, // use of undeclared label + E0427, // cannot use `ref` binding mode with ... + E0428, // duplicate definition of ... + E0429, // `self` imports are only allowed within a { } list + E0430, // `self` import can only appear once in the list + E0431 // `self` import can only appear in an import list with a non-empty + // prefix } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b314772c8cb15..c0e42f269ee2f 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -26,6 +26,16 @@ #![feature(slice_extras)] #![feature(staged_api)] +#![macro_use] + +macro_rules! resolve_err { + ($this:expr, $span:expr, $code:ident, $($rest:tt)*) => { + if $this.emit_errors { + span_err!($this.session, $span, $code, $($rest)*); + } + } +} + #[macro_use] extern crate log; #[macro_use] extern crate syntax; #[macro_use] #[no_link] extern crate rustc_bitflags; @@ -109,21 +119,6 @@ mod record_exports; mod build_reduced_graph; mod resolve_imports; -macro_rules! span_err { - ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - __diagnostic_used!($code); - $session.span_err_with_code($span, &format!($($message)*), stringify!($code)) - }) -} - -macro_rules! resolve_err { - ($this:expr, $span:expr, $code:ident, $($rest:tt)*) => { - if $this.emit_errors { - span_err!($this.session, $span, $code, $($rest)*); - } - } -} - #[derive(Copy, Clone)] struct BindingInfo { span: Span, @@ -1318,10 +1313,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathSearch, true) { Failed(Some((span, msg))) => { - /*self.resolve_error(span, - &format!("failed to resolve. {}", - msg));*/ - resolve_err!(self, span, E0253, "failed to resolve. {}", msg); + resolve_err!(self, span, E0397, "failed to resolve. {}", msg); }, Failed(None) => (), // Continue up the search chain. Indeterminate => { @@ -1579,15 +1571,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .span_to_snippet((*imports)[index].span) .unwrap(); if sn.contains("::") { - /*self.resolve_error((*imports)[index].span, - "unresolved import");*/ - resolve_err!(self, (*imports)[index].span, E0253, + resolve_err!(self, (*imports)[index].span, E0398, "{}", "unresolved import"); } else { - /*let err = format!("unresolved import (maybe you meant `{}::*`?)", - sn); - self.resolve_error((*imports)[index].span, &err[..]);*/ - resolve_err!(self, (*imports)[index].span, E0253, + resolve_err!(self, (*imports)[index].span, E0398, "unresolved import (maybe you meant `{}::*`?)", sn); } } @@ -1714,21 +1701,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. - - /*self.resolve_error(span, - "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead");*/ - resolve_err!(self, span, E0253, "{}", + resolve_err!(self, span, E0399, "{}", "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); return None; } ConstantItemRibKind => { // Still doesn't deal with upvars - /*self.resolve_error(span, - "attempt to use a non-constant \ - value in a constant");*/ - resolve_err!(self, span, E0253, "{}", + resolve_err!(self, span, E0400, "{}", "attempt to use a non-constant \ value in a constant"); return None; @@ -1746,11 +1726,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This was an attempt to use a type parameter outside // its scope. - /*self.resolve_error(span, - "can't use type parameters from \ - outer function; try using a local \ - type parameter instead");*/ - resolve_err!(self, span, E0253, "{}", + resolve_err!(self, span, E0401, "{}", "can't use type parameters from \ outer function; try using a local \ type parameter instead"); @@ -1758,10 +1734,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } ConstantItemRibKind => { // see #9186 - /*self.resolve_error(span, - "cannot use an outer type \ - parameter in this context");*/ - resolve_err!(self, span, E0253, "{}", + resolve_err!(self, span, E0402, "{}", "cannot use an outer type \ parameter in this context"); return None; @@ -1961,13 +1934,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("with_type_parameter_rib: {}", type_parameter.id); if seen_bindings.contains(&name) { - /*self.resolve_error(type_parameter.span, - &format!("the name `{}` is already \ - used for a type \ - parameter in this type \ - parameter list", - name))*/ - resolve_err!(self, type_parameter.span, E0253, + resolve_err!(self, type_parameter.span, E0403, "the name `{}` is already \ used for a type \ parameter in this type \ @@ -2059,10 +2026,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving trait) found trait def: {:?}", path_res); Ok(path_res) } else { - /*self.resolve_error(trait_path.span, - &format!("`{}` is not a trait", - path_names_to_string(trait_path, path_depth)));*/ - resolve_err!(self, trait_path.span, E0253, + resolve_err!(self, trait_path.span, E0404, "`{}` is not a trait", path_names_to_string(trait_path, path_depth)); @@ -2074,10 +2038,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Err(()) } } else { - /*let msg = format!("use of undeclared trait name `{}`", - path_names_to_string(trait_path, path_depth)); - self.resolve_error(trait_path.span, &msg);*/ - resolve_err!(self, trait_path.span, E0253, + resolve_err!(self, trait_path.span, E0405, "use of undeclared trait name `{}`", path_names_to_string(trait_path, path_depth)); Err(()) @@ -2097,8 +2058,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res { self.record_def(eq_pred.id, path_res.unwrap()); } else { - //self.resolve_error(eq_pred.path.span, "undeclared associated type"); - resolve_err!(self, eq_pred.span, E0253, "{}", + resolve_err!(self, eq_pred.span, E0406, "{}", "undeclared associated type"); } } @@ -2224,11 +2184,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some((did, ref trait_ref)) = self.current_trait_ref { if !self.trait_item_map.contains_key(&(name, did)) { let path_str = path_names_to_string(&trait_ref.path, 0); - /*self.resolve_error(span, - &format!("method `{}` is not a member of trait `{}`", - name, - path_str));*/ - resolve_err!(self, span, E0253, "method `{}` is not a member of trait `{}`", + resolve_err!(self, span, E0407, "method `{}` is not a member of trait `{}`", name, path_str); } } @@ -2276,13 +2232,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&key, &binding_0) in &map_0 { match map_i.get(&key) { None => { - /*self.resolve_error( - p.span, - &format!("variable `{}` from pattern #1 is \ - not bound in pattern #{}", - key, - i + 1));*/ - resolve_err!(self, p.span, E0253, + resolve_err!(self, p.span, E0408, "variable `{}` from pattern #1 is \ not bound in pattern #{}", key, @@ -2290,13 +2240,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { - /*self.resolve_error( - binding_i.span, - &format!("variable `{}` is bound with different \ - mode in pattern #{} than in pattern #1", - key, - i + 1));*/ - resolve_err!(self, binding_i.span, E0253, + resolve_err!(self, binding_i.span, E0409, "variable `{}` is bound with different \ mode in pattern #{} than in pattern #1", key, @@ -2308,13 +2252,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&key, &binding) in &map_i { if !map_0.contains_key(&key) { - /*self.resolve_error( - binding.span, - &format!("variable `{}` from pattern {}{} is \ - not bound in pattern {}1", - key, - "#", i + 1, "#"));*/ - resolve_err!(self, binding.span, E0253, + resolve_err!(self, binding.span, E0410, "variable `{}` from pattern {}{} is \ not bound in pattern {}1", key, @@ -2431,16 +2369,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { path.segments.len() > 0 && maybe_qself.is_none() && path.segments[0].identifier.name == self_type_name; - let msg = if is_invalid_self_type_name { - "use of `Self` outside of an impl or trait".to_string() + if is_invalid_self_type_name { + resolve_err!(self, ty.span, E0411, + "{}", + "use of `Self` outside of an impl or trait"); } else { - format!("use of undeclared {} `{}`", - kind, path_names_to_string(path, 0)) - }; - - //self.resolve_error(ty.span, &msg[..]); - resolve_err!(self, ty.span, E0253, - "{}", msg); + resolve_err!(self, ty.span, E0412, + "use of undeclared {} `{}`", + kind, + path_names_to_string(path, 0)); + } } } } @@ -2491,13 +2429,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } FoundStructOrEnumVariant(..) => { - /*self.resolve_error( - pattern.span, - &format!("declaration of `{}` shadows an enum \ - variant or unit-like struct in \ - scope", - renamed));*/ - resolve_err!(self, pattern.span, E0253, + resolve_err!(self, pattern.span, E0413, "declaration of `{}` shadows an enum \ variant or unit-like struct in \ scope", @@ -2519,10 +2451,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } FoundConst(..) => { - /*self.resolve_error(pattern.span, - "only irrefutable patterns \ - allowed here");*/ - resolve_err!(self, pattern.span, E0253, + resolve_err!(self, pattern.span, E0414, "{}", "only irrefutable patterns \ allowed here"); @@ -2557,16 +2486,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { bindings_list.contains_key(&renamed) { // Forbid duplicate bindings in the same // parameter list. - /*self.resolve_error(pattern.span, - &format!("identifier `{}` \ - is bound more \ - than once in \ - this parameter \ - list", - token::get_ident( - ident)) - )*/ - resolve_err!(self, pattern.span, E0253, + resolve_err!(self, pattern.span, E0415, "identifier `{}` \ is bound more \ than once in \ @@ -2577,12 +2497,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(&pat_id) { // Then this is a duplicate variable in the // same disjunction, which is an error. - /*self.resolve_error(pattern.span, - &format!("identifier `{}` is bound \ - more than once in the same \ - pattern", - token::get_ident(ident)));*/ - resolve_err!(self, pattern.span, E0253, + resolve_err!(self, pattern.span, E0416, "identifier `{}` is bound \ more than once in the same \ pattern", @@ -2617,11 +2532,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, path_res); } DefStatic(..) => { - /*self.resolve_error(path.span, - "static variables cannot be \ - referenced in a pattern, \ - use a `const` instead");*/ - resolve_err!(self, path.span, E0253, "{}", + resolve_err!(self, path.span, E0417, "{}", "static variables cannot be \ referenced in a pattern, \ use a `const` instead"); @@ -2632,12 +2543,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // partially resolved, that's OK, because it may // be a `T::CONST` that typeck will resolve. if path_res.depth == 0 { - /*self.resolve_error( - path.span, - &format!("`{}` is not an enum variant, struct or const", - token::get_ident( - path.segments.last().unwrap().identifier)));*/ - resolve_err!(self, path.span, E0253, + resolve_err!(self, path.span, E0418, "`{}` is not an enum variant, struct or const", token::get_ident( path.segments.last().unwrap().identifier)); @@ -2651,10 +2557,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } else { - /*self.resolve_error(path.span, - &format!("unresolved enum variant, struct or const `{}`", - token::get_ident(path.segments.last().unwrap().identifier)));*/ - resolve_err!(self, path.span, E0253, + resolve_err!(self, path.span, E0419, "unresolved enum variant, struct or const `{}`", token::get_ident(path.segments.last().unwrap().identifier)); } @@ -2688,21 +2591,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, path_res); } _ => { - /*self.resolve_error(path.span, - &format!("`{}` is not an associated const", - token::get_ident( - path.segments.last().unwrap().identifier)));*/ - resolve_err!(self, path.span, E0253, + resolve_err!(self, path.span, E0420, "`{}` is not an associated const", token::get_ident( path.segments.last().unwrap().identifier)); } } } else { - /*self.resolve_error(path.span, - &format!("unresolved associated const `{}`", - token::get_ident(path.segments.last().unwrap().identifier)));*/ - resolve_err!(self, path.span, E0253, + resolve_err!(self, path.span, E0421, "unresolved associated const `{}`", token::get_ident(path.segments.last().unwrap().identifier)); } @@ -2717,10 +2613,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result => { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); - /*let msg = format!("`{}` does not name a structure", - path_names_to_string(path, 0)); - self.resolve_error(path.span, &msg[..]);*/ - resolve_err!(self, path.span, E0253, + resolve_err!(self, path.span, E0422, "`{}` does not name a structure", path_names_to_string(path, 0)); } @@ -2768,11 +2661,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return FoundConst(def, LastMod(AllPublic)); } DefStatic(..) => { - /*self.resolve_error(span, - "static variables cannot be \ - referenced in a pattern, \ - use a `const` instead");*/ - resolve_err!(self, span, E0253, + resolve_err!(self, span, E0417, "{}", "static variables cannot be \ referenced in a pattern, \ @@ -2793,9 +2682,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Failed(err) => { match err { Some((span, msg)) => { - /*self.resolve_error(span, &format!("failed to resolve: {}", - msg));*/ - resolve_err!(self, span, E0253, + resolve_err!(self, span, E0397, "failed to resolve: {}", msg); } @@ -3026,9 +2913,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - /*self.resolve_error(span, &format!("failed to resolve. {}", - msg));*/ - resolve_err!(self, span, E0253, + resolve_err!(self, span, E0397, "failed to resolve: {}", msg); return None; @@ -3091,7 +2976,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /*self.resolve_error(span, &format!("failed to resolve. {}", msg));*/ - resolve_err!(self, span, E0253, + resolve_err!(self, span, E0397, "failed to resolve: {}", msg); return None; @@ -3189,8 +3074,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { failed to resolve {}", name); if let Some((span, msg)) = err { - //self.resolve_error(span, &format!("failed to resolve. {}", msg)) - resolve_err!(self, span, E0253, + resolve_err!(self, span, E0397, "failed to resolve: {}", msg) } @@ -3400,12 +3284,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Check if struct variant if let DefVariant(_, _, true) = path_res.base_def { let path_name = path_names_to_string(path, 0); - /*self.resolve_error(expr.span, - &format!("`{}` is a struct variant name, but \ - this expression \ - uses it like a function name", - path_name));*/ - resolve_err!(self, expr.span, E0253, + resolve_err!(self, expr.span, E0423, "`{}` is a struct variant name, but \ this expression \ uses it like a function name", @@ -3446,12 +3325,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match type_res.map(|r| r.base_def) { Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => { - /*self.resolve_error(expr.span, - &format!("`{}` is a structure name, but \ - this expression \ - uses it like a function name", - path_name));*/ - resolve_err!(self, expr.span, E0253, + resolve_err!(self, expr.span, E0423, "{}` is a structure name, but \ this expression \ uses it like a function name", @@ -3482,12 +3356,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if method_scope && &token::get_name(special_names::self_)[..] == path_name { - /*self.resolve_error( - expr.span, - "`self` is not available \ - in a static method. Maybe a \ - `self` argument is missing?");*/ - resolve_err!(self, expr.span, E0253, + resolve_err!(self, expr.span, E0424, "{}", "`self` is not available \ in a static method. Maybe a \ @@ -3515,11 +3384,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { msg = format!(". Did you mean {}?", msg) } - /*self.resolve_error( - expr.span, - &format!("unresolved name `{}`{}", - path_name, msg));*/ - resolve_err!(self, expr.span, E0253, + resolve_err!(self, expr.span, E0425, "unresolved name `{}`{}", path_name, msg); @@ -3539,10 +3404,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(definition) => self.record_def(expr.id, definition), None => { debug!("(resolving expression) didn't find struct def",); - /*let msg = format!("`{}` does not name a structure", - path_names_to_string(path, 0)); - self.resolve_error(path.span, &msg[..]);*/ - resolve_err!(self, path.span, E0253, + resolve_err!(self, path.span, E0422, "`{}` does not name a structure", path_names_to_string(path, 0)); } @@ -3569,11 +3431,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let renamed = mtwt::resolve(label); match self.search_label(renamed) { None => { - /*self.resolve_error( - expr.span, - &format!("use of undeclared label `{}`", - token::get_ident(label)))*/ - resolve_err!(self, expr.span, E0253, + resolve_err!(self, expr.span, E0426, "use of undeclared label `{}`", token::get_ident(label)) } @@ -3721,11 +3579,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match pat_binding_mode { BindByValue(_) => {} BindByRef(..) => { - /*self.resolve_error(pat.span, - &format!("cannot use `ref` binding mode \ - with {}", - descr));*/ - resolve_err!(self, pat.span, E0253, + resolve_err!(self, pat.span, E0427, "cannot use `ref` binding mode with {}", descr); } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index a08d022ffcd7e..cbaa96c4334e3 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -272,12 +272,12 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { Some((span, msg)) => (span, format!(". {}", msg)), None => (import_directive.span, String::new()) }; - let msg = format!("unresolved import `{}`{}", - import_path_to_string( + resolve_err!(self.resolver, span, E0398, + "unresolved import `{}`{}", + import_path_to_string( &import_directive.module_path, import_directive.subclass), - help); - self.resolver.resolve_error(span, &msg[..]); + help); } ResolveResult::Indeterminate => break, // Bail out. We'll come around next time. ResolveResult::Success(()) => () // Good. Continue. From f1b231dd714cb0edb0a632a5bd804b53423b3d4c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Mon, 13 Jul 2015 00:40:54 +0200 Subject: [PATCH 12/47] Remove unused method --- src/librustc_resolve/lib.rs | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c0e42f269ee2f..b0cff1406c5cc 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -26,16 +26,6 @@ #![feature(slice_extras)] #![feature(staged_api)] -#![macro_use] - -macro_rules! resolve_err { - ($this:expr, $span:expr, $code:ident, $($rest:tt)*) => { - if $this.emit_errors { - span_err!($this.session, $span, $code, $($rest)*); - } - } -} - #[macro_use] extern crate log; #[macro_use] extern crate syntax; #[macro_use] #[no_link] extern crate rustc_bitflags; @@ -109,11 +99,18 @@ use std::usize; use resolve_imports::{Target, ImportDirective, ImportResolution}; use resolve_imports::Shadowable; - // NB: This module needs to be declared first so diagnostics are // registered before they are used. pub mod diagnostics; +macro_rules! resolve_err { + ($this:expr, $span:expr, $code:ident, $($rest:tt)*) => { + if $this.emit_errors { + span_err!($this.session, $span, $code, $($rest)*); + } + } +} + mod check_unused; mod record_exports; mod build_reduced_graph; @@ -2253,10 +2250,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&key, &binding) in &map_i { if !map_0.contains_key(&key) { resolve_err!(self, binding.span, E0410, - "variable `{}` from pattern {}{} is \ - not bound in pattern {}1", + "variable `{}` from pattern #{} is \ + not bound in pattern #1", key, - "#", i + 1, "#"); + i + 1); } } } @@ -2371,7 +2368,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { path.segments[0].identifier.name == self_type_name; if is_invalid_self_type_name { resolve_err!(self, ty.span, E0411, - "{}", "use of `Self` outside of an impl or trait"); } else { resolve_err!(self, ty.span, E0412, @@ -3093,12 +3089,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { rs } - fn resolve_error(&self, span: Span, s: &str) { - if self.emit_errors { - self.session.span_err(span, s); - } - } - fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion { fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks) -> Option<(Path, NodeId, FallbackChecks)> { From 48ee57e656ea955fe634df7c7e9f37c27c65580a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Mon, 13 Jul 2015 00:57:16 +0200 Subject: [PATCH 13/47] Update error codes --- src/librustc_resolve/diagnostics.rs | 10 +++++----- src/librustc_resolve/lib.rs | 18 +++++++++--------- src/librustc_resolve/resolve_imports.rs | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 34cd6ef002ec8..939991da20307 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -210,10 +210,6 @@ register_diagnostics! { E0258, E0364, // item is private E0365, // item is private - E0397, // failed to resolve - E0398, // unresolved import - E0399, // can't capture dynamic environment in a fn item - E0400, // attempt to use a non-constant value in a constant E0401, // can't use type parameters from outer function E0402, // cannot use an outer type parameter in this context E0403, // the name `{}` is already used @@ -248,6 +244,10 @@ register_diagnostics! { E0428, // duplicate definition of ... E0429, // `self` imports are only allowed within a { } list E0430, // `self` import can only appear once in the list - E0431 // `self` import can only appear in an import list with a non-empty + E0431, // `self` import can only appear in an import list with a non-empty // prefix + E0432, // unresolved import + E0433, // failed to resolve + E0434, // can't capture dynamic environment in a fn item + E0435 // attempt to use a non-constant value in a constant } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b0cff1406c5cc..58c91aa81c771 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1310,7 +1310,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathSearch, true) { Failed(Some((span, msg))) => { - resolve_err!(self, span, E0397, "failed to resolve. {}", msg); + resolve_err!(self, span, E0433, "failed to resolve. {}", msg); }, Failed(None) => (), // Continue up the search chain. Indeterminate => { @@ -1568,10 +1568,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .span_to_snippet((*imports)[index].span) .unwrap(); if sn.contains("::") { - resolve_err!(self, (*imports)[index].span, E0398, + resolve_err!(self, (*imports)[index].span, E0432, "{}", "unresolved import"); } else { - resolve_err!(self, (*imports)[index].span, E0398, + resolve_err!(self, (*imports)[index].span, E0432, "unresolved import (maybe you meant `{}::*`?)", sn); } } @@ -1698,14 +1698,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. - resolve_err!(self, span, E0399, "{}", + resolve_err!(self, span, E0434, "{}", "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); return None; } ConstantItemRibKind => { // Still doesn't deal with upvars - resolve_err!(self, span, E0400, "{}", + resolve_err!(self, span, E0435, "{}", "attempt to use a non-constant \ value in a constant"); return None; @@ -2678,7 +2678,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Failed(err) => { match err { Some((span, msg)) => { - resolve_err!(self, span, E0397, + resolve_err!(self, span, E0433, "failed to resolve: {}", msg); } @@ -2909,7 +2909,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - resolve_err!(self, span, E0397, + resolve_err!(self, span, E0433, "failed to resolve: {}", msg); return None; @@ -2972,7 +2972,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /*self.resolve_error(span, &format!("failed to resolve. {}", msg));*/ - resolve_err!(self, span, E0397, + resolve_err!(self, span, E0433, "failed to resolve: {}", msg); return None; @@ -3070,7 +3070,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { failed to resolve {}", name); if let Some((span, msg)) = err { - resolve_err!(self, span, E0397, + resolve_err!(self, span, E0433, "failed to resolve: {}", msg) } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index cbaa96c4334e3..162dc4bd3815a 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -272,7 +272,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { Some((span, msg)) => (span, format!(". {}", msg)), None => (import_directive.span, String::new()) }; - resolve_err!(self.resolver, span, E0398, + resolve_err!(self.resolver, span, E0432, "unresolved import `{}`{}", import_path_to_string( &import_directive.module_path, From cbf0b1b399e884cff01393e817738da48bab64fd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Mon, 13 Jul 2015 02:05:02 +0200 Subject: [PATCH 14/47] Remove warnings by centralizing error codes usage --- src/librustc_resolve/lib.rs | 92 +++++++++++++++---------- src/librustc_resolve/resolve_imports.rs | 13 ++-- 2 files changed, 63 insertions(+), 42 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 58c91aa81c771..82e5df7728180 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -116,6 +116,26 @@ mod record_exports; mod build_reduced_graph; mod resolve_imports; +fn resolve_err_417<'a, 'tcx>(this: &Resolver<'a, 'tcx>, span: syntax::codemap::Span, formatted: &str) { + resolve_err!(this, span, E0417, "{}", formatted); +} + +fn resolve_err_422<'a, 'tcx>(this: &Resolver<'a, 'tcx>, span: syntax::codemap::Span, formatted: &str) { + resolve_err!(this, span, E0422, "{}", formatted); +} + +fn resolve_err_423<'a, 'tcx>(this: &Resolver<'a, 'tcx>, span: syntax::codemap::Span, formatted: &str) { + resolve_err!(this, span, E0423, "{}", formatted); +} + +fn resolve_err_432<'a, 'tcx>(this: &Resolver<'a, 'tcx>, span: syntax::codemap::Span, formatted: &str) { + resolve_err!(this, span, E0432, "{}", formatted); +} + +fn resolve_err_433<'a, 'tcx>(this: &Resolver<'a, 'tcx>, span: syntax::codemap::Span, formatted: &str) { + resolve_err!(this, span, E0433, "{}", formatted); +} + #[derive(Copy, Clone)] struct BindingInfo { span: Span, @@ -1310,7 +1330,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathSearch, true) { Failed(Some((span, msg))) => { - resolve_err!(self, span, E0433, "failed to resolve. {}", msg); + resolve_err_433(self, span, &*format!("failed to resolve. {}", msg)); }, Failed(None) => (), // Continue up the search chain. Indeterminate => { @@ -1568,11 +1588,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .span_to_snippet((*imports)[index].span) .unwrap(); if sn.contains("::") { - resolve_err!(self, (*imports)[index].span, E0432, - "{}", "unresolved import"); + resolve_err_432(self, (*imports)[index].span, "unresolved import"); } else { - resolve_err!(self, (*imports)[index].span, E0432, - "unresolved import (maybe you meant `{}::*`?)", sn); + resolve_err_432(self, (*imports)[index].span, + &*format!("unresolved import (maybe you meant `{}::*`?)", + sn) + ); } } @@ -2528,7 +2549,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, path_res); } DefStatic(..) => { - resolve_err!(self, path.span, E0417, "{}", + resolve_err_417(self, path.span, "static variables cannot be \ referenced in a pattern, \ use a `const` instead"); @@ -2609,9 +2630,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result => { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); - resolve_err!(self, path.span, E0422, - "`{}` does not name a structure", - path_names_to_string(path, 0)); + resolve_err_422(self, path.span, + &*format!("`{}` does not name a structure", + path_names_to_string(path, 0))); } } visit::walk_path(self, path); @@ -2657,8 +2678,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return FoundConst(def, LastMod(AllPublic)); } DefStatic(..) => { - resolve_err!(self, span, E0417, - "{}", + resolve_err_417(self, span, "static variables cannot be \ referenced in a pattern, \ use a `const` instead"); @@ -2678,9 +2698,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Failed(err) => { match err { Some((span, msg)) => { - resolve_err!(self, span, E0433, - "failed to resolve: {}", - msg); + resolve_err_433(self, span, + &*format!("failed to resolve: {}", + msg)); } None => () } @@ -2909,9 +2929,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - resolve_err!(self, span, E0433, - "failed to resolve: {}", - msg); + resolve_err_433(self, span, + &*format!("failed to resolve: {}", + msg)); return None; } Indeterminate => panic!("indeterminate unexpected"), @@ -2972,9 +2992,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /*self.resolve_error(span, &format!("failed to resolve. {}", msg));*/ - resolve_err!(self, span, E0433, - "failed to resolve: {}", - msg); + resolve_err_433(self, span, + &*format!("failed to resolve: {}", + msg)); return None; } @@ -3070,9 +3090,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { failed to resolve {}", name); if let Some((span, msg)) = err { - resolve_err!(self, span, E0433, - "failed to resolve: {}", - msg) + resolve_err_433(self, span, + &*format!("failed to resolve: {}", + msg)) } return None; @@ -3274,11 +3294,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Check if struct variant if let DefVariant(_, _, true) = path_res.base_def { let path_name = path_names_to_string(path, 0); - resolve_err!(self, expr.span, E0423, - "`{}` is a struct variant name, but \ - this expression \ - uses it like a function name", - path_name); + resolve_err_423(self, expr.span, + &*format!("`{}` is a struct variant name, but \ + this expression \ + uses it like a function name", + path_name)); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3315,11 +3335,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match type_res.map(|r| r.base_def) { Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => { - resolve_err!(self, expr.span, E0423, - "{}` is a structure name, but \ - this expression \ - uses it like a function name", - path_name); + resolve_err_423(self, expr.span, + &*format!("{}` is a structure name, but \ + this expression \ + uses it like a function name", + path_name)); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3394,9 +3414,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(definition) => self.record_def(expr.id, definition), None => { debug!("(resolving expression) didn't find struct def",); - resolve_err!(self, path.span, E0422, - "`{}` does not name a structure", - path_names_to_string(path, 0)); + resolve_err_422(self, path.span, + &*format!("`{}` does not name a structure", + path_names_to_string(path, 0))); } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 162dc4bd3815a..c5f451e5649ef 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -272,12 +272,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { Some((span, msg)) => (span, format!(". {}", msg)), None => (import_directive.span, String::new()) }; - resolve_err!(self.resolver, span, E0432, - "unresolved import `{}`{}", - import_path_to_string( - &import_directive.module_path, - import_directive.subclass), - help); + ::resolve_err_432(self.resolver, span, + &*format!("unresolved import `{}`{}", + import_path_to_string( + &import_directive.module_path, + import_directive.subclass), + help) + ); } ResolveResult::Indeterminate => break, // Bail out. We'll come around next time. ResolveResult::Success(()) => () // Good. Continue. From 4ec3ab61c085b887848aafc9cfab3a74197db2d2 Mon Sep 17 00:00:00 2001 From: Michael Sproul <micsproul@gmail.com> Date: Mon, 13 Jul 2015 23:21:33 +1000 Subject: [PATCH 15/47] diagnostics: Fix E0303 explanation. --- src/librustc/diagnostics.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 9aa5daa3a0a27..4b77c211df983 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -972,16 +972,16 @@ Updates to the borrow checker in a future version of Rust may remove this restriction, but for now patterns must be rewritten without sub-bindings. ``` -// Code like this... -match Some(5) { - ref op_num @ Some(num) => ... +// Before. +match Some("hi".to_string()) { + ref op_string_ref @ Some(ref s) => ... None => ... } // After. match Some("hi".to_string()) { Some(ref s) => { - let op_string_ref = &Some(&s); + let op_string_ref = &Some(s); ... } None => ... From 26ef17d1a937ab61c3cd7d41c97066a966e0fc51 Mon Sep 17 00:00:00 2001 From: Corey Farwell <coreyf@rwell.org> Date: Sun, 12 Jul 2015 20:32:32 +0900 Subject: [PATCH 16/47] Add regression test for #22312 Closes #22312 --- src/test/compile-fail/issue-22312.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/test/compile-fail/issue-22312.rs diff --git a/src/test/compile-fail/issue-22312.rs b/src/test/compile-fail/issue-22312.rs new file mode 100644 index 0000000000000..4d6e6eded2118 --- /dev/null +++ b/src/test/compile-fail/issue-22312.rs @@ -0,0 +1,27 @@ +// 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. + +use std::ops::Index; + +pub trait Array2D: Index<usize> { + fn rows(&self) -> usize; + fn columns(&self) -> usize; + fn get<'a>(&'a self, y: usize, x: usize) -> Option<&'a <Self as Index<usize>>::Output> { + if y >= self.rows() || x >= self.columns() { + return None; + } + let i = y * self.columns() + x; + let indexer = &(*self as &Index<usize, Output = <Self as Index<usize>>::Output>); + //~^ERROR non-scalar cast + Some(indexer.index(i)) + } +} + +fn main() {} From 00f726803bfdfa49d4f43bb8038f91ff3f8551d5 Mon Sep 17 00:00:00 2001 From: Corey Farwell <coreyf@rwell.org> Date: Sun, 12 Jul 2015 20:34:08 +0900 Subject: [PATCH 17/47] Add regression test for #20544 Closes #20544 --- src/test/run-pass/issue-20544.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/test/run-pass/issue-20544.rs diff --git a/src/test/run-pass/issue-20544.rs b/src/test/run-pass/issue-20544.rs new file mode 100644 index 0000000000000..c70b059d3e787 --- /dev/null +++ b/src/test/run-pass/issue-20544.rs @@ -0,0 +1,27 @@ +// 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. + +#![feature(unboxed_closures)] +#![feature(core)] + +struct Fun<F>(F); + +impl<F, T> FnOnce<(T,)> for Fun<F> where F: Fn(T) -> T { + type Output = T; + + extern "rust-call" fn call_once(self, (t,): (T,)) -> T { + (self.0)(t) + } +} + +fn main() { + let fun = Fun(|i: isize| i * 2); + println!("{}", fun(3)); +} From 9d94ef52638d3ac3b43c7061d68b08fbd2cd99d0 Mon Sep 17 00:00:00 2001 From: Corey Farwell <coreyf@rwell.org> Date: Sun, 12 Jul 2015 20:39:54 +0900 Subject: [PATCH 18/47] Add regression tests for #23595 Closes #23595 --- src/test/compile-fail/issue-23595-1.rs | 22 ++++++++++++++++++++++ src/test/compile-fail/issue-23595-2.rs | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/test/compile-fail/issue-23595-1.rs create mode 100644 src/test/compile-fail/issue-23595-2.rs diff --git a/src/test/compile-fail/issue-23595-1.rs b/src/test/compile-fail/issue-23595-1.rs new file mode 100644 index 0000000000000..4dc717558b176 --- /dev/null +++ b/src/test/compile-fail/issue-23595-1.rs @@ -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. + +use std::ops::{Index}; + +trait Hierarchy { + type Value; + type ChildKey; + type Children = Index<Self::ChildKey, Output=Hierarchy>; + //~^ ERROR: the value of the associated type must be specified + + fn data(&self) -> Option<(Self::Value, Self::Children)>; +} + +fn main() {} diff --git a/src/test/compile-fail/issue-23595-2.rs b/src/test/compile-fail/issue-23595-2.rs new file mode 100644 index 0000000000000..78a3f42f1a6a7 --- /dev/null +++ b/src/test/compile-fail/issue-23595-2.rs @@ -0,0 +1,18 @@ +// 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 C<AType: A> {a:AType} + +pub trait A { + type B = C<Self::anything_here_kills_it>; + //~^ ERROR: associated type `anything_here_kills_it` not found for `Self` +} + +fn main() {} From f52a87c44e84a0089819e77ad85ea24b88d547e7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Mon, 13 Jul 2015 19:32:45 +0200 Subject: [PATCH 19/47] Centralize error spaning and add an enum to make this treatment easier --- src/librustc_resolve/lib.rs | 133 ++++++++++++++---------- src/librustc_resolve/resolve_imports.rs | 6 +- 2 files changed, 80 insertions(+), 59 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 82e5df7728180..1fa8e63f57e17 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -116,24 +116,37 @@ mod record_exports; mod build_reduced_graph; mod resolve_imports; -fn resolve_err_417<'a, 'tcx>(this: &Resolver<'a, 'tcx>, span: syntax::codemap::Span, formatted: &str) { - resolve_err!(this, span, E0417, "{}", formatted); +pub enum ResolutionError<'b, 'a:'b, 'tcx:'a> { + /// error: static variables cannot be referenced in a pattern + StaticVariableReference(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error: does not name a struct + DoesNotNameAStruct(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error: is a struct variant name, but this expression uses it like a function name + StructVariantUsedAsFunction(&'a Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error: unresolved import + UnresolvedImport(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error: failed to resolve + FailedToResolve(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), } -fn resolve_err_422<'a, 'tcx>(this: &Resolver<'a, 'tcx>, span: syntax::codemap::Span, formatted: &str) { - resolve_err!(this, span, E0422, "{}", formatted); -} - -fn resolve_err_423<'a, 'tcx>(this: &Resolver<'a, 'tcx>, span: syntax::codemap::Span, formatted: &str) { - resolve_err!(this, span, E0423, "{}", formatted); -} - -fn resolve_err_432<'a, 'tcx>(this: &Resolver<'a, 'tcx>, span: syntax::codemap::Span, formatted: &str) { - resolve_err!(this, span, E0432, "{}", formatted); -} - -fn resolve_err_433<'a, 'tcx>(this: &Resolver<'a, 'tcx>, span: syntax::codemap::Span, formatted: &str) { - resolve_err!(this, span, E0433, "{}", formatted); +fn resolve_error<'b, 'a:'b, 'tcx:'a>(resolution_error: &ResolutionError<'b, 'a, 'tcx>, formatted: &str) { + match resolution_error { + &ResolutionError::StaticVariableReference(resolver, span) => { + resolve_err!(resolver, span, E0417, "{}", formatted); + }, + &ResolutionError::DoesNotNameAStruct(resolver, span) => { + resolve_err!(resolver, span, E0422, "{}", formatted); + }, + &ResolutionError::StructVariantUsedAsFunction(resolver, span) => { + resolve_err!(resolver, span, E0423, "{}", formatted); + }, + &ResolutionError::UnresolvedImport(resolver, span) => { + resolve_err!(resolver, span, E0432, "{}", formatted); + }, + &ResolutionError::FailedToResolve(resolver, span) => { + resolve_err!(resolver, span, E0433, "{}", formatted); + }, + } } #[derive(Copy, Clone)] @@ -1330,7 +1343,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathSearch, true) { Failed(Some((span, msg))) => { - resolve_err_433(self, span, &*format!("failed to resolve. {}", msg)); + resolve_error(&ResolutionError::FailedToResolve(self, span), + &*format!("failed to resolve. {}", + msg) + ); }, Failed(None) => (), // Continue up the search chain. Indeterminate => { @@ -1588,12 +1604,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .span_to_snippet((*imports)[index].span) .unwrap(); if sn.contains("::") { - resolve_err_432(self, (*imports)[index].span, "unresolved import"); + resolve_error(&ResolutionError::UnresolvedImport(self, (*imports)[index].span), + "unresolved import"); } else { - resolve_err_432(self, (*imports)[index].span, - &*format!("unresolved import (maybe you meant `{}::*`?)", - sn) - ); + resolve_error(&ResolutionError::UnresolvedImport(self, (*imports)[index].span), + &*format!("unresolved import (maybe you meant `{}::*`?)", + sn) + ); } } @@ -2549,10 +2566,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, path_res); } DefStatic(..) => { - resolve_err_417(self, path.span, - "static variables cannot be \ - referenced in a pattern, \ - use a `const` instead"); + resolve_error(&ResolutionError::StaticVariableReference(&self, path.span), + "static variables cannot be \ + referenced in a pattern, \ + use a `const` instead"); } _ => { // If anything ends up here entirely resolved, @@ -2630,7 +2647,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result => { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); - resolve_err_422(self, path.span, + resolve_error(&ResolutionError::DoesNotNameAStruct(self, path.span), &*format!("`{}` does not name a structure", path_names_to_string(path, 0))); } @@ -2678,10 +2695,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return FoundConst(def, LastMod(AllPublic)); } DefStatic(..) => { - resolve_err_417(self, span, - "static variables cannot be \ - referenced in a pattern, \ - use a `const` instead"); + resolve_error(&ResolutionError::StaticVariableReference(self, span), + "static variables cannot be \ + referenced in a pattern, \ + use a `const` instead"); return BareIdentifierPatternUnresolved; } _ => { @@ -2698,9 +2715,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Failed(err) => { match err { Some((span, msg)) => { - resolve_err_433(self, span, - &*format!("failed to resolve: {}", - msg)); + resolve_error(&ResolutionError::FailedToResolve(self, span), + &*format!("failed to resolve. {}", + msg) + ); } None => () } @@ -2929,9 +2947,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - resolve_err_433(self, span, - &*format!("failed to resolve: {}", - msg)); + resolve_error(&ResolutionError::FailedToResolve(self, span), + &*format!("failed to resolve. {}", + msg) + ); return None; } Indeterminate => panic!("indeterminate unexpected"), @@ -2990,11 +3009,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - /*self.resolve_error(span, &format!("failed to resolve. {}", - msg));*/ - resolve_err_433(self, span, - &*format!("failed to resolve: {}", - msg)); + resolve_error(&ResolutionError::FailedToResolve(self, span), + &*format!("failed to resolve. {}", + msg) + ); return None; } @@ -3090,9 +3108,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { failed to resolve {}", name); if let Some((span, msg)) = err { - resolve_err_433(self, span, - &*format!("failed to resolve: {}", - msg)) + resolve_error(&ResolutionError::FailedToResolve(self, span), + &*format!("failed to resolve. {}", + msg) + ) } return None; @@ -3294,11 +3313,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Check if struct variant if let DefVariant(_, _, true) = path_res.base_def { let path_name = path_names_to_string(path, 0); - resolve_err_423(self, expr.span, - &*format!("`{}` is a struct variant name, but \ - this expression \ - uses it like a function name", - path_name)); + + resolve_error(&ResolutionError::StructVariantUsedAsFunction(self, expr.span), + &*format!("`{}` is a struct variant name, but \ + this expression \ + uses it like a function name", + path_name)); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3335,11 +3355,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match type_res.map(|r| r.base_def) { Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => { - resolve_err_423(self, expr.span, - &*format!("{}` is a structure name, but \ - this expression \ - uses it like a function name", - path_name)); + resolve_error(&ResolutionError::StructVariantUsedAsFunction(self, expr.span), + &*format!("`{}` is a struct variant name, but \ + this expression \ + uses it like a function name", + path_name)); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3414,7 +3434,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(definition) => self.record_def(expr.id, definition), None => { debug!("(resolving expression) didn't find struct def",); - resolve_err_422(self, path.span, + + resolve_error(&ResolutionError::DoesNotNameAStruct(self, path.span), &*format!("`{}` does not name a structure", path_names_to_string(path, 0))); } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index c5f451e5649ef..196de63bfd979 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -272,13 +272,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { Some((span, msg)) => (span, format!(". {}", msg)), None => (import_directive.span, String::new()) }; - ::resolve_err_432(self.resolver, span, - &*format!("unresolved import `{}`{}", + ::resolve_error(&::ResolutionError::UnresolvedImport(self.resolver, span), + &*format!("unresolved import `{}`{}", import_path_to_string( &import_directive.module_path, import_directive.subclass), help) - ); + ); } ResolveResult::Indeterminate => break, // Bail out. We'll come around next time. ResolveResult::Success(()) => () // Good. Continue. From eaee43aeba955e9f6ddb708a01b8e31ce536aece Mon Sep 17 00:00:00 2001 From: Akos Kiss <akiss@inf.u-szeged.hu> Date: Mon, 13 Jul 2015 20:06:04 +0200 Subject: [PATCH 20/47] Fix section of __morestack for aarch64-unknown-linux-gnu When building for AArch64/Linux, __morestack ends up in the .note.GNU-stack section, which causes missing references for the linker. By using the func/endfunc macros from macros.S we get __morestack right to .text (and a bit more on the side). --- src/rt/arch/aarch64/morestack.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rt/arch/aarch64/morestack.S b/src/rt/arch/aarch64/morestack.S index c5e412140e44a..8b7366ebed431 100644 --- a/src/rt/arch/aarch64/morestack.S +++ b/src/rt/arch/aarch64/morestack.S @@ -24,7 +24,7 @@ #endif #if !defined(__APPLE__) -.type MORESTACK,%function +func MORESTACK #endif // FIXME(AARCH64): this might not be perfectly right but works for now @@ -33,3 +33,7 @@ MORESTACK: bl STACK_EXHAUSTED // the above function ensures that it never returns .cfi_endproc + +#if !defined(__APPLE__) +endfunc MORESTACK +#endif From 2e1f75acc48ba084f5bd24ec75ec831de6a5677a Mon Sep 17 00:00:00 2001 From: Jose Narvaez <jnarvaez@zendesk.com> Date: Mon, 13 Jul 2015 20:54:33 +0100 Subject: [PATCH 21/47] Fixed snippet to return the proper error. --- src/doc/trpl/error-handling.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md index 580eaa6ca5571..8dd5a3650ef52 100644 --- a/src/doc/trpl/error-handling.md +++ b/src/doc/trpl/error-handling.md @@ -50,6 +50,8 @@ is very wrong. Wrong enough that we can't continue with things in the current state. Another example is using the `unreachable!()` macro: ```rust,ignore +use Event::NewRelease; + enum Event { NewRelease, } @@ -71,7 +73,7 @@ fn descriptive_probability(event: Event) -> &'static str { } fn main() { - std::io::println(descriptive_probability(NewRelease)); + println!("{}", descriptive_probability(NewRelease)); } ``` From 68781e25c5465021d25e2ff9d3818577e70c6545 Mon Sep 17 00:00:00 2001 From: Brian Anderson <banderson@mozilla.com> Date: Sat, 11 Jul 2015 12:12:19 -0700 Subject: [PATCH 22/47] std: Refining crate docs Yet another attempt to make the prose on the std crate page clearer and more informative. This does a lot of things: tightens up the opening, adds useful links (including a link to the search bar), offers guidance on how to use the docs, and expands the prelude docs as a useful newbie entrypoint. --- src/libstd/lib.rs | 147 +++++++++++++++++++++++++++++++------- src/libstd/prelude/mod.rs | 103 ++++++++++++++++++++++++-- 2 files changed, 217 insertions(+), 33 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 1e82a03f28630..e6049ab286356 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -10,29 +10,122 @@ //! # The Rust Standard Library //! -//! The Rust Standard Library provides the essential runtime -//! functionality for building portable Rust software. +//! The Rust Standard Library is the foundation of portable Rust +//! software, a set of minimal and battle-tested shared abstractions +//! for the [broader Rust ecosystem](https://crates.io). It offers +//! core types (e.g. [`Vec`](vec/index.html) +//! and[`Option`](option/index.html)), library-defined [operations on +//! language primitives](#primitive) (e.g. [`u32`](u32/index.html) and +//! [`str`](str/index.html)), [standard macros](#macros), +//! [I/O](io/index.html) and [multithreading](thread/index.html), among +//! [many other lovely +//! things](#what-is-in-the-standard-library-documentation?). //! -//! The Rust Standard Library is available to all Rust crates by -//! default, just as if contained an `extern crate std` import at the -//! crate root. Therefore the standard library can be accessed in -//! `use` statements through the path `std`, as in `use std::thread`, -//! or in expressions through the absolute path `::std`, as in -//! `::std::thread::sleep_ms(100)`. +//! `std` is available to all Rust crates by default, just as if each +//! one contained an `extern crate std` import at the [crate +//! root][book-crate-root]. Therefore the standard library can be +//! accessed in [`use`][book-use] statements through the path `std`, +//! as in [`use std::env`](env/index.html), or in expressions +//! through the absolute path `::std`, as in +//! [`::std::env::args()`](env/fn.args.html). +//! +//! [book-crate-root]: file:///home/brian/dev/rust2/build/doc/book/crates-and-modules.html#basic-terminology:-crates-and-modules +//! [book-use]: ../book/crates-and-modules.html#importing-modules-with-use //! //! Furthermore, the standard library defines [The Rust //! Prelude](prelude/index.html), a small collection of items, mostly -//! traits, that are imported into and available in every module. +//! traits, that are imported into every module and through trait +//! resolution provide Rust with much of its *standard flavor*. +//! +//! # How to read this documentation +//! +//! If you already know the name of what you are looking for the +//! fastest way to find it is to use the <a href="#" +//! onclick="document.getElementsByName('search')[0].focus();">search +//! bar</a> at the top of the page. +//! +//! Otherwise, you may want to jump to one of these useful sections: +//! +//! * [`std::*` modules](#modules) +//! * [Primitive types](#primitives) +//! * [Standard macros](#macros) +//! * [The Rust Prelude](prelude/index.html) +//! +//! If this is your first time, the documentation for the standard +//! library is written to be casually perused and clicking on +//! interesting things should generally lead you to interesting +//! places. Still, there are important bits you don't want to miss, so +//! read on for a tour of the standard library and its documentation. +//! +//! Once you are familiar with the contents of the standard library +//! you may begin to find the verbosity of the prose distracting. At +//! this stage in your development you may want to press the **[-]** +//! button near the top of the page to collapse it into a more +//! skimmable view. +//! +//! While you are looking at that **[-]** button also notice the +//! **[src]** button. Rust's API documentation comes with the source +//! code and you are encouraged to read it. The standard library +//! source is generally high quality and a peek behind the curtains is +//! often enlightening. +//! +//! # What is in the standard library documentation? //! -//! ## What is in the standard library +//! Lots of stuff. Well, broadly four things actually. //! -//! The standard library is a set of minimal, battle-tested -//! core types and shared abstractions for the [broader Rust -//! ecosystem](https://crates.io) to build on. +//! First of all, The Rust Standard Library is divided into a number +//! of focused modules, [all listed further down this page](#modules). +//! These modules are the bedrock upon which all of Rust is forged, +//! and they have mighty names like [`std::slice`](slice/index.html) +//! and [`std::cmp`](cmp/index.html). Modules' documentation typically +//! includes an overview of the module along with examples, and are +//! a smart place to start familiarizing yourself with the library. //! -//! The [primitive types](#primitives), though not defined in the -//! standard library, are documented here, as are the predefined -//! [macros](#macros). +//! Secondly, implicit methods on [primitive +//! types](../book/primitive-types.html) are documented here. This can +//! be a source of confusion for two reasons: +//! +//! 1. While primitives are implemented by the compiler, the standard +//! library implements methods directly on the primitive types (and +//! it is the only library that does so), which are [documented in +//! the section on primitives](#primitives). +//! 2. The standard library exports many modules *with the same name +//! as primitive types*. These define additional items related +//! to the primitive type, but not the all-important methods. +//! +//! So for example there is a [page for the primitive type +//! `i32`](primitive.i32.html) that lists all the methods that can be +//! called on 32-bit integers (mega useful), and there is a [page for +//! the module `std::i32`](i32/index.html) that documents the constant +//! values `MIN` and `MAX` (rarely useful). +//! +//! Note the documentation for the primitives +//! [`str`](primitive.str.html) and [`[T]`](primitive.slice.html) +//! (also called 'slice'). Many method calls on +//! [`String`](string/struct.String.html) and +//! [`Vec`](vec/struct.Vec.html) are actually calls to methods on +//! `str` and `[T]` respectively, via [deref +//! coercions](../book/deref-coercions.html). *Accepting that +//! primitive types are documented on their own pages will bring you a +//! deep inner wisdom. Embrace it now before proceeding.* +//! +//! Thirdly, the standard library defines [The Rust +//! Prelude](prelude/index.html), a small collection of items - mostly +//! traits - that are imported into every module. The traits in the +//! prelude are pervasive, making the prelude documentation a good +//! entry point to learning about the library. +//! +//! And lastly, the standard library exports a number of standard +//! macros, and [lists them on this page](#macros) (technically, not +//! all of the standard macros are defined by the standard library - +//! some are defined by the compiler - but they are documented here +//! the same). Like the prelude, the standard macros are imported by +//! default into all crates. +//! +//! # A Tour of The Rust Standard Library +//! +//! The rest of this crate documentation is dedicated to pointing +//! out notable features of The Rust Standard Library. //! //! ## Containers and collections //! @@ -43,17 +136,18 @@ //! [`Iterator`](iter/trait.Iterator.html), which works with the `for` //! loop to access collections. //! -//! The common container type, `Vec`, a growable vector backed by an array, -//! lives in the [`vec`](vec/index.html) module. Contiguous, unsized regions -//! of memory, `[T]`, commonly called "slices", and their borrowed versions, -//! `&[T]`, commonly called "borrowed slices", are built-in types for which the -//! [`slice`](slice/index.html) module defines many methods. +//! The common container type, `Vec`, a growable vector backed by an +//! array, lives in the [`vec`](vec/index.html) module. Contiguous, +//! unsized regions of memory, `[T]`, commonly called "slices", and +//! their borrowed versions, `&[T]`, commonly called "borrowed +//! slices", are primitive types [with many implicit +//! methods](primitive.slice.html) defined by the standard library. //! -//! `&str`, a UTF-8 string, is a built-in type, and the standard library -//! defines methods for it on a variety of traits in the -//! [`str`](str/index.html) module. Rust strings are immutable; -//! use the `String` type defined in [`string`](string/index.html) -//! for a mutable string builder. +//! `str`, a UTF-8 string, is a primitive type, and the standard +//! library defines [many methods for it](primitive.str.html). +//! Rust `str`s are immutable; use the owned `String` type +//! defined in [`string`](string/index.html) for building and mutating +//! strings. //! //! For converting to strings use the [`format!`](fmt/index.html) //! macro, and for converting from strings use the @@ -88,6 +182,7 @@ //! [`atomic`](sync/atomic/index.html) and //! [`mpsc`](sync/mpsc/index.html), which contains the channel types //! for message passing. +//! // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364) #![cfg_attr(stage0, feature(custom_attribute))] diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index 156a3d428debd..bb1041a76c81c 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -22,18 +22,107 @@ //! with the `std::` path prefix, as in `use std::vec`, `use std::thread::spawn`, //! etc. //! -//! Additionally, `std` contains a `prelude` module that reexports many of the -//! most common traits, types and functions. The contents of the prelude are -//! imported into every *module* by default. Implicitly, all modules behave as if -//! they contained the following prologue: +//! Additionally, `std` contains a versioned *prelude* that reexports many of the +//! most common traits, types and functions. *The contents of the prelude are +//! imported into every module by default*. Implicitly, all modules behave as if +//! they contained the following [`use` statement][book-use]: +//! +//! [book-use]: ../../book/crates-and-modules.html#importing-modules-with-use //! //! ```ignore //! use std::prelude::v1::*; //! ``` //! -//! The prelude is primarily concerned with exporting *traits* that are so -//! pervasive that it would be obnoxious to import for every use, particularly -//! those that define methods on primitive types. +//! The prelude is primarily concerned with exporting *traits* that +//! are so pervasive that it would be onerous to import for every use, +//! particularly those that are commonly mentioned in [generic type +//! bounds][book-traits], and that are often used +//! +//! The current version of the prelude (version 1) lives in +//! [`std::prelude::v1`](v1/index.html), and reexports the following. +//! +//! * `std::marker::`{ +//! [`Copy`](../marker/trait.Copy.html), +//! [`Send`](../marker/trait.Send.html), +//! [`Sized`](../marker/trait.Sized.html), +//! [`Sync`](../marker/trait.Sync.html) +//! }. +//! The marker traits indicate fundamental properties of types. +//! * `std::ops::`{ +//! [`Drop`](../ops/trait.Drop.html), +//! [`Fn`](../ops/trait.Fn.html), +//! [`FnMut`](../ops/trait.FnMut.html), +//! [`FnOnce`](../ops/trait.FnOnce.html) +//! }. +//! The [destructor][book-dtor] trait and the +//! [closure][book-closures] traits, reexported from the same +//! [module that also defines overloaded +//! operators](../ops/index.html). +//! * `std::mem::`[`drop`](../mem/fn.drop.html). +//! A convenience function for explicitly dropping a value. +//! * `std::boxed::`[`Box`](../boxed/struct.Box.html). +//! The owned heap pointer. +//! * `std::borrow::`[`ToOwned`](../borrow/trait.ToOwned.html). +//! The conversion trait that defines `to_owned`, the generic method +//! for creating an owned type from a borrowed type. +//! * `std::clone::`[`Clone`](../clone/trait.Clone.html). +//! The ubiquitous trait that defines `clone`, the method for +//! producing copies of values that are consider expensive to copy. +//! * `std::cmp::`{ +//! [`PartialEq`](../cmp/trait.PartialEq.html), +//! [`PartialOrd`](../cmp/trait.PartialOrd.html), +//! [`Eq`](../cmp/trait.Eq.html), +//! [`Ord`](../cmp/trait.Ord.html) +//! }. +//! The comparision traits, which implement the comparison operators +//! and are often seen in trait bounds. +//! * `std::convert::`{ +//! [`AsRef`](../convert/trait.AsRef.html), +//! [`AsMut`](../convert/trait.AsMut.html), +//! [`Into`](../convert/trait.Into.html), +//! [`From`](../convert/trait.From.html) +//! }. +//! Generic conversions, used by savvy API authors to create +//! overloaded methods. +//! * `std::default::`[`Default`](../default/trait.Default). +//! Types that have default values. +//! * `std::iter::`{ +//! [`Iterator`](../iter/trait.Iterator.html), +//! [`Extend`](../iter/trait.Extend.html), +//! [`IntoIterator`](../iter/trait.IntoIterator.html), +//! [`DoubleEndedIterator`](../iter/trait.DoubleEndedIterator.html), +//! [`ExactSizeIterator`](../iter/trait.ExactSizeIterator.html) +//! }. +//! [Iterators][book-iter]. +//! * `std::option::Option::`{ +//! [`self`](../option/enum.Option.html), +//! [`Some`](../option/enum.Option.html), +//! [`None`](../option/enum.Option.html) +//! }. +//! The ubiquitous `Option` type and its two [variants][book-enums], +//! `Some` and `None`. +//! * `std::result::Result::`{ +//! [`self`](../result/enum.Result.html), +//! [`Some`](../result/enum.Result.html), +//! [`None`](../result/enum.Result.html) +//! }. +//! The ubiquitous `Result` type and its two [variants][book-enums], +//! `Ok` and `Err`. +//! * `std::slice::`[`SliceConcatExt`](../slice/trait.SliceConcatExt.html). +//! An unstable extension to slices that shouldn't have to exist. +//! * `std::string::`{ +//! [`String`](../string/struct.String.html), +//! [`ToString`](../string/trait.ToString.html) +//! }. +//! Heap allocated strings. +//! * `std::vec::`[`Vec`](../vec/struct.Vec.html). +//! Heap allocated vectors. +//! +//! [book-traits]: ../../book/traits.html +//! [book-closures]: ../../book/closures.html +//! [book-dtor]: ../../book/drop.html +//! [book-iter]: ../../book/iterators.html +//! [book-enums]: ../../book/enums.html #![stable(feature = "rust1", since = "1.0.0")] From 4089ba873e7e64540764b8aa7438d02b36206d51 Mon Sep 17 00:00:00 2001 From: Brian Anderson <banderson@mozilla.com> Date: Sat, 11 Jul 2015 15:30:43 -0700 Subject: [PATCH 23/47] Fix local path --- src/libstd/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index e6049ab286356..00d59fc4cd849 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -29,7 +29,7 @@ //! through the absolute path `::std`, as in //! [`::std::env::args()`](env/fn.args.html). //! -//! [book-crate-root]: file:///home/brian/dev/rust2/build/doc/book/crates-and-modules.html#basic-terminology:-crates-and-modules +//! [book-crate-root]: ../book/crates-and-modules.html#basic-terminology:-crates-and-modules //! [book-use]: ../book/crates-and-modules.html#importing-modules-with-use //! //! Furthermore, the standard library defines [The Rust From 3a180d15f81d3f9dfcb965c7c89d02b64a90f62e Mon Sep 17 00:00:00 2001 From: Brian Anderson <banderson@mozilla.com> Date: Mon, 13 Jul 2015 17:56:31 -0700 Subject: [PATCH 24/47] Address feedback --- src/librustdoc/html/static/main.js | 5 +++ src/libstd/lib.rs | 66 ++++++++++++++++-------------- src/libstd/prelude/mod.rs | 4 +- 3 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index c77cdd4d02183..f77e639f83319 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -951,3 +951,8 @@ }()); }()); + +// Sets the focus on the search bar at the top of the page +function focusSearchBar() { + document.getElementsByName('search')[0].focus(); +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 00d59fc4cd849..004bdf8666188 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -14,7 +14,7 @@ //! software, a set of minimal and battle-tested shared abstractions //! for the [broader Rust ecosystem](https://crates.io). It offers //! core types (e.g. [`Vec`](vec/index.html) -//! and[`Option`](option/index.html)), library-defined [operations on +//! and [`Option`](option/index.html)), library-defined [operations on //! language primitives](#primitive) (e.g. [`u32`](u32/index.html) and //! [`str`](str/index.html)), [standard macros](#macros), //! [I/O](io/index.html) and [multithreading](thread/index.html), among @@ -32,17 +32,11 @@ //! [book-crate-root]: ../book/crates-and-modules.html#basic-terminology:-crates-and-modules //! [book-use]: ../book/crates-and-modules.html#importing-modules-with-use //! -//! Furthermore, the standard library defines [The Rust -//! Prelude](prelude/index.html), a small collection of items, mostly -//! traits, that are imported into every module and through trait -//! resolution provide Rust with much of its *standard flavor*. -//! //! # How to read this documentation //! //! If you already know the name of what you are looking for the //! fastest way to find it is to use the <a href="#" -//! onclick="document.getElementsByName('search')[0].focus();">search -//! bar</a> at the top of the page. +//! onclick="focusSearchBar();">search bar</a> at the top of the page. //! //! Otherwise, you may want to jump to one of these useful sections: //! @@ -52,10 +46,10 @@ //! * [The Rust Prelude](prelude/index.html) //! //! If this is your first time, the documentation for the standard -//! library is written to be casually perused and clicking on -//! interesting things should generally lead you to interesting -//! places. Still, there are important bits you don't want to miss, so -//! read on for a tour of the standard library and its documentation. +//! library is written to be casually perused. Clicking on interesting +//! things should generally lead you to interesting places. Still, +//! there are important bits you don't want to miss, so read on for a +//! tour of the standard library and its documentation! //! //! Once you are familiar with the contents of the standard library //! you may begin to find the verbosity of the prose distracting. At @@ -81,7 +75,7 @@ //! includes an overview of the module along with examples, and are //! a smart place to start familiarizing yourself with the library. //! -//! Secondly, implicit methods on [primitive +//! Second, implicit methods on [primitive //! types](../book/primitive-types.html) are documented here. This can //! be a source of confusion for two reasons: //! @@ -109,17 +103,17 @@ //! primitive types are documented on their own pages will bring you a //! deep inner wisdom. Embrace it now before proceeding.* //! -//! Thirdly, the standard library defines [The Rust +//! Third, the standard library defines [The Rust //! Prelude](prelude/index.html), a small collection of items - mostly -//! traits - that are imported into every module. The traits in the -//! prelude are pervasive, making the prelude documentation a good -//! entry point to learning about the library. +//! traits - that are imported into every module of every crate. The +//! traits in the prelude are pervasive, making the prelude +//! documentation a good entry point to learning about the library. //! -//! And lastly, the standard library exports a number of standard +//! And finally, the standard library exports a number of standard //! macros, and [lists them on this page](#macros) (technically, not //! all of the standard macros are defined by the standard library - //! some are defined by the compiler - but they are documented here -//! the same). Like the prelude, the standard macros are imported by +//! the same). Like the prelude, the standard macros are imported by //! default into all crates. //! //! # A Tour of The Rust Standard Library @@ -136,18 +130,28 @@ //! [`Iterator`](iter/trait.Iterator.html), which works with the `for` //! loop to access collections. //! -//! The common container type, `Vec`, a growable vector backed by an -//! array, lives in the [`vec`](vec/index.html) module. Contiguous, -//! unsized regions of memory, `[T]`, commonly called "slices", and -//! their borrowed versions, `&[T]`, commonly called "borrowed -//! slices", are primitive types [with many implicit -//! methods](primitive.slice.html) defined by the standard library. -//! -//! `str`, a UTF-8 string, is a primitive type, and the standard -//! library defines [many methods for it](primitive.str.html). -//! Rust `str`s are immutable; use the owned `String` type -//! defined in [`string`](string/index.html) for building and mutating -//! strings. +//! The standard library exposes 3 common ways to deal with contiguous +//! regions of memory: +//! +//! * [`Vec<T>`](vec/index.html) - A heap-allocated *vector* that is +//! resizable at runtime. +//! * [`[T; n]`](primitive.array.html) - An inline *array* with a +//! fixed size at compile time. +//! * [`[T]`](primitive.slice.html) - A dynamically sized *slice* into +//! any other kind of contiguous storage, whether heap-allocated or +//! not. +//! +//! Slices can only be handled through some kind of *pointer*, and as +//! such come in many flavours such as: +//! +//! * `&[T]` - *shared slice* +//! * `&mut [T]` - *mutable slice* +//! * [`Box<[T]>`](boxed/index.html) - *owned slice* +//! +//! `str`, a UTF-8 string slice, is a primitive type, and the standard +//! library defines [many methods for it](primitive.str.html). Rust +//! `str`s are immutable; use the owned `String` type defined in +//! [`string`](string/index.html) for building and mutating strings. //! //! For converting to strings use the [`format!`](fmt/index.html) //! macro, and for converting from strings use the diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index bb1041a76c81c..275f415c6fc80 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -34,9 +34,9 @@ //! ``` //! //! The prelude is primarily concerned with exporting *traits* that -//! are so pervasive that it would be onerous to import for every use, +//! are so pervasive that they would be onerous to import for every use, //! particularly those that are commonly mentioned in [generic type -//! bounds][book-traits], and that are often used +//! bounds][book-traits]. //! //! The current version of the prelude (version 1) lives in //! [`std::prelude::v1`](v1/index.html), and reexports the following. From e6e636845472cb843d978ae865317fae08e50a74 Mon Sep 17 00:00:00 2001 From: Nick Cameron <ncameron@mozilla.com> Date: Tue, 14 Jul 2015 13:40:02 +1200 Subject: [PATCH 25/47] save-analysis: make generated_code pub --- src/librustc_trans/save/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 4e0b34b7ef8ac..59da0c09d3408 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -753,6 +753,6 @@ fn escape(s: String) -> String { // If the expression is a macro expansion or other generated code, run screaming // and don't index. -fn generated_code(span: Span) -> bool { +pub fn generated_code(span: Span) -> bool { span.expn_id != NO_EXPANSION || span == DUMMY_SP } From 41b056823cbfb34ea1cc7daed4a0cdd739620d30 Mon Sep 17 00:00:00 2001 From: Nick Cameron <ncameron@mozilla.com> Date: Tue, 14 Jul 2015 14:21:54 +1200 Subject: [PATCH 26/47] save-analysis: tweak constructors --- src/librustc_trans/save/dump_csv.rs | 8 ++------ src/librustc_trans/save/mod.rs | 11 ++++++++--- src/librustc_trans/save/span_utils.rs | 7 +++++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index c5196d09e00a1..680999717eae5 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -35,7 +35,6 @@ use session::Session; use middle::def; use middle::ty::{self, Ty}; -use std::cell::Cell; use std::fs::File; use std::path::Path; @@ -76,14 +75,11 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { pub fn new(tcx: &'l ty::ctxt<'tcx>, analysis: &'l ty::CrateAnalysis, output_file: Box<File>) -> DumpCsvVisitor<'l, 'tcx> { - let span_utils = SpanUtils { - sess: &tcx.sess, - err_count: Cell::new(0) - }; + let span_utils = SpanUtils::new(&tcx.sess); DumpCsvVisitor { sess: &tcx.sess, tcx: tcx, - save_ctxt: SaveContext::new(tcx, span_utils.clone()), + save_ctxt: SaveContext::from_span_utils(tcx, span_utils.clone()), analysis: analysis, span: span_utils.clone(), fmt: FmtStrs::new(box Recorder { diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 59da0c09d3408..89668928060d9 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -163,9 +163,14 @@ pub struct MethodCallData { impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { - pub fn new(tcx: &'l ty::ctxt<'tcx>, - span_utils: SpanUtils<'l>) - -> SaveContext<'l, 'tcx> { + pub fn new(tcx: &'l ty::ctxt<'tcx>) -> SaveContext <'l, 'tcx> { + let span_utils = SpanUtils::new(&tcx.sess); + SaveContext::from_span_utils(tcx, span_utils) + } + + pub fn from_span_utils(tcx: &'l ty::ctxt<'tcx>, + span_utils: SpanUtils<'l>) + -> SaveContext<'l, 'tcx> { SaveContext { tcx: tcx, span_utils: span_utils, diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs index 08cbd777c095c..ee7b1c4ff6e29 100644 --- a/src/librustc_trans/save/span_utils.rs +++ b/src/librustc_trans/save/span_utils.rs @@ -28,6 +28,13 @@ pub struct SpanUtils<'a> { } impl<'a> SpanUtils<'a> { + pub fn new(sess: &'a Session) -> SpanUtils<'a> { + SpanUtils { + sess: sess, + err_count: Cell::new(0) + } + } + // Standard string for extents/location. pub fn extent_str(&self, span: Span) -> String { let lo_loc = self.sess.codemap().lookup_char_pos(span.lo); From 94f13ac376f44711106f08175241ed909578de06 Mon Sep 17 00:00:00 2001 From: Nick Cameron <ncameron@mozilla.com> Date: Tue, 14 Jul 2015 20:56:25 +1200 Subject: [PATCH 27/47] save-analysis: handle a few more kinds of paths --- src/librustc_trans/save/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 89668928060d9..4c5daccba85b4 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -532,7 +532,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ref_id: def.def_id(), }) } - def::DefStruct(def_id) | def::DefTy(def_id, _) => { + def::DefStruct(def_id) | + def::DefTy(def_id, _) | + def::DefTrait(def_id) | + def::DefTyParam(_, _, def_id, _) => { Data::TypeRefData(TypeRefData { span: sub_span.unwrap(), ref_id: def_id, From 49d3a93c52e65b5b37370390dd352471c21dbaf7 Mon Sep 17 00:00:00 2001 From: Nick Cameron <ncameron@mozilla.com> Date: Tue, 14 Jul 2015 22:03:14 +1200 Subject: [PATCH 28/47] save-analysis: fix def_ids for method calls We were sometime emitting the decl as a def. --- src/librustc/ast_map/mod.rs | 7 +++++++ src/librustc_trans/save/mod.rs | 27 ++++++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/librustc/ast_map/mod.rs b/src/librustc/ast_map/mod.rs index 3205141e604c2..5c10cc6aaa8db 100644 --- a/src/librustc/ast_map/mod.rs +++ b/src/librustc/ast_map/mod.rs @@ -411,6 +411,13 @@ impl<'ast> Map<'ast> { } } + pub fn expect_trait_item(&self, id: NodeId) -> &'ast TraitItem { + match self.find(id) { + Some(NodeTraitItem(item)) => item, + _ => panic!("expected trait item, found {}", self.node_to_string(id)) + } + } + pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef { match self.find(id) { Some(NodeItem(i)) => { diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 4c5daccba85b4..26da803de6557 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -548,13 +548,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let ti = self.tcx.impl_or_trait_item(decl_id); match provenence { def::FromTrait(def_id) => { - Some(self.tcx.trait_items(def_id) - .iter() - .find(|mr| { - mr.name() == ti.name() - }) - .unwrap() - .def_id()) + self.tcx.trait_items(def_id) + .iter() + .find(|mr| { + mr.name() == ti.name() && self.trait_method_has_body(mr) + }) + .map(|mr| mr.def_id()) } def::FromImpl(def_id) => { let impl_items = self.tcx.impl_items.borrow(); @@ -594,6 +593,20 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } + fn trait_method_has_body(&self, mr: &ty::ImplOrTraitItem) -> bool { + let def_id = mr.def_id(); + if def_id.krate != ast::LOCAL_CRATE { + return false; + } + + let trait_item = self.tcx.map.expect_trait_item(def_id.node); + if let ast::TraitItem_::MethodTraitItem(_, Some(_)) = trait_item.node { + true + } else { + false + } + } + pub fn get_field_ref_data(&self, field_ref: &ast::Field, struct_id: DefId, From c5f7c19cf274f510b48d6835f5677ae22e978d6d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Tue, 14 Jul 2015 15:37:52 +0200 Subject: [PATCH 29/47] End of error code spanning centralization --- src/librustc_resolve/build_reduced_graph.rs | 36 +- src/librustc_resolve/lib.rs | 572 ++++++++++++++------ src/librustc_resolve/resolve_imports.rs | 11 +- 3 files changed, 430 insertions(+), 189 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 00745136eef22..782e0a3660b33 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -208,10 +208,13 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // Return an error here by looking up the namespace that // had the duplicate. let ns = ns.unwrap(); - resolve_err!(self, sp, E0428, - "duplicate definition of {} `{}`", - namespace_error_to_string(duplicate_type), - token::get_name(name)); + ::resolve_error( + &::ResolutionError::DuplicateDefinition( + self, + sp, + namespace_error_to_string(duplicate_type), + &*token::get_name(name)) + ); { let r = child.span_for_namespace(ns); if let Some(sp) = r { @@ -304,9 +307,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { full_path.segments.last().unwrap().identifier.name; if &token::get_name(source_name)[..] == "mod" || &token::get_name(source_name)[..] == "self" { - resolve_err!(self, view_path.span, E0429, - "{}", - "`self` imports are only allowed within a { } list"); + ::resolve_error(&::ResolutionError::SelfImportsOnlyAllowedWithin( + self, + view_path.span) + ); } let subclass = SingleImport(binding.name, @@ -326,9 +330,11 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { _ => None }).collect::<Vec<Span>>(); if mod_spans.len() > 1 { - resolve_err!(self, mod_spans[0], E0430, - "{}", - "`self` import can only appear once in the list"); + ::resolve_error( + &::ResolutionError::SelfImportCanOnlyAppearOnceInTheList( + self, + mod_spans[0]) + ); for other_span in mod_spans.iter().skip(1) { self.session.span_note(*other_span, "another `self` import appears here"); @@ -343,10 +349,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let name = match module_path.last() { Some(name) => *name, None => { - resolve_err!(self, source_item.span, E0431, - "{}", - "`self` import can only appear in an import list \ - with a non-empty prefix"); + ::resolve_error( + &::ResolutionError:: + SelfImportOnlyInImportListWithNonEmptyPrefix( + self, + source_item.span) + ); continue; } }; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 1fa8e63f57e17..850a5d1db2682 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -117,34 +117,266 @@ mod build_reduced_graph; mod resolve_imports; pub enum ResolutionError<'b, 'a:'b, 'tcx:'a> { - /// error: static variables cannot be referenced in a pattern + /// error E0401: can't use type parameters from outer function + TypeParametersFromOuterFunction(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0402: cannot use an outer type parameter in this context + OuterTypeParameterContext(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0403: the name is already used for a type parameter in this type parameter list + NameAlreadyUsedInTypeParameterList(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, + syntax::ast::Name), + /// error E0404: is not a trait + IsNotATrait(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0405: use of undeclared trait name + UndeclaredTraitName(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0406: undeclared associated type + UndeclaredAssociatedType(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0407: method is not a member of trait + MethodNotMemberOfTrait(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, syntax::ast::Name, + &'b str), + /// error E0408: variable `{}` from pattern #1 is not bound in pattern + VariableNotBoundInPattern(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, syntax::ast::Name, + usize), + /// error E0409: variable is bound with different mode in pattern #{} than in pattern #1 + VariableBoundWithDifferentMode(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, + syntax::ast::Name, usize), + /// error E0410: variable from pattern is not bound in pattern #1 + VariableNotBoundInParentPattern(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, + syntax::ast::Name, usize), + /// error E0411: use of `Self` outside of an impl or trait + SelfUsedOutsideImplOrTrait(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0412: use of undeclared + UseOfUndeclared(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str, &'b str), + /// error E0413: declaration shadows an enum variant or unit-like struct in scope + DeclarationShadowsEnumVariantOrUnitLikeStruct(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, + syntax::ast::Name), + /// error E0414: only irrefutable patterns allowed here + OnlyIrrefutablePatternsAllowedHere(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0415: identifier is bound more than once in this parameter list + IdentifierBoundMoreThanOnceInParameterList(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, + &'b str), + /// error E0416: identifier is bound more than once in the same pattern + IdentifierBoundMoreThanOnceInSamePattern(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, + &'b str), + /// error E0417: static variables cannot be referenced in a pattern StaticVariableReference(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), - /// error: does not name a struct - DoesNotNameAStruct(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), - /// error: is a struct variant name, but this expression uses it like a function name - StructVariantUsedAsFunction(&'a Resolver<'a, 'tcx>, syntax::codemap::Span), - /// error: unresolved import - UnresolvedImport(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), - /// error: failed to resolve - FailedToResolve(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0418: is not an enum variant, struct or const + NotAnEnumVariantStructOrConst(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0419: unresolved enum variant, struct or const + UnresolvedEnumVariantStructOrConst(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0420: is not an associated const + NotAnAssociatedConst(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0421: unresolved associated const + UnresolvedAssociatedConst(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0422: does not name a struct + DoesNotNameAStruct(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0423: is a struct variant name, but this expression uses it like a function name + StructVariantUsedAsFunction(&'a Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0424: `self` is not available in a static method + SelfNotAvailableInStaticMethod(&'a Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0425: unresolved name + UnresolvedName(&'a Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str, &'b str), + /// error E0426: use of undeclared label + UndeclaredLabel(&'a Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0427: cannot use `ref` binding mode with ... + CannotUseRefBindingModeWith(&'a Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0428: duplicate definition + DuplicateDefinition(&'a Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str, &'b str), + /// error E0429: `self` imports are only allowed within a { } list + SelfImportsOnlyAllowedWithin(&'a Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0430: `self` import can only appear once in the list + SelfImportCanOnlyAppearOnceInTheList(&'a Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0431: `self` import can only appear in an import list with a non-empty prefix + SelfImportOnlyInImportListWithNonEmptyPrefix(&'a Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0432: unresolved import + UnresolvedImport(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, + Option<(&'b str, Option<&'b str>)>), + /// error E0433: failed to resolve + FailedToResolve(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + /// error E0434: can't capture dynamic environment in a fn item + CannotCaptureDynamicEnvironmentInFnItem(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + /// error E0435: attempt to use a non-constant value in a constant + AttemptToUseNonConstantValueInConstant(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), } -fn resolve_error<'b, 'a:'b, 'tcx:'a>(resolution_error: &ResolutionError<'b, 'a, 'tcx>, formatted: &str) { +fn resolve_error<'b, 'a:'b, 'tcx:'a>(resolution_error: &ResolutionError<'b, 'a, 'tcx>) { match resolution_error { + &ResolutionError::TypeParametersFromOuterFunction(resolver, span) => { + resolve_err!(resolver, span, E0401, "can't use type parameters from \ + outer function; try using a local \ + type parameter instead"); + }, + &ResolutionError::OuterTypeParameterContext(resolver, span) => { + resolve_err!(resolver, span, E0402, + "cannot use an outer type parameter in this context"); + }, + &ResolutionError::NameAlreadyUsedInTypeParameterList(resolver, span, name) => { + resolve_err!(resolver, span, E0403, + "the name `{}` is already used for a type \ + parameter in this type parameter list", name); + }, + &ResolutionError::IsNotATrait(resolver, span, name) => { + resolve_err!(resolver, span, E0404, + "`{}` is not a trait", + name); + }, + &ResolutionError::UndeclaredTraitName(resolver, span, name) => { + resolve_err!(resolver, span, E0405, + "use of undeclared trait name `{}`", + name); + }, + &ResolutionError::UndeclaredAssociatedType(resolver, span) => { + resolve_err!(resolver, span, E0406, "undeclared associated type"); + }, + &ResolutionError::MethodNotMemberOfTrait(resolver, span, method, trait_) => { + resolve_err!(resolver, span, E0407, + "method `{}` is not a member of trait `{}`", + method, + trait_); + }, + &ResolutionError::VariableNotBoundInPattern(resolver, span, variable_name, + pattern_number) => { + resolve_err!(resolver, span, E0408, + "variable `{}` from pattern #1 is not bound in pattern #{}", + variable_name, + pattern_number); + }, + &ResolutionError::VariableBoundWithDifferentMode(resolver, span, variable_name, + pattern_number) => { + resolve_err!(resolver, span, E0409, + "variable `{}` is bound with different \ + mode in pattern #{} than in pattern #1", + variable_name, + pattern_number); + }, + &ResolutionError::VariableNotBoundInParentPattern(resolver, span, variable_name, + pattern_number) => { + resolve_err!(resolver, span, E0410, + "variable `{}` from pattern #{} is not bound in pattern #1", + variable_name, + pattern_number); + }, + &ResolutionError::SelfUsedOutsideImplOrTrait(resolver, span) => { + resolve_err!(resolver, span, E0411, "use of `Self` outside of an impl or trait"); + }, + &ResolutionError::UseOfUndeclared(resolver, span, kind, name) => { + resolve_err!(resolver, span, E0412, + "use of undeclared {} `{}`", + kind, + name); + }, + &ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(resolver, span, name) => { + resolve_err!(resolver, span, E0413, + "declaration of `{}` shadows an enum variant or unit-like struct in \ + scope", + name); + }, + &ResolutionError::OnlyIrrefutablePatternsAllowedHere(resolver, span) => { + resolve_err!(resolver, span, E0414, "only irrefutable patterns allowed here"); + }, + &ResolutionError::IdentifierBoundMoreThanOnceInParameterList(resolver, span, + identifier) => { + resolve_err!(resolver, span, E0415, + "identifier `{}` is bound more than once in this parameter list", + identifier); + }, + &ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(resolver, span, identifier) => { + resolve_err!(resolver, span, E0416, + "identifier `{}` is bound more than once in the same pattern", + identifier); + }, &ResolutionError::StaticVariableReference(resolver, span) => { - resolve_err!(resolver, span, E0417, "{}", formatted); + resolve_err!(resolver, span, E0417, "static variables cannot be \ + referenced in a pattern, \ + use a `const` instead"); + }, + &ResolutionError::NotAnEnumVariantStructOrConst(resolver, span, name) => { + resolve_err!(resolver, span, E0418, + "`{}` is not an enum variant, struct or const", + name); + }, + &ResolutionError::UnresolvedEnumVariantStructOrConst(resolver, span, name) => { + resolve_err!(resolver, span, E0419, + "unresolved enum variant, struct or const `{}`", + name); + }, + &ResolutionError::NotAnAssociatedConst(resolver, span, name) => { + resolve_err!(resolver, span, E0420, + "`{}` is not an associated const", + name); }, - &ResolutionError::DoesNotNameAStruct(resolver, span) => { - resolve_err!(resolver, span, E0422, "{}", formatted); + &ResolutionError::UnresolvedAssociatedConst(resolver, span, name) => { + resolve_err!(resolver, span, E0421, + "unresolved associated const `{}`", + name); }, - &ResolutionError::StructVariantUsedAsFunction(resolver, span) => { - resolve_err!(resolver, span, E0423, "{}", formatted); + &ResolutionError::DoesNotNameAStruct(resolver, span, name) => { + resolve_err!(resolver, span, E0422, "`{}` does not name a structure", name); }, - &ResolutionError::UnresolvedImport(resolver, span) => { - resolve_err!(resolver, span, E0432, "{}", formatted); + &ResolutionError::StructVariantUsedAsFunction(resolver, span, path_name) => { + resolve_err!(resolver, span, E0423, + "`{}` is a struct variant name, but \ + this expression \ + uses it like a function name", + path_name); }, - &ResolutionError::FailedToResolve(resolver, span) => { - resolve_err!(resolver, span, E0433, "{}", formatted); + &ResolutionError::SelfNotAvailableInStaticMethod(resolver, span) => { + resolve_err!(resolver, span, E0424, "`self` is not available in a static method. \ + Maybe a `self` argument is missing?"); + }, + &ResolutionError::UnresolvedName(resolver, span, path, name) => { + resolve_err!(resolver, span, E0425, + "unresolved name `{}`{}", + path, + name); + }, + &ResolutionError::UndeclaredLabel(resolver, span, name) => { + resolve_err!(resolver, span, E0426, + "use of undeclared label `{}`", + name); + }, + &ResolutionError::CannotUseRefBindingModeWith(resolver, span, descr) => { + resolve_err!(resolver, span, E0427, + "cannot use `ref` binding mode with {}", + descr); + }, + &ResolutionError::DuplicateDefinition(resolver, span, namespace, name) => { + resolve_err!(resolver, span, E0428, + "duplicate definition of {} `{}`", + namespace, + name); + }, + &ResolutionError::SelfImportsOnlyAllowedWithin(resolver, span) => { + resolve_err!(resolver, span, E0429, "{}", + "`self` imports are only allowed within a { } list"); + }, + &ResolutionError::SelfImportCanOnlyAppearOnceInTheList(resolver, span) => { + resolve_err!(resolver, span, E0430, + "`self` import can only appear once in the list"); + }, + &ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix(resolver, span) => { + resolve_err!(resolver, span, E0431, + "`self` import can only appear in an import list with a \ + non-empty prefix"); + } + &ResolutionError::UnresolvedImport(resolver, span, name) => { + let msg = match name { + Some((n, Some(p))) => format!("unresolved import `{}`{}", n, p), + Some((n, None)) => format!("unresolved import (maybe you meant `{}::*`?)", n), + None => "unresolved import".to_owned() + }; + resolve_err!(resolver, span, E0432, "{}", msg); + }, + &ResolutionError::FailedToResolve(resolver, span, msg) => { + resolve_err!(resolver, span, E0433, "failed to resolve. {}", msg); + }, + &ResolutionError::CannotCaptureDynamicEnvironmentInFnItem(resolver, span) => { + resolve_err!(resolver, span, E0434, "{}", + "can't capture dynamic environment in a fn item; \ + use the || { ... } closure form instead"); + }, + &ResolutionError::AttemptToUseNonConstantValueInConstant(resolver, span) =>{ + resolve_err!(resolver, span, E0435, + "attempt to use a non-constant value in a constant"); }, } } @@ -1343,10 +1575,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathSearch, true) { Failed(Some((span, msg))) => { - resolve_error(&ResolutionError::FailedToResolve(self, span), - &*format!("failed to resolve. {}", - msg) - ); + resolve_error(&ResolutionError::FailedToResolve(self, span, &*msg)); }, Failed(None) => (), // Continue up the search chain. Indeterminate => { @@ -1604,13 +1833,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .span_to_snippet((*imports)[index].span) .unwrap(); if sn.contains("::") { - resolve_error(&ResolutionError::UnresolvedImport(self, (*imports)[index].span), - "unresolved import"); + resolve_error(&ResolutionError::UnresolvedImport(self, + (*imports)[index].span, + None)); } else { - resolve_error(&ResolutionError::UnresolvedImport(self, (*imports)[index].span), - &*format!("unresolved import (maybe you meant `{}::*`?)", - sn) - ); + resolve_error(&ResolutionError::UnresolvedImport(self, + (*imports)[index].span, + Some((&*sn, None)))); } } @@ -1736,16 +1965,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. - resolve_err!(self, span, E0434, "{}", - "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); + resolve_error( + &ResolutionError::CannotCaptureDynamicEnvironmentInFnItem( + self, + span) + ); return None; } ConstantItemRibKind => { // Still doesn't deal with upvars - resolve_err!(self, span, E0435, "{}", - "attempt to use a non-constant \ - value in a constant"); + resolve_error( + &ResolutionError::AttemptToUseNonConstantValueInConstant( + self, + span) + ); return None; } } @@ -1761,17 +1994,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This was an attempt to use a type parameter outside // its scope. - resolve_err!(self, span, E0401, "{}", - "can't use type parameters from \ - outer function; try using a local \ - type parameter instead"); + resolve_error(&ResolutionError::TypeParametersFromOuterFunction(self, + span)); return None; } ConstantItemRibKind => { // see #9186 - resolve_err!(self, span, E0402, "{}", - "cannot use an outer type \ - parameter in this context"); + resolve_error(&ResolutionError::OuterTypeParameterContext(self, span)); return None; } } @@ -1969,12 +2198,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("with_type_parameter_rib: {}", type_parameter.id); if seen_bindings.contains(&name) { - resolve_err!(self, type_parameter.span, E0403, - "the name `{}` is already \ - used for a type \ - parameter in this type \ - parameter list", - name) + resolve_error(&ResolutionError::NameAlreadyUsedInTypeParameterList( + self, + type_parameter.span, + name)); } seen_bindings.insert(name); @@ -2061,9 +2288,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving trait) found trait def: {:?}", path_res); Ok(path_res) } else { - resolve_err!(self, trait_path.span, E0404, - "`{}` is not a trait", - path_names_to_string(trait_path, path_depth)); + resolve_error(&ResolutionError::IsNotATrait(self, trait_path.span, + &*path_names_to_string(trait_path, + path_depth)) + ); // If it's a typedef, give a note if let DefTy(..) = path_res.base_def { @@ -2073,9 +2301,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Err(()) } } else { - resolve_err!(self, trait_path.span, E0405, - "use of undeclared trait name `{}`", - path_names_to_string(trait_path, path_depth)); + resolve_error(&ResolutionError::UndeclaredTraitName(self, + trait_path.span, + &*path_names_to_string(trait_path, + path_depth))); Err(()) } } @@ -2093,8 +2322,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res { self.record_def(eq_pred.id, path_res.unwrap()); } else { - resolve_err!(self, eq_pred.span, E0406, "{}", - "undeclared associated type"); + resolve_error(&ResolutionError::UndeclaredAssociatedType(self, + eq_pred.span)); } } } @@ -2219,8 +2448,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some((did, ref trait_ref)) = self.current_trait_ref { if !self.trait_item_map.contains_key(&(name, did)) { let path_str = path_names_to_string(&trait_ref.path, 0); - resolve_err!(self, span, E0407, "method `{}` is not a member of trait `{}`", - name, path_str); + resolve_error(&ResolutionError::MethodNotMemberOfTrait(self, + span, + name, + &*path_str)); } } } @@ -2267,19 +2498,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&key, &binding_0) in &map_0 { match map_i.get(&key) { None => { - resolve_err!(self, p.span, E0408, - "variable `{}` from pattern #1 is \ - not bound in pattern #{}", - key, - i + 1); + resolve_error(&ResolutionError::VariableNotBoundInPattern(self, + p.span, + key, + i + 1)); } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { - resolve_err!(self, binding_i.span, E0409, - "variable `{}` is bound with different \ - mode in pattern #{} than in pattern #1", - key, - i + 1); + resolve_error(&ResolutionError::VariableBoundWithDifferentMode( + self, + binding_i.span, + key, + i + 1) + ); } } } @@ -2287,11 +2518,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&key, &binding) in &map_i { if !map_0.contains_key(&key) { - resolve_err!(self, binding.span, E0410, - "variable `{}` from pattern #{} is \ - not bound in pattern #1", - key, - i + 1); + resolve_error(&ResolutionError::VariableNotBoundInParentPattern(self, + binding.span, + key, + i + 1)); } } } @@ -2405,13 +2635,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { maybe_qself.is_none() && path.segments[0].identifier.name == self_type_name; if is_invalid_self_type_name { - resolve_err!(self, ty.span, E0411, - "use of `Self` outside of an impl or trait"); + resolve_error(&ResolutionError::SelfUsedOutsideImplOrTrait(self, + ty.span)); } else { - resolve_err!(self, ty.span, E0412, - "use of undeclared {} `{}`", - kind, - path_names_to_string(path, 0)); + resolve_error(&ResolutionError::UseOfUndeclared( + self, + ty.span, + kind, + &*path_names_to_string(path, + 0)) + ); } } } @@ -2463,11 +2696,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } FoundStructOrEnumVariant(..) => { - resolve_err!(self, pattern.span, E0413, - "declaration of `{}` shadows an enum \ - variant or unit-like struct in \ - scope", - renamed); + resolve_error( + &ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct( + self, + pattern.span, + renamed) + ); } FoundConst(def, lp) if mode == RefutableMode => { debug!("(resolving pattern) resolving `{}` to \ @@ -2485,10 +2719,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } FoundConst(..) => { - resolve_err!(self, pattern.span, E0414, - "{}", - "only irrefutable patterns \ - allowed here"); + resolve_error( + &ResolutionError::OnlyIrrefutablePatternsAllowedHere( + self, + pattern.span) + ); } BareIdentifierPatternUnresolved => { debug!("(resolving pattern) binding `{}`", @@ -2520,22 +2755,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { bindings_list.contains_key(&renamed) { // Forbid duplicate bindings in the same // parameter list. - resolve_err!(self, pattern.span, E0415, - "identifier `{}` \ - is bound more \ - than once in \ - this parameter \ - list", - token::get_ident(ident)); + resolve_error( + &ResolutionError::IdentifierBoundMoreThanOnceInParameterList( + self, + pattern.span, + &*token::get_ident(ident)) + ); } else if bindings_list.get(&renamed) == Some(&pat_id) { // Then this is a duplicate variable in the // same disjunction, which is an error. - resolve_err!(self, pattern.span, E0416, - "identifier `{}` is bound \ - more than once in the same \ - pattern", - token::get_ident(ident)); + resolve_error( + &ResolutionError::IdentifierBoundMoreThanOnceInSamePattern( + self, + pattern.span, + &*token::get_ident(ident)) + ); } // Else, not bound in the same pattern: do // nothing. @@ -2566,10 +2801,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, path_res); } DefStatic(..) => { - resolve_error(&ResolutionError::StaticVariableReference(&self, path.span), - "static variables cannot be \ - referenced in a pattern, \ - use a `const` instead"); + resolve_error(&ResolutionError::StaticVariableReference(&self, + path.span)); } _ => { // If anything ends up here entirely resolved, @@ -2577,10 +2810,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // partially resolved, that's OK, because it may // be a `T::CONST` that typeck will resolve. if path_res.depth == 0 { - resolve_err!(self, path.span, E0418, - "`{}` is not an enum variant, struct or const", - token::get_ident( - path.segments.last().unwrap().identifier)); + resolve_error( + &ResolutionError::NotAnEnumVariantStructOrConst( + self, + path.span, + &*token::get_ident( + path.segments.last().unwrap().identifier) + ) + ); } else { let const_name = path.segments.last().unwrap() .identifier.name; @@ -2591,9 +2828,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } else { - resolve_err!(self, path.span, E0419, - "unresolved enum variant, struct or const `{}`", - token::get_ident(path.segments.last().unwrap().identifier)); + resolve_error( + &ResolutionError::UnresolvedEnumVariantStructOrConst( + self, + path.span, + &*token::get_ident(path.segments.last().unwrap().identifier)) + ); } visit::walk_path(self, path); } @@ -2625,16 +2865,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, path_res); } _ => { - resolve_err!(self, path.span, E0420, - "`{}` is not an associated const", - token::get_ident( - path.segments.last().unwrap().identifier)); + resolve_error( + &ResolutionError::NotAnAssociatedConst( + self, + path.span, + &*token::get_ident( + path.segments.last().unwrap().identifier) + ) + ); } } } else { - resolve_err!(self, path.span, E0421, - "unresolved associated const `{}`", - token::get_ident(path.segments.last().unwrap().identifier)); + resolve_error( + &ResolutionError::UnresolvedAssociatedConst( + self, + path.span, + &*token::get_ident(path.segments.last().unwrap().identifier) + ) + ); } visit::walk_pat(self, pattern); } @@ -2647,9 +2895,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result => { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); - resolve_error(&ResolutionError::DoesNotNameAStruct(self, path.span), - &*format!("`{}` does not name a structure", - path_names_to_string(path, 0))); + resolve_error(&ResolutionError::DoesNotNameAStruct( + self, + path.span, + &*path_names_to_string(path, 0)) + ); } } visit::walk_path(self, path); @@ -2695,10 +2945,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return FoundConst(def, LastMod(AllPublic)); } DefStatic(..) => { - resolve_error(&ResolutionError::StaticVariableReference(self, span), - "static variables cannot be \ - referenced in a pattern, \ - use a `const` instead"); + resolve_error(&ResolutionError::StaticVariableReference(self, + span)); return BareIdentifierPatternUnresolved; } _ => { @@ -2715,10 +2963,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Failed(err) => { match err { Some((span, msg)) => { - resolve_error(&ResolutionError::FailedToResolve(self, span), - &*format!("failed to resolve. {}", - msg) - ); + resolve_error(&ResolutionError::FailedToResolve(self, span, &*msg)); } None => () } @@ -2947,10 +3192,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - resolve_error(&ResolutionError::FailedToResolve(self, span), - &*format!("failed to resolve. {}", - msg) - ); + resolve_error(&ResolutionError::FailedToResolve(self, span, &*msg)); return None; } Indeterminate => panic!("indeterminate unexpected"), @@ -3009,10 +3251,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - resolve_error(&ResolutionError::FailedToResolve(self, span), - &*format!("failed to resolve. {}", - msg) - ); + resolve_error(&ResolutionError::FailedToResolve(self, span, &*msg)); return None; } @@ -3108,10 +3347,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { failed to resolve {}", name); if let Some((span, msg)) = err { - resolve_error(&ResolutionError::FailedToResolve(self, span), - &*format!("failed to resolve. {}", - msg) - ) + resolve_error(&ResolutionError::FailedToResolve(self, span, &*msg)) } return None; @@ -3314,11 +3550,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let DefVariant(_, _, true) = path_res.base_def { let path_name = path_names_to_string(path, 0); - resolve_error(&ResolutionError::StructVariantUsedAsFunction(self, expr.span), - &*format!("`{}` is a struct variant name, but \ - this expression \ - uses it like a function name", - path_name)); + resolve_error(&ResolutionError::StructVariantUsedAsFunction(self, + expr.span, + &*path_name)); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3355,11 +3589,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match type_res.map(|r| r.base_def) { Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => { - resolve_error(&ResolutionError::StructVariantUsedAsFunction(self, expr.span), - &*format!("`{}` is a struct variant name, but \ - this expression \ - uses it like a function name", - path_name)); + resolve_error(&ResolutionError::StructVariantUsedAsFunction(self, + expr.span, + &*path_name)); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3386,11 +3618,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if method_scope && &token::get_name(special_names::self_)[..] == path_name { - resolve_err!(self, expr.span, E0424, - "{}", - "`self` is not available \ - in a static method. Maybe a \ - `self` argument is missing?"); + resolve_error( + &ResolutionError::SelfNotAvailableInStaticMethod( + self, + expr.span) + ); } else { let last_name = path.segments.last().unwrap().identifier.name; let mut msg = match self.find_fallback_in_self_type(last_name) { @@ -3414,10 +3646,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { msg = format!(". Did you mean {}?", msg) } - resolve_err!(self, expr.span, E0425, - "unresolved name `{}`{}", - path_name, - msg); + resolve_error(&ResolutionError::UnresolvedName(self, + expr.span, + &*path_name, + &*msg)); } } } @@ -3435,9 +3667,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { debug!("(resolving expression) didn't find struct def",); - resolve_error(&ResolutionError::DoesNotNameAStruct(self, path.span), - &*format!("`{}` does not name a structure", - path_names_to_string(path, 0))); + resolve_error(&ResolutionError::DoesNotNameAStruct( + self, + path.span, + &*path_names_to_string(path, 0)) + ); } } @@ -3462,9 +3696,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let renamed = mtwt::resolve(label); match self.search_label(renamed) { None => { - resolve_err!(self, expr.span, E0426, - "use of undeclared label `{}`", - token::get_ident(label)) + resolve_error(&ResolutionError::UndeclaredLabel(self, + expr.span, + &*token::get_ident(label))) } Some(DlDef(def @ DefLabel(_))) => { // Since this def is a label, it is never read. @@ -3610,9 +3844,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match pat_binding_mode { BindByValue(_) => {} BindByRef(..) => { - resolve_err!(self, pat.span, E0427, - "cannot use `ref` binding mode with {}", - descr); + resolve_error(&ResolutionError::CannotUseRefBindingModeWith(self, + pat.span, + descr)); } } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 196de63bfd979..3b06eab8cf2ec 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -272,12 +272,11 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { Some((span, msg)) => (span, format!(". {}", msg)), None => (import_directive.span, String::new()) }; - ::resolve_error(&::ResolutionError::UnresolvedImport(self.resolver, span), - &*format!("unresolved import `{}`{}", - import_path_to_string( - &import_directive.module_path, - import_directive.subclass), - help) + ::resolve_error(&::ResolutionError::UnresolvedImport(self.resolver, span, + Some((&*import_path_to_string( + &import_directive.module_path, + import_directive.subclass), + Some(&*help)))) ); } ResolveResult::Indeterminate => break, // Bail out. We'll come around next time. From 7954096bc8b0519164f20a3b8178efb221fb86b0 Mon Sep 17 00:00:00 2001 From: Corey Farwell <coreyf@rwell.org> Date: Sun, 12 Jul 2015 20:42:06 +0900 Subject: [PATCH 30/47] Add regression test for #21140 Closes #21140 --- src/test/compile-fail/issue-23595-1.rs | 4 +++- src/test/run-pass/issue-21140.rs | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/issue-21140.rs diff --git a/src/test/compile-fail/issue-23595-1.rs b/src/test/compile-fail/issue-23595-1.rs index 4dc717558b176..749b261e38719 100644 --- a/src/test/compile-fail/issue-23595-1.rs +++ b/src/test/compile-fail/issue-23595-1.rs @@ -14,7 +14,9 @@ trait Hierarchy { type Value; type ChildKey; type Children = Index<Self::ChildKey, Output=Hierarchy>; - //~^ ERROR: the value of the associated type must be specified + //~^ ERROR: the value of the associated type `ChildKey` + //~^^ ERROR: the value of the associated type `Children` + //~^^^ ERROR: the value of the associated type `Value` fn data(&self) -> Option<(Self::Value, Self::Children)>; } diff --git a/src/test/run-pass/issue-21140.rs b/src/test/run-pass/issue-21140.rs new file mode 100644 index 0000000000000..c19f3327fbb41 --- /dev/null +++ b/src/test/run-pass/issue-21140.rs @@ -0,0 +1,15 @@ +// 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 trait Trait where Self::Out: std::fmt::Display { + type Out; +} + +fn main() {} From 31262c206e9d0152610572859092132555c7d492 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Tue, 14 Jul 2015 16:32:43 +0200 Subject: [PATCH 31/47] Arguments are now passed directly to the function instead of the enum variants --- src/librustc_resolve/build_reduced_graph.rs | 22 +- src/librustc_resolve/lib.rs | 367 ++++++++++---------- src/librustc_resolve/resolve_imports.rs | 4 +- 3 files changed, 197 insertions(+), 196 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 782e0a3660b33..67eeb19e6fd78 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -209,9 +209,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // had the duplicate. let ns = ns.unwrap(); ::resolve_error( + self, + sp, &::ResolutionError::DuplicateDefinition( - self, - sp, namespace_error_to_string(duplicate_type), &*token::get_name(name)) ); @@ -307,9 +307,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { full_path.segments.last().unwrap().identifier.name; if &token::get_name(source_name)[..] == "mod" || &token::get_name(source_name)[..] == "self" { - ::resolve_error(&::ResolutionError::SelfImportsOnlyAllowedWithin( - self, - view_path.span) + ::resolve_error(self, + view_path.span, + &::ResolutionError::SelfImportsOnlyAllowedWithin ); } @@ -331,9 +331,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { }).collect::<Vec<Span>>(); if mod_spans.len() > 1 { ::resolve_error( - &::ResolutionError::SelfImportCanOnlyAppearOnceInTheList( - self, - mod_spans[0]) + self, + mod_spans[0], + &::ResolutionError::SelfImportCanOnlyAppearOnceInTheList ); for other_span in mod_spans.iter().skip(1) { self.session.span_note(*other_span, @@ -350,10 +350,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { Some(name) => *name, None => { ::resolve_error( + self, + source_item.span, &::ResolutionError:: - SelfImportOnlyInImportListWithNonEmptyPrefix( - self, - source_item.span) + SelfImportOnlyInImportListWithNonEmptyPrefix ); continue; } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 850a5d1db2682..6a8022341b07a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -116,249 +116,237 @@ mod record_exports; mod build_reduced_graph; mod resolve_imports; -pub enum ResolutionError<'b, 'a:'b, 'tcx:'a> { +pub enum ResolutionError<'b> { /// error E0401: can't use type parameters from outer function - TypeParametersFromOuterFunction(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + TypeParametersFromOuterFunction, /// error E0402: cannot use an outer type parameter in this context - OuterTypeParameterContext(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + OuterTypeParameterContext, /// error E0403: the name is already used for a type parameter in this type parameter list - NameAlreadyUsedInTypeParameterList(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, - syntax::ast::Name), + NameAlreadyUsedInTypeParameterList(syntax::ast::Name), /// error E0404: is not a trait - IsNotATrait(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + IsNotATrait(&'b str), /// error E0405: use of undeclared trait name - UndeclaredTraitName(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + UndeclaredTraitName(&'b str), /// error E0406: undeclared associated type - UndeclaredAssociatedType(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + UndeclaredAssociatedType, /// error E0407: method is not a member of trait - MethodNotMemberOfTrait(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, syntax::ast::Name, - &'b str), + MethodNotMemberOfTrait(syntax::ast::Name, &'b str), /// error E0408: variable `{}` from pattern #1 is not bound in pattern - VariableNotBoundInPattern(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, syntax::ast::Name, - usize), + VariableNotBoundInPattern(syntax::ast::Name, usize), /// error E0409: variable is bound with different mode in pattern #{} than in pattern #1 - VariableBoundWithDifferentMode(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, - syntax::ast::Name, usize), + VariableBoundWithDifferentMode(syntax::ast::Name, usize), /// error E0410: variable from pattern is not bound in pattern #1 - VariableNotBoundInParentPattern(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, - syntax::ast::Name, usize), + VariableNotBoundInParentPattern(syntax::ast::Name, usize), /// error E0411: use of `Self` outside of an impl or trait - SelfUsedOutsideImplOrTrait(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + SelfUsedOutsideImplOrTrait, /// error E0412: use of undeclared - UseOfUndeclared(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str, &'b str), + UseOfUndeclared(&'b str, &'b str), /// error E0413: declaration shadows an enum variant or unit-like struct in scope - DeclarationShadowsEnumVariantOrUnitLikeStruct(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, - syntax::ast::Name), + DeclarationShadowsEnumVariantOrUnitLikeStruct(syntax::ast::Name), /// error E0414: only irrefutable patterns allowed here - OnlyIrrefutablePatternsAllowedHere(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + OnlyIrrefutablePatternsAllowedHere, /// error E0415: identifier is bound more than once in this parameter list - IdentifierBoundMoreThanOnceInParameterList(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, - &'b str), + IdentifierBoundMoreThanOnceInParameterList(&'b str), /// error E0416: identifier is bound more than once in the same pattern - IdentifierBoundMoreThanOnceInSamePattern(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, - &'b str), + IdentifierBoundMoreThanOnceInSamePattern(&'b str), /// error E0417: static variables cannot be referenced in a pattern - StaticVariableReference(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + StaticVariableReference, /// error E0418: is not an enum variant, struct or const - NotAnEnumVariantStructOrConst(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + NotAnEnumVariantStructOrConst(&'b str), /// error E0419: unresolved enum variant, struct or const - UnresolvedEnumVariantStructOrConst(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + UnresolvedEnumVariantStructOrConst(&'b str), /// error E0420: is not an associated const - NotAnAssociatedConst(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + NotAnAssociatedConst(&'b str), /// error E0421: unresolved associated const - UnresolvedAssociatedConst(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + UnresolvedAssociatedConst(&'b str), /// error E0422: does not name a struct - DoesNotNameAStruct(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + DoesNotNameAStruct(&'b str), /// error E0423: is a struct variant name, but this expression uses it like a function name - StructVariantUsedAsFunction(&'a Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + StructVariantUsedAsFunction(&'b str), /// error E0424: `self` is not available in a static method - SelfNotAvailableInStaticMethod(&'a Resolver<'a, 'tcx>, syntax::codemap::Span), + SelfNotAvailableInStaticMethod, /// error E0425: unresolved name - UnresolvedName(&'a Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str, &'b str), + UnresolvedName(&'b str, &'b str), /// error E0426: use of undeclared label - UndeclaredLabel(&'a Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + UndeclaredLabel(&'b str), /// error E0427: cannot use `ref` binding mode with ... - CannotUseRefBindingModeWith(&'a Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + CannotUseRefBindingModeWith(&'b str), /// error E0428: duplicate definition - DuplicateDefinition(&'a Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str, &'b str), + DuplicateDefinition(&'b str, &'b str), /// error E0429: `self` imports are only allowed within a { } list - SelfImportsOnlyAllowedWithin(&'a Resolver<'a, 'tcx>, syntax::codemap::Span), + SelfImportsOnlyAllowedWithin, /// error E0430: `self` import can only appear once in the list - SelfImportCanOnlyAppearOnceInTheList(&'a Resolver<'a, 'tcx>, syntax::codemap::Span), + SelfImportCanOnlyAppearOnceInTheList, /// error E0431: `self` import can only appear in an import list with a non-empty prefix - SelfImportOnlyInImportListWithNonEmptyPrefix(&'a Resolver<'a, 'tcx>, syntax::codemap::Span), + SelfImportOnlyInImportListWithNonEmptyPrefix, /// error E0432: unresolved import - UnresolvedImport(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, - Option<(&'b str, Option<&'b str>)>), + UnresolvedImport(Option<(&'b str, Option<&'b str>)>), /// error E0433: failed to resolve - FailedToResolve(&'b Resolver<'a, 'tcx>, syntax::codemap::Span, &'b str), + FailedToResolve(&'b str), /// error E0434: can't capture dynamic environment in a fn item - CannotCaptureDynamicEnvironmentInFnItem(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + CannotCaptureDynamicEnvironmentInFnItem, /// error E0435: attempt to use a non-constant value in a constant - AttemptToUseNonConstantValueInConstant(&'b Resolver<'a, 'tcx>, syntax::codemap::Span), + AttemptToUseNonConstantValueInConstant, } -fn resolve_error<'b, 'a:'b, 'tcx:'a>(resolution_error: &ResolutionError<'b, 'a, 'tcx>) { +fn resolve_error<'b, 'a:'b, 'tcx:'a>(resolver: &'b Resolver<'a, 'tcx>, span: syntax::codemap::Span, + resolution_error: &ResolutionError<'b>) { match resolution_error { - &ResolutionError::TypeParametersFromOuterFunction(resolver, span) => { + &ResolutionError::TypeParametersFromOuterFunction => { resolve_err!(resolver, span, E0401, "can't use type parameters from \ outer function; try using a local \ type parameter instead"); }, - &ResolutionError::OuterTypeParameterContext(resolver, span) => { + &ResolutionError::OuterTypeParameterContext => { resolve_err!(resolver, span, E0402, "cannot use an outer type parameter in this context"); }, - &ResolutionError::NameAlreadyUsedInTypeParameterList(resolver, span, name) => { + &ResolutionError::NameAlreadyUsedInTypeParameterList(name) => { resolve_err!(resolver, span, E0403, "the name `{}` is already used for a type \ parameter in this type parameter list", name); }, - &ResolutionError::IsNotATrait(resolver, span, name) => { + &ResolutionError::IsNotATrait(name) => { resolve_err!(resolver, span, E0404, "`{}` is not a trait", name); }, - &ResolutionError::UndeclaredTraitName(resolver, span, name) => { + &ResolutionError::UndeclaredTraitName(name) => { resolve_err!(resolver, span, E0405, "use of undeclared trait name `{}`", name); }, - &ResolutionError::UndeclaredAssociatedType(resolver, span) => { + &ResolutionError::UndeclaredAssociatedType => { resolve_err!(resolver, span, E0406, "undeclared associated type"); }, - &ResolutionError::MethodNotMemberOfTrait(resolver, span, method, trait_) => { + &ResolutionError::MethodNotMemberOfTrait(method, trait_) => { resolve_err!(resolver, span, E0407, "method `{}` is not a member of trait `{}`", method, trait_); }, - &ResolutionError::VariableNotBoundInPattern(resolver, span, variable_name, - pattern_number) => { + &ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => { resolve_err!(resolver, span, E0408, "variable `{}` from pattern #1 is not bound in pattern #{}", variable_name, pattern_number); }, - &ResolutionError::VariableBoundWithDifferentMode(resolver, span, variable_name, - pattern_number) => { + &ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => { resolve_err!(resolver, span, E0409, "variable `{}` is bound with different \ mode in pattern #{} than in pattern #1", variable_name, pattern_number); }, - &ResolutionError::VariableNotBoundInParentPattern(resolver, span, variable_name, - pattern_number) => { + &ResolutionError::VariableNotBoundInParentPattern(variable_name, pattern_number) => { resolve_err!(resolver, span, E0410, "variable `{}` from pattern #{} is not bound in pattern #1", variable_name, pattern_number); }, - &ResolutionError::SelfUsedOutsideImplOrTrait(resolver, span) => { + &ResolutionError::SelfUsedOutsideImplOrTrait => { resolve_err!(resolver, span, E0411, "use of `Self` outside of an impl or trait"); }, - &ResolutionError::UseOfUndeclared(resolver, span, kind, name) => { + &ResolutionError::UseOfUndeclared(kind, name) => { resolve_err!(resolver, span, E0412, "use of undeclared {} `{}`", kind, name); }, - &ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(resolver, span, name) => { + &ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => { resolve_err!(resolver, span, E0413, "declaration of `{}` shadows an enum variant or unit-like struct in \ scope", name); }, - &ResolutionError::OnlyIrrefutablePatternsAllowedHere(resolver, span) => { + &ResolutionError::OnlyIrrefutablePatternsAllowedHere => { resolve_err!(resolver, span, E0414, "only irrefutable patterns allowed here"); }, - &ResolutionError::IdentifierBoundMoreThanOnceInParameterList(resolver, span, - identifier) => { + &ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => { resolve_err!(resolver, span, E0415, "identifier `{}` is bound more than once in this parameter list", identifier); }, - &ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(resolver, span, identifier) => { + &ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => { resolve_err!(resolver, span, E0416, "identifier `{}` is bound more than once in the same pattern", identifier); }, - &ResolutionError::StaticVariableReference(resolver, span) => { + &ResolutionError::StaticVariableReference => { resolve_err!(resolver, span, E0417, "static variables cannot be \ referenced in a pattern, \ use a `const` instead"); }, - &ResolutionError::NotAnEnumVariantStructOrConst(resolver, span, name) => { + &ResolutionError::NotAnEnumVariantStructOrConst(name) => { resolve_err!(resolver, span, E0418, "`{}` is not an enum variant, struct or const", name); }, - &ResolutionError::UnresolvedEnumVariantStructOrConst(resolver, span, name) => { + &ResolutionError::UnresolvedEnumVariantStructOrConst(name) => { resolve_err!(resolver, span, E0419, "unresolved enum variant, struct or const `{}`", name); }, - &ResolutionError::NotAnAssociatedConst(resolver, span, name) => { + &ResolutionError::NotAnAssociatedConst(name) => { resolve_err!(resolver, span, E0420, "`{}` is not an associated const", name); }, - &ResolutionError::UnresolvedAssociatedConst(resolver, span, name) => { + &ResolutionError::UnresolvedAssociatedConst(name) => { resolve_err!(resolver, span, E0421, "unresolved associated const `{}`", name); }, - &ResolutionError::DoesNotNameAStruct(resolver, span, name) => { + &ResolutionError::DoesNotNameAStruct(name) => { resolve_err!(resolver, span, E0422, "`{}` does not name a structure", name); }, - &ResolutionError::StructVariantUsedAsFunction(resolver, span, path_name) => { + &ResolutionError::StructVariantUsedAsFunction(path_name) => { resolve_err!(resolver, span, E0423, "`{}` is a struct variant name, but \ this expression \ uses it like a function name", path_name); }, - &ResolutionError::SelfNotAvailableInStaticMethod(resolver, span) => { + &ResolutionError::SelfNotAvailableInStaticMethod => { resolve_err!(resolver, span, E0424, "`self` is not available in a static method. \ Maybe a `self` argument is missing?"); }, - &ResolutionError::UnresolvedName(resolver, span, path, name) => { + &ResolutionError::UnresolvedName(path, name) => { resolve_err!(resolver, span, E0425, "unresolved name `{}`{}", path, name); }, - &ResolutionError::UndeclaredLabel(resolver, span, name) => { + &ResolutionError::UndeclaredLabel(name) => { resolve_err!(resolver, span, E0426, "use of undeclared label `{}`", name); }, - &ResolutionError::CannotUseRefBindingModeWith(resolver, span, descr) => { + &ResolutionError::CannotUseRefBindingModeWith(descr) => { resolve_err!(resolver, span, E0427, "cannot use `ref` binding mode with {}", descr); }, - &ResolutionError::DuplicateDefinition(resolver, span, namespace, name) => { + &ResolutionError::DuplicateDefinition(namespace, name) => { resolve_err!(resolver, span, E0428, "duplicate definition of {} `{}`", namespace, name); }, - &ResolutionError::SelfImportsOnlyAllowedWithin(resolver, span) => { + &ResolutionError::SelfImportsOnlyAllowedWithin => { resolve_err!(resolver, span, E0429, "{}", "`self` imports are only allowed within a { } list"); }, - &ResolutionError::SelfImportCanOnlyAppearOnceInTheList(resolver, span) => { + &ResolutionError::SelfImportCanOnlyAppearOnceInTheList => { resolve_err!(resolver, span, E0430, "`self` import can only appear once in the list"); }, - &ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix(resolver, span) => { + &ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => { resolve_err!(resolver, span, E0431, "`self` import can only appear in an import list with a \ non-empty prefix"); } - &ResolutionError::UnresolvedImport(resolver, span, name) => { + &ResolutionError::UnresolvedImport(name) => { let msg = match name { Some((n, Some(p))) => format!("unresolved import `{}`{}", n, p), Some((n, None)) => format!("unresolved import (maybe you meant `{}::*`?)", n), @@ -366,15 +354,15 @@ fn resolve_error<'b, 'a:'b, 'tcx:'a>(resolution_error: &ResolutionError<'b, 'a, }; resolve_err!(resolver, span, E0432, "{}", msg); }, - &ResolutionError::FailedToResolve(resolver, span, msg) => { + &ResolutionError::FailedToResolve(msg) => { resolve_err!(resolver, span, E0433, "failed to resolve. {}", msg); }, - &ResolutionError::CannotCaptureDynamicEnvironmentInFnItem(resolver, span) => { + &ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { resolve_err!(resolver, span, E0434, "{}", "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); }, - &ResolutionError::AttemptToUseNonConstantValueInConstant(resolver, span) =>{ + &ResolutionError::AttemptToUseNonConstantValueInConstant =>{ resolve_err!(resolver, span, E0435, "attempt to use a non-constant value in a constant"); }, @@ -1575,7 +1563,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathSearch, true) { Failed(Some((span, msg))) => { - resolve_error(&ResolutionError::FailedToResolve(self, span, &*msg)); + resolve_error(self, span, &ResolutionError::FailedToResolve(&*msg)); }, Failed(None) => (), // Continue up the search chain. Indeterminate => { @@ -1833,13 +1821,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .span_to_snippet((*imports)[index].span) .unwrap(); if sn.contains("::") { - resolve_error(&ResolutionError::UnresolvedImport(self, - (*imports)[index].span, - None)); + resolve_error(self, + (*imports)[index].span, + &ResolutionError::UnresolvedImport(None)); } else { - resolve_error(&ResolutionError::UnresolvedImport(self, - (*imports)[index].span, - Some((&*sn, None)))); + resolve_error(self, + (*imports)[index].span, + &ResolutionError::UnresolvedImport(Some((&*sn, None)))); } } @@ -1966,18 +1954,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // named function item. This is not allowed, so we // report an error. resolve_error( - &ResolutionError::CannotCaptureDynamicEnvironmentInFnItem( - self, - span) + self, + span, + &ResolutionError::CannotCaptureDynamicEnvironmentInFnItem ); return None; } ConstantItemRibKind => { // Still doesn't deal with upvars resolve_error( - &ResolutionError::AttemptToUseNonConstantValueInConstant( - self, - span) + self, + span, + &ResolutionError::AttemptToUseNonConstantValueInConstant ); return None; } @@ -1994,13 +1982,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This was an attempt to use a type parameter outside // its scope. - resolve_error(&ResolutionError::TypeParametersFromOuterFunction(self, - span)); + resolve_error(self, + span, + &ResolutionError::TypeParametersFromOuterFunction); return None; } ConstantItemRibKind => { // see #9186 - resolve_error(&ResolutionError::OuterTypeParameterContext(self, span)); + resolve_error(self, span, &ResolutionError::OuterTypeParameterContext); return None; } } @@ -2198,10 +2187,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("with_type_parameter_rib: {}", type_parameter.id); if seen_bindings.contains(&name) { - resolve_error(&ResolutionError::NameAlreadyUsedInTypeParameterList( - self, - type_parameter.span, - name)); + resolve_error(self, + type_parameter.span, + &ResolutionError::NameAlreadyUsedInTypeParameterList( + name) + ); } seen_bindings.insert(name); @@ -2288,9 +2278,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving trait) found trait def: {:?}", path_res); Ok(path_res) } else { - resolve_error(&ResolutionError::IsNotATrait(self, trait_path.span, - &*path_names_to_string(trait_path, - path_depth)) + resolve_error(self, + trait_path.span, + &ResolutionError::IsNotATrait(&*path_names_to_string(trait_path, + path_depth)) ); // If it's a typedef, give a note @@ -2301,10 +2292,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Err(()) } } else { - resolve_error(&ResolutionError::UndeclaredTraitName(self, - trait_path.span, - &*path_names_to_string(trait_path, - path_depth))); + resolve_error(self, + trait_path.span, + &ResolutionError::UndeclaredTraitName( + &*path_names_to_string(trait_path, path_depth)) + ); Err(()) } } @@ -2322,8 +2314,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res { self.record_def(eq_pred.id, path_res.unwrap()); } else { - resolve_error(&ResolutionError::UndeclaredAssociatedType(self, - eq_pred.span)); + resolve_error(self, + eq_pred.span, + &ResolutionError::UndeclaredAssociatedType); } } } @@ -2448,9 +2441,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some((did, ref trait_ref)) = self.current_trait_ref { if !self.trait_item_map.contains_key(&(name, did)) { let path_str = path_names_to_string(&trait_ref.path, 0); - resolve_error(&ResolutionError::MethodNotMemberOfTrait(self, - span, - name, + resolve_error(self, + span, + &ResolutionError::MethodNotMemberOfTrait(name, &*path_str)); } } @@ -2498,18 +2491,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&key, &binding_0) in &map_0 { match map_i.get(&key) { None => { - resolve_error(&ResolutionError::VariableNotBoundInPattern(self, - p.span, - key, + resolve_error(self, + p.span, + &ResolutionError::VariableNotBoundInPattern(key, i + 1)); } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { - resolve_error(&ResolutionError::VariableBoundWithDifferentMode( - self, - binding_i.span, - key, - i + 1) + resolve_error(self, + binding_i.span, + &ResolutionError::VariableBoundWithDifferentMode(key, + i + 1) ); } } @@ -2518,9 +2510,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for (&key, &binding) in &map_i { if !map_0.contains_key(&key) { - resolve_error(&ResolutionError::VariableNotBoundInParentPattern(self, - binding.span, - key, + resolve_error(self, + binding.span, + &ResolutionError::VariableNotBoundInParentPattern(key, i + 1)); } } @@ -2635,12 +2627,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { maybe_qself.is_none() && path.segments[0].identifier.name == self_type_name; if is_invalid_self_type_name { - resolve_error(&ResolutionError::SelfUsedOutsideImplOrTrait(self, - ty.span)); + resolve_error(self, + ty.span, + &ResolutionError::SelfUsedOutsideImplOrTrait); } else { - resolve_error(&ResolutionError::UseOfUndeclared( - self, - ty.span, + resolve_error(self, + ty.span, + &ResolutionError::UseOfUndeclared( kind, &*path_names_to_string(path, 0)) @@ -2697,9 +2690,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } FoundStructOrEnumVariant(..) => { resolve_error( + self, + pattern.span, &ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct( - self, - pattern.span, renamed) ); } @@ -2720,9 +2713,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } FoundConst(..) => { resolve_error( - &ResolutionError::OnlyIrrefutablePatternsAllowedHere( - self, - pattern.span) + self, + pattern.span, + &ResolutionError::OnlyIrrefutablePatternsAllowedHere ); } BareIdentifierPatternUnresolved => { @@ -2756,9 +2749,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Forbid duplicate bindings in the same // parameter list. resolve_error( + self, + pattern.span, &ResolutionError::IdentifierBoundMoreThanOnceInParameterList( - self, - pattern.span, &*token::get_ident(ident)) ); } else if bindings_list.get(&renamed) == @@ -2766,9 +2759,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Then this is a duplicate variable in the // same disjunction, which is an error. resolve_error( + self, + pattern.span, &ResolutionError::IdentifierBoundMoreThanOnceInSamePattern( - self, - pattern.span, &*token::get_ident(ident)) ); } @@ -2801,8 +2794,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, path_res); } DefStatic(..) => { - resolve_error(&ResolutionError::StaticVariableReference(&self, - path.span)); + resolve_error(&self, + path.span, + &ResolutionError::StaticVariableReference); } _ => { // If anything ends up here entirely resolved, @@ -2811,9 +2805,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // be a `T::CONST` that typeck will resolve. if path_res.depth == 0 { resolve_error( + self, + path.span, &ResolutionError::NotAnEnumVariantStructOrConst( - self, - path.span, &*token::get_ident( path.segments.last().unwrap().identifier) ) @@ -2829,9 +2823,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } else { resolve_error( + self, + path.span, &ResolutionError::UnresolvedEnumVariantStructOrConst( - self, - path.span, &*token::get_ident(path.segments.last().unwrap().identifier)) ); } @@ -2866,9 +2860,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } _ => { resolve_error( + self, + path.span, &ResolutionError::NotAnAssociatedConst( - self, - path.span, &*token::get_ident( path.segments.last().unwrap().identifier) ) @@ -2877,9 +2871,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } else { resolve_error( + self, + path.span, &ResolutionError::UnresolvedAssociatedConst( - self, - path.span, &*token::get_ident(path.segments.last().unwrap().identifier) ) ); @@ -2895,11 +2889,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result => { debug!("(resolving pattern) didn't find struct \ def: {:?}", result); - resolve_error(&ResolutionError::DoesNotNameAStruct( - self, - path.span, - &*path_names_to_string(path, 0)) - ); + resolve_error( + self, + path.span, + &ResolutionError::DoesNotNameAStruct( + &*path_names_to_string(path, 0)) + ); } } visit::walk_path(self, path); @@ -2945,8 +2940,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return FoundConst(def, LastMod(AllPublic)); } DefStatic(..) => { - resolve_error(&ResolutionError::StaticVariableReference(self, - span)); + resolve_error(self, + span, + &ResolutionError::StaticVariableReference); return BareIdentifierPatternUnresolved; } _ => { @@ -2963,7 +2959,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Failed(err) => { match err { Some((span, msg)) => { - resolve_error(&ResolutionError::FailedToResolve(self, span, &*msg)); + resolve_error(self, span, &ResolutionError::FailedToResolve(&*msg)); } None => () } @@ -3192,7 +3188,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - resolve_error(&ResolutionError::FailedToResolve(self, span, &*msg)); + resolve_error(self, span, &ResolutionError::FailedToResolve(&*msg)); return None; } Indeterminate => panic!("indeterminate unexpected"), @@ -3251,7 +3247,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - resolve_error(&ResolutionError::FailedToResolve(self, span, &*msg)); + resolve_error(self, span, &ResolutionError::FailedToResolve(&*msg)); return None; } @@ -3347,7 +3343,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { failed to resolve {}", name); if let Some((span, msg)) = err { - resolve_error(&ResolutionError::FailedToResolve(self, span, &*msg)) + resolve_error(self, span, &ResolutionError::FailedToResolve(&*msg)) } return None; @@ -3550,9 +3546,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let DefVariant(_, _, true) = path_res.base_def { let path_name = path_names_to_string(path, 0); - resolve_error(&ResolutionError::StructVariantUsedAsFunction(self, - expr.span, - &*path_name)); + resolve_error(self, + expr.span, + &ResolutionError::StructVariantUsedAsFunction(&*path_name)); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3589,9 +3585,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match type_res.map(|r| r.base_def) { Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => { - resolve_error(&ResolutionError::StructVariantUsedAsFunction(self, - expr.span, - &*path_name)); + resolve_error( + self, + expr.span, + &ResolutionError::StructVariantUsedAsFunction( + &*path_name) + ); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3619,9 +3618,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if method_scope && &token::get_name(special_names::self_)[..] == path_name { resolve_error( - &ResolutionError::SelfNotAvailableInStaticMethod( - self, - expr.span) + self, + expr.span, + &ResolutionError::SelfNotAvailableInStaticMethod ); } else { let last_name = path.segments.last().unwrap().identifier.name; @@ -3646,9 +3645,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { msg = format!(". Did you mean {}?", msg) } - resolve_error(&ResolutionError::UnresolvedName(self, - expr.span, - &*path_name, + resolve_error(self, + expr.span, + &ResolutionError::UnresolvedName(&*path_name, &*msg)); } } @@ -3667,9 +3666,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { debug!("(resolving expression) didn't find struct def",); - resolve_error(&ResolutionError::DoesNotNameAStruct( - self, - path.span, + resolve_error(self, + path.span, + &ResolutionError::DoesNotNameAStruct( &*path_names_to_string(path, 0)) ); } @@ -3696,9 +3695,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let renamed = mtwt::resolve(label); match self.search_label(renamed) { None => { - resolve_error(&ResolutionError::UndeclaredLabel(self, - expr.span, - &*token::get_ident(label))) + resolve_error(self, + expr.span, + &ResolutionError::UndeclaredLabel(&*token::get_ident(label))) } Some(DlDef(def @ DefLabel(_))) => { // Since this def is a label, it is never read. @@ -3844,9 +3843,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match pat_binding_mode { BindByValue(_) => {} BindByRef(..) => { - resolve_error(&ResolutionError::CannotUseRefBindingModeWith(self, - pat.span, - descr)); + resolve_error(self, + pat.span, + &ResolutionError::CannotUseRefBindingModeWith(descr)); } } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 3b06eab8cf2ec..080c99b07d622 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -272,7 +272,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { Some((span, msg)) => (span, format!(". {}", msg)), None => (import_directive.span, String::new()) }; - ::resolve_error(&::ResolutionError::UnresolvedImport(self.resolver, span, + ::resolve_error(self.resolver, + span, + &::ResolutionError::UnresolvedImport( Some((&*import_path_to_string( &import_directive.module_path, import_directive.subclass), From a878f35d3b6669ca473dce7b741788abb95e061f Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda <ariel.byd@gmail.com> Date: Mon, 13 Jul 2015 21:04:00 +0300 Subject: [PATCH 32/47] don't ICE when FRU is used on an enum variant Fixes #26948. --- src/librustc_typeck/check/mod.rs | 5 +++++ src/librustc_typeck/diagnostics.rs | 3 ++- src/test/compile-fail/issue-26948.rs | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/issue-26948.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5a71d1ed0b5bd..a2fee09168941 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3426,6 +3426,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let def = lookup_full_def(tcx, path.span, id); let struct_id = match def { def::DefVariant(enum_id, variant_id, true) => { + if let &Some(ref base_expr) = base_expr { + span_err!(tcx.sess, base_expr.span, E0401, + "functional record update syntax requires a struct"); + fcx.write_error(base_expr.id); + } check_struct_enum_variant(fcx, id, expr.span, enum_id, variant_id, &fields[..]); enum_id diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 5027be5fb62a3..636a8aeb544e7 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2209,6 +2209,7 @@ register_diagnostics! { E0392, // parameter `{}` is never used E0393, // the type parameter `{}` must be explicitly specified in an object // type because its default value `{}` references the type `Self`" - E0399 // trait items need to be implemented because the associated + E0399, // trait items need to be implemented because the associated // type `{}` was overridden + E0401 // functional record update requires a struct } diff --git a/src/test/compile-fail/issue-26948.rs b/src/test/compile-fail/issue-26948.rs new file mode 100644 index 0000000000000..c63cb5defb7e3 --- /dev/null +++ b/src/test/compile-fail/issue-26948.rs @@ -0,0 +1,16 @@ +// 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. + +fn main() { + enum Foo { A { x: u32 } } + let orig = Foo::A { x: 5 }; + Foo::A { x: 6, ..orig }; + //~^ ERROR functional record update syntax requires a struct +} From 86d954ba2b97d971e866a70b588d73b53f3c29a0 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup <bluss@users.noreply.github.com> Date: Tue, 14 Jul 2015 02:13:26 +0200 Subject: [PATCH 33/47] core: Revive SipHash's tests These tests were bitrotting, include them in the crate and bring them up to date and compiling.. and they pass. --- src/libcore/hash/sip.rs | 2 - src/libcoretest/hash/mod.rs | 2 + src/libcoretest/hash/sip.rs | 126 +++++++++++++++++------------------- 3 files changed, 61 insertions(+), 69 deletions(-) diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index a92b72e0f00fa..d26e9ab707205 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -10,8 +10,6 @@ //! An implementation of SipHash 2-4. -#![allow(deprecated)] // until the next snapshot for inherent wrapping ops - use prelude::*; use super::Hasher; diff --git a/src/libcoretest/hash/mod.rs b/src/libcoretest/hash/mod.rs index 5c11f0196aeb8..697c3ee254b98 100644 --- a/src/libcoretest/hash/mod.rs +++ b/src/libcoretest/hash/mod.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +mod sip; + use std::mem; use std::hash::{Hash, Hasher}; use std::default::Default; diff --git a/src/libcoretest/hash/sip.rs b/src/libcoretest/hash/sip.rs index 8289d06d04c61..7832985d3f1c1 100644 --- a/src/libcoretest/hash/sip.rs +++ b/src/libcoretest/hash/sip.rs @@ -8,28 +8,55 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. use test::Bencher; -use std::prelude::*; -use std::fmt; -use str::Str; -use string::String; -use slice::{AsSlice, SlicePrelude}; -use vec::Vec; - -use core::hash::{Hash, Writer}; -use core::hash::sip::{SipState, hash, hash_with_keys}; +use core::hash::{Hash, Hasher}; +use core::hash::SipHasher; // Hash just the bytes of the slice, without length prefix struct Bytes<'a>(&'a [u8]); -impl<'a, S: Writer> Hash<S> for Bytes<'a> { +impl<'a> Hash for Bytes<'a> { #[allow(unused_must_use)] - fn hash(&self, state: &mut S) { + fn hash<H: Hasher>(&self, state: &mut H) { let Bytes(v) = *self; state.write(v); } } +macro_rules! u8to64_le { + ($buf:expr, $i:expr) => + ($buf[0+$i] as u64 | + ($buf[1+$i] as u64) << 8 | + ($buf[2+$i] as u64) << 16 | + ($buf[3+$i] as u64) << 24 | + ($buf[4+$i] as u64) << 32 | + ($buf[5+$i] as u64) << 40 | + ($buf[6+$i] as u64) << 48 | + ($buf[7+$i] as u64) << 56); + ($buf:expr, $i:expr, $len:expr) => + ({ + let mut t = 0; + let mut out = 0; + while t < $len { + out |= ($buf[t+$i] as u64) << t*8; + t += 1; + } + out + }); +} + +fn hash<T: Hash>(x: &T) -> u64 { + let mut st = SipHasher::new(); + x.hash(&mut st); + st.finish() +} + +fn hash_with_keys<T: Hash>(k1: u64, k2: u64, x: &T) -> u64 { + let mut st = SipHasher::new_with_keys(k1, k2); + x.hash(&mut st); + st.finish() +} + #[test] #[allow(unused_must_use)] fn test_siphash() { @@ -104,79 +131,43 @@ fn test_siphash() { let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08; let mut buf = Vec::new(); let mut t = 0; - let mut state_inc = SipState::new_with_keys(k0, k1); - let mut state_full = SipState::new_with_keys(k0, k1); - - fn to_hex_str(r: &[u8; 8]) -> String { - let mut s = String::new(); - for b in r { - s.push_str(format!("{}", fmt::radix(*b, 16))); - } - s - } - - fn result_bytes(h: u64) -> Vec<u8> { - vec![(h >> 0) as u8, - (h >> 8) as u8, - (h >> 16) as u8, - (h >> 24) as u8, - (h >> 32) as u8, - (h >> 40) as u8, - (h >> 48) as u8, - (h >> 56) as u8, - ] - } - - fn result_str(h: u64) -> String { - let r = result_bytes(h); - let mut s = String::new(); - for b in &r { - s.push_str(format!("{}", fmt::radix(*b, 16))); - } - s - } + let mut state_inc = SipHasher::new_with_keys(k0, k1); while t < 64 { - debug!("siphash test {}: {}", t, buf); let vec = u8to64_le!(vecs[t], 0); - let out = hash_with_keys(k0, k1, &Bytes(buf)); - debug!("got {}, expected {}", out, vec); + let out = hash_with_keys(k0, k1, &Bytes(&buf)); assert_eq!(vec, out); - state_full.reset(); - state_full.write(buf); - let f = result_str(state_full.result()); - let i = result_str(state_inc.result()); - let v = to_hex_str(&vecs[t]); - debug!("{}: ({}) => inc={} full={}", t, v, i, f); + let full = hash_with_keys(k0, k1, &Bytes(&buf)); + let i = state_inc.finish(); - assert_eq!(f, i); - assert_eq!(f, v); + assert_eq!(full, i); + assert_eq!(full, vec); buf.push(t as u8); - state_inc.write(&[t as u8]); + Hasher::write(&mut state_inc, &[t as u8]); t += 1; } } #[test] #[cfg(target_arch = "arm")] -fn test_hash_uint() { +fn test_hash_usize() { let val = 0xdeadbeef_deadbeef_u64; - assert!(hash(&(val as u64)) != hash(&(val as uint))); - assert_eq!(hash(&(val as u32)), hash(&(val as uint))); + assert!(hash(&(val as u64)) != hash(&(val as usize))); + assert_eq!(hash(&(val as u32)), hash(&(val as usize))); } #[test] #[cfg(target_arch = "x86_64")] -fn test_hash_uint() { +fn test_hash_usize() { let val = 0xdeadbeef_deadbeef_u64; - assert_eq!(hash(&(val as u64)), hash(&(val as uint))); - assert!(hash(&(val as u32)) != hash(&(val as uint))); + assert_eq!(hash(&(val as u64)), hash(&(val as usize))); + assert!(hash(&(val as u32)) != hash(&(val as usize))); } #[test] #[cfg(target_arch = "x86")] -fn test_hash_uint() { +fn test_hash_usize() { let val = 0xdeadbeef_deadbeef_u64; - assert!(hash(&(val as u64)) != hash(&(val as uint))); - assert_eq!(hash(&(val as u32)), hash(&(val as uint))); + assert!(hash(&(val as u64)) != hash(&(val as usize))); + assert_eq!(hash(&(val as u32)), hash(&(val as usize))); } #[test] @@ -200,7 +191,7 @@ fn test_hash_no_bytes_dropped_64() { assert!(hash(&val) != hash(&zero_byte(val, 6))); assert!(hash(&val) != hash(&zero_byte(val, 7))); - fn zero_byte(val: u64, byte: uint) -> u64 { + fn zero_byte(val: u64, byte: usize) -> u64 { assert!(byte < 8); val & !(0xff << (byte * 8)) } @@ -215,7 +206,7 @@ fn test_hash_no_bytes_dropped_32() { assert!(hash(&val) != hash(&zero_byte(val, 2))); assert!(hash(&val) != hash(&zero_byte(val, 3))); - fn zero_byte(val: u32, byte: uint) -> u32 { + fn zero_byte(val: u32, byte: usize) -> u32 { assert!(byte < 4); val & !(0xff << (byte * 8)) } @@ -230,8 +221,9 @@ fn test_hash_no_concat_alias() { assert!(s != t && t != u); assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u)); - let v: (&[u8], &[u8], &[u8]) = (&[1], &[0, 0], &[0]); - let w: (&[u8], &[u8], &[u8]) = (&[1, 0, 0, 0], &[], &[]); + let u = [1, 0, 0, 0]; + let v = (&u[..1], &u[1..3], &u[3..]); + let w = (&u[..], &u[4..4], &u[4..4]); assert!(v != w); assert!(hash(&v) != hash(&w)); From 6d5ae6b20dd86de5d65cfcac28664357b6d5d953 Mon Sep 17 00:00:00 2001 From: Brian Anderson <banderson@mozilla.com> Date: Tue, 14 Jul 2015 10:25:54 -0700 Subject: [PATCH 34/47] Address more feedback --- src/libstd/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 004bdf8666188..2bb914f2095b3 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -132,7 +132,7 @@ //! //! The standard library exposes 3 common ways to deal with contiguous //! regions of memory: -//! +//! //! * [`Vec<T>`](vec/index.html) - A heap-allocated *vector* that is //! resizable at runtime. //! * [`[T; n]`](primitive.array.html) - An inline *array* with a @@ -147,10 +147,11 @@ //! * `&[T]` - *shared slice* //! * `&mut [T]` - *mutable slice* //! * [`Box<[T]>`](boxed/index.html) - *owned slice* -//! +//! //! `str`, a UTF-8 string slice, is a primitive type, and the standard -//! library defines [many methods for it](primitive.str.html). Rust -//! `str`s are immutable; use the owned `String` type defined in +//! library defines [many methods for it](primitive.str.html). Rust +//! `str`s are typically accessed as immutable references: `&mut +//! str`. Use the owned `String` type defined in //! [`string`](string/index.html) for building and mutating strings. //! //! For converting to strings use the [`format!`](fmt/index.html) From a266ab0563fdcde4799e76ee1a6eb8a09469aae8 Mon Sep 17 00:00:00 2001 From: Brian Anderson <banderson@mozilla.com> Date: Tue, 14 Jul 2015 10:32:23 -0700 Subject: [PATCH 35/47] Mention that removal of `#[packed]` was a breaking change in 1.2 --- RELEASES.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 636bcc4312eb8..db1c7380a788b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -28,6 +28,9 @@ Breaking Changes in, and the same value reported by clang's `alignof`. [`mem::min_align_of`] is deprecated. This is not known to break real code. +* [The `#[packed]` attribute is no longer silently accepted by the + compiler][packed]. This attribute did nothing and code that + mentioned it likely did not work as intended. Language -------- @@ -140,7 +143,7 @@ Misc [fat]: https://github.com/rust-lang/rust/pull/26411 [dst]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md [parcodegen]: https://github.com/rust-lang/rust/pull/26018 - +[packed]: https://github.com/rust-lang/rust/pull/25541 Version 1.1.0 (June 2015) ========================= From 60133aa6dd4bf288cacbaba72368f80c131d252c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez <guillaume1.gomez@gmail.com> Date: Tue, 14 Jul 2015 19:42:38 +0200 Subject: [PATCH 36/47] Remove macro, import function and enum --- src/librustc_resolve/build_reduced_graph.rs | 19 +- src/librustc_resolve/lib.rs | 289 ++++++++++---------- src/librustc_resolve/resolve_imports.rs | 5 +- 3 files changed, 155 insertions(+), 158 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 67eeb19e6fd78..f8ccbe4cecd5a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -26,6 +26,7 @@ use ParentLink::{self, ModuleParentLink, BlockParentLink}; use Resolver; use resolve_imports::Shadowable; use TypeNsDef; +use {resolve_error, ResolutionError}; use self::DuplicateCheckingMode::*; use self::NamespaceError::*; @@ -208,12 +209,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { // Return an error here by looking up the namespace that // had the duplicate. let ns = ns.unwrap(); - ::resolve_error( + resolve_error( self, sp, - &::ResolutionError::DuplicateDefinition( + ResolutionError::DuplicateDefinition( namespace_error_to_string(duplicate_type), - &*token::get_name(name)) + name) ); { let r = child.span_for_namespace(ns); @@ -307,9 +308,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { full_path.segments.last().unwrap().identifier.name; if &token::get_name(source_name)[..] == "mod" || &token::get_name(source_name)[..] == "self" { - ::resolve_error(self, + resolve_error(self, view_path.span, - &::ResolutionError::SelfImportsOnlyAllowedWithin + ResolutionError::SelfImportsOnlyAllowedWithin ); } @@ -330,10 +331,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { _ => None }).collect::<Vec<Span>>(); if mod_spans.len() > 1 { - ::resolve_error( + resolve_error( self, mod_spans[0], - &::ResolutionError::SelfImportCanOnlyAppearOnceInTheList + ResolutionError::SelfImportCanOnlyAppearOnceInTheList ); for other_span in mod_spans.iter().skip(1) { self.session.span_note(*other_span, @@ -349,10 +350,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> { let name = match module_path.last() { Some(name) => *name, None => { - ::resolve_error( + resolve_error( self, source_item.span, - &::ResolutionError:: + ResolutionError:: SelfImportOnlyInImportListWithNonEmptyPrefix ); continue; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6a8022341b07a..2d48f32272499 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -103,76 +103,68 @@ use resolve_imports::Shadowable; // registered before they are used. pub mod diagnostics; -macro_rules! resolve_err { - ($this:expr, $span:expr, $code:ident, $($rest:tt)*) => { - if $this.emit_errors { - span_err!($this.session, $span, $code, $($rest)*); - } - } -} - mod check_unused; mod record_exports; mod build_reduced_graph; mod resolve_imports; -pub enum ResolutionError<'b> { +pub enum ResolutionError<'a> { /// error E0401: can't use type parameters from outer function TypeParametersFromOuterFunction, /// error E0402: cannot use an outer type parameter in this context OuterTypeParameterContext, /// error E0403: the name is already used for a type parameter in this type parameter list - NameAlreadyUsedInTypeParameterList(syntax::ast::Name), + NameAlreadyUsedInTypeParameterList(Name), /// error E0404: is not a trait - IsNotATrait(&'b str), + IsNotATrait(&'a str), /// error E0405: use of undeclared trait name - UndeclaredTraitName(&'b str), + UndeclaredTraitName(&'a str), /// error E0406: undeclared associated type UndeclaredAssociatedType, /// error E0407: method is not a member of trait - MethodNotMemberOfTrait(syntax::ast::Name, &'b str), + MethodNotMemberOfTrait(Name, &'a str), /// error E0408: variable `{}` from pattern #1 is not bound in pattern - VariableNotBoundInPattern(syntax::ast::Name, usize), + VariableNotBoundInPattern(Name, usize), /// error E0409: variable is bound with different mode in pattern #{} than in pattern #1 - VariableBoundWithDifferentMode(syntax::ast::Name, usize), + VariableBoundWithDifferentMode(Name, usize), /// error E0410: variable from pattern is not bound in pattern #1 - VariableNotBoundInParentPattern(syntax::ast::Name, usize), + VariableNotBoundInParentPattern(Name, usize), /// error E0411: use of `Self` outside of an impl or trait SelfUsedOutsideImplOrTrait, /// error E0412: use of undeclared - UseOfUndeclared(&'b str, &'b str), + UseOfUndeclared(&'a str, &'a str), /// error E0413: declaration shadows an enum variant or unit-like struct in scope - DeclarationShadowsEnumVariantOrUnitLikeStruct(syntax::ast::Name), + DeclarationShadowsEnumVariantOrUnitLikeStruct(Name), /// error E0414: only irrefutable patterns allowed here OnlyIrrefutablePatternsAllowedHere, /// error E0415: identifier is bound more than once in this parameter list - IdentifierBoundMoreThanOnceInParameterList(&'b str), + IdentifierBoundMoreThanOnceInParameterList(&'a str), /// error E0416: identifier is bound more than once in the same pattern - IdentifierBoundMoreThanOnceInSamePattern(&'b str), + IdentifierBoundMoreThanOnceInSamePattern(&'a str), /// error E0417: static variables cannot be referenced in a pattern StaticVariableReference, /// error E0418: is not an enum variant, struct or const - NotAnEnumVariantStructOrConst(&'b str), + NotAnEnumVariantStructOrConst(&'a str), /// error E0419: unresolved enum variant, struct or const - UnresolvedEnumVariantStructOrConst(&'b str), + UnresolvedEnumVariantStructOrConst(&'a str), /// error E0420: is not an associated const - NotAnAssociatedConst(&'b str), + NotAnAssociatedConst(&'a str), /// error E0421: unresolved associated const - UnresolvedAssociatedConst(&'b str), + UnresolvedAssociatedConst(&'a str), /// error E0422: does not name a struct - DoesNotNameAStruct(&'b str), + DoesNotNameAStruct(&'a str), /// error E0423: is a struct variant name, but this expression uses it like a function name - StructVariantUsedAsFunction(&'b str), + StructVariantUsedAsFunction(&'a str), /// error E0424: `self` is not available in a static method SelfNotAvailableInStaticMethod, /// error E0425: unresolved name - UnresolvedName(&'b str, &'b str), + UnresolvedName(&'a str, &'a str), /// error E0426: use of undeclared label - UndeclaredLabel(&'b str), + UndeclaredLabel(&'a str), /// error E0427: cannot use `ref` binding mode with ... - CannotUseRefBindingModeWith(&'b str), + CannotUseRefBindingModeWith(&'a str), /// error E0428: duplicate definition - DuplicateDefinition(&'b str, &'b str), + DuplicateDefinition(&'a str, Name), /// error E0429: `self` imports are only allowed within a { } list SelfImportsOnlyAllowedWithin, /// error E0430: `self` import can only appear once in the list @@ -180,9 +172,9 @@ pub enum ResolutionError<'b> { /// error E0431: `self` import can only appear in an import list with a non-empty prefix SelfImportOnlyInImportListWithNonEmptyPrefix, /// error E0432: unresolved import - UnresolvedImport(Option<(&'b str, Option<&'b str>)>), + UnresolvedImport(Option<(&'a str, Option<&'a str>)>), /// error E0433: failed to resolve - FailedToResolve(&'b str), + FailedToResolve(&'a str), /// error E0434: can't capture dynamic environment in a fn item CannotCaptureDynamicEnvironmentInFnItem, /// error E0435: attempt to use a non-constant value in a constant @@ -190,180 +182,183 @@ pub enum ResolutionError<'b> { } fn resolve_error<'b, 'a:'b, 'tcx:'a>(resolver: &'b Resolver<'a, 'tcx>, span: syntax::codemap::Span, - resolution_error: &ResolutionError<'b>) { + resolution_error: ResolutionError<'b>) { + if !resolver.emit_errors { + return; + } match resolution_error { - &ResolutionError::TypeParametersFromOuterFunction => { - resolve_err!(resolver, span, E0401, "can't use type parameters from \ - outer function; try using a local \ - type parameter instead"); + ResolutionError::TypeParametersFromOuterFunction => { + span_err!(resolver.session, span, E0401, "can't use type parameters from \ + outer function; try using a local \ + type parameter instead"); }, - &ResolutionError::OuterTypeParameterContext => { - resolve_err!(resolver, span, E0402, + ResolutionError::OuterTypeParameterContext => { + span_err!(resolver.session, span, E0402, "cannot use an outer type parameter in this context"); }, - &ResolutionError::NameAlreadyUsedInTypeParameterList(name) => { - resolve_err!(resolver, span, E0403, + ResolutionError::NameAlreadyUsedInTypeParameterList(name) => { + span_err!(resolver.session, span, E0403, "the name `{}` is already used for a type \ parameter in this type parameter list", name); }, - &ResolutionError::IsNotATrait(name) => { - resolve_err!(resolver, span, E0404, + ResolutionError::IsNotATrait(name) => { + span_err!(resolver.session, span, E0404, "`{}` is not a trait", name); }, - &ResolutionError::UndeclaredTraitName(name) => { - resolve_err!(resolver, span, E0405, + ResolutionError::UndeclaredTraitName(name) => { + span_err!(resolver.session, span, E0405, "use of undeclared trait name `{}`", name); }, - &ResolutionError::UndeclaredAssociatedType => { - resolve_err!(resolver, span, E0406, "undeclared associated type"); + ResolutionError::UndeclaredAssociatedType => { + span_err!(resolver.session, span, E0406, "undeclared associated type"); }, - &ResolutionError::MethodNotMemberOfTrait(method, trait_) => { - resolve_err!(resolver, span, E0407, + ResolutionError::MethodNotMemberOfTrait(method, trait_) => { + span_err!(resolver.session, span, E0407, "method `{}` is not a member of trait `{}`", method, trait_); }, - &ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => { - resolve_err!(resolver, span, E0408, + ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => { + span_err!(resolver.session, span, E0408, "variable `{}` from pattern #1 is not bound in pattern #{}", variable_name, pattern_number); }, - &ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => { - resolve_err!(resolver, span, E0409, + ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => { + span_err!(resolver.session, span, E0409, "variable `{}` is bound with different \ mode in pattern #{} than in pattern #1", variable_name, pattern_number); }, - &ResolutionError::VariableNotBoundInParentPattern(variable_name, pattern_number) => { - resolve_err!(resolver, span, E0410, + ResolutionError::VariableNotBoundInParentPattern(variable_name, pattern_number) => { + span_err!(resolver.session, span, E0410, "variable `{}` from pattern #{} is not bound in pattern #1", variable_name, pattern_number); }, - &ResolutionError::SelfUsedOutsideImplOrTrait => { - resolve_err!(resolver, span, E0411, "use of `Self` outside of an impl or trait"); + ResolutionError::SelfUsedOutsideImplOrTrait => { + span_err!(resolver.session, span, E0411, "use of `Self` outside of an impl or trait"); }, - &ResolutionError::UseOfUndeclared(kind, name) => { - resolve_err!(resolver, span, E0412, + ResolutionError::UseOfUndeclared(kind, name) => { + span_err!(resolver.session, span, E0412, "use of undeclared {} `{}`", kind, name); }, - &ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => { - resolve_err!(resolver, span, E0413, + ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => { + span_err!(resolver.session, span, E0413, "declaration of `{}` shadows an enum variant or unit-like struct in \ scope", name); }, - &ResolutionError::OnlyIrrefutablePatternsAllowedHere => { - resolve_err!(resolver, span, E0414, "only irrefutable patterns allowed here"); + ResolutionError::OnlyIrrefutablePatternsAllowedHere => { + span_err!(resolver.session, span, E0414, "only irrefutable patterns allowed here"); }, - &ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => { - resolve_err!(resolver, span, E0415, + ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => { + span_err!(resolver.session, span, E0415, "identifier `{}` is bound more than once in this parameter list", identifier); }, - &ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => { - resolve_err!(resolver, span, E0416, + ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => { + span_err!(resolver.session, span, E0416, "identifier `{}` is bound more than once in the same pattern", identifier); }, - &ResolutionError::StaticVariableReference => { - resolve_err!(resolver, span, E0417, "static variables cannot be \ - referenced in a pattern, \ - use a `const` instead"); + ResolutionError::StaticVariableReference => { + span_err!(resolver.session, span, E0417, "static variables cannot be \ + referenced in a pattern, \ + use a `const` instead"); }, - &ResolutionError::NotAnEnumVariantStructOrConst(name) => { - resolve_err!(resolver, span, E0418, + ResolutionError::NotAnEnumVariantStructOrConst(name) => { + span_err!(resolver.session, span, E0418, "`{}` is not an enum variant, struct or const", name); }, - &ResolutionError::UnresolvedEnumVariantStructOrConst(name) => { - resolve_err!(resolver, span, E0419, + ResolutionError::UnresolvedEnumVariantStructOrConst(name) => { + span_err!(resolver.session, span, E0419, "unresolved enum variant, struct or const `{}`", name); }, - &ResolutionError::NotAnAssociatedConst(name) => { - resolve_err!(resolver, span, E0420, + ResolutionError::NotAnAssociatedConst(name) => { + span_err!(resolver.session, span, E0420, "`{}` is not an associated const", name); }, - &ResolutionError::UnresolvedAssociatedConst(name) => { - resolve_err!(resolver, span, E0421, + ResolutionError::UnresolvedAssociatedConst(name) => { + span_err!(resolver.session, span, E0421, "unresolved associated const `{}`", name); }, - &ResolutionError::DoesNotNameAStruct(name) => { - resolve_err!(resolver, span, E0422, "`{}` does not name a structure", name); + ResolutionError::DoesNotNameAStruct(name) => { + span_err!(resolver.session, span, E0422, "`{}` does not name a structure", name); }, - &ResolutionError::StructVariantUsedAsFunction(path_name) => { - resolve_err!(resolver, span, E0423, + ResolutionError::StructVariantUsedAsFunction(path_name) => { + span_err!(resolver.session, span, E0423, "`{}` is a struct variant name, but \ this expression \ uses it like a function name", path_name); }, - &ResolutionError::SelfNotAvailableInStaticMethod => { - resolve_err!(resolver, span, E0424, "`self` is not available in a static method. \ - Maybe a `self` argument is missing?"); + ResolutionError::SelfNotAvailableInStaticMethod => { + span_err!(resolver.session, span, E0424, "`self` is not available in a static method. \ + Maybe a `self` argument is missing?"); }, - &ResolutionError::UnresolvedName(path, name) => { - resolve_err!(resolver, span, E0425, + ResolutionError::UnresolvedName(path, name) => { + span_err!(resolver.session, span, E0425, "unresolved name `{}`{}", path, name); }, - &ResolutionError::UndeclaredLabel(name) => { - resolve_err!(resolver, span, E0426, + ResolutionError::UndeclaredLabel(name) => { + span_err!(resolver.session, span, E0426, "use of undeclared label `{}`", name); }, - &ResolutionError::CannotUseRefBindingModeWith(descr) => { - resolve_err!(resolver, span, E0427, + ResolutionError::CannotUseRefBindingModeWith(descr) => { + span_err!(resolver.session, span, E0427, "cannot use `ref` binding mode with {}", descr); }, - &ResolutionError::DuplicateDefinition(namespace, name) => { - resolve_err!(resolver, span, E0428, + ResolutionError::DuplicateDefinition(namespace, name) => { + span_err!(resolver.session, span, E0428, "duplicate definition of {} `{}`", namespace, name); }, - &ResolutionError::SelfImportsOnlyAllowedWithin => { - resolve_err!(resolver, span, E0429, "{}", + ResolutionError::SelfImportsOnlyAllowedWithin => { + span_err!(resolver.session, span, E0429, "{}", "`self` imports are only allowed within a { } list"); }, - &ResolutionError::SelfImportCanOnlyAppearOnceInTheList => { - resolve_err!(resolver, span, E0430, + ResolutionError::SelfImportCanOnlyAppearOnceInTheList => { + span_err!(resolver.session, span, E0430, "`self` import can only appear once in the list"); }, - &ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => { - resolve_err!(resolver, span, E0431, + ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => { + span_err!(resolver.session, span, E0431, "`self` import can only appear in an import list with a \ non-empty prefix"); } - &ResolutionError::UnresolvedImport(name) => { + ResolutionError::UnresolvedImport(name) => { let msg = match name { Some((n, Some(p))) => format!("unresolved import `{}`{}", n, p), Some((n, None)) => format!("unresolved import (maybe you meant `{}::*`?)", n), None => "unresolved import".to_owned() }; - resolve_err!(resolver, span, E0432, "{}", msg); + span_err!(resolver.session, span, E0432, "{}", msg); }, - &ResolutionError::FailedToResolve(msg) => { - resolve_err!(resolver, span, E0433, "failed to resolve. {}", msg); + ResolutionError::FailedToResolve(msg) => { + span_err!(resolver.session, span, E0433, "failed to resolve. {}", msg); }, - &ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { - resolve_err!(resolver, span, E0434, "{}", + ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { + span_err!(resolver.session, span, E0434, "{}", "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); }, - &ResolutionError::AttemptToUseNonConstantValueInConstant =>{ - resolve_err!(resolver, span, E0435, + ResolutionError::AttemptToUseNonConstantValueInConstant =>{ + span_err!(resolver.session, span, E0435, "attempt to use a non-constant value in a constant"); }, } @@ -1563,7 +1558,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathSearch, true) { Failed(Some((span, msg))) => { - resolve_error(self, span, &ResolutionError::FailedToResolve(&*msg)); + resolve_error(self, span, ResolutionError::FailedToResolve(&*msg)); }, Failed(None) => (), // Continue up the search chain. Indeterminate => { @@ -1823,11 +1818,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if sn.contains("::") { resolve_error(self, (*imports)[index].span, - &ResolutionError::UnresolvedImport(None)); + ResolutionError::UnresolvedImport(None)); } else { resolve_error(self, (*imports)[index].span, - &ResolutionError::UnresolvedImport(Some((&*sn, None)))); + ResolutionError::UnresolvedImport(Some((&*sn, None)))); } } @@ -1956,7 +1951,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, span, - &ResolutionError::CannotCaptureDynamicEnvironmentInFnItem + ResolutionError::CannotCaptureDynamicEnvironmentInFnItem ); return None; } @@ -1965,7 +1960,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, span, - &ResolutionError::AttemptToUseNonConstantValueInConstant + ResolutionError::AttemptToUseNonConstantValueInConstant ); return None; } @@ -1984,12 +1979,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error(self, span, - &ResolutionError::TypeParametersFromOuterFunction); + ResolutionError::TypeParametersFromOuterFunction); return None; } ConstantItemRibKind => { // see #9186 - resolve_error(self, span, &ResolutionError::OuterTypeParameterContext); + resolve_error(self, span, ResolutionError::OuterTypeParameterContext); return None; } } @@ -2189,7 +2184,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if seen_bindings.contains(&name) { resolve_error(self, type_parameter.span, - &ResolutionError::NameAlreadyUsedInTypeParameterList( + ResolutionError::NameAlreadyUsedInTypeParameterList( name) ); } @@ -2280,7 +2275,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } else { resolve_error(self, trait_path.span, - &ResolutionError::IsNotATrait(&*path_names_to_string(trait_path, + ResolutionError::IsNotATrait(&*path_names_to_string(trait_path, path_depth)) ); @@ -2294,7 +2289,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } else { resolve_error(self, trait_path.span, - &ResolutionError::UndeclaredTraitName( + ResolutionError::UndeclaredTraitName( &*path_names_to_string(trait_path, path_depth)) ); Err(()) @@ -2316,7 +2311,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } else { resolve_error(self, eq_pred.span, - &ResolutionError::UndeclaredAssociatedType); + ResolutionError::UndeclaredAssociatedType); } } } @@ -2443,7 +2438,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let path_str = path_names_to_string(&trait_ref.path, 0); resolve_error(self, span, - &ResolutionError::MethodNotMemberOfTrait(name, + ResolutionError::MethodNotMemberOfTrait(name, &*path_str)); } } @@ -2493,14 +2488,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { resolve_error(self, p.span, - &ResolutionError::VariableNotBoundInPattern(key, + ResolutionError::VariableNotBoundInPattern(key, i + 1)); } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { resolve_error(self, binding_i.span, - &ResolutionError::VariableBoundWithDifferentMode(key, + ResolutionError::VariableBoundWithDifferentMode(key, i + 1) ); } @@ -2512,7 +2507,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !map_0.contains_key(&key) { resolve_error(self, binding.span, - &ResolutionError::VariableNotBoundInParentPattern(key, + ResolutionError::VariableNotBoundInParentPattern(key, i + 1)); } } @@ -2629,11 +2624,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if is_invalid_self_type_name { resolve_error(self, ty.span, - &ResolutionError::SelfUsedOutsideImplOrTrait); + ResolutionError::SelfUsedOutsideImplOrTrait); } else { resolve_error(self, ty.span, - &ResolutionError::UseOfUndeclared( + ResolutionError::UseOfUndeclared( kind, &*path_names_to_string(path, 0)) @@ -2692,7 +2687,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, pattern.span, - &ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct( + ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct( renamed) ); } @@ -2715,7 +2710,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, pattern.span, - &ResolutionError::OnlyIrrefutablePatternsAllowedHere + ResolutionError::OnlyIrrefutablePatternsAllowedHere ); } BareIdentifierPatternUnresolved => { @@ -2751,7 +2746,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, pattern.span, - &ResolutionError::IdentifierBoundMoreThanOnceInParameterList( + ResolutionError::IdentifierBoundMoreThanOnceInParameterList( &*token::get_ident(ident)) ); } else if bindings_list.get(&renamed) == @@ -2761,7 +2756,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, pattern.span, - &ResolutionError::IdentifierBoundMoreThanOnceInSamePattern( + ResolutionError::IdentifierBoundMoreThanOnceInSamePattern( &*token::get_ident(ident)) ); } @@ -2796,7 +2791,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { DefStatic(..) => { resolve_error(&self, path.span, - &ResolutionError::StaticVariableReference); + ResolutionError::StaticVariableReference); } _ => { // If anything ends up here entirely resolved, @@ -2807,7 +2802,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, path.span, - &ResolutionError::NotAnEnumVariantStructOrConst( + ResolutionError::NotAnEnumVariantStructOrConst( &*token::get_ident( path.segments.last().unwrap().identifier) ) @@ -2825,7 +2820,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, path.span, - &ResolutionError::UnresolvedEnumVariantStructOrConst( + ResolutionError::UnresolvedEnumVariantStructOrConst( &*token::get_ident(path.segments.last().unwrap().identifier)) ); } @@ -2862,7 +2857,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, path.span, - &ResolutionError::NotAnAssociatedConst( + ResolutionError::NotAnAssociatedConst( &*token::get_ident( path.segments.last().unwrap().identifier) ) @@ -2873,7 +2868,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, path.span, - &ResolutionError::UnresolvedAssociatedConst( + ResolutionError::UnresolvedAssociatedConst( &*token::get_ident(path.segments.last().unwrap().identifier) ) ); @@ -2892,7 +2887,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, path.span, - &ResolutionError::DoesNotNameAStruct( + ResolutionError::DoesNotNameAStruct( &*path_names_to_string(path, 0)) ); } @@ -2942,7 +2937,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { DefStatic(..) => { resolve_error(self, span, - &ResolutionError::StaticVariableReference); + ResolutionError::StaticVariableReference); return BareIdentifierPatternUnresolved; } _ => { @@ -2959,7 +2954,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Failed(err) => { match err { Some((span, msg)) => { - resolve_error(self, span, &ResolutionError::FailedToResolve(&*msg)); + resolve_error(self, span, ResolutionError::FailedToResolve(&*msg)); } None => () } @@ -3188,7 +3183,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - resolve_error(self, span, &ResolutionError::FailedToResolve(&*msg)); + resolve_error(self, span, ResolutionError::FailedToResolve(&*msg)); return None; } Indeterminate => panic!("indeterminate unexpected"), @@ -3247,7 +3242,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }; - resolve_error(self, span, &ResolutionError::FailedToResolve(&*msg)); + resolve_error(self, span, ResolutionError::FailedToResolve(&*msg)); return None; } @@ -3343,7 +3338,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { failed to resolve {}", name); if let Some((span, msg)) = err { - resolve_error(self, span, &ResolutionError::FailedToResolve(&*msg)) + resolve_error(self, span, ResolutionError::FailedToResolve(&*msg)) } return None; @@ -3548,7 +3543,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error(self, expr.span, - &ResolutionError::StructVariantUsedAsFunction(&*path_name)); + ResolutionError::StructVariantUsedAsFunction(&*path_name)); let msg = format!("did you mean to write: \ `{} {{ /* fields */ }}`?", @@ -3588,7 +3583,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, expr.span, - &ResolutionError::StructVariantUsedAsFunction( + ResolutionError::StructVariantUsedAsFunction( &*path_name) ); @@ -3620,7 +3615,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error( self, expr.span, - &ResolutionError::SelfNotAvailableInStaticMethod + ResolutionError::SelfNotAvailableInStaticMethod ); } else { let last_name = path.segments.last().unwrap().identifier.name; @@ -3647,7 +3642,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error(self, expr.span, - &ResolutionError::UnresolvedName(&*path_name, + ResolutionError::UnresolvedName(&*path_name, &*msg)); } } @@ -3668,7 +3663,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolve_error(self, path.span, - &ResolutionError::DoesNotNameAStruct( + ResolutionError::DoesNotNameAStruct( &*path_names_to_string(path, 0)) ); } @@ -3697,7 +3692,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => { resolve_error(self, expr.span, - &ResolutionError::UndeclaredLabel(&*token::get_ident(label))) + ResolutionError::UndeclaredLabel(&*token::get_ident(label))) } Some(DlDef(def @ DefLabel(_))) => { // Since this def is a label, it is never read. @@ -3845,7 +3840,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { BindByRef(..) => { resolve_error(self, pat.span, - &ResolutionError::CannotUseRefBindingModeWith(descr)); + ResolutionError::CannotUseRefBindingModeWith(descr)); } } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 080c99b07d622..e797da7b8f64b 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -22,6 +22,7 @@ use ResolveResult; use Resolver; use UseLexicalScopeFlag; use {names_to_string, module_to_string}; +use {resolve_error, ResolutionError}; use build_reduced_graph; @@ -272,9 +273,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { Some((span, msg)) => (span, format!(". {}", msg)), None => (import_directive.span, String::new()) }; - ::resolve_error(self.resolver, + resolve_error(self.resolver, span, - &::ResolutionError::UnresolvedImport( + ResolutionError::UnresolvedImport( Some((&*import_path_to_string( &import_directive.module_path, import_directive.subclass), From 833e88db52f060089e1d771edb153ad1840d04de Mon Sep 17 00:00:00 2001 From: Steven Allen <steven@stebalien.com> Date: Tue, 14 Jul 2015 14:04:21 -0400 Subject: [PATCH 37/47] Don't mention packed attribute in reference.md --- src/doc/reference.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 060f954274a9d..ff49eb63bf20f 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1957,8 +1957,6 @@ macro scope. object file that this item's contents will be placed into. - `no_mangle` - on any item, do not apply the standard name mangling. Set the symbol for this item to its identifier. -- `packed` - on structs or enums, eliminate any padding that would be used to - align fields. - `simd` - on certain tuple structs, derive the arithmetic operators, which lower to the target's SIMD instructions, if any; the `simd` feature gate is necessary to use this attribute. From 2881bbad59633e77a26c60dcc38f5206bd79a5f5 Mon Sep 17 00:00:00 2001 From: Brian Anderson <banderson@mozilla.com> Date: Tue, 14 Jul 2015 14:41:50 -0700 Subject: [PATCH 38/47] Address more feedback --- src/libstd/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 2bb914f2095b3..1146ea0e0d8ad 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -150,9 +150,9 @@ //! //! `str`, a UTF-8 string slice, is a primitive type, and the standard //! library defines [many methods for it](primitive.str.html). Rust -//! `str`s are typically accessed as immutable references: `&mut -//! str`. Use the owned `String` type defined in -//! [`string`](string/index.html) for building and mutating strings. +//! `str`s are typically accessed as immutable references: `&str`. Use +//! the owned `String` type defined in [`string`](string/index.html) +//! for building and mutating strings. //! //! For converting to strings use the [`format!`](fmt/index.html) //! macro, and for converting from strings use the From 441b1c6103c55eb78532f9e3695463bddd3b5913 Mon Sep 17 00:00:00 2001 From: Nick Cameron <ncameron@mozilla.com> Date: Wed, 15 Jul 2015 11:38:24 +1200 Subject: [PATCH 39/47] Some more default implementations for the compiler driver callbacks. --- src/librustc_driver/lib.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 7ccada1079ff9..6a229ef3f5e97 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -204,7 +204,9 @@ pub trait CompilerCalls<'a> { fn early_callback(&mut self, &getopts::Matches, &diagnostics::registry::Registry) - -> Compilation; + -> Compilation { + Compilation::Continue + } // Hook for a callback late in the process of handling arguments. This will // be called just before actual compilation starts (and before build_controller @@ -215,7 +217,9 @@ pub trait CompilerCalls<'a> { &Input, &Option<PathBuf>, &Option<PathBuf>) - -> Compilation; + -> Compilation { + Compilation::Continue + } // Called after we extract the input from the arguments. Gives the implementer // an opportunity to change the inputs or to add some custom input handling. @@ -236,7 +240,9 @@ pub trait CompilerCalls<'a> { &Option<PathBuf>, &Option<PathBuf>, &diagnostics::registry::Registry) - -> Option<(Input, Option<PathBuf>)>; + -> Option<(Input, Option<PathBuf>)> { + None + } // Parse pretty printing information from the arguments. The implementer can // choose to ignore this (the default will return None) which will skip pretty From 5ec1deae3b2e4e98f766d58578aae7b3a5d3c0b9 Mon Sep 17 00:00:00 2001 From: Nick Hamann <nick@wabbo.org> Date: Tue, 14 Jul 2015 18:51:47 -0500 Subject: [PATCH 40/47] Change int/uint => isize/usize in compiler docs. --- .../middle/infer/higher_ranked/README.md | 12 +-- .../middle/infer/region_inference/README.md | 18 ++--- src/librustc/middle/traits/README.md | 76 +++++++++---------- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/librustc/middle/infer/higher_ranked/README.md b/src/librustc/middle/infer/higher_ranked/README.md index 3414c7515a374..57665b6d93923 100644 --- a/src/librustc/middle/infer/higher_ranked/README.md +++ b/src/librustc/middle/infer/higher_ranked/README.md @@ -17,7 +17,7 @@ The problem we are addressing is that there is a kind of subtyping between functions with bound region parameters. Consider, for example, whether the following relation holds: - for<'a> fn(&'a int) <: for<'b> fn(&'b int)? (Yes, a => b) + for<'a> fn(&'a isize) <: for<'b> fn(&'b isize)? (Yes, a => b) The answer is that of course it does. These two types are basically the same, except that in one we used the name `a` and one we used @@ -27,14 +27,14 @@ In the examples that follow, it becomes very important to know whether a lifetime is bound in a function type (that is, is a lifetime parameter) or appears free (is defined in some outer scope). Therefore, from now on I will always write the bindings explicitly, -using the Rust syntax `for<'a> fn(&'a int)` to indicate that `a` is a +using the Rust syntax `for<'a> fn(&'a isize)` to indicate that `a` is a lifetime parameter. Now let's consider two more function types. Here, we assume that the `'b` lifetime is defined somewhere outside and hence is not a lifetime parameter bound by the function type (it "appears free"): - for<'a> fn(&'a int) <: fn(&'b int)? (Yes, a => b) + for<'a> fn(&'a isize) <: fn(&'b isize)? (Yes, a => b) This subtyping relation does in fact hold. To see why, you have to consider what subtyping means. One way to look at `T1 <: T2` is to @@ -51,7 +51,7 @@ to the same thing: a function that accepts pointers with any lifetime So, what if we reverse the order of the two function types, like this: - fn(&'b int) <: for<'a> fn(&'a int)? (No) + fn(&'b isize) <: for<'a> fn(&'a isize)? (No) Does the subtyping relationship still hold? The answer of course is no. In this case, the function accepts *only the lifetime `'b`*, @@ -60,8 +60,8 @@ accepted any lifetime. What about these two examples: - for<'a,'b> fn(&'a int, &'b int) <: for<'a> fn(&'a int, &'a int)? (Yes) - for<'a> fn(&'a int, &'a int) <: for<'a,'b> fn(&'a int, &'b int)? (No) + for<'a,'b> fn(&'a isize, &'b isize) <: for<'a> fn(&'a isize, &'a isize)? (Yes) + for<'a> fn(&'a isize, &'a isize) <: for<'a,'b> fn(&'a isize, &'b isize)? (No) Here, it is true that functions which take two pointers with any two lifetimes can be treated as if they only accepted two pointers with diff --git a/src/librustc/middle/infer/region_inference/README.md b/src/librustc/middle/infer/region_inference/README.md index e44211da4a7bb..2dc16d4fa1dd4 100644 --- a/src/librustc/middle/infer/region_inference/README.md +++ b/src/librustc/middle/infer/region_inference/README.md @@ -121,7 +121,7 @@ every expression, block, and pattern (patterns are considered to "execute" by testing the value they are applied to and creating any relevant bindings). So, for example: - fn foo(x: int, y: int) { // -+ + fn foo(x: isize, y: isize) { // -+ // +------------+ // | // | +-----+ // | // | +-+ +-+ +-+ // | @@ -168,13 +168,13 @@ an error. Here is a more involved example (which is safe) so we can see what's going on: - struct Foo { f: uint, g: uint } + struct Foo { f: usize, g: usize } ... - fn add(p: &mut uint, v: uint) { + fn add(p: &mut usize, v: usize) { *p += v; } ... - fn inc(p: &mut uint) -> uint { + fn inc(p: &mut usize) -> usize { *p += 1; *p } fn weird() { @@ -199,8 +199,8 @@ in a call expression: 'a: { 'a_arg1: let a_temp1: ... = add; - 'a_arg2: let a_temp2: &'a mut uint = &'a mut (*x).f; - 'a_arg3: let a_temp3: uint = { + 'a_arg2: let a_temp2: &'a mut usize = &'a mut (*x).f; + 'a_arg3: let a_temp3: usize = { let b_temp1: ... = inc; let b_temp2: &'b = &'b mut (*x).f; 'b_call: b_temp1(b_temp2) @@ -225,13 +225,13 @@ it will not be *dereferenced* during the evaluation of the second argument, it can still be *invalidated* by that evaluation. Consider this similar but unsound example: - struct Foo { f: uint, g: uint } + struct Foo { f: usize, g: usize } ... - fn add(p: &mut uint, v: uint) { + fn add(p: &mut usize, v: usize) { *p += v; } ... - fn consume(x: Box<Foo>) -> uint { + fn consume(x: Box<Foo>) -> usize { x.f + x.g } fn weird() { diff --git a/src/librustc/middle/traits/README.md b/src/librustc/middle/traits/README.md index 853d12172af5e..92982af92dcfe 100644 --- a/src/librustc/middle/traits/README.md +++ b/src/librustc/middle/traits/README.md @@ -12,10 +12,10 @@ reference to a trait. So, for example, if there is a generic function like: and then a call to that function: - let v: Vec<int> = clone_slice([1, 2, 3]) + let v: Vec<isize> = clone_slice([1, 2, 3]) it is the job of trait resolution to figure out (in which case) -whether there exists an impl of `int : Clone` +whether there exists an impl of `isize : Clone` Note that in some cases, like generic functions, we may not be able to find a specific impl, but we can figure out that the caller must @@ -115,27 +115,27 @@ trait Convert<Target> { This trait just has one method. It's about as simple as it gets. It converts from the (implicit) `Self` type to the `Target` type. If we -wanted to permit conversion between `int` and `uint`, we might +wanted to permit conversion between `isize` and `usize`, we might implement `Convert` like so: ```rust -impl Convert<uint> for int { ... } // int -> uint -impl Convert<int> for uint { ... } // uint -> int +impl Convert<usize> for isize { ... } // isize -> usize +impl Convert<isize> for usize { ... } // usize -> isize ``` Now imagine there is some code like the following: ```rust -let x: int = ...; +let x: isize = ...; let y = x.convert(); ``` The call to convert will generate a trait reference `Convert<$Y> for -int`, where `$Y` is the type variable representing the type of +isize`, where `$Y` is the type variable representing the type of `y`. When we match this against the two impls we can see, we will find -that only one remains: `Convert<uint> for int`. Therefore, we can +that only one remains: `Convert<usize> for isize`. Therefore, we can select this impl, which will cause the type of `$Y` to be unified to -`uint`. (Note that while assembling candidates, we do the initial +`usize`. (Note that while assembling candidates, we do the initial unifications in a transaction, so that they don't affect one another.) There are tests to this effect in src/test/run-pass: @@ -225,7 +225,7 @@ Confirmation unifies the output type parameters of the trait with the values found in the obligation, possibly yielding a type error. If we return to our example of the `Convert` trait from the previous section, confirmation is where an error would be reported, because the -impl specified that `T` would be `uint`, but the obligation reported +impl specified that `T` would be `usize`, but the obligation reported `char`. Hence the result of selection would be an error. ### Selection during translation @@ -250,12 +250,12 @@ Here is an example: trait Foo { ... } impl<U,T:Bar<U>> Foo for Vec<T> { ... } - impl Bar<uint> for int { ... } + impl Bar<usize> for isize { ... } -After one shallow round of selection for an obligation like `Vec<int> +After one shallow round of selection for an obligation like `Vec<isize> : Foo`, we would know which impl we want, and we would know that -`T=int`, but we do not know the type of `U`. We must select the -nested obligation `int : Bar<U>` to find out that `U=uint`. +`T=isize`, but we do not know the type of `U`. We must select the +nested obligation `isize : Bar<U>` to find out that `U=usize`. It would be good to only do *just as much* nested resolution as necessary. Currently, though, we just do a full resolution. @@ -263,7 +263,7 @@ necessary. Currently, though, we just do a full resolution. # Higher-ranked trait bounds One of the more subtle concepts at work are *higher-ranked trait -bounds*. An example of such a bound is `for<'a> MyTrait<&'a int>`. +bounds*. An example of such a bound is `for<'a> MyTrait<&'a isize>`. Let's walk through how selection on higher-ranked trait references works. @@ -279,21 +279,21 @@ trait Foo<X> { ``` Let's say we have a function `want_hrtb` that wants a type which -implements `Foo<&'a int>` for any `'a`: +implements `Foo<&'a isize>` for any `'a`: ```rust -fn want_hrtb<T>() where T : for<'a> Foo<&'a int> { ... } +fn want_hrtb<T>() where T : for<'a> Foo<&'a isize> { ... } ``` -Now we have a struct `AnyInt` that implements `Foo<&'a int>` for any +Now we have a struct `AnyInt` that implements `Foo<&'a isize>` for any `'a`: ```rust struct AnyInt; -impl<'a> Foo<&'a int> for AnyInt { } +impl<'a> Foo<&'a isize> for AnyInt { } ``` -And the question is, does `AnyInt : for<'a> Foo<&'a int>`? We want the +And the question is, does `AnyInt : for<'a> Foo<&'a isize>`? We want the answer to be yes. The algorithm for figuring it out is closely related to the subtyping for higher-ranked types (which is described in `middle::infer::higher_ranked::doc`, but also in a [paper by SPJ] that @@ -306,12 +306,12 @@ I recommend you read). [paper by SPJ]: http://research.microsoft.com/en-us/um/people/simonpj/papers/higher-rank/ So let's work through our example. The first thing we would do is to -skolemize the obligation, yielding `AnyInt : Foo<&'0 int>` (here `'0` +skolemize the obligation, yielding `AnyInt : Foo<&'0 isize>` (here `'0` represents skolemized region #0). Note that now have no quantifiers; in terms of the compiler type, this changes from a `ty::PolyTraitRef` to a `TraitRef`. We would then create the `TraitRef` from the impl, using fresh variables for it's bound regions (and thus getting -`Foo<&'$a int>`, where `'$a` is the inference variable for `'a`). Next +`Foo<&'$a isize>`, where `'$a` is the inference variable for `'a`). Next we relate the two trait refs, yielding a graph with the constraint that `'0 == '$a`. Finally, we check for skolemization "leaks" -- a leak is basically any attempt to relate a skolemized region to another @@ -327,13 +327,13 @@ Let's consider a failure case. Imagine we also have a struct ```rust struct StaticInt; -impl Foo<&'static int> for StaticInt; +impl Foo<&'static isize> for StaticInt; ``` -We want the obligation `StaticInt : for<'a> Foo<&'a int>` to be +We want the obligation `StaticInt : for<'a> Foo<&'a isize>` to be considered unsatisfied. The check begins just as before. `'a` is skolemized to `'0` and the impl trait reference is instantiated to -`Foo<&'static int>`. When we relate those two, we get a constraint +`Foo<&'static isize>`. When we relate those two, we get a constraint like `'static == '0`. This means that the taint set for `'0` is `{'0, 'static}`, which fails the leak check. @@ -358,13 +358,13 @@ impl<X,F> Foo<X> for F } ``` -Now let's say we have a obligation `for<'a> Foo<&'a int>` and we match +Now let's say we have a obligation `for<'a> Foo<&'a isize>` and we match this impl. What obligation is generated as a result? We want to get -`for<'a> Bar<&'a int>`, but how does that happen? +`for<'a> Bar<&'a isize>`, but how does that happen? After the matching, we are in a position where we have a skolemized -substitution like `X => &'0 int`. If we apply this substitution to the -impl obligations, we get `F : Bar<&'0 int>`. Obviously this is not +substitution like `X => &'0 isize`. If we apply this substitution to the +impl obligations, we get `F : Bar<&'0 isize>`. Obviously this is not directly usable because the skolemized region `'0` cannot leak out of our computation. @@ -375,7 +375,7 @@ leak check passed, so this taint set consists solely of the skolemized region itself plus various intermediate region variables. We then walk the trait-reference and convert every region in that taint set back to a late-bound region, so in this case we'd wind up with `for<'a> F : -Bar<&'a int>`. +Bar<&'a isize>`. # Caching and subtle considerations therewith @@ -391,8 +391,8 @@ but *replay* its effects on the type variables. The high-level idea of how the cache works is that we first replace all unbound inference variables with skolemized versions. Therefore, -if we had a trait reference `uint : Foo<$1>`, where `$n` is an unbound -inference variable, we might replace it with `uint : Foo<%0>`, where +if we had a trait reference `usize : Foo<$1>`, where `$n` is an unbound +inference variable, we might replace it with `usize : Foo<%0>`, where `%n` is a skolemized type. We would then look this up in the cache. If we found a hit, the hit would tell us the immediate next step to take in the selection process: i.e., apply impl #22, or apply where @@ -401,17 +401,17 @@ Therefore, we search through impls and where clauses and so forth, and we come to the conclusion that the only possible impl is this one, with def-id 22: - impl Foo<int> for uint { ... } // Impl #22 + impl Foo<isize> for usize { ... } // Impl #22 -We would then record in the cache `uint : Foo<%0> ==> +We would then record in the cache `usize : Foo<%0> ==> ImplCandidate(22)`. Next we would confirm `ImplCandidate(22)`, which -would (as a side-effect) unify `$1` with `int`. +would (as a side-effect) unify `$1` with `isize`. -Now, at some later time, we might come along and see a `uint : -Foo<$3>`. When skolemized, this would yield `uint : Foo<%0>`, just as +Now, at some later time, we might come along and see a `usize : +Foo<$3>`. When skolemized, this would yield `usize : Foo<%0>`, just as before, and hence the cache lookup would succeed, yielding `ImplCandidate(22)`. We would confirm `ImplCandidate(22)` which would -(as a side-effect) unify `$3` with `int`. +(as a side-effect) unify `$3` with `isize`. ## Where clauses and the local vs global cache From e8a03285b724df71cbc32a96099ebe834ba09a00 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner <a.beingessner@gmail.com> Date: Mon, 13 Jul 2015 17:29:01 -0700 Subject: [PATCH 41/47] Ratchet up travis to build stage1 and our own LLVM. Tidy is still run first for failing fast on the easy stuff. To accomplish this we have travis actually persist ccache across builds. This has LLVM built within 6 minutes, and all of stage1 built within 18. Caching should work on fresh PRs (cache acquired from the master branch). Because all we persist is ccache, there is minimal danger of persisting corrupt build state. I had to mangle `configure` a bit to make --enable-ccache work when custom compilers are provide via CC and CXX. --- .travis.yml | 30 ++++++++++++++++++++++++------ configure | 34 +++++++++++++++++++++++----------- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 29d287bfb4849..dc955bc2f2be2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,9 @@ -# Use something that's not 'ruby' so we don't set up things like -# RVM/bundler/ruby and whatnot. Right now 'rust' as a language actually -# downloads a rust/cargo snapshot, which we don't really want for building rust. +# ccache support is disabled unless your language is a C-derivative. However +# `language: C` unconditionally sets `CC=compiler`. If we just set it in our +# `env` it will be overwritten by the default (gcc 4.6). language: c +compiler: /usr/bin/gcc-4.7 +cache: ccache sudo: false # The test suite is in general way too stressful for travis, especially in @@ -9,12 +11,28 @@ sudo: false # back to only build the stage1 compiler and run a subset of tests, but this # didn't end up panning out very well. # -# As a result, we're just using travis to run `make tidy` now. It'll help -# everyone find out about their trailing spaces early on! +# As a result, we're just using travis to run `make tidy` and *only* build +# stage1 but *not* test it for now (a strict subset of the bootstrap). This will +# catch "obvious" errors like style or not even compiling. +# +# We need gcc4.7 or higher to build LLVM, and travis (well, Ubuntu 12.04) +# currently ships with 4.6. Gotta download our own. before_script: - - ./configure --llvm-root=path/to/nowhere + - ./configure --enable-ccache script: - make tidy + - make rustc-stage1 -j4 + +env: + - CXX=/usr/bin/g++-4.7 + +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.7 + - g++-4.7 # Real testing happens on http://buildbot.rust-lang.org/ # diff --git a/configure b/configure index 1d3611f88f0a9..da8630c46ffd8 100755 --- a/configure +++ b/configure @@ -1016,15 +1016,12 @@ fi if [ ! -z "$CFG_ENABLE_CCACHE" ] then - if [ -z "$CC" ] + if [ -z "$CFG_CCACHE" ] then - if [ -z "$CFG_CCACHE" ] - then - err "ccache requested but not found" - fi - - CFG_CC="ccache $CFG_CC" + err "ccache requested but not found" fi + + CFG_CC="ccache $CFG_CC" fi if [ -z "$CC" -a -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ] @@ -1513,11 +1510,26 @@ do (*) msg "inferring LLVM_CXX/CC from CXX/CC = $CXX/$CC" - LLVM_CXX_32="$CXX" - LLVM_CC_32="$CC" + if [ ! -z "$CFG_ENABLE_CCACHE" ] + then + if [ -z "$CFG_CCACHE" ] + then + err "ccache requested but not found" + fi + + LLVM_CXX_32="ccache $CXX" + LLVM_CC_32="ccache $CC" + + LLVM_CXX_64="ccache $CXX" + LLVM_CC_64="ccache $CC" + else + LLVM_CXX_32="$CXX" + LLVM_CC_32="$CC" + + LLVM_CXX_64="$CXX" + LLVM_CC_64="$CC" + fi - LLVM_CXX_64="$CXX" - LLVM_CC_64="$CC" ;; esac From 98f287240ff9518c1ea5519c5cd03dc2ba6d4452 Mon Sep 17 00:00:00 2001 From: Alisdair Owens <awo101@zepler.net> Date: Fri, 10 Jul 2015 17:34:07 +0100 Subject: [PATCH 42/47] Add specializations of read_to_end for Stdin, TcpStream and File, allowing them to read into a buffer containing uninitialized data, rather than pay the cost of zeroing. --- src/libstd/fs.rs | 4 + src/libstd/io/mod.rs | 11 +++ src/libstd/io/stdio.rs | 4 + src/libstd/net/tcp.rs | 7 ++ src/libstd/sys/common/io.rs | 139 +++++++++++++++++++++++++++++++++++ src/libstd/sys/common/mod.rs | 1 + 6 files changed, 166 insertions(+) create mode 100644 src/libstd/sys/common/io.rs diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 7598a1c7a48f0..2c78b2894311d 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -25,6 +25,7 @@ use io::{self, SeekFrom, Seek, Read, Write}; use path::{Path, PathBuf}; use sys::fs as fs_imp; use sys_common::{AsInnerMut, FromInner, AsInner}; +use sys_common::io::read_to_end_uninitialized; use vec::Vec; /// A reference to an open file on the filesystem. @@ -328,6 +329,9 @@ impl Read for File { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.inner.read(buf) } + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + unsafe { read_to_end_uninitialized(self, buf) } + } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for File { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 50c44299dc709..d0453c2e77692 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -906,6 +906,8 @@ mod tests { use io::prelude::*; use io; use super::Cursor; + use test; + use super::repeat; #[test] fn read_until() { @@ -1024,4 +1026,13 @@ mod tests { let mut buf = [0; 1]; assert_eq!(0, R.take(0).read(&mut buf).unwrap()); } + + #[bench] + fn bench_read_to_end(b: &mut test::Bencher) { + b.iter(|| { + let mut lr = repeat(1).take(10000000); + let mut vec = Vec::with_capacity(1024); + super::read_to_end(&mut lr, &mut vec); + }); + } } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 62bbb939a71f5..d8b7c8a282ca2 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -18,6 +18,7 @@ use io::lazy::Lazy; use io::{self, BufReader, LineWriter}; use sync::{Arc, Mutex, MutexGuard}; use sys::stdio; +use sys_common::io::{read_to_end_uninitialized}; use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use libc; @@ -277,6 +278,9 @@ impl<'a> Read for StdinLock<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.inner.read(buf) } + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + unsafe { read_to_end_uninitialized(self, buf) } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 085ba286dc3d9..66c8403b2685e 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -19,6 +19,7 @@ use io; use net::{ToSocketAddrs, SocketAddr, Shutdown}; use sys_common::net as net_imp; use sys_common::{AsInner, FromInner}; +use sys_common::io::read_to_end_uninitialized; use time::Duration; /// A structure which represents a TCP stream between a local socket and a @@ -189,6 +190,9 @@ impl TcpStream { #[stable(feature = "rust1", since = "1.0.0")] impl Read for TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + unsafe { read_to_end_uninitialized(self, buf) } + } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for TcpStream { @@ -198,6 +202,9 @@ impl Write for TcpStream { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Read for &'a TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + unsafe { read_to_end_uninitialized(self, buf) } + } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for &'a TcpStream { diff --git a/src/libstd/sys/common/io.rs b/src/libstd/sys/common/io.rs new file mode 100644 index 0000000000000..151d853fc9f7e --- /dev/null +++ b/src/libstd/sys/common/io.rs @@ -0,0 +1,139 @@ +// 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. +use prelude::v1::*; +use io; +use io::ErrorKind; +use io::Read; +use slice::from_raw_parts_mut; + +// Provides read_to_end functionality over an uninitialized buffer. +// This function is unsafe because it calls the underlying +// read function with a slice into uninitialized memory. The default +// implementation of read_to_end for readers will zero out new memory in +// the buf before passing it to read, but avoiding this zero can often +// lead to a fairly significant performance win. +// +// Implementations using this method have to adhere to two guarantees: +// * The implementation of read never reads the buffer provided. +// * The implementation of read correctly reports how many bytes were written. +pub unsafe fn read_to_end_uninitialized(r: &mut Read, buf: &mut Vec<u8>) -> io::Result<usize> { + + let start_len = buf.len(); + buf.reserve(16); + + // Always try to read into the empty space of the vector (from the length to the capacity). + // If the vector ever fills up then we reserve an extra byte which should trigger the normal + // reallocation routines for the vector, which will likely double the size. + // + // This function is similar to the read_to_end function in std::io, but the logic about + // reservations and slicing is different enough that this is duplicated here. + loop { + if buf.len() == buf.capacity() { + buf.reserve(1); + } + + let buf_slice = from_raw_parts_mut(buf.as_mut_ptr().offset(buf.len() as isize), + buf.capacity() - buf.len()); + + match r.read(buf_slice) { + Ok(0) => { return Ok(buf.len() - start_len); } + Ok(n) => { let len = buf.len() + n; buf.set_len(len); }, + Err(ref e) if e.kind() == ErrorKind::Interrupted => { } + Err(e) => { return Err(e); } + } + } +} + +#[cfg(test)] +mod tests { + use prelude::v1::*; + use io::prelude::*; + use super::*; + use io; + use io::{ErrorKind, Take, Repeat, repeat}; + use test; + use slice::from_raw_parts; + + struct ErrorRepeat { + lr: Take<Repeat> + } + + fn error_repeat(byte: u8, limit: u64) -> ErrorRepeat { + ErrorRepeat { lr: repeat(byte).take(limit) } + } + + impl Read for ErrorRepeat { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + let ret = self.lr.read(buf); + if let Ok(0) = ret { + return Err(io::Error::new(ErrorKind::Other, "")) + } + ret + } + } + + fn init_vec_data() -> Vec<u8> { + let mut vec = vec![10u8; 200]; + unsafe { vec.set_len(0); } + vec + } + + fn assert_all_eq(buf: &[u8], value: u8) { + for n in buf { + assert_eq!(*n, value); + } + } + + fn validate(buf: &Vec<u8>, good_read_len: usize) { + assert_all_eq(buf, 1u8); + let cap = buf.capacity(); + let end_slice = unsafe { from_raw_parts(buf.as_ptr().offset(good_read_len as isize), + cap - good_read_len) }; + assert_all_eq(end_slice, 10u8); + } + + #[test] + fn read_to_end_uninit_error() { + let mut er = error_repeat(1,100); + let mut vec = init_vec_data(); + if let Err(_) = unsafe { read_to_end_uninitialized(&mut er, &mut vec) } { + validate(&vec, 100); + } else { + assert!(false); + } + } + + #[test] + fn read_to_end_uninit_zero_len_vec() { + let mut er = repeat(1).take(100); + let mut vec = Vec::new(); + let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() }; + assert_all_eq(&vec, 1u8); + assert_eq!(vec.len(), n); + } + + #[test] + fn read_to_end_uninit_good() { + let mut er = repeat(1).take(100); + let mut vec = init_vec_data(); + let n = unsafe{ read_to_end_uninitialized(&mut er, &mut vec).unwrap() }; + validate(&vec, 100); + assert_eq!(vec.len(), n); + } + + #[bench] + fn bench_uninitialized(b: &mut test::Bencher) { + b.iter(|| { + let mut lr = repeat(1).take(10000000); + let mut vec = Vec::with_capacity(1024); + unsafe { read_to_end_uninitialized(&mut lr, &mut vec) }; + }); + } +} diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs index b528575bbed33..69c54f9891759 100644 --- a/src/libstd/sys/common/mod.rs +++ b/src/libstd/sys/common/mod.rs @@ -16,6 +16,7 @@ pub mod backtrace; pub mod condvar; pub mod mutex; pub mod net; +pub mod io; pub mod poison; pub mod remutex; pub mod rwlock; From cfa8e48b21fad7748659b6a4d74754fab9020891 Mon Sep 17 00:00:00 2001 From: Vincent Bernat <vincent@bernat.im> Date: Wed, 15 Jul 2015 23:32:58 +0200 Subject: [PATCH 43/47] doc: add rel=prev/next for links to adjacent sections This help people using keyboard navigation or with disabilities to easily browse through pagination. For example, in Vimium, a reader can do `[[` or `]]` to browse through the pages. --- src/rustbook/javascript.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rustbook/javascript.rs b/src/rustbook/javascript.rs index f33b79cc1888f..8e530bee39aad 100644 --- a/src/rustbook/javascript.rs +++ b/src/rustbook/javascript.rs @@ -57,11 +57,13 @@ document.addEventListener("DOMContentLoaded", function(event) { if (i > 0) { var prevNode = toc[i-1].cloneNode(true); prevNode.className = 'left'; + prevNode.setAttribute('rel', 'prev'); nav.appendChild(prevNode); } if (i < toc.length - 1) { var nextNode = toc[i+1].cloneNode(true); nextNode.className = 'right'; + nextNode.setAttribute('rel', 'next'); nav.appendChild(nextNode); } document.getElementById('page').appendChild(nav); From e1073dd50142825256e70e350c4e92e0f93d1b3c Mon Sep 17 00:00:00 2001 From: Tamir Duberstein <tamird@gmail.com> Date: Wed, 15 Jul 2015 23:51:51 -0400 Subject: [PATCH 44/47] Remove reference to gdb-pretty-struct-and-enums.rs It was removed in bba934f19ab26d5afc4f0be923ea699010883906. Fixes #27059. --- src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs index fa15e31450f8b..5dd428119569d 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// This test uses only GDB Python API features which should be available in -// older versions of GDB too. A more extensive test can be found in -// gdb-pretty-struct-and-enums.rs - // ignore-bitrig // ignore-windows failing on win32 bot // ignore-freebsd: gdb package too new From 30ac7e78e26f1f52fc8c5b56bbdab4cc27bb3263 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 16 Jul 2015 15:21:59 +0530 Subject: [PATCH 45/47] Fixup #27046 with pattern bindings --- src/librustc_driver/lib.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index a8856e42da432..873950b0be893 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -202,8 +202,8 @@ pub trait CompilerCalls<'a> { // be called straight after options have been parsed but before anything // else (e.g., selecting input and output). fn early_callback(&mut self, - &getopts::Matches, - &diagnostics::registry::Registry) + _: &getopts::Matches, + _: &diagnostics::registry::Registry) -> Compilation { Compilation::Continue } @@ -212,11 +212,11 @@ pub trait CompilerCalls<'a> { // be called just before actual compilation starts (and before build_controller // is called), after all arguments etc. have been completely handled. fn late_callback(&mut self, - &getopts::Matches, - &Session, - &Input, - &Option<PathBuf>, - &Option<PathBuf>) + _: &getopts::Matches, + _: &Session, + _: &Input, + _: &Option<PathBuf>, + _: &Option<PathBuf>) -> Compilation { Compilation::Continue } @@ -235,11 +235,11 @@ pub trait CompilerCalls<'a> { // emitting error messages. Returning None will cause compilation to stop // at this point. fn no_input(&mut self, - &getopts::Matches, - &config::Options, - &Option<PathBuf>, - &Option<PathBuf>, - &diagnostics::registry::Registry) + _: &getopts::Matches, + _: &config::Options, + _: &Option<PathBuf>, + _: &Option<PathBuf>, + _: &diagnostics::registry::Registry) -> Option<(Input, Option<PathBuf>)> { None } From 7c202a39c156d9a51c3dd1ebe34ecaaea188a175 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 16 Jul 2015 16:37:30 +0530 Subject: [PATCH 46/47] Fixup test --- src/test/compile-fail/issue-6702.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/compile-fail/issue-6702.rs b/src/test/compile-fail/issue-6702.rs index e464ddf54c2d9..bfda113ae8bc9 100644 --- a/src/test/compile-fail/issue-6702.rs +++ b/src/test/compile-fail/issue-6702.rs @@ -14,6 +14,6 @@ struct Monster { fn main() { - let _m = Monster(); //~ ERROR `Monster` is a structure name, but + let _m = Monster(); //~ ERROR `Monster` is a struct variant name, but //~^ HELP did you mean to write: `Monster { /* fields */ }`? } From 69e6dc0444bb62a474c8c5f7490c660f9d88c172 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar <manishsmail@gmail.com> Date: Thu, 16 Jul 2015 17:19:08 +0530 Subject: [PATCH 47/47] Fix diagnostics name clash --- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/diagnostics.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a2fee09168941..9042cedccc857 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3427,7 +3427,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, let struct_id = match def { def::DefVariant(enum_id, variant_id, true) => { if let &Some(ref base_expr) = base_expr { - span_err!(tcx.sess, base_expr.span, E0401, + span_err!(tcx.sess, base_expr.span, E0436, "functional record update syntax requires a struct"); fcx.write_error(base_expr.id); } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 636a8aeb544e7..2069e3098e638 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2211,5 +2211,5 @@ register_diagnostics! { // type because its default value `{}` references the type `Self`" E0399, // trait items need to be implemented because the associated // type `{}` was overridden - E0401 // functional record update requires a struct + E0436 // functional record update requires a struct }