]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #44959 - arielb1:generic-errors, r=eddyb
authorbors <bors@rust-lang.org>
Mon, 2 Oct 2017 10:06:32 +0000 (10:06 +0000)
committerbors <bors@rust-lang.org>
Mon, 2 Oct 2017 10:06:32 +0000 (10:06 +0000)
handle nested generics in Generics::type_param/region_param

Fixes #44952.

r? @eddyb

19 files changed:
src/liballoc/vec.rs
src/libcore/mem.rs
src/librustc/middle/region.rs
src/librustc_errors/diagnostic.rs
src/librustc_errors/emitter.rs
src/librustc_lint/builtin.rs
src/librustc_lint/unused.rs
src/librustc_mir/util/pretty.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/mod.rs
src/libsyntax/feature_gate.rs
src/test/compile-fail/feature-gate-no-debug.rs
src/test/compile-fail/issue-1962.rs
src/test/compile-fail/type-path-err-node-types.rs
src/test/ui/lint/suggestions.rs [new file with mode: 0644]
src/test/ui/lint/suggestions.stderr [new file with mode: 0644]
src/test/ui/lint/unused_parens_json_suggestion.rs [new file with mode: 0644]
src/test/ui/lint/unused_parens_json_suggestion.stderr [new file with mode: 0644]
src/test/ui/path-lookahead.stderr

