/// 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
///
/// 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
///
/// ```
/// 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"))]
/// 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>,
}
/// 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)
}
/// 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 {
/// * 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 {
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 {
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();
}
}
}
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;
}
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;
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();
}
}
}
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();
}
}
}
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 };
}
}
Def::Err => {
- for segment in &path.segments {
- segment.with_parameters(|parameters| {
- for ty in ¶meters.types {
- self.ast_ty_to_ty(ty);
- }
- for binding in ¶meters.bindings {
- self.ast_ty_to_ty(&binding.ty);
- }
- });
- }
self.set_tainted_by_errors();
return self.tcx().types.err;
}
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 {}",
("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",
#![allow(deprecated)]
-#[no_debug] //~ ERROR the `#[no_debug]` attribute is
+#[no_debug] //~ ERROR the `#[no_debug]` attribute was
fn main() {}
// 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; }
}
// 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() {}
--- /dev/null
+// 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);
+ }
+}
--- /dev/null
+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
+ | ^^^^^^^^^^
+
--- /dev/null
+// 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));
+}
--- /dev/null
+{"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}
--> $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