diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 285140060be45..8a009b66b593e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -188,8 +188,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut bx); + let mut all_consts_ok = true; for const_ in &mir.required_consts { if let Err(err) = fx.eval_mir_constant(const_) { + all_consts_ok = false; match err { // errored or at least linted ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {} @@ -199,6 +201,25 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } } + if !all_consts_ok { + // There is no delay_span_bug here, we just have to rely on a hard error actually having + // been raised. + bx.abort(); + // `abort` does not terminate the block, so we still need to generate + // an `unreachable` terminator after it. + bx.unreachable(); + // We also have to delete all the other basic blocks again... + for bb in mir.basic_blocks().indices() { + if bb != mir::START_BLOCK { + unsafe { + bx.delete_basic_block(fx.blocks[bb]); + } + } + } + // FIXME: Can we somehow avoid all this by evaluating the consts before creating the basic + // blocks? The tricky part is doing that without duplicating `fx.eval_mir_constant`. + return; + } let memory_locals = analyze::non_ssa_locals(&fx); diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 08a4ae3962bee..25e84c38ed315 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -6,9 +6,8 @@ use crate::glue; use crate::traits::*; use crate::MemFlags; -use rustc_errors::ErrorReported; use rustc_middle::mir; -use rustc_middle::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar}; +use rustc_middle::mir::interpret::{ConstValue, Pointer, Scalar}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::Ty; use rustc_target::abi::{Abi, Align, LayoutOf, Size}; @@ -439,25 +438,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Operand::Constant(ref constant) => { - self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|err| { - match err { - // errored or at least linted - ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {} - ErrorHandled::TooGeneric => { - bug!("codegen encountered polymorphic constant") - } - } - // Allow RalfJ to sleep soundly knowing that even refactorings that remove - // the above error (or silence it under some conditions) will not cause UB. - bx.abort(); - // We still have to return an operand but it doesn't matter, - // this code is unreachable. - let ty = self.monomorphize(constant.literal.ty); - let layout = bx.cx().layout_of(ty); - bx.load_operand(PlaceRef::new_sized( - bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))), - layout, - )) + // This cannot fail because we checked all required_consts in advance. + self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|_err| { + span_bug!(constant.span, "erroneous constant not captured by required_consts") }) } } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs index e1af6fc07cf8f..73196c732f5bb 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs @@ -1,9 +1,12 @@ use rustc_hir as hir; use rustc_hir::Node; use rustc_index::vec::Idx; -use rustc_middle::mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location}; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::{ + hir::place::PlaceBase, + mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, Location}, +}; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; @@ -241,6 +244,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { format!("mut {}", self.local_names[local].unwrap()), Applicability::MachineApplicable, ); + let tcx = self.infcx.tcx; + if let ty::Closure(id, _) = the_place_err.ty(self.body, tcx).ty.kind() { + self.show_mutating_upvar(tcx, id, the_place_err, &mut err); + } } // Also suggest adding mut for upvars @@ -271,6 +278,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ); } } + + let tcx = self.infcx.tcx; + if let ty::Ref(_, ty, Mutability::Mut) = the_place_err.ty(self.body, tcx).ty.kind() + { + if let ty::Closure(id, _) = ty.kind() { + self.show_mutating_upvar(tcx, id, the_place_err, &mut err); + } + } } // complete hack to approximate old AST-borrowck @@ -463,6 +478,45 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.buffer(&mut self.errors_buffer); } + // point to span of upvar making closure call require mutable borrow + fn show_mutating_upvar( + &self, + tcx: TyCtxt<'_>, + id: &hir::def_id::DefId, + the_place_err: PlaceRef<'tcx>, + err: &mut DiagnosticBuilder<'_>, + ) { + let id = id.expect_local(); + let tables = tcx.typeck(id); + let hir_id = tcx.hir().local_def_id_to_hir_id(id); + let (span, place) = &tables.closure_kind_origins()[hir_id]; + let reason = if let PlaceBase::Upvar(upvar_id) = place.base { + let upvar = ty::place_to_string_for_capture(tcx, place); + match tables.upvar_capture(upvar_id) { + ty::UpvarCapture::ByRef(ty::UpvarBorrow { + kind: ty::BorrowKind::MutBorrow, + .. + }) => { + format!("mutable borrow of `{}`", upvar) + } + ty::UpvarCapture::ByValue(_) => { + format!("possible mutation of `{}`", upvar) + } + _ => bug!("upvar `{}` borrowed, but not mutably", upvar), + } + } else { + bug!("not an upvar") + }; + err.span_label( + *span, + format!( + "calling `{}` requires mutable binding due to {}", + self.describe_place(the_place_err).unwrap(), + reason + ), + ); + } + /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected. fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) { err.span_label(sp, format!("cannot {}", act)); diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index d9437a312aec0..88236458a213a 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -511,6 +511,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Constant(ref constant) => { let val = self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal); + // This can still fail: + // * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all + // checked yet. + // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail. self.const_to_op(val, layout)? } }; diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_mir/src/interpret/validity.rs index 423d1270ac865..0b7492631c41d 100644 --- a/compiler/rustc_mir/src/interpret/validity.rs +++ b/compiler/rustc_mir/src/interpret/validity.rs @@ -515,7 +515,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(true) } ty::Float(_) | ty::Int(_) | ty::Uint(_) => { - let value = self.ecx.read_scalar(value)?; + let value = try_validation!( + self.ecx.read_scalar(value), + self.path, + err_unsup!(ReadPointerAsBytes) => { "read of part of a pointer" }, + ); // NOTE: Keep this in sync with the array optimization for int/float // types below! if self.ctfe_mode.is_some() { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7b90e5b611cd1..2e7c9701c0c67 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -622,6 +622,7 @@ symbols! { intel, into_iter, into_result, + into_trait, intra_doc_pointers, intrinsics, irrefutable_let_patterns, @@ -1159,6 +1160,8 @@ symbols! { truncf32, truncf64, try_blocks, + try_from_trait, + try_into_trait, try_trait, tt, tuple, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1830aaa4471a6..0ab00fddfafc8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -286,21 +286,32 @@ fn suggest_restriction( ); } else { // Trivial case: `T` needs an extra bound: `T: Bound`. - let (sp, suggestion) = match super_traits { - None => predicate_constraint( + let (sp, suggestion) = match ( + generics + .params + .iter() + .filter( + |p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: Some(_), ..}), + ) + .next(), + super_traits, + ) { + (_, None) => predicate_constraint( generics, trait_ref.without_const().to_predicate(tcx).to_string(), ), - Some((ident, bounds)) => match bounds { - [.., bound] => ( - bound.span().shrink_to_hi(), - format!(" + {}", trait_ref.print_only_trait_path().to_string()), - ), - [] => ( - ident.span.shrink_to_hi(), - format!(": {}", trait_ref.print_only_trait_path().to_string()), - ), - }, + (None, Some((ident, []))) => ( + ident.span.shrink_to_hi(), + format!(": {}", trait_ref.print_only_trait_path().to_string()), + ), + (_, Some((_, [.., bounds]))) => ( + bounds.span().shrink_to_hi(), + format!(" + {}", trait_ref.print_only_trait_path().to_string()), + ), + (Some(_), Some((_, []))) => ( + generics.span.shrink_to_hi(), + format!(": {}", trait_ref.print_only_trait_path().to_string()), + ), }; err.span_suggestion_verbose( diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 139863bbe7f81..a6d3b5ef813f1 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -267,6 +267,7 @@ pub trait AsMut { /// /// [`String`]: ../../std/string/struct.String.html /// [`Vec`]: ../../std/vec/struct.Vec.html +#[rustc_diagnostic_item = "into_trait"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Into: Sized { /// Performs the conversion. @@ -382,6 +383,7 @@ pub trait From: Sized { /// /// This suffers the same restrictions and reasoning as implementing /// [`Into`], see there for details. +#[rustc_diagnostic_item = "try_into_trait"] #[stable(feature = "try_from", since = "1.34.0")] pub trait TryInto: Sized { /// The type returned in the event of a conversion error. @@ -462,6 +464,7 @@ pub trait TryInto: Sized { /// /// [`try_from`]: TryFrom::try_from /// [`!`]: ../../std/primitive.never.html +#[rustc_diagnostic_item = "try_from_trait"] #[stable(feature = "try_from", since = "1.34.0")] pub trait TryFrom: Sized { /// The type returned in the event of a conversion error. diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 0051c9eede070..14e4e4da3b96d 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -428,6 +428,40 @@ impl Option { } } + /// Returns the contained [`Some`] value, consuming the `self` value, + /// without checking that the value is not [`None`]. + /// + /// # Safety + /// + /// Calling this method on [`None`] is *[undefined behavior]*. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// #![feature(option_result_unwrap_unchecked)] + /// let x = Some("air"); + /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); + /// ``` + /// + /// ```no_run + /// #![feature(option_result_unwrap_unchecked)] + /// let x: Option<&str> = None; + /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); // Undefined behavior! + /// ``` + #[inline] + #[track_caller] + #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")] + pub unsafe fn unwrap_unchecked(self) -> T { + debug_assert!(self.is_some()); + match self { + Some(val) => val, + // SAFETY: the safety contract must be upheld by the caller. + None => unsafe { hint::unreachable_unchecked() }, + } + } + ///////////////////////////////////////////////////////////////////////// // Transforming contained values ///////////////////////////////////////////////////////////////////////// diff --git a/library/core/src/result.rs b/library/core/src/result.rs index d6d1762572928..a43ba5882edcd 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -229,7 +229,7 @@ use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; use crate::ops::{self, Deref, DerefMut}; -use crate::{convert, fmt}; +use crate::{convert, fmt, hint}; /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). /// @@ -821,6 +821,74 @@ impl Result { Err(e) => op(e), } } + + /// Returns the contained [`Ok`] value, consuming the `self` value, + /// without checking that the value is not an [`Err`]. + /// + /// # Safety + /// + /// Calling this method on an [`Err`] is *[undefined behavior]*. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ``` + /// #![feature(option_result_unwrap_unchecked)] + /// let x: Result = Ok(2); + /// assert_eq!(unsafe { x.unwrap_unchecked() }, 2); + /// ``` + /// + /// ```no_run + /// #![feature(option_result_unwrap_unchecked)] + /// let x: Result = Err("emergency failure"); + /// unsafe { x.unwrap_unchecked(); } // Undefined behavior! + /// ``` + #[inline] + #[track_caller] + #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")] + pub unsafe fn unwrap_unchecked(self) -> T { + debug_assert!(self.is_ok()); + match self { + Ok(t) => t, + // SAFETY: the safety contract must be upheld by the caller. + Err(_) => unsafe { hint::unreachable_unchecked() }, + } + } + + /// Returns the contained [`Err`] value, consuming the `self` value, + /// without checking that the value is not an [`Ok`]. + /// + /// # Safety + /// + /// Calling this method on an [`Ok`] is *[undefined behavior]*. + /// + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html + /// + /// # Examples + /// + /// ```no_run + /// #![feature(option_result_unwrap_unchecked)] + /// let x: Result = Ok(2); + /// unsafe { x.unwrap_err_unchecked() }; // Undefined behavior! + /// ``` + /// + /// ``` + /// #![feature(option_result_unwrap_unchecked)] + /// let x: Result = Err("emergency failure"); + /// assert_eq!(unsafe { x.unwrap_err_unchecked() }, "emergency failure"); + /// ``` + #[inline] + #[track_caller] + #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")] + pub unsafe fn unwrap_err_unchecked(self) -> E { + debug_assert!(self.is_err()); + match self { + // SAFETY: the safety contract must be upheld by the caller. + Ok(_) => unsafe { hint::unreachable_unchecked() }, + Err(e) => e, + } + } } impl Result<&T, E> { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 98f5982fbb2c1..b7a406c30e91b 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -64,6 +64,7 @@ #![feature(const_raw_ptr_deref)] #![feature(never_type)] #![feature(unwrap_infallible)] +#![feature(option_result_unwrap_unchecked)] #![feature(option_unwrap_none)] #![feature(peekable_next_if)] #![feature(peekable_peek_mut)] diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index 5388b4756245a..9470451278cc4 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -160,6 +160,13 @@ fn test_unwrap_or_else() { assert_eq!(x.unwrap_or_else(|| 2), 2); } +#[test] +fn test_unwrap_unchecked() { + assert_eq!(unsafe { Some(1).unwrap_unchecked() }, 1); + let s = unsafe { Some("hello".to_string()).unwrap_unchecked() }; + assert_eq!(s, "hello"); +} + #[test] fn test_iter() { let val = 5; diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs index 81660870e95e4..7aa44c6e593b3 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -119,6 +119,18 @@ pub fn test_unwrap_or_else_panic() { let _: isize = bad_err.unwrap_or_else(handler); } +#[test] +fn test_unwrap_unchecked() { + let ok: Result = Ok(100); + assert_eq!(unsafe { ok.unwrap_unchecked() }, 100); +} + +#[test] +fn test_unwrap_err_unchecked() { + let ok_err: Result = Err("Err"); + assert_eq!(unsafe { ok_err.unwrap_err_unchecked() }, "Err"); +} + #[test] pub fn test_expect_ok() { let ok: Result = Ok(100); diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 656d9669e81d2..f6b692404606d 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -25,6 +25,7 @@ #![feature(nll)] #![feature(available_concurrency)] #![feature(internal_output_capture)] +#![feature(option_unwrap_none)] #![feature(panic_unwind)] #![feature(staged_api)] #![feature(termination_trait_lib)] @@ -208,9 +209,15 @@ where use std::collections::{self, HashMap}; use std::hash::BuildHasherDefault; use std::sync::mpsc::RecvTimeoutError; + + struct RunningTest { + timeout: Instant, + join_handle: Option>, + } + // Use a deterministic hasher type TestMap = - HashMap>; + HashMap>; let tests_len = tests.len(); @@ -260,7 +267,11 @@ where let now = Instant::now(); let timed_out = running_tests .iter() - .filter_map(|(desc, timeout)| if &now >= timeout { Some(desc.clone()) } else { None }) + .filter_map( + |(desc, running_test)| { + if now >= running_test.timeout { Some(desc.clone()) } else { None } + }, + ) .collect(); for test in &timed_out { running_tests.remove(test); @@ -269,9 +280,9 @@ where } fn calc_timeout(running_tests: &TestMap) -> Option { - running_tests.values().min().map(|next_timeout| { + running_tests.values().map(|running_test| running_test.timeout).min().map(|next_timeout| { let now = Instant::now(); - if *next_timeout >= now { *next_timeout - now } else { Duration::new(0, 0) } + if next_timeout >= now { next_timeout - now } else { Duration::new(0, 0) } }) } @@ -280,7 +291,8 @@ where let test = remaining.pop().unwrap(); let event = TestEvent::TeWait(test.desc.clone()); notify_about_test_event(event)?; - run_test(opts, !opts.run_tests, test, run_strategy, tx.clone(), Concurrent::No); + run_test(opts, !opts.run_tests, test, run_strategy, tx.clone(), Concurrent::No) + .unwrap_none(); let completed_test = rx.recv().unwrap(); let event = TestEvent::TeResult(completed_test); @@ -291,11 +303,19 @@ where while pending < concurrency && !remaining.is_empty() { let test = remaining.pop().unwrap(); let timeout = time::get_default_test_timeout(); - running_tests.insert(test.desc.clone(), timeout); + let desc = test.desc.clone(); let event = TestEvent::TeWait(test.desc.clone()); notify_about_test_event(event)?; //here no pad - run_test(opts, !opts.run_tests, test, run_strategy, tx.clone(), Concurrent::Yes); + let join_handle = run_test( + opts, + !opts.run_tests, + test, + run_strategy, + tx.clone(), + Concurrent::Yes, + ); + running_tests.insert(desc, RunningTest { timeout, join_handle }); pending += 1; } @@ -323,8 +343,16 @@ where } } - let completed_test = res.unwrap(); - running_tests.remove(&completed_test.desc); + let mut completed_test = res.unwrap(); + let running_test = running_tests.remove(&completed_test.desc).unwrap(); + if let Some(join_handle) = running_test.join_handle { + if let Err(_) = join_handle.join() { + if let TrOk = completed_test.result { + completed_test.result = + TrFailedMsg("panicked after reporting success".to_string()); + } + } + } let event = TestEvent::TeResult(completed_test); notify_about_test_event(event)?; @@ -415,7 +443,7 @@ pub fn run_test( strategy: RunStrategy, monitor_ch: Sender, concurrency: Concurrent, -) { +) -> Option> { let TestDescAndFn { desc, testfn } = test; // Emscripten can catch panics but other wasm targets cannot @@ -426,7 +454,7 @@ pub fn run_test( if force_ignore || desc.ignore || ignore_because_no_process_support { let message = CompletedTest::new(desc, TrIgnored, None, Vec::new()); monitor_ch.send(message).unwrap(); - return; + return None; } struct TestRunOpts { @@ -441,7 +469,7 @@ pub fn run_test( monitor_ch: Sender, testfn: Box, opts: TestRunOpts, - ) { + ) -> Option> { let concurrency = opts.concurrency; let name = desc.name.clone(); @@ -469,9 +497,10 @@ pub fn run_test( let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_arch = "wasm32"); if concurrency == Concurrent::Yes && supports_threads { let cfg = thread::Builder::new().name(name.as_slice().to_owned()); - cfg.spawn(runtest).unwrap(); + Some(cfg.spawn(runtest).unwrap()) } else { runtest(); + None } } @@ -484,10 +513,12 @@ pub fn run_test( crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| { bencher.run(harness) }); + None } StaticBenchFn(benchfn) => { // Benchmarks aren't expected to panic, so we run them all in-process. crate::bench::benchmark(desc, monitor_ch, opts.nocapture, benchfn); + None } DynTestFn(f) => { match strategy { @@ -499,7 +530,7 @@ pub fn run_test( monitor_ch, Box::new(move || __rust_begin_short_backtrace(f)), test_run_opts, - ); + ) } StaticTestFn(f) => run_test_inner( desc, diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 74bd348e9ac1c..53f0831852456 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1,9 +1,6 @@ -// From rust: -/* global ALIASES */ - // Local js definitions: -/* global addClass, getCurrentValue, hasClass */ -/* global onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */ +/* global addClass, getSettingValue, hasClass */ +/* global onEach, onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */ /* global hideThemeButtonState, showThemeButtonState */ if (!String.prototype.startsWith) { @@ -2214,7 +2211,7 @@ function defocusSearchBar() { } } - function toggleAllDocs(pageId, fromAutoCollapse) { + function toggleAllDocs(fromAutoCollapse) { var innerToggle = document.getElementById(toggleAllDocsId); if (!innerToggle) { return; @@ -2257,14 +2254,14 @@ function defocusSearchBar() { } if (!parent || !superParent || superParent.id !== "main" || hasClass(parent, "impl") === false) { - collapseDocs(e, "hide", pageId); + collapseDocs(e, "hide"); } }); } } } - function collapseDocs(toggle, mode, pageId) { + function collapseDocs(toggle, mode) { if (!toggle || !toggle.parentNode) { return; } @@ -2384,27 +2381,27 @@ function defocusSearchBar() { } } - function collapser(pageId, e, collapse) { + function collapser(e, collapse) { // inherent impl ids are like "impl" or impl-'. // they will never be hidden by default. var n = e.parentElement; if (n.id.match(/^impl(?:-\d+)?$/) === null) { // Automatically minimize all non-inherent impls if (collapse || hasClass(n, "impl")) { - collapseDocs(e, "hide", pageId); + collapseDocs(e, "hide"); } } } - function autoCollapse(pageId, collapse) { + function autoCollapse(collapse) { if (collapse) { - toggleAllDocs(pageId, true); + toggleAllDocs(true); } else if (getSettingValue("auto-hide-trait-implementations") !== "false") { var impl_list = document.getElementById("trait-implementations-list"); if (impl_list !== null) { onEachLazy(impl_list.getElementsByClassName("collapse-toggle"), function(e) { - collapser(pageId, e, collapse); + collapser(e, collapse); }); } @@ -2412,7 +2409,7 @@ function defocusSearchBar() { if (blanket_list !== null) { onEachLazy(blanket_list.getElementsByClassName("collapse-toggle"), function(e) { - collapser(pageId, e, collapse); + collapser(e, collapse); }); } } @@ -2475,7 +2472,6 @@ function defocusSearchBar() { var toggle = createSimpleToggle(false); var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true"; var hideImplementors = getSettingValue("auto-collapse-implementors") !== "false"; - var pageId = getPageId(); var func = function(e) { var next = e.nextElementSibling; @@ -2489,7 +2485,7 @@ function defocusSearchBar() { var newToggle = toggle.cloneNode(true); insertAfter(newToggle, e.childNodes[e.childNodes.length - 1]); if (hideMethodDocs === true && hasClass(e, "method") === true) { - collapseDocs(newToggle, "hide", pageId); + collapseDocs(newToggle, "hide"); } } }; @@ -2513,7 +2509,7 @@ function defocusSearchBar() { // In case the option "auto-collapse implementors" is not set to false, we collapse // all implementors. if (hideImplementors === true && e.parentNode.id === "implementors-list") { - collapseDocs(newToggle, "hide", pageId); + collapseDocs(newToggle, "hide"); } } }; @@ -2527,7 +2523,7 @@ function defocusSearchBar() { if (e.id.match(/^impl(?:-\d+)?$/) === null) { // Automatically minimize all non-inherent impls if (hasClass(e, "impl") === true) { - collapseDocs(newToggle, "hide", pageId); + collapseDocs(newToggle, "hide"); } } }; @@ -2562,14 +2558,12 @@ function defocusSearchBar() { } onEachLazy(document.getElementsByClassName("impl-items"), function(e) { onEachLazy(e.getElementsByClassName("associatedconstant"), func); - var hiddenElems = e.getElementsByClassName("hidden"); - var needToggle = false; - - var needToggle = onEachLazy(e.getElementsByClassName("hidden"), function(hiddenElem) { - if (hasClass(hiddenElem, "content") === false && - hasClass(hiddenElem, "docblock") === false) { - return true; - } + // We transform the DOM iterator into a vec of DOM elements to prevent performance + // issues on webkit browsers. + var hiddenElems = Array.prototype.slice.call(e.getElementsByClassName("hidden")); + var needToggle = hiddenElems.some(function(hiddenElem) { + return hasClass(hiddenElem, "content") === false && + hasClass(hiddenElem, "docblock") === false; }); if (needToggle === true) { var inner_toggle = newToggle.cloneNode(true); @@ -2672,10 +2666,10 @@ function defocusSearchBar() { onEachLazy(document.getElementsByClassName("docblock"), buildToggleWrapper); onEachLazy(document.getElementsByClassName("sub-variant"), buildToggleWrapper); - var pageId = getPageId(); - autoCollapse(pageId, getSettingValue("collapse") === "true"); + autoCollapse(getSettingValue("collapse") === "true"); + var pageId = getPageId(); if (pageId !== null) { expandSection(pageId); } diff --git a/src/librustdoc/html/static/settings.js b/src/librustdoc/html/static/settings.js index bc14420232c4d..4f10e14e8558c 100644 --- a/src/librustdoc/html/static/settings.js +++ b/src/librustdoc/html/static/settings.js @@ -1,5 +1,5 @@ // Local js definitions: -/* global getCurrentValue, getVirtualKey, updateLocalStorage, updateSystemTheme */ +/* global getSettingValue, getVirtualKey, onEachLazy, updateLocalStorage, updateSystemTheme */ (function () { function changeSetting(settingName, value) { diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js index a9cc0ffdf79b0..42b54e4cc1e46 100644 --- a/src/librustdoc/html/static/source-script.js +++ b/src/librustdoc/html/static/source-script.js @@ -113,6 +113,8 @@ function createSidebarToggle() { return sidebarToggle; } +// This function is called from "source-files.js", generated in `html/render/mod.rs`. +// eslint-disable-next-line no-unused-vars function createSourceSidebar() { if (window.rootPath.endsWith("/") === false) { window.rootPath += "/"; diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js index d081781f14be1..9c5ac1625afea 100644 --- a/src/librustdoc/html/static/storage.js +++ b/src/librustdoc/html/static/storage.js @@ -1,5 +1,5 @@ // From rust: -/* global resourcesSuffix, getSettingValue */ +/* global resourcesSuffix */ var darkThemes = ["dark", "ayu"]; var currentTheme = document.getElementById("themeStyle"); @@ -35,10 +35,12 @@ var localStoredTheme = getSettingValue("theme"); var savedHref = []; +// eslint-disable-next-line no-unused-vars function hasClass(elem, className) { return elem && elem.classList && elem.classList.contains(className); } +// eslint-disable-next-line no-unused-vars function addClass(elem, className) { if (!elem || !elem.classList) { return; @@ -46,6 +48,7 @@ function addClass(elem, className) { elem.classList.add(className); } +// eslint-disable-next-line no-unused-vars function removeClass(elem, className) { if (!elem || !elem.classList) { return; @@ -81,6 +84,7 @@ function onEachLazy(lazyArray, func, reversed) { reversed); } +// eslint-disable-next-line no-unused-vars function hasOwnProperty(obj, property) { return Object.prototype.hasOwnProperty.call(obj, property); } @@ -148,6 +152,8 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { } } +// This function is called from "theme.js", generated in `html/render/mod.rs`. +// eslint-disable-next-line no-unused-vars function useSystemTheme(value) { if (value === undefined) { value = true; @@ -172,7 +178,7 @@ var updateSystemTheme = (function() { switchTheme( currentTheme, mainTheme, - JSON.parse(cssTheme) || light, + JSON.parse(cssTheme) || "light", true ); }; diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr index 44dde0fd80b0d..ea74fb966846f 100644 --- a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -20,7 +20,9 @@ error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable | LL | let f = || { | - help: consider changing this to be mutable: `mut f` -... +LL | let y = &raw mut x; + | - calling `f` requires mutable binding due to mutable borrow of `x` +LL | }; LL | f(); | ^ cannot borrow as mutable diff --git a/src/test/ui/bound-suggestions.fixed b/src/test/ui/bound-suggestions.fixed index a3fe67a95954f..be61b7dda256a 100644 --- a/src/test/ui/bound-suggestions.fixed +++ b/src/test/ui/bound-suggestions.fixed @@ -40,4 +40,29 @@ fn test_many_bounds_where(x: X) where X: Sized, X: Sized, X: Debug { //~^ ERROR doesn't implement } -pub fn main() { } +trait Foo: Sized { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bar: std::fmt::Display + Sized { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Baz: Sized where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Qux: Sized where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bat: std::fmt::Display + Sized { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +fn main() { } diff --git a/src/test/ui/bound-suggestions.rs b/src/test/ui/bound-suggestions.rs index de6133d7f59ac..86f708d42f5e7 100644 --- a/src/test/ui/bound-suggestions.rs +++ b/src/test/ui/bound-suggestions.rs @@ -40,4 +40,29 @@ fn test_many_bounds_where(x: X) where X: Sized, X: Sized { //~^ ERROR doesn't implement } -pub fn main() { } +trait Foo { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bar: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Baz where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Qux where Self: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +trait Bat: std::fmt::Display { + const SIZE: usize = core::mem::size_of::(); + //~^ ERROR the size for values of type `Self` cannot be known at compilation time +} + +fn main() { } diff --git a/src/test/ui/bound-suggestions.stderr b/src/test/ui/bound-suggestions.stderr index 010f95d8ad6f0..12e67e90265ab 100644 --- a/src/test/ui/bound-suggestions.stderr +++ b/src/test/ui/bound-suggestions.stderr @@ -76,6 +76,86 @@ help: consider further restricting type parameter `X` LL | fn test_many_bounds_where(x: X) where X: Sized, X: Sized, X: Debug { | ^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:44:46 + | +LL | const SIZE: usize = core::mem::size_of::(); + | ^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` + | +help: consider further restricting `Self` + | +LL | trait Foo: Sized { + | ^^^^^^^ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:49:46 + | +LL | const SIZE: usize = core::mem::size_of::(); + | ^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` + | +help: consider further restricting `Self` + | +LL | trait Bar: std::fmt::Display + Sized { + | ^^^^^^^ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:54:46 + | +LL | const SIZE: usize = core::mem::size_of::(); + | ^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` + | +help: consider further restricting `Self` + | +LL | trait Baz: Sized where Self: std::fmt::Display { + | ^^^^^^^ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:59:46 + | +LL | const SIZE: usize = core::mem::size_of::(); + | ^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` + | +help: consider further restricting `Self` + | +LL | trait Qux: Sized where Self: std::fmt::Display { + | ^^^^^^^ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/bound-suggestions.rs:64:46 + | +LL | const SIZE: usize = core::mem::size_of::(); + | ^^^^ doesn't have a size known at compile-time + | + ::: $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | pub const fn size_of() -> usize { + | - required by this bound in `std::mem::size_of` + | +help: consider further restricting `Self` + | +LL | trait Bat: std::fmt::Display + Sized { + | ^^^^^^^ + +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.rs b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.rs new file mode 100644 index 0000000000000..ff210ae06a3bd --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = || { + &mut my_var; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr new file mode 100644 index 0000000000000..bf9e1febdbba4 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutable-borrow-in-closure.rs:6:5 + | +LL | let callback = || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | &mut my_var; + | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs new file mode 100644 index 0000000000000..8f2d8a676302c --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = move || { + &mut my_var; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr new file mode 100644 index 0000000000000..b67cec6a609f0 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutable-borrow-in-move-closure.rs:6:5 + | +LL | let callback = move || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | &mut my_var; + | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/issue-80313-mutation-in-closure.rs b/src/test/ui/closures/issue-80313-mutation-in-closure.rs new file mode 100644 index 0000000000000..e082ea562ef22 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = || { + my_var = true; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutation-in-closure.stderr b/src/test/ui/closures/issue-80313-mutation-in-closure.stderr new file mode 100644 index 0000000000000..6e98549f6b84f --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutation-in-closure.rs:6:5 + | +LL | let callback = || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | my_var = true; + | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/closures/issue-80313-mutation-in-move-closure.rs b/src/test/ui/closures/issue-80313-mutation-in-move-closure.rs new file mode 100644 index 0000000000000..f66bf4e062831 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-move-closure.rs @@ -0,0 +1,7 @@ +fn main() { + let mut my_var = false; + let callback = move || { + my_var = true; + }; + callback(); //~ ERROR E0596 +} diff --git a/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr b/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr new file mode 100644 index 0000000000000..edd55422a0bd4 --- /dev/null +++ b/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr @@ -0,0 +1,14 @@ +error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable + --> $DIR/issue-80313-mutation-in-move-closure.rs:6:5 + | +LL | let callback = move || { + | -------- help: consider changing this to be mutable: `mut callback` +LL | my_var = true; + | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` +LL | }; +LL | callback(); + | ^^^^^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/consts/issue-79690.rs b/src/test/ui/consts/issue-79690.rs new file mode 100644 index 0000000000000..a2e7b97b3187d --- /dev/null +++ b/src/test/ui/consts/issue-79690.rs @@ -0,0 +1,32 @@ +// ignore-32bit +// This test gives a different error on 32-bit architectures. + +union Transmute { + t: T, + u: U, +} +trait Bar { + fn bar(&self) -> u32; +} +struct Foo { + foo: u32, + bar: bool, +} +impl Bar for Foo { + fn bar(&self) -> u32 { + self.foo + } +} +#[derive(Copy, Clone)] +struct Fat<'a>(&'a Foo, &'static VTable); +struct VTable { + size: Foo, +} +const FOO: &dyn Bar = &Foo { + foo: 128, + bar: false, +}; +const G: Fat = unsafe { Transmute { t: FOO }.u }; +//~^ ERROR it is undefined behavior to use this value + +fn main() {} diff --git a/src/test/ui/consts/issue-79690.stderr b/src/test/ui/consts/issue-79690.stderr new file mode 100644 index 0000000000000..918dd4c20f96c --- /dev/null +++ b/src/test/ui/consts/issue-79690.stderr @@ -0,0 +1,11 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-79690.rs:29:1 + | +LL | const G: Fat = unsafe { Transmute { t: FOO }.u }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered read of part of a pointer at .1..size.foo + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr index 5dea424596e9c..a0ed56d4bcf7b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr @@ -3,6 +3,8 @@ error[E0596]: cannot borrow `tick1` as mutable, as it is not declared as mutable | LL | let tick1 = || { | ----- help: consider changing this to be mutable: `mut tick1` +LL | counter += 1; + | ------- calling `tick1` requires mutable binding due to mutable borrow of `counter` ... LL | tick1(); | ^^^^^ cannot borrow as mutable @@ -12,6 +14,8 @@ error[E0596]: cannot borrow `tick2` as mutable, as it is not declared as mutable | LL | let tick2 = || { | ----- help: consider changing this to be mutable: `mut tick2` +LL | tick1(); + | ----- calling `tick2` requires mutable binding due to mutable borrow of `tick1` ... LL | tick2(); | ^^^^^ cannot borrow as mutable diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr index eb398628846dd..27d23e3fa044b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr @@ -2,7 +2,9 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:7:5 | LL | let tick = || counter += 1; - | ---- help: consider changing this to be mutable: `mut tick` + | ---- ------- calling `tick` requires mutable binding due to mutable borrow of `counter` + | | + | help: consider changing this to be mutable: `mut tick` LL | tick(); | ^^^^ cannot borrow as mutable diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr index b9d76d9a752ce..c00f986c397a7 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr @@ -2,7 +2,9 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:7:5 | LL | let tick = move || counter += 1; - | ---- help: consider changing this to be mutable: `mut tick` + | ---- ------- calling `tick` requires mutable binding due to possible mutation of `counter` + | | + | help: consider changing this to be mutable: `mut tick` LL | tick(); | ^^^^ cannot borrow as mutable diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index 9f389c8d2f9e7..527905e375d28 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -1,7 +1,4 @@ -use crate::utils::paths::FROM_TRAIT; -use crate::utils::{ - is_expn_of, is_type_diagnostic_item, match_def_path, match_panic_def_id, method_chain_args, span_lint_and_then, -}; +use crate::utils::{is_expn_of, is_type_diagnostic_item, match_panic_def_id, method_chain_args, span_lint_and_then}; use if_chain::if_chain; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -59,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { if_chain! { if let hir::ItemKind::Impl(impl_) = &item.kind; if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id); - if match_def_path(cx, impl_trait_ref.def_id, &FROM_TRAIT); + if cx.tcx.is_diagnostic_item(sym::from_trait, impl_trait_ref.def_id); then { lint_impl_body(cx, item.span, impl_.items); } diff --git a/src/tools/clippy/clippy_lints/src/utils/paths.rs b/src/tools/clippy/clippy_lints/src/utils/paths.rs index c0b203b5388dc..432cc5b59f684 100644 --- a/src/tools/clippy/clippy_lints/src/utils/paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/paths.rs @@ -48,7 +48,6 @@ pub const FN_MUT: [&str; 3] = ["core", "ops", "FnMut"]; pub const FN_ONCE: [&str; 3] = ["core", "ops", "FnOnce"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "FromIterator"]; -pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"]; pub const HASH: [&str; 3] = ["core", "hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"];