index 725d3e15f4a614c52250f20a0cd06cb6e8bdf4af..861291194f3693a41794a710c1d7e96804f0e2d3 100644 (file)
@@ -507,13 +507,9 @@ pub fn shrink_to_fit(&mut self) {
 
     /// Converts the vector into [`Box<[T]>`][owned slice].
     ///
-    /// Note that this will drop any excess capacity. Calling this and
-    /// converting back to a vector with [`into_vec`] is equivalent to calling
-    /// [`shrink_to_fit`].
+    /// Note that this will drop any excess capacity.
     ///
     /// [owned slice]: ../../std/boxed/struct.Box.html
-    /// [`into_vec`]: ../../std/primitive.slice.html#method.into_vec
-    /// [`shrink_to_fit`]: #method.shrink_to_fit
     ///
     /// # Examples
     ///
index c869054cee81abdfb31db0c70fbea540e57645e9..e085d427b8ce9214bf6fb3caf61d40d5d0c87c3e 100644 (file)
@@ -209,6 +209,35 @@ pub fn forget<T>(t: T) {
 /// The mutability of a pointer does not change its size. As such, `&T` and `&mut T`
 /// have the same size. Likewise for `*const T` and `*mut T`.
 ///
+/// # Size of `#[repr(C)]` items
+///
+/// The `C` representation for items has a defined layout. With this layout,
+/// the size of items is also stable as long as all fields have a stable size.
+///
+/// ## Size of Structs
+///
+/// For `structs`, the size is determined by the following algorithm.
+///
+/// For each field in the struct ordered by declaration order:
+///
+/// 1. Add the size of the field.
+/// 2. Round up the current size to the nearest multiple of the next field's [alignment].
+///
+/// Finally, round the size of the struct to the nearest multiple of its [alignment].
+///
+/// Unlike `C`, zero sized structs are not rounded up to one byte in size.
+///
+/// ## Size of Enums
+///
+/// Enums that carry no data other than the descriminant have the same size as C enums
+/// on the platform they are compiled for.
+///
+/// ## Size of Unions
+///
+/// The size of a union is the size of its largest field.
+///
+/// Unlike `C`, zero sized unions are not rounded up to one byte in size.
+///
 /// # Examples
 ///
 /// ```
@@ -231,6 +260,55 @@ pub fn forget<T>(t: T) {
 /// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>());
 /// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<i32>>>());
 /// ```
+///
+/// Using `#[repr(C)]`.
+///
+/// ```
+/// use std::mem;
+///
+/// #[repr(C)]
+/// struct FieldStruct {
+///     first: u8,
+///     second: u16,
+///     third: u8
+/// }
+///
+/// // The size of the first field is 1, so add 1 to the size. Size is 1.
+/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2.
+/// // The size of the second field is 2, so add 2 to the size. Size is 4.
+/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4.
+/// // The size of the third field is 1, so add 1 to the size. Size is 5.
+/// // Finally, the alignment of the struct is 2, so add 1 to the size for padding. Size is 6.
+/// assert_eq!(6, mem::size_of::<FieldStruct>());
+///
+/// #[repr(C)]
+/// struct TupleStruct(u8, u16, u8);
+///
+/// // Tuple structs follow the same rules.
+/// assert_eq!(6, mem::size_of::<TupleStruct>());
+///
+/// // Note that reordering the fields can lower the size. We can remove both padding bytes
+/// // by putting `third` before `second`.
+/// #[repr(C)]
+/// struct FieldStructOptimized {
+///     first: u8,
+///     third: u8,
+///     second: u16
+/// }
+///
+/// assert_eq!(4, mem::size_of::<FieldStructOptimized>());
+///
+/// // Union size is the size of the largest field.
+/// #[repr(C)]
+/// union ExampleUnion {
+///     smaller: u8,
+///     larger: u16
+/// }
+///
+/// assert_eq!(2, mem::size_of::<ExampleUnion>());
+/// ```
+///
+/// [alignment]: ./fn.align_of.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_size_of"))]
index 59c9e8b4c432caaf1d17e78bc5e96b7fcd0b45d6..b909ee9f93bcd2f0103593a4c0404f6fada11198 100644 (file)
@@ -413,7 +413,7 @@ pub struct ScopeTree {
 
     /// The number of visit_expr and visit_pat calls done in the body.
     /// Used to sanity check visit_expr/visit_pat call count when
-    /// calculating geneartor interiors.
+    /// calculating generator interiors.
     body_expr_count: FxHashMap<hir::BodyId, usize>,
 }
 
@@ -785,7 +785,7 @@ pub fn yield_in_scope(&self, scope: Scope) -> Option<(Span, usize)> {
 
     /// Gives the number of expressions visited in a body.
     /// Used to sanity check visit_expr call count when
-    /// calculating geneartor interiors.
+    /// calculating generator interiors.
     pub fn body_expr_count(&self, body_id: hir::BodyId) -> Option<usize> {
         self.body_expr_count.get(&body_id).map(|r| *r)
     }
index 9aae188f9ecdfdf4b7644ed5c0f3a78ca01d241b..02c0307e98cc8c0a8a0728212221a09bae710c12 100644 (file)
@@ -208,7 +208,7 @@ pub fn span_help<S: Into<MultiSpan>>(&mut self,
     /// Prints out a message with a suggested edit of the code. If the suggestion is presented
     /// inline it will only show the text message and not the text.
     ///
-    /// See `diagnostic::CodeSuggestion` for more information.
+    /// See `CodeSuggestion` for more information.
     pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
             substitution_parts: vec![Substitution {
@@ -235,7 +235,7 @@ pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String)
     /// * may look like "to do xyz, use" or "to do xyz, use abc"
     /// * may contain a name of a function, variable or type, but not whole expressions
     ///
-    /// See `diagnostic::CodeSuggestion` for more information.
+    /// See `CodeSuggestion` for more information.
     pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
         self.suggestions.push(CodeSuggestion {
             substitution_parts: vec![Substitution {
index daa132dbf6213b35202b2fd375f44e043ed7b51d..2f994de396c6f10d3f5205e8c1e15a158b5c4024 100644 (file)
@@ -48,7 +48,7 @@ fn emit(&mut self, db: &DiagnosticBuilder) {
                sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
                 let substitution = &sugg.substitution_parts[0].substitutions[0];
                 let msg = if substitution.len() == 0 || !sugg.show_code_when_inline {
-                    // This substitution is only removal or we explicitely don't want to show the
+                    // This substitution is only removal or we explicitly don't want to show the
                     // code inline, don't show it
                     format!("help: {}", sugg.msg)
                 } else {
index f3bf37c11a5468866b6feb2cdedabdb7bf2b280f..7f331418d4242193bf597e6063fe5ef2551df518 100644 (file)
@@ -76,9 +76,13 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
             if let hir::ExprLit(ref lit) = cond.node {
                 if let ast::LitKind::Bool(true) = lit.node {
                     if lit.span.ctxt() == SyntaxContext::empty() {
-                        cx.span_lint(WHILE_TRUE,
-                                    e.span,
-                                    "denote infinite loops with loop { ... }");
+                        let msg = "denote infinite loops with `loop { ... }`";
+                        let mut err = cx.struct_span_lint(WHILE_TRUE, e.span, msg);
+                        let condition_span = cx.tcx.sess.codemap().def_span(e.span);
+                        err.span_suggestion_short(condition_span,
+                                                  "use `loop`",
+                                                  "loop".to_owned());
+                        err.emit();
                     }
                 }
             }
@@ -650,10 +654,11 @@ fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
                                              ref name,
                                              ref reason,
                                              _) = g {
-                    cx.span_lint(DEPRECATED,
-                                 attr.span,
-                                 &format!("use of deprecated attribute `{}`: {}. See {}",
-                                          name, reason, link));
+                    let msg = format!("use of deprecated attribute `{}`: {}. See {}",
+                                      name, reason, link);
+                    let mut err = cx.struct_span_lint(DEPRECATED, attr.span, &msg);
+                    err.span_suggestion_short(attr.span, "remove this attribute", "".to_owned());
+                    err.emit();
                 }
                 return;
             }
index b97920dd18b77a1caccc3a9f2256c23393298573..e2ade19b6e2856a4f9a6361ad168ff412ea5578e 100644 (file)
@@ -22,6 +22,7 @@
 use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType};
 use syntax::symbol::keywords;
 use syntax::ptr::P;
+use syntax::print::pprust;
 use syntax::util::parser;
 use syntax_pos::Span;
 
@@ -70,9 +71,13 @@ fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P<hir::Pat>]) {
         let used_mutables = cx.tcx.used_mut_nodes.borrow();
         for (_, v) in &mutables {
             if !v.iter().any(|e| used_mutables.contains(e)) {
-                cx.span_lint(UNUSED_MUT,
-                             cx.tcx.hir.span(v[0]),
-                             "variable does not need to be mutable");
+                let binding_span = cx.tcx.hir.span(v[0]);
+                let mut_span = cx.tcx.sess.codemap().span_until_char(binding_span, ' ');
+                let mut err = cx.struct_span_lint(UNUSED_MUT,
+                                                  binding_span,
+                                                  "variable does not need to be mutable");
+                err.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned());
+                err.emit();
             }
         }
     }
@@ -325,9 +330,40 @@ fn check_unused_parens_core(&self,
             let necessary = struct_lit_needs_parens &&
                             parser::contains_exterior_struct_lit(&inner);
             if !necessary {
-                cx.span_lint(UNUSED_PARENS,
-                             value.span,
-                             &format!("unnecessary parentheses around {}", msg))
+                let span_msg = format!("unnecessary parentheses around {}", msg);
+                let mut err = cx.struct_span_lint(UNUSED_PARENS,
+                                                  value.span,
+                                                  &span_msg);
+                // Remove exactly one pair of parentheses (rather than naïvely
+                // stripping all paren characters)
+                let mut ate_left_paren = false;
+                let mut ate_right_paren = false;
+                let parens_removed = pprust::expr_to_string(value)
+                    .trim_matches(|c| {
+                        match c {
+                            '(' => {
+                                if ate_left_paren {
+                                    false
+                                } else {
+                                    ate_left_paren = true;
+                                    true
+                                }
+                            },
+                            ')' => {
+                                if ate_right_paren {
+                                    false
+                                } else {
+                                    ate_right_paren = true;
+                                    true
+                                }
+                            },
+                            _ => false,
+                        }
+                    }).to_owned();
+                err.span_suggestion_short(value.span,
+                                          "remove these parentheses",
+                                          parens_removed);
+                err.emit();
             }
         }
     }
index 0811783a9e57f7b75c211652c2398cc84b346c81..9e1f05f6d2f777cc2b5893c59227ff9848991237 100644 (file)
@@ -188,7 +188,9 @@ pub fn write_basic_block(tcx: TyCtxt,
     let data = &mir[block];
 
     // Basic block label at the top.
-    writeln!(w, "{}{:?}: {{", INDENT, block)?;
+    let cleanup_text = if data.is_cleanup { " // cleanup" } else { "" };
+    let lbl = format!("{}{:?}: {{", INDENT, block);
+    writeln!(w, "{0:1$}{2}", lbl, ALIGN, cleanup_text)?;
 
     // List of statements in the middle.
     let mut current_location = Location { block: block, statement_index: 0 };
index 54fd070e93cbcbb4943952386b405461bc83f606..22001d00896098ed7ddb09f79390617cc573ef95 100644 (file)
@@ -988,16 +988,6 @@ pub fn def_to_ty(&self,
                 }
             }
             Def::Err => {
-                for segment in &path.segments {
-                    segment.with_parameters(|parameters| {
-                        for ty in &parameters.types {
-                            self.ast_ty_to_ty(ty);
-                        }
-                        for binding in &parameters.bindings {
-                            self.ast_ty_to_ty(&binding.ty);
-                        }
-                    });
-                }
                 self.set_tainted_by_errors();
                 return self.tcx().types.err;
             }
index a0099a48c896bc73bf28b6962bff527239bc61f1..09294332a4f1540f05d945a7f6ef142ce2a4c041 100644 (file)
@@ -2009,7 +2009,7 @@ pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
     pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
         match self.tables.borrow().node_types().get(id) {
             Some(&t) => t,
-            None if self.err_count_since_creation() != 0 => self.tcx.types.err,
+            None if self.is_tainted_by_errors() => self.tcx.types.err,
             None => {
                 let node_id = self.tcx.hir.definitions().find_node_for_hir_id(id);
                 bug!("no type for node {}: {} in fcx {}",
index e92a7484f33676a1abf5725547536f95180549c4..f6e85ed6725ceafbd6bbe3d40d2e44aab63bec2f 100644 (file)
@@ -824,7 +824,8 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     ("no_debug", Whitelisted, Gated(
         Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721"),
         "no_debug",
-        "the `#[no_debug]` attribute is an experimental feature",
+        "the `#[no_debug]` attribute was an experimental feature that has been \
+         deprecated due to lack of demand",
         cfg_fn!(no_debug))),
     ("omit_gdb_pretty_printer_section", Whitelisted, Gated(Stability::Unstable,
                                                        "omit_gdb_pretty_printer_section",
index 9815db6550d66cc99751050870bde7dc91efc7b9..d21493de50a7fed484baf5aff3f234cf3df31b3a 100644 (file)
@@ -10,5 +10,5 @@
 
 #![allow(deprecated)]
 
-#[no_debug] //~ ERROR the `#[no_debug]` attribute is
+#[no_debug] //~ ERROR the `#[no_debug]` attribute was
 fn main() {}
index db3e9c23b76217ab8927770b5baf2bfceefc03cb..9de3040bb616c0c4707312271581b123da881ac7 100644 (file)
@@ -11,7 +11,7 @@
 // compile-flags: -D while-true
 fn main() {
   let mut i = 0;
-  while true  { //~ ERROR denote infinite loops with loop
+  while true  { //~ ERROR denote infinite loops with `loop
     i += 1;
     if i == 5 { break; }
   }
index 8f26777b441d4e5849befc3c6fa855f053501db0..7ef099d0410a60730ae508196157339bcf56162a 100644 (file)
@@ -8,10 +8,29 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Type arguments of unresolved types should have their types recorded
+// Type arguments in unresolved entities (reporting errors before type checking)
+// should have their types recorded.
 
-fn main() {
+trait Tr<T> {}
+
+fn local_type() {
     let _: Nonexistent<u8, Assoc = u16>; //~ ERROR cannot find type `Nonexistent` in this scope
+}
 
-    let _ = |a, b: _| -> _ { 0 };
+fn ufcs_trait() {
+    <u8 as Tr<u8>>::nonexistent(); //~ ERROR cannot find method or associated constant `nonexistent`
 }
+
+fn ufcs_item() {
+    NonExistent::Assoc::<u8>; //~ ERROR undeclared type or module `NonExistent`
+}
+
+fn method() {
+    nonexistent.nonexistent::<u8>(); //~ ERROR cannot find value `nonexistent`
+}
+
+fn closure() {
+    let _ = |a, b: _| -> _ { 0 }; // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs
new file mode 100644 (file)
index 0000000..874124a
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2017 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.
+
+#![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
+#![feature(no_debug)]
+
+#[no_debug] // should suggest removal of deprecated attribute
+fn main() {
+    while true { // should suggest `loop`
+        let mut a = (1); // should suggest no `mut`, no parens
+        println!("{}", a);
+    }
+}
diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr
new file mode 100644 (file)
index 0000000..5b2a4f5
--- /dev/null
@@ -0,0 +1,45 @@
+warning: unnecessary parentheses around assigned value
+  --> $DIR/suggestions.rs:17:21
+   |
+17 |         let mut a = (1); // should suggest no `mut`, no parens
+   |                     ^^^ help: remove these parentheses
+   |
+   = note: #[warn(unused_parens)] on by default
+
+warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
+  --> $DIR/suggestions.rs:14:1
+   |
+14 | #[no_debug] // should suggest removal of deprecated attribute
+   | ^^^^^^^^^^^ help: remove this attribute
+   |
+   = note: #[warn(deprecated)] on by default
+
+warning: denote infinite loops with `loop { ... }`
+  --> $DIR/suggestions.rs:16:5
+   |
+16 |       while true { // should suggest `loop`
+   |       ^---------
+   |       |
+   |  _____help: use `loop`
+   | |
+17 | |         let mut a = (1); // should suggest no `mut`, no parens
+18 | |         println!("{}", a);
+19 | |     }
+   | |_____^
+   |
+   = note: #[warn(while_true)] on by default
+
+warning: variable does not need to be mutable
+  --> $DIR/suggestions.rs:17:13
+   |
+17 |         let mut a = (1); // should suggest no `mut`, no parens
+   |             ---^^
+   |             |
+   |             help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/suggestions.rs:11:9
+   |
+11 | #![warn(unused_mut)] // UI tests pass `-A unused`—see Issue #43896
+   |         ^^^^^^^^^^
+
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs
new file mode 100644 (file)
index 0000000..d7cbd11
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2017 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.
+
+// compile-flags: --error-format json
+
+// ignore-windows (see Issue #44968)
+
+// The output for humans should just highlight the whole span without showing
+// the suggested replacement, but we also want to test that suggested
+// replacement only removes one set of parentheses, rather than naïvely
+// stripping away any starting or ending parenthesis characters—hence this
+// test of the JSON error format.
+
+fn main() {
+    // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not
+    // the malformed `1 / (2 + 3`
+    let _a = (1 / (2 + 3));
+}
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr
new file mode 100644 (file)
index 0000000..140224e
--- /dev/null
@@ -0,0 +1 @@
+{"message":"unnecessary parentheses around assigned value","code":null,"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1014,"byte_end":1027,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"#[warn(unused_parens)] on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1014,"byte_end":1027,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":"    let _a = 1 / (2 + 3);"}],"rendered":null}
index 1d4ab35046b4861d45fe89f51265371c5b66a292..19e22b3f6f94fc8c10aa82f013f0b1ced61ca61e 100644 (file)
@@ -2,7 +2,7 @@ warning: unnecessary parentheses around `return` value
   --> $DIR/path-lookahead.rs:18:10
    |
 18 |   return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
    |
    = note: #[warn(unused_parens)] on by default