diff --git a/config.toml.example b/config.toml.example index 312270532affc..1c851999130a0 100644 --- a/config.toml.example +++ b/config.toml.example @@ -243,19 +243,36 @@ # ============================================================================= [rust] -# Indicates that the build should be optimized for debugging Rust. Note that -# this is typically not what you want as it takes an incredibly large amount of -# time to have a debug-mode rustc compile any code (notably libstd). If this -# value is set to `true` it will affect a number of configuration options below -# as well, if unconfigured. -#debug = false - -# Whether or not to optimize the compiler and standard library +# Whether or not to optimize the compiler and standard library. +# # Note: the slowness of the non optimized compiler compiling itself usually # outweighs the time gains in not doing optimizations, therefore a -# full bootstrap takes much more time with optimize set to false. +# full bootstrap takes much more time with `optimize` set to false. #optimize = true +# Indicates that the build should be configured for debugging Rust. A +# `debug`-enabled compiler and standard library will be somewhat +# slower (due to e.g. checking of debug assertions) but should remain +# usable. +# +# Note: If this value is set to `true`, it will affect a number of +# configuration options below as well, if they have been left +# unconfigured in this file. +# +# Note: changes to the `debug` setting do *not* affect `optimize` +# above. In theory, a "maximally debuggable" environment would +# set `optimize` to `false` above to assist the introspection +# facilities of debuggers like lldb and gdb. To recreate such an +# environment, explicitly set `optimize` to `false` and `debug` +# to `true`. In practice, everyone leaves `optimize` set to +# `true`, because an unoptimized rustc with debugging +# enabled becomes *unusably slow* (e.g. rust-lang/rust#24840 +# reported a 25x slowdown) and bootstrapping the supposed +# "maximally debuggable" environment (notably libstd) takes +# hours to build. +# +#debug = false + # Number of codegen units to use for each compiler invocation. A value of 0 # means "the number of cores on this machine", and 1+ is passed through to the # compiler. diff --git a/src/Cargo.lock b/src/Cargo.lock index 6a9488226b1bd..62ce956c1efc8 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1269,7 +1269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "minifier" -version = "0.0.19" +version = "0.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2484,7 +2484,7 @@ dependencies = [ name = "rustdoc" version = "0.0.0" dependencies = [ - "minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3289,7 +3289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9908ed7c62f990c21ab41fdca53a864a3ada0da69d8729c4de727b397e27bc11" +"checksum minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "96c269bb45c39b333392b2b18ad71760b34ac65666591386b0e959ed58b3f474" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" "checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index c3fbc8eeca6ba..a5ed096a73581 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -628,6 +628,9 @@ impl Config { let default = false; config.llvm_assertions = llvm_assertions.unwrap_or(default); + let default = true; + config.rust_optimize = optimize.unwrap_or(default); + let default = match &config.channel[..] { "stable" | "beta" | "nightly" => true, _ => false, @@ -640,7 +643,6 @@ impl Config { config.debug_jemalloc = debug_jemalloc.unwrap_or(default); config.rust_debuginfo = debuginfo.unwrap_or(default); config.rust_debug_assertions = debug_assertions.unwrap_or(default); - config.rust_optimize = optimize.unwrap_or(!default); let default = config.channel == "dev"; config.ignore_git = ignore_git.unwrap_or(default); diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md index de76ddf33c17e..b01aed0915d08 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -279,7 +279,7 @@ warning: functions generic over types must be mangled 1 | #[no_mangle] | ------------ help: remove this attribute 2 | / fn foo(t: T) { -3 | | +3 | | 4 | | } | |_^ | @@ -513,7 +513,7 @@ This will produce: warning: borrow of packed field requires unsafe function or block (error E0133) --> src/main.rs:11:13 | -11 | let y = &x.data.0; +11 | let y = &x.data.0; | ^^^^^^^^^ | = note: #[warn(safe_packed_borrows)] on by default @@ -874,7 +874,7 @@ fn main() { This will produce: ```text -warning: unused `std::result::Result` which must be used +warning: unused `std::result::Result` that must be used --> src/main.rs:6:5 | 6 | returns_result(); diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 2bc037e3fee12..f7a0bbdceafc9 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -120,11 +120,17 @@ use raw_vec::RawVec; /// assert_eq!(vec, [1, 2, 3, 4]); /// ``` /// -/// It can also initialize each element of a `Vec` with a given value: +/// It can also initialize each element of a `Vec` with a given value. +/// This may be more efficient than performing allocation and initialization +/// in separate steps, especially when initializing a vector of zeros: /// /// ``` /// let vec = vec![0; 5]; /// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// +/// // The following is equivalent, but potentially slower: +/// let mut vec1 = Vec::with_capacity(5); +/// vec1.resize(5, 0); /// ``` /// /// Use a `Vec` as an efficient stack: diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index ef3f4ced4f9b2..c42fb7019c771 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -253,7 +253,7 @@ //! using it. The compiler will warn us about this kind of behavior: //! //! ```text -//! warning: unused result which must be used: iterator adaptors are lazy and +//! warning: unused result that must be used: iterator adaptors are lazy and //! do nothing unless consumed //! ``` //! diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 0255f7a0885ea..cf1c77041b91f 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -867,8 +867,6 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(option_replace)] - /// /// let mut x = Some(2); /// let old = x.replace(5); /// assert_eq!(x, Some(5)); @@ -880,7 +878,7 @@ impl Option { /// assert_eq!(old, None); /// ``` #[inline] - #[unstable(feature = "option_replace", issue = "51998")] + #[stable(feature = "option_replace", since = "1.31.0")] pub fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) } diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index ada61d8dfd873..0beb60a127097 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -39,7 +39,6 @@ #![feature(reverse_bits)] #![feature(inner_deref)] #![feature(slice_internals)] -#![feature(option_replace)] #![feature(slice_partition_dedup)] #![feature(copy_within)] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 4405c0aef9023..0514bd20c985a 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -21,7 +21,6 @@ #![feature(box_syntax)] #![cfg_attr(unix, feature(libc))] #![feature(nll)] -#![feature(option_replace)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index ae178888b6a1c..4612f1fc41403 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -59,15 +59,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { } let t = cx.tables.expr_ty(&expr); - let ty_warned = match t.sty { - ty::Tuple(ref tys) if tys.is_empty() => return, - ty::Never => return, + // FIXME(varkor): replace with `t.is_unit() || t.conservative_is_uninhabited()`. + let type_permits_no_use = match t.sty { + ty::Tuple(ref tys) if tys.is_empty() => true, + ty::Never => true, ty::Adt(def, _) => { if def.variants.is_empty() { - return; + true + } else { + check_must_use(cx, def.did, s.span, "") } - check_must_use(cx, def.did, s.span, "") - }, + } _ => false, }; @@ -95,7 +97,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { if let Some(def) = maybe_def { let def_id = def.def_id(); fn_warned = check_must_use(cx, def_id, s.span, "return value of "); + } else if type_permits_no_use { + // We don't warn about unused unit or uninhabited types. + // (See https://github.com/rust-lang/rust/issues/43806 for details.) + return; } + let must_use_op = match expr.node { // Hardcoding operators here seemed more expedient than the // refactoring that would be needed to look up the `#[must_use]` @@ -135,18 +142,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { if let Some(must_use_op) = must_use_op { cx.span_lint(UNUSED_MUST_USE, expr.span, - &format!("unused {} which must be used", must_use_op)); + &format!("unused {} that must be used", must_use_op)); op_warned = true; } - if !(ty_warned || fn_warned || op_warned) { + if !(type_permits_no_use || fn_warned || op_warned) { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } fn check_must_use(cx: &LateContext, def_id: DefId, sp: Span, describe_path: &str) -> bool { for attr in cx.tcx.get_attrs(def_id).iter() { if attr.check_name("must_use") { - let msg = format!("unused {}`{}` which must be used", + let msg = format!("unused {}`{}` that must be used", describe_path, cx.tcx.item_path_str(def_id)); let mut err = cx.struct_span_lint(UNUSED_MUST_USE, sp, &msg); // check for #[must_use = "..."] @@ -233,7 +240,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { .find(|&&(builtin, ty, _)| name == builtin && ty == AttributeType::CrateLevel) .is_some(); - // Has a plugin registered this attribute as one which must be used at + // Has a plugin registered this attribute as one that must be used at // the crate level? let plugin_crate = plugin_attributes.iter() .find(|&&(ref x, t)| name == &**x && AttributeType::CrateLevel == t) diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index ba625fb08c82c..5ab1605d7f07a 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -218,6 +218,38 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { debug!("report_mutability_error: act={:?}, acted_on={:?}", act, acted_on); match the_place_err { + // Suggest making an existing shared borrow in a struct definition a mutable borrow. + // + // This is applicable when we have a deref of a field access to a deref of a local - + // something like `*((*_1).0`. The local that we get will be a reference to the + // struct we've got a field access of (it must be a reference since there's a deref + // after the field access). + Place::Projection(box Projection { + base: Place::Projection(box Projection { + base: Place::Projection(box Projection { + base, + elem: ProjectionElem::Deref, + }), + elem: ProjectionElem::Field(field, _), + }), + elem: ProjectionElem::Deref, + }) => { + err.span_label(span, format!("cannot {ACT}", ACT = act)); + + if let Some((span, message)) = annotate_struct_field( + self.infcx.tcx, + base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx), + field, + ) { + err.span_suggestion_with_applicability( + span, + "consider changing this to be mutable", + message, + Applicability::MaybeIncorrect, + ); + } + }, + // Suggest removing a `&mut` from the use of a mutable reference. Place::Local(local) if { @@ -592,3 +624,54 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>( fn is_closure_or_generator(ty: ty::Ty) -> bool { ty.is_closure() || ty.is_generator() } + +/// Add a suggestion to a struct definition given a field access to a local. +/// This function expects the local to be a reference to a struct in order to produce a suggestion. +/// +/// ```text +/// LL | s: &'a String +/// | ---------- use `&'a mut String` here to make mutable +/// ``` +fn annotate_struct_field( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + ty: ty::Ty<'tcx>, + field: &mir::Field, +) -> Option<(Span, String)> { + // Expect our local to be a reference to a struct of some kind. + if let ty::TyKind::Ref(_, ty, _) = ty.sty { + if let ty::TyKind::Adt(def, _) = ty.sty { + let field = def.all_fields().nth(field.index())?; + // Use the HIR types to construct the diagnostic message. + let node_id = tcx.hir.as_local_node_id(field.did)?; + let node = tcx.hir.find(node_id)?; + // Now we're dealing with the actual struct that we're going to suggest a change to, + // we can expect a field that is an immutable reference to a type. + if let hir::Node::Field(field) = node { + if let hir::TyKind::Rptr(lifetime, hir::MutTy { + mutbl: hir::Mutability::MutImmutable, + ref ty + }) = field.ty.node { + // Get the snippets in two parts - the named lifetime (if there is one) and + // type being referenced, that way we can reconstruct the snippet without loss + // of detail. + let type_snippet = tcx.sess.source_map().span_to_snippet(ty.span).ok()?; + let lifetime_snippet = if !lifetime.is_elided() { + format!("{} ", tcx.sess.source_map().span_to_snippet(lifetime.span).ok()?) + } else { + String::new() + }; + + return Some(( + field.ty.span, + format!( + "&{}mut {}", + lifetime_snippet, &*type_snippet, + ), + )); + } + } + } + } + + None +} diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index e55469436abf0..307112f8ba16a 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -13,8 +13,10 @@ use borrow_check::error_reporting::UseSpans; use borrow_check::nll::region_infer::Cause; use borrow_check::{Context, MirBorrowckCtxt, WriteKind}; use rustc::ty::{self, Region, TyCtxt}; -use rustc::mir::{FakeReadCause, Local, Location, Mir, Operand}; -use rustc::mir::{Place, StatementKind, TerminatorKind}; +use rustc::mir::{ + CastKind, FakeReadCause, Local, Location, Mir, Operand, Place, Projection, ProjectionElem, + Rvalue, Statement, StatementKind, TerminatorKind +}; use rustc_errors::DiagnosticBuilder; use syntax_pos::Span; @@ -34,6 +36,7 @@ pub(in borrow_check) enum BorrowExplanation<'tcx> { #[derive(Clone, Copy)] pub(in borrow_check) enum LaterUseKind { + TraitCapture, ClosureCapture, Call, FakeLetRead, @@ -51,6 +54,7 @@ impl<'tcx> BorrowExplanation<'tcx> { match *self { BorrowExplanation::UsedLater(later_use_kind, var_or_use_span) => { let message = match later_use_kind { + LaterUseKind::TraitCapture => "borrow later captured here by trait object", LaterUseKind::ClosureCapture => "borrow later captured here by closure", LaterUseKind::Call => "borrow later used by call", LaterUseKind::FakeLetRead => "borrow later stored here", @@ -60,9 +64,10 @@ impl<'tcx> BorrowExplanation<'tcx> { }, BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span) => { let message = match later_use_kind { - LaterUseKind::ClosureCapture => { - "borrow captured here by closure, in later iteration of loop" - }, + LaterUseKind::TraitCapture => + "borrow captured here by trait object, in later iteration of loop", + LaterUseKind::ClosureCapture => + "borrow captured here by closure, in later iteration of loop", LaterUseKind::Call => "borrow used by call, in later iteration of loop", LaterUseKind::FakeLetRead => "borrow later stored here", LaterUseKind::Other => "borrow used here, in later iteration of loop", @@ -200,13 +205,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .or_else(|| self.borrow_spans(span, location)); if self.is_borrow_location_in_loop(context.loc) { - let later_use = self.later_use_kind(spans, location); + let later_use = self.later_use_kind(borrow, spans, location); BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1) } else { // Check if the location represents a `FakeRead`, and adapt the error // message to the `FakeReadCause` it is from: in particular, // the ones inserted in optimized `let var = ` patterns. - let later_use = self.later_use_kind(spans, location); + let later_use = self.later_use_kind(borrow, spans, location); BorrowExplanation::UsedLater(later_use.0, later_use.1) } } @@ -316,42 +321,184 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { false } - fn later_use_kind(&self, use_spans: UseSpans, location: Location) -> (LaterUseKind, Span) { - use self::LaterUseKind::*; - - let block = &self.mir.basic_blocks()[location.block]; + /// Determine how the borrow was later used. + fn later_use_kind( + &self, + borrow: &BorrowData<'tcx>, + use_spans: UseSpans, + location: Location + ) -> (LaterUseKind, Span) { match use_spans { - UseSpans::ClosureUse { var_span, .. } => (LaterUseKind::ClosureCapture, var_span), + UseSpans::ClosureUse { var_span, .. } => { + // Used in a closure. + (LaterUseKind::ClosureCapture, var_span) + }, UseSpans::OtherUse(span) => { - (if let Some(stmt) = block.statements.get(location.statement_index) { - match stmt.kind { - StatementKind::FakeRead(FakeReadCause::ForLet, _) => FakeLetRead, - _ => Other, + let block = &self.mir.basic_blocks()[location.block]; + + let kind = if let Some(&Statement { + kind: StatementKind::FakeRead(FakeReadCause::ForLet, _), + .. + }) = block.statements.get(location.statement_index) { + LaterUseKind::FakeLetRead + } else if self.was_captured_by_trait_object(borrow) { + LaterUseKind::TraitCapture + } else if location.statement_index == block.statements.len() { + if let TerminatorKind::Call { + ref func, from_hir_call: true, .. + } = block.terminator().kind { + // Just point to the function, to reduce the chance of overlapping spans. + let function_span = match func { + Operand::Constant(c) => c.span, + Operand::Copy(Place::Local(l)) | Operand::Move(Place::Local(l)) => { + let local_decl = &self.mir.local_decls[*l]; + if local_decl.name.is_none() { + local_decl.source_info.span + } else { + span + } + }, + _ => span, + }; + return (LaterUseKind::Call, function_span); + } else { + LaterUseKind::Other } } else { - assert_eq!(location.statement_index, block.statements.len()); - match block.terminator().kind { - TerminatorKind::Call { ref func, from_hir_call: true, .. } => { - // Just point to the function, to reduce the chance - // of overlapping spans. - let function_span = match func { - Operand::Constant(c) => c.span, - Operand::Copy(Place::Local(l)) | Operand::Move(Place::Local(l)) => { - let local_decl = &self.mir.local_decls[*l]; - if local_decl.name.is_none() { - local_decl.source_info.span - } else { - span - } - }, - _ => span, - }; - return (Call, function_span); + LaterUseKind::Other + }; + + (kind, span) + } + } + } + + /// Check if a borrowed value was captured by a trait object. We do this by + /// looking forward in the MIR from the reserve location and checking if we see + /// a unsized cast to a trait object on our data. + fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool { + // Start at the reserve location, find the place that we want to see cast to a trait object. + let location = borrow.reserve_location; + let block = &self.mir[location.block]; + let stmt = block.statements.get(location.statement_index); + debug!("was_captured_by_trait_object: location={:?} stmt={:?}", location, stmt); + + // We make a `queue` vector that has the locations we want to visit. As of writing, this + // will only ever have one item at any given time, but by using a vector, we can pop from + // it which simplifies the termination logic. + let mut queue = vec![location]; + let mut target = if let Some(&Statement { + kind: StatementKind::Assign(Place::Local(local), _), + .. + }) = stmt { + local + } else { + return false; + }; + + debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue); + while let Some(current_location) = queue.pop() { + debug!("was_captured_by_trait: target={:?}", target); + let block = &self.mir[current_location.block]; + // We need to check the current location to find out if it is a terminator. + let is_terminator = current_location.statement_index == block.statements.len(); + if !is_terminator { + let stmt = &block.statements[current_location.statement_index]; + debug!("was_captured_by_trait_object: stmt={:?}", stmt); + + // The only kind of statement that we care about is assignments... + if let StatementKind::Assign( + place, + box rvalue, + ) = &stmt.kind { + let into = match place { + Place::Local(into) => into, + Place::Projection(box Projection { + base: Place::Local(into), + elem: ProjectionElem::Deref, + }) => into, + _ => { + // Continue at the next location. + queue.push(current_location.successor_within_block()); + continue; }, - _ => Other, + }; + + match rvalue { + // If we see a use, we should check whether it is our data, and if so + // update the place that we're looking for to that new place. + Rvalue::Use(operand) => match operand { + Operand::Copy(Place::Local(from)) | + Operand::Move(Place::Local(from)) if *from == target => { + target = *into; + }, + _ => {}, + }, + // If we see a unsized cast, then if it is our data we should check + // whether it is being cast to a trait object. + Rvalue::Cast(CastKind::Unsize, operand, ty) => match operand { + Operand::Copy(Place::Local(from)) | + Operand::Move(Place::Local(from)) if *from == target => { + debug!("was_captured_by_trait_object: ty={:?}", ty); + // Check the type for a trait object. + match ty.sty { + // `&dyn Trait` + ty::TyKind::Ref(_, ty, _) if ty.is_trait() => return true, + // `Box` + _ if ty.is_box() && ty.boxed_ty().is_trait() => + return true, + // `dyn Trait` + _ if ty.is_trait() => return true, + // Anything else. + _ => return false, + } + }, + _ => return false, + }, + _ => {}, } - }, span) + } + + // Continue at the next location. + queue.push(current_location.successor_within_block()); + } else { + // The only thing we need to do for terminators is progress to the next block. + let terminator = block.terminator(); + debug!("was_captured_by_trait_object: terminator={:?}", terminator); + + match &terminator.kind { + TerminatorKind::Call { + destination: Some((Place::Local(dest), block)), + args, + .. + } => { + debug!( + "was_captured_by_trait_object: target={:?} dest={:?} args={:?}", + target, dest, args + ); + // Check if one of the arguments to this function is the target place. + let found_target = args.iter().any(|arg| { + if let Operand::Move(Place::Local(potential)) = arg { + *potential == target + } else { + false + } + }); + + // If it is, follow this to the next block and update the target. + if found_target { + target = *dest; + queue.push(block.start_location()); + } + }, + _ => {}, + } } + + debug!("was_captured_by_trait: queue={:?}", queue); } + + // We didn't find anything and ran out of locations to check. + false } } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index b53bcfa993d53..c0c97b0cabe00 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -11,7 +11,6 @@ //! Functions concerning immediate values and operands, and reading from operands. //! All high-level functions to read from memory work on operands as sources. -use std::hash::{Hash, Hasher}; use std::convert::TryInto; use rustc::{mir, ty}; @@ -221,7 +220,7 @@ impl Operand { } } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct OpTy<'tcx> { crate op: Operand, // ideally we'd make this private, but const_prop needs this pub layout: TyLayout<'tcx>, @@ -255,20 +254,6 @@ impl<'tcx> From> for OpTy<'tcx> { } } -// Validation needs to hash OpTy, but we cannot hash Layout -- so we just hash the type -impl<'tcx> Hash for OpTy<'tcx> { - fn hash(&self, state: &mut H) { - self.op.hash(state); - self.layout.ty.hash(state); - } -} -impl<'tcx> PartialEq for OpTy<'tcx> { - fn eq(&self, other: &Self) -> bool { - self.op == other.op && self.layout.ty == other.layout.ty - } -} -impl<'tcx> Eq for OpTy<'tcx> {} - // Use the existing layout if given (but sanity check in debug mode), // or compute the layout. #[inline(always)] diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 96eb69163220e..6b28fd091748f 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -874,7 +874,7 @@ impl LayoutDetails { /// to those obtained from `layout_of(ty)`, as we need to produce /// layouts for which Rust types do not exist, such as enum variants /// or synthetic fields of enums (i.e. discriminants) and fat pointers. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct TyLayout<'a, Ty> { pub ty: Ty, pub details: &'a LayoutDetails diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 845bfad7807d3..8bac007b748ac 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,6 +9,6 @@ path = "lib.rs" [dependencies] pulldown-cmark = { version = "0.1.2", default-features = false } -minifier = "0.0.19" +minifier = "0.0.20" tempfile = "3" parking_lot = "0.6.4" diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1c61e73fae03c..23f1e15de3c92 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -4098,12 +4098,13 @@ impl<'a> fmt::Display for Sidebar<'a> { ", version)?; } + } + write!(fmt, "
")?; + if it.is_crate() { write!(fmt, "

See all {}'s items

", it.name.as_ref().expect("crates always have a name"))?; } - - write!(fmt, "
")?; match it.inner { clean::StructItem(ref s) => sidebar_struct(fmt, it, s)?, clean::TraitItem(ref t) => sidebar_trait(fmt, it, t)?, diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 58ac46d22717b..91ff03a327df4 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -908,10 +908,9 @@ span.since { padding-top: 0px; } - .sidebar { + body > .sidebar { height: 45px; min-height: 40px; - width: calc(100% + 30px); margin: 0; margin-left: -15px; padding: 0 15px; @@ -1013,6 +1012,10 @@ span.since { .anchor { display: none !important; } + + h1.fqn { + overflow: initial; + } } @media print { @@ -1112,6 +1115,18 @@ h4 > .important-traits { top: 2px; } +#all-types { + text-align: center; + border: 1px solid; + margin: 0 10px; + margin-bottom: 10px; + display: block; + border-radius: 7px; +} +#all-types > p { + margin: 5px 0; +} + @media (max-width: 700px) { h4 > .important-traits { position: absolute; @@ -1135,6 +1150,9 @@ h4 > .important-traits { background-color: rgba(0,0,0,0); height: 100%; } + .sidebar { + width: calc(100% + 30px); + } .show-it { display: block; @@ -1180,6 +1198,10 @@ h4 > .important-traits { .impl > .collapse-toggle { left: -10px; } + + #all-types { + margin: 10px; + } } @@ -1383,17 +1405,6 @@ kbd { #main > ul > li { list-style: none; } -#all-types { - text-align: center; - border: 1px solid; - margin: 0 10px; - margin-bottom: 10px; - display: block; - border-radius: 7px; -} -#all-types > p { - margin: 5px 0; -} .non-exhaustive { margin-bottom: 1em; diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 48a9b2f4a93de..5c87035d8e929 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -79,7 +79,7 @@ pub use core::panic::{PanicInfo, Location}; /// /// Simply put, a type `T` implements `UnwindSafe` if it cannot easily allow /// witnessing a broken invariant through the use of `catch_unwind` (catching a -/// panic). This trait is a marker trait, so it is automatically implemented for +/// panic). This trait is an auto trait, so it is automatically implemented for /// many types, and it is also structurally composed (e.g. a struct is unwind /// safe if all of its components are unwind safe). /// diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 8d54728a75f42..3b432d0513209 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -908,11 +908,36 @@ mod prim_usize { } /// `&mut T` references can be freely coerced into `&T` references with the same referent type, and /// references with longer lifetimes can be freely coerced into references with shorter ones. /// +/// Reference equality by address, instead of comparing the values pointed to, is accomplished via +/// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while +/// [`PartialEq`] compares values. +/// +/// [`ptr::eq`]: ptr/fn.eq.html +/// [`PartialEq`]: cmp/trait.PartialEq.html +/// +/// ``` +/// use std::ptr; +/// +/// let five = 5; +/// let other_five = 5; +/// let five_ref = &five; +/// let same_five_ref = &five; +/// let other_five_ref = &other_five; +/// +/// assert!(five_ref == same_five_ref); +/// assert!(five_ref == other_five_ref); +/// +/// assert!(ptr::eq(five_ref, same_five_ref)); +/// assert!(!ptr::eq(five_ref, other_five_ref)); +/// ``` +/// /// For more information on how to use references, see [the book's section on "References and /// Borrowing"][book-refs]. /// /// [book-refs]: ../book/second-edition/ch04-02-references-and-borrowing.html /// +/// # Trait implementations +/// /// The following traits are implemented for all `&T`, regardless of the type of its referent: /// /// * [`Copy`] diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 17cb614ba11ff..98845e457b25c 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -329,7 +329,7 @@ impl Once { /// assert!(handle.join().is_err()); /// assert_eq!(INIT.is_completed(), false); /// ``` - #[unstable(feature = "once_is_completed", issue = "42")] + #[unstable(feature = "once_is_completed", issue = "54890")] #[inline] pub fn is_completed(&self) -> bool { // An `Acquire` load is enough because that makes all the initialization diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d653ed819fddd..1a7e660a4d3a7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1430,6 +1430,23 @@ impl<'a> Parser<'a> { attrs.extend(inner_attrs.iter().cloned()); Some(body) } + token::Interpolated(ref nt) => { + match &nt.0 { + token::NtBlock(..) => { + *at_end = true; + let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; + attrs.extend(inner_attrs.iter().cloned()); + Some(body) + } + _ => { + let token_str = self.this_token_to_string(); + let mut err = self.fatal(&format!("expected `;` or `{{`, found `{}`", + token_str)); + err.span_label(self.span, "expected `;` or `{`"); + return Err(err); + } + } + } _ => { let token_str = self.this_token_to_string(); let mut err = self.fatal(&format!("expected `;` or `{{`, found `{}`", @@ -3866,6 +3883,9 @@ impl<'a> Parser<'a> { // check that a comma comes after every field if !ate_comma { let err = self.struct_span_err(self.prev_span, "expected `,`"); + if let Some(mut delayed) = delayed_err { + delayed.emit(); + } return Err(err); } ate_comma = false; diff --git a/src/test/run-pass/macros/macro-as-fn-body.rs b/src/test/run-pass/macros/macro-as-fn-body.rs new file mode 100644 index 0000000000000..8c3c9fdc66df2 --- /dev/null +++ b/src/test/run-pass/macros/macro-as-fn-body.rs @@ -0,0 +1,42 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// run-pass +// +// Description - ensure Interpolated blocks can act as valid function bodies +// Covered cases: free functions, struct methods, and default trait functions + +macro_rules! def_fn { + ($body:block) => { + fn bar() $body + } +} + +trait Foo { + def_fn!({ println!("foo"); }); +} + +struct Baz {} + +impl Foo for Baz {} + +struct Qux {} + +impl Qux { + def_fn!({ println!("qux"); }); +} + +def_fn!({ println!("quux"); }); + +pub fn main() { + Baz::bar(); + Qux::bar(); + bar(); +} diff --git a/src/test/ui/did_you_mean/issue-38147-2.nll.stderr b/src/test/ui/did_you_mean/issue-38147-2.nll.stderr index 21fc4079d5b59..ebd44d46eb2ce 100644 --- a/src/test/ui/did_you_mean/issue-38147-2.nll.stderr +++ b/src/test/ui/did_you_mean/issue-38147-2.nll.stderr @@ -1,6 +1,9 @@ error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference --> $DIR/issue-38147-2.rs:17:9 | +LL | s: &'a String + | ---------- help: consider changing this to be mutable: `&'a mut String` +... LL | self.s.push('x'); | ^^^^^^ cannot borrow as mutable diff --git a/src/test/ui/did_you_mean/issue-38147-3.nll.stderr b/src/test/ui/did_you_mean/issue-38147-3.nll.stderr index d426c1f37fc1c..d644a84c7bbce 100644 --- a/src/test/ui/did_you_mean/issue-38147-3.nll.stderr +++ b/src/test/ui/did_you_mean/issue-38147-3.nll.stderr @@ -1,6 +1,9 @@ error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference --> $DIR/issue-38147-3.rs:17:9 | +LL | s: &'a String + | ---------- help: consider changing this to be mutable: `&'a mut String` +... LL | self.s.push('x'); | ^^^^^^ cannot borrow as mutable diff --git a/src/test/ui/fn_must_use.stderr b/src/test/ui/fn_must_use.stderr index b5bad22f3dc78..08d8e11ed898d 100644 --- a/src/test/ui/fn_must_use.stderr +++ b/src/test/ui/fn_must_use.stderr @@ -1,4 +1,4 @@ -warning: unused return value of `need_to_use_this_value` which must be used +warning: unused return value of `need_to_use_this_value` that must be used --> $DIR/fn_must_use.rs:60:5 | LL | need_to_use_this_value(); //~ WARN unused return value @@ -11,13 +11,13 @@ LL | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ = note: it's important -warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used +warning: unused return value of `MyStruct::need_to_use_this_method_value` that must be used --> $DIR/fn_must_use.rs:65:5 | LL | m.need_to_use_this_method_value(); //~ WARN unused return value | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: unused return value of `EvenNature::is_even` which must be used +warning: unused return value of `EvenNature::is_even` that must be used --> $DIR/fn_must_use.rs:66:5 | LL | m.is_even(); // trait method! @@ -25,25 +25,25 @@ LL | m.is_even(); // trait method! | = note: no side effects -warning: unused return value of `std::cmp::PartialEq::eq` which must be used +warning: unused return value of `std::cmp::PartialEq::eq` that must be used --> $DIR/fn_must_use.rs:72:5 | LL | 2.eq(&3); //~ WARN unused return value | ^^^^^^^^^ -warning: unused return value of `std::cmp::PartialEq::eq` which must be used +warning: unused return value of `std::cmp::PartialEq::eq` that must be used --> $DIR/fn_must_use.rs:73:5 | LL | m.eq(&n); //~ WARN unused return value | ^^^^^^^^^ -warning: unused comparison which must be used +warning: unused comparison that must be used --> $DIR/fn_must_use.rs:76:5 | LL | 2 == 3; //~ WARN unused comparison | ^^^^^^ -warning: unused comparison which must be used +warning: unused comparison that must be used --> $DIR/fn_must_use.rs:77:5 | LL | m == n; //~ WARN unused comparison diff --git a/src/test/ui/lint/must-use-ops.stderr b/src/test/ui/lint/must-use-ops.stderr index 5703536ef48fd..0f8bd97525187 100644 --- a/src/test/ui/lint/must-use-ops.stderr +++ b/src/test/ui/lint/must-use-ops.stderr @@ -1,4 +1,4 @@ -warning: unused comparison which must be used +warning: unused comparison that must be used --> $DIR/must-use-ops.rs:22:5 | LL | val == 1; @@ -10,121 +10,121 @@ note: lint level defined here LL | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ -warning: unused comparison which must be used +warning: unused comparison that must be used --> $DIR/must-use-ops.rs:23:5 | LL | val < 1; | ^^^^^^^ -warning: unused comparison which must be used +warning: unused comparison that must be used --> $DIR/must-use-ops.rs:24:5 | LL | val <= 1; | ^^^^^^^^ -warning: unused comparison which must be used +warning: unused comparison that must be used --> $DIR/must-use-ops.rs:25:5 | LL | val != 1; | ^^^^^^^^ -warning: unused comparison which must be used +warning: unused comparison that must be used --> $DIR/must-use-ops.rs:26:5 | LL | val >= 1; | ^^^^^^^^ -warning: unused comparison which must be used +warning: unused comparison that must be used --> $DIR/must-use-ops.rs:27:5 | LL | val > 1; | ^^^^^^^ -warning: unused arithmetic operation which must be used +warning: unused arithmetic operation that must be used --> $DIR/must-use-ops.rs:30:5 | LL | val + 2; | ^^^^^^^ -warning: unused arithmetic operation which must be used +warning: unused arithmetic operation that must be used --> $DIR/must-use-ops.rs:31:5 | LL | val - 2; | ^^^^^^^ -warning: unused arithmetic operation which must be used +warning: unused arithmetic operation that must be used --> $DIR/must-use-ops.rs:32:5 | LL | val / 2; | ^^^^^^^ -warning: unused arithmetic operation which must be used +warning: unused arithmetic operation that must be used --> $DIR/must-use-ops.rs:33:5 | LL | val * 2; | ^^^^^^^ -warning: unused arithmetic operation which must be used +warning: unused arithmetic operation that must be used --> $DIR/must-use-ops.rs:34:5 | LL | val % 2; | ^^^^^^^ -warning: unused logical operation which must be used +warning: unused logical operation that must be used --> $DIR/must-use-ops.rs:37:5 | LL | true && true; | ^^^^^^^^^^^^ -warning: unused logical operation which must be used +warning: unused logical operation that must be used --> $DIR/must-use-ops.rs:38:5 | LL | false || true; | ^^^^^^^^^^^^^ -warning: unused bitwise operation which must be used +warning: unused bitwise operation that must be used --> $DIR/must-use-ops.rs:41:5 | LL | 5 ^ val; | ^^^^^^^ -warning: unused bitwise operation which must be used +warning: unused bitwise operation that must be used --> $DIR/must-use-ops.rs:42:5 | LL | 5 & val; | ^^^^^^^ -warning: unused bitwise operation which must be used +warning: unused bitwise operation that must be used --> $DIR/must-use-ops.rs:43:5 | LL | 5 | val; | ^^^^^^^ -warning: unused bitwise operation which must be used +warning: unused bitwise operation that must be used --> $DIR/must-use-ops.rs:44:5 | LL | 5 << val; | ^^^^^^^^ -warning: unused bitwise operation which must be used +warning: unused bitwise operation that must be used --> $DIR/must-use-ops.rs:45:5 | LL | 5 >> val; | ^^^^^^^^ -warning: unused unary operation which must be used +warning: unused unary operation that must be used --> $DIR/must-use-ops.rs:48:5 | LL | !val; | ^^^^ -warning: unused unary operation which must be used +warning: unused unary operation that must be used --> $DIR/must-use-ops.rs:49:5 | LL | -val; | ^^^^ -warning: unused unary operation which must be used +warning: unused unary operation that must be used --> $DIR/must-use-ops.rs:50:5 | LL | *val_pointer; diff --git a/src/test/ui/lint/must_use-unit.rs b/src/test/ui/lint/must_use-unit.rs new file mode 100644 index 0000000000000..92568252164f6 --- /dev/null +++ b/src/test/ui/lint/must_use-unit.rs @@ -0,0 +1,17 @@ +#![feature(never_type)] + +#![deny(unused_must_use)] + +#[must_use] +fn foo() {} + +#[must_use] +fn bar() -> ! { + unimplemented!() +} + +fn main() { + foo(); //~ unused return value of `foo` + + bar(); //~ unused return value of `bar` +} diff --git a/src/test/ui/lint/must_use-unit.stderr b/src/test/ui/lint/must_use-unit.stderr new file mode 100644 index 0000000000000..0a956f74611b5 --- /dev/null +++ b/src/test/ui/lint/must_use-unit.stderr @@ -0,0 +1,20 @@ +error: unused return value of `foo` which must be used + --> $DIR/must_use-unit.rs:14:5 + | +LL | foo(); //~ unused return value of `foo` + | ^^^^^^ + | +note: lint level defined here + --> $DIR/must_use-unit.rs:3:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused return value of `bar` which must be used + --> $DIR/must_use-unit.rs:16:5 + | +LL | bar(); //~ unused return value of `bar` + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/nll/issue-52663-trait-object.rs b/src/test/ui/nll/issue-52663-trait-object.rs new file mode 100644 index 0000000000000..65d73eeae67c4 --- /dev/null +++ b/src/test/ui/nll/issue-52663-trait-object.rs @@ -0,0 +1,27 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] +#![feature(nll)] + +trait Foo { fn get(&self); } + +impl Foo for A { + fn get(&self) { } +} + +fn main() { + let _ = { + let tmp0 = 3; + let tmp1 = &tmp0; + box tmp1 as Box + }; + //~^^^ ERROR `tmp0` does not live long enough +} diff --git a/src/test/ui/nll/issue-52663-trait-object.stderr b/src/test/ui/nll/issue-52663-trait-object.stderr new file mode 100644 index 0000000000000..035422f245825 --- /dev/null +++ b/src/test/ui/nll/issue-52663-trait-object.stderr @@ -0,0 +1,13 @@ +error[E0597]: `tmp0` does not live long enough + --> $DIR/issue-52663-trait-object.rs:23:20 + | +LL | let tmp1 = &tmp0; + | ^^^^^ borrowed value does not live long enough +LL | box tmp1 as Box + | ------------------------- borrow later captured here by trait object +LL | }; + | - `tmp0` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/resolve/issue-54379.rs b/src/test/ui/resolve/issue-54379.rs new file mode 100644 index 0000000000000..24aa758ea6c23 --- /dev/null +++ b/src/test/ui/resolve/issue-54379.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +struct MyStruct { + pub s1: Option, +} + +fn main() { + let thing = MyStruct { s1: None }; + + match thing { + MyStruct { .., Some(_) } => {}, + _ => {} + } +} diff --git a/src/test/ui/resolve/issue-54379.stderr b/src/test/ui/resolve/issue-54379.stderr new file mode 100644 index 0000000000000..d1d693a3817b9 --- /dev/null +++ b/src/test/ui/resolve/issue-54379.stderr @@ -0,0 +1,24 @@ +error: expected `}`, found `,` + --> $DIR/issue-54379.rs:18:22 + | +LL | MyStruct { .., Some(_) } => {}, + | --^ + | | | + | | expected `}` + | `..` must be at the end and cannot have a trailing comma + +error: expected `,` + --> $DIR/issue-54379.rs:18:24 + | +LL | MyStruct { .., Some(_) } => {}, + | ^^^^ + +error[E0027]: pattern does not mention field `s1` + --> $DIR/issue-54379.rs:18:9 + | +LL | MyStruct { .., Some(_) } => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^ missing field `s1` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr index f8e5e3914eb3c..11fa447b5489a 100644 --- a/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr +++ b/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr @@ -4,7 +4,7 @@ error[E0597]: `tmp0` does not live long enough LL | let tmp1 = &tmp0; | ^^^^^ borrowed value does not live long enough LL | repeater3(tmp1) - | --------------- borrow later used here + | --------------- borrow later captured here by trait object LL | }; | - `tmp0` dropped here while still borrowed diff --git a/src/test/ui/unused/unused-result.rs b/src/test/ui/unused/unused-result.rs index 363ab6220bd6e..69d226ef1d0ed 100644 --- a/src/test/ui/unused/unused-result.rs +++ b/src/test/ui/unused/unused-result.rs @@ -28,8 +28,8 @@ fn qux() -> MustUseMsg { return foo::(); } #[allow(unused_results)] fn test() { foo::(); - foo::(); //~ ERROR: unused `MustUse` which must be used - foo::(); //~ ERROR: unused `MustUseMsg` which must be used + foo::(); //~ ERROR: unused `MustUse` that must be used + foo::(); //~ ERROR: unused `MustUseMsg` that must be used //~^ NOTE: some message } @@ -42,8 +42,8 @@ fn test2() { fn main() { foo::(); //~ ERROR: unused result - foo::(); //~ ERROR: unused `MustUse` which must be used - foo::(); //~ ERROR: unused `MustUseMsg` which must be used + foo::(); //~ ERROR: unused `MustUse` that must be used + foo::(); //~ ERROR: unused `MustUseMsg` that must be used //~^ NOTE: some message let _ = foo::(); diff --git a/src/test/ui/unused/unused-result.stderr b/src/test/ui/unused/unused-result.stderr index e6ca7b8fab8fd..156ec889387b0 100644 --- a/src/test/ui/unused/unused-result.stderr +++ b/src/test/ui/unused/unused-result.stderr @@ -1,7 +1,7 @@ -error: unused `MustUse` which must be used +error: unused `MustUse` that must be used --> $DIR/unused-result.rs:31:5 | -LL | foo::(); //~ ERROR: unused `MustUse` which must be used +LL | foo::(); //~ ERROR: unused `MustUse` that must be used | ^^^^^^^^^^^^^^^^^ | note: lint level defined here @@ -10,10 +10,10 @@ note: lint level defined here LL | #![deny(unused_results, unused_must_use)] | ^^^^^^^^^^^^^^^ -error: unused `MustUseMsg` which must be used +error: unused `MustUseMsg` that must be used --> $DIR/unused-result.rs:32:5 | -LL | foo::(); //~ ERROR: unused `MustUseMsg` which must be used +LL | foo::(); //~ ERROR: unused `MustUseMsg` that must be used | ^^^^^^^^^^^^^^^^^^^^ | = note: some message @@ -30,16 +30,16 @@ note: lint level defined here LL | #![deny(unused_results, unused_must_use)] | ^^^^^^^^^^^^^^ -error: unused `MustUse` which must be used +error: unused `MustUse` that must be used --> $DIR/unused-result.rs:45:5 | -LL | foo::(); //~ ERROR: unused `MustUse` which must be used +LL | foo::(); //~ ERROR: unused `MustUse` that must be used | ^^^^^^^^^^^^^^^^^ -error: unused `MustUseMsg` which must be used +error: unused `MustUseMsg` that must be used --> $DIR/unused-result.rs:46:5 | -LL | foo::(); //~ ERROR: unused `MustUseMsg` which must be used +LL | foo::(); //~ ERROR: unused `MustUseMsg` that must be used | ^^^^^^^^^^^^^^^^^^^^ | = note: some message