mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #120226 - matthiaskrgr:rollup-9xwx0si, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #118714 ( Explanation that fields are being used when deriving `(Partial)Ord` on enums) - #119710 (Improve `let_underscore_lock`) - #119726 (Tweak Library Integer Division Docs) - #119746 (rustdoc: hide modals when resizing the sidebar) - #119986 (Fix error counting) - #120194 (Shorten `#[must_use]` Diagnostic Message for `Option::is_none`) - #120200 (Correct the anchor of an URL in an error message) - #120203 (Replace `#!/bin/bash` with `#!/usr/bin/env bash` in rust-installer tests) - #120212 (Give nnethercote more reviews) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
366d112fa6
@ -529,7 +529,7 @@ fn make_format_args(
|
||||
|
||||
// Only check for unused named argument names if there are no other errors to avoid causing
|
||||
// too much noise in output errors, such as when a named argument is entirely unused.
|
||||
if invalid_refs.is_empty() && ecx.dcx().err_count() == 0 {
|
||||
if invalid_refs.is_empty() && ecx.dcx().has_errors().is_none() {
|
||||
for &(index, span, used_as) in &numeric_refences_to_named_arg {
|
||||
let (position_sp_to_replace, position_sp_for_msg) = match used_as {
|
||||
Placeholder(pspan) => (span, pspan),
|
||||
|
@ -325,7 +325,7 @@ codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
|
||||
|
||||
codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
|
||||
|
||||
codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
|
||||
codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib)
|
||||
|
||||
codegen_ssa_version_script_write_failure = failed to write version script: {$error}
|
||||
|
||||
|
@ -421,16 +421,16 @@ pub struct DiagCtxt {
|
||||
struct DiagCtxtInner {
|
||||
flags: DiagCtxtFlags,
|
||||
|
||||
/// The number of lint errors that have been emitted.
|
||||
/// The number of lint errors that have been emitted, including duplicates.
|
||||
lint_err_count: usize,
|
||||
/// The number of errors that have been emitted, including duplicates.
|
||||
///
|
||||
/// This is not necessarily the count that's reported to the user once
|
||||
/// compilation ends.
|
||||
/// The number of non-lint errors that have been emitted, including duplicates.
|
||||
err_count: usize,
|
||||
|
||||
/// The error count shown to the user at the end.
|
||||
deduplicated_err_count: usize,
|
||||
/// The warning count, used for a recap upon finishing
|
||||
/// The warning count shown to the user at the end.
|
||||
deduplicated_warn_count: usize,
|
||||
|
||||
/// Has this diagnostic context printed any diagnostics? (I.e. has
|
||||
/// `self.emitter.emit_diagnostic()` been called?
|
||||
has_printed: bool,
|
||||
@ -927,11 +927,13 @@ impl DiagCtxt {
|
||||
self.struct_bug(msg).emit()
|
||||
}
|
||||
|
||||
/// This excludes lint errors and delayed bugs.
|
||||
#[inline]
|
||||
pub fn err_count(&self) -> usize {
|
||||
self.inner.borrow().err_count
|
||||
}
|
||||
|
||||
/// This excludes lint errors and delayed bugs.
|
||||
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
|
||||
self.inner.borrow().has_errors().then(|| {
|
||||
#[allow(deprecated)]
|
||||
@ -939,30 +941,24 @@ impl DiagCtxt {
|
||||
})
|
||||
}
|
||||
|
||||
/// This excludes delayed bugs. Unless absolutely necessary, prefer
|
||||
/// `has_errors` to this method.
|
||||
pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
|
||||
let inner = self.inner.borrow();
|
||||
let has_errors_or_lint_errors = inner.has_errors() || inner.lint_err_count > 0;
|
||||
has_errors_or_lint_errors.then(|| {
|
||||
let result = inner.has_errors() || inner.lint_err_count > 0;
|
||||
result.then(|| {
|
||||
#[allow(deprecated)]
|
||||
ErrorGuaranteed::unchecked_claim_error_was_emitted()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn has_errors_or_span_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
|
||||
/// Unless absolutely necessary, prefer `has_errors` or
|
||||
/// `has_errors_or_lint_errors` to this method.
|
||||
pub fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
|
||||
let inner = self.inner.borrow();
|
||||
let has_errors_or_span_delayed_bugs =
|
||||
inner.has_errors() || !inner.span_delayed_bugs.is_empty();
|
||||
has_errors_or_span_delayed_bugs.then(|| {
|
||||
#[allow(deprecated)]
|
||||
ErrorGuaranteed::unchecked_claim_error_was_emitted()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_compilation_going_to_fail(&self) -> Option<ErrorGuaranteed> {
|
||||
let inner = self.inner.borrow();
|
||||
let will_fail =
|
||||
let result =
|
||||
inner.has_errors() || inner.lint_err_count > 0 || !inner.span_delayed_bugs.is_empty();
|
||||
will_fail.then(|| {
|
||||
result.then(|| {
|
||||
#[allow(deprecated)]
|
||||
ErrorGuaranteed::unchecked_claim_error_was_emitted()
|
||||
})
|
||||
@ -1162,7 +1158,7 @@ impl DiagCtxt {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
|
||||
if loud && lint_level.is_error() {
|
||||
inner.err_count += 1;
|
||||
inner.lint_err_count += 1;
|
||||
inner.panic_if_treat_err_as_bug();
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ where
|
||||
let errors = wfcx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
let err = infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||
if tcx.dcx().err_count() > 0 {
|
||||
if tcx.dcx().has_errors().is_some() {
|
||||
return Err(err);
|
||||
} else {
|
||||
// HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs
|
||||
|
@ -312,7 +312,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Option<Svh>) {
|
||||
|
||||
let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone();
|
||||
|
||||
if let Some(_) = sess.dcx().has_errors_or_span_delayed_bugs() {
|
||||
if sess.dcx().has_errors_or_lint_errors_or_delayed_bugs().is_some() {
|
||||
// If there have been any errors during compilation, we don't want to
|
||||
// publish this session directory. Rather, we'll just delete it.
|
||||
|
||||
|
@ -31,8 +31,8 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
|
||||
if sess.opts.incremental.is_none() {
|
||||
return;
|
||||
}
|
||||
// This is going to be deleted in finalize_session_directory, so let's not create it
|
||||
if let Some(_) = sess.dcx().has_errors_or_span_delayed_bugs() {
|
||||
// This is going to be deleted in finalize_session_directory, so let's not create it.
|
||||
if sess.dcx().has_errors_or_lint_errors_or_delayed_bugs().is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ pub fn save_work_product_index(
|
||||
return;
|
||||
}
|
||||
// This is going to be deleted in finalize_session_directory, so let's not create it
|
||||
if let Some(_) = sess.dcx().has_errors_or_span_delayed_bugs() {
|
||||
if sess.dcx().has_errors_or_lint_errors().is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -117,9 +117,9 @@ fn escape_literal(s: &str) -> String {
|
||||
/// field is only populated during an in-progress typeck.
|
||||
/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
|
||||
///
|
||||
/// You must only create this if you intend to actually emit an error.
|
||||
/// This provides a lot of utility methods which should not be used
|
||||
/// during the happy path.
|
||||
/// You must only create this if you intend to actually emit an error (or
|
||||
/// perhaps a warning, though preferably not.) It provides a lot of utility
|
||||
/// methods which should not be used during the happy path.
|
||||
pub struct TypeErrCtxt<'a, 'tcx> {
|
||||
pub infcx: &'a InferCtxt<'tcx>,
|
||||
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
|
||||
@ -133,9 +133,10 @@ pub struct TypeErrCtxt<'a, 'tcx> {
|
||||
|
||||
impl Drop for TypeErrCtxt<'_, '_> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(_) = self.dcx().has_errors_or_span_delayed_bugs() {
|
||||
// ok, emitted an error.
|
||||
if self.dcx().has_errors().is_some() {
|
||||
// Ok, emitted an error.
|
||||
} else {
|
||||
// Didn't emit an error; maybe it was created but not yet emitted.
|
||||
self.infcx
|
||||
.tcx
|
||||
.sess
|
||||
|
@ -345,6 +345,9 @@ lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple
|
||||
lint_node_source = `forbid` level set here
|
||||
.note = {$reason}
|
||||
|
||||
lint_non_binding_let_multi_drop_fn =
|
||||
consider immediately dropping the value using `drop(..)` after the `let` statement
|
||||
|
||||
lint_non_binding_let_multi_suggestion =
|
||||
consider immediately dropping the value
|
||||
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::{sym, Symbol};
|
||||
|
||||
declare_lint! {
|
||||
/// The `let_underscore_drop` lint checks for statements which don't bind
|
||||
@ -105,51 +105,70 @@ const SYNC_GUARD_SYMBOLS: [Symbol; 3] = [
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
|
||||
fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) {
|
||||
if !matches!(local.pat.kind, hir::PatKind::Wild) {
|
||||
return;
|
||||
}
|
||||
|
||||
if matches!(local.source, rustc_hir::LocalSource::AsyncFn) {
|
||||
return;
|
||||
}
|
||||
if let Some(init) = local.init {
|
||||
let init_ty = cx.typeck_results().expr_ty(init);
|
||||
// If the type has a trivial Drop implementation, then it doesn't
|
||||
// matter that we drop the value immediately.
|
||||
if !init_ty.needs_drop(cx.tcx, cx.param_env) {
|
||||
|
||||
let mut top_level = true;
|
||||
|
||||
// We recursively walk through all patterns, so that we can catch cases where the lock is nested in a pattern.
|
||||
// For the basic `let_underscore_drop` lint, we only look at the top level, since there are many legitimate reasons
|
||||
// to bind a sub-pattern to an `_`, if we're only interested in the rest.
|
||||
// But with locks, we prefer having the chance of "false positives" over missing cases, since the effects can be
|
||||
// quite catastrophic.
|
||||
local.pat.walk_always(|pat| {
|
||||
let is_top_level = top_level;
|
||||
top_level = false;
|
||||
|
||||
if !matches!(pat.kind, hir::PatKind::Wild) {
|
||||
return;
|
||||
}
|
||||
let is_sync_lock = match init_ty.kind() {
|
||||
|
||||
let ty = cx.typeck_results().pat_ty(pat);
|
||||
|
||||
// If the type has a trivial Drop implementation, then it doesn't
|
||||
// matter that we drop the value immediately.
|
||||
if !ty.needs_drop(cx.tcx, cx.param_env) {
|
||||
return;
|
||||
}
|
||||
// Lint for patterns like `mutex.lock()`, which returns `Result<MutexGuard, _>` as well.
|
||||
let potential_lock_type = match ty.kind() {
|
||||
ty::Adt(adt, args) if cx.tcx.is_diagnostic_item(sym::Result, adt.did()) => {
|
||||
args.type_at(0)
|
||||
}
|
||||
_ => ty,
|
||||
};
|
||||
let is_sync_lock = match potential_lock_type.kind() {
|
||||
ty::Adt(adt, _) => SYNC_GUARD_SYMBOLS
|
||||
.iter()
|
||||
.any(|guard_symbol| cx.tcx.is_diagnostic_item(*guard_symbol, adt.did())),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let can_use_init = is_top_level.then_some(local.init).flatten();
|
||||
|
||||
let sub = NonBindingLetSub {
|
||||
suggestion: local.pat.span,
|
||||
multi_suggestion_start: local.span.until(init.span),
|
||||
multi_suggestion_end: init.span.shrink_to_hi(),
|
||||
suggestion: pat.span,
|
||||
// We can't suggest `drop()` when we're on the top level.
|
||||
drop_fn_start_end: can_use_init
|
||||
.map(|init| (local.span.until(init.span), init.span.shrink_to_hi())),
|
||||
is_assign_desugar: matches!(local.source, rustc_hir::LocalSource::AssignDesugar(_)),
|
||||
};
|
||||
if is_sync_lock {
|
||||
let mut span = MultiSpan::from_spans(vec![local.pat.span, init.span]);
|
||||
let mut span = MultiSpan::from_span(pat.span);
|
||||
span.push_span_label(
|
||||
local.pat.span,
|
||||
pat.span,
|
||||
"this lock is not assigned to a binding and is immediately dropped".to_string(),
|
||||
);
|
||||
span.push_span_label(
|
||||
init.span,
|
||||
"this binding will immediately drop the value assigned to it".to_string(),
|
||||
);
|
||||
cx.emit_spanned_lint(LET_UNDERSCORE_LOCK, span, NonBindingLet::SyncLock { sub });
|
||||
} else {
|
||||
// Only emit let_underscore_drop for top-level `_` patterns.
|
||||
} else if can_use_init.is_some() {
|
||||
cx.emit_spanned_lint(
|
||||
LET_UNDERSCORE_DROP,
|
||||
local.span,
|
||||
NonBindingLet::DropType { sub },
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -930,8 +930,7 @@ pub enum NonBindingLet {
|
||||
|
||||
pub struct NonBindingLetSub {
|
||||
pub suggestion: Span,
|
||||
pub multi_suggestion_start: Span,
|
||||
pub multi_suggestion_end: Span,
|
||||
pub drop_fn_start_end: Option<(Span, Span)>,
|
||||
pub is_assign_desugar: bool,
|
||||
}
|
||||
|
||||
@ -940,6 +939,9 @@ impl AddToDiagnostic for NonBindingLetSub {
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar;
|
||||
|
||||
if can_suggest_binding {
|
||||
let prefix = if self.is_assign_desugar { "let " } else { "" };
|
||||
diag.span_suggestion_verbose(
|
||||
self.suggestion,
|
||||
@ -947,14 +949,21 @@ impl AddToDiagnostic for NonBindingLetSub {
|
||||
format!("{prefix}_unused"),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
diag.span_help(self.suggestion, fluent::lint_non_binding_let_suggestion);
|
||||
}
|
||||
if let Some(drop_fn_start_end) = self.drop_fn_start_end {
|
||||
diag.multipart_suggestion(
|
||||
fluent::lint_non_binding_let_multi_suggestion,
|
||||
vec![
|
||||
(self.multi_suggestion_start, "drop(".to_string()),
|
||||
(self.multi_suggestion_end, ")".to_string()),
|
||||
(drop_fn_start_end.0, "drop(".to_string()),
|
||||
(drop_fn_start_end.1, ")".to_string()),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
diag.help(fluent::lint_non_binding_let_multi_drop_fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,10 +55,13 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
|
||||
}
|
||||
fn error_reported(&self) -> Result<(), ErrorGuaranteed> {
|
||||
if self.references_error() {
|
||||
if let Some(reported) = ty::tls::with(|tcx| tcx.dcx().is_compilation_going_to_fail()) {
|
||||
// We must include lint errors and span delayed bugs here.
|
||||
if let Some(reported) =
|
||||
ty::tls::with(|tcx| tcx.dcx().has_errors_or_lint_errors_or_delayed_bugs())
|
||||
{
|
||||
Err(reported)
|
||||
} else {
|
||||
bug!("expect tcx.sess.is_compilation_going_to_fail return `Some`");
|
||||
bug!("expected some kind of error in `error_reported`");
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
|
@ -818,7 +818,7 @@ impl<D: Deps> DepGraphData<D> {
|
||||
None => {}
|
||||
}
|
||||
|
||||
if let None = qcx.dep_context().sess().dcx().has_errors_or_span_delayed_bugs() {
|
||||
if let None = qcx.dep_context().sess().dcx().has_errors_or_lint_errors_or_delayed_bugs() {
|
||||
panic!("try_mark_previous_green() - Forcing the DepNode should have set its color")
|
||||
}
|
||||
|
||||
|
@ -323,6 +323,7 @@ impl Session {
|
||||
}
|
||||
|
||||
pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> {
|
||||
// We must include lint errors here.
|
||||
if let Some(reported) = self.dcx().has_errors_or_lint_errors() {
|
||||
let _ = self.dcx().emit_stashed_diagnostics();
|
||||
Err(reported)
|
||||
|
@ -710,7 +710,8 @@ impl<T: Clone> Clone for Reverse<T> {
|
||||
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering
|
||||
/// based on the top-to-bottom declaration order of the struct's members.
|
||||
///
|
||||
/// When `derive`d on enums, variants are ordered by their discriminants.
|
||||
/// When `derive`d on enums, variants are ordered primarily by their discriminants.
|
||||
/// Secondarily, they are ordered by their fields.
|
||||
/// By default, the discriminant is smallest for variants at the top, and
|
||||
/// largest for variants at the bottom. Here's an example:
|
||||
///
|
||||
@ -963,7 +964,8 @@ pub macro Ord($item:item) {
|
||||
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering
|
||||
/// based on the top-to-bottom declaration order of the struct's members.
|
||||
///
|
||||
/// When `derive`d on enums, variants are ordered by their discriminants.
|
||||
/// When `derive`d on enums, variants are primarily ordered by their discriminants.
|
||||
/// Secondarily, they are ordered by their fields.
|
||||
/// By default, the discriminant is smallest for variants at the top, and
|
||||
/// largest for variants at the bottom. Here's an example:
|
||||
///
|
||||
|
@ -1643,6 +1643,10 @@ macro_rules! int_impl {
|
||||
/// Saturating integer division. Computes `self / rhs`, saturating at the
|
||||
/// numeric bounds instead of overflowing.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if `rhs` is 0.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
@ -1653,11 +1657,6 @@ macro_rules! int_impl {
|
||||
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_div(-1), ", stringify!($SelfT), "::MAX);")]
|
||||
///
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
#[doc = concat!("let _ = 1", stringify!($SelfT), ".saturating_div(0);")]
|
||||
///
|
||||
/// ```
|
||||
#[stable(feature = "saturating_div", since = "1.58.0")]
|
||||
#[rustc_const_stable(feature = "saturating_div", since = "1.58.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
@ -2435,6 +2434,7 @@ macro_rules! int_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
|
||||
if unlikely!(rhs == -1) {
|
||||
(0, self == Self::MIN)
|
||||
@ -2674,7 +2674,8 @@ macro_rules! int_impl {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if `rhs` is 0 or the division results in overflow.
|
||||
/// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is
|
||||
/// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -2694,7 +2695,7 @@ macro_rules! int_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
#[track_caller]
|
||||
pub const fn div_euclid(self, rhs: Self) -> Self {
|
||||
let q = self / rhs;
|
||||
if self % rhs < 0 {
|
||||
@ -2712,7 +2713,8 @@ macro_rules! int_impl {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if `rhs` is 0 or the division results in overflow.
|
||||
/// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is
|
||||
/// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -2733,7 +2735,7 @@ macro_rules! int_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
#[track_caller]
|
||||
pub const fn rem_euclid(self, rhs: Self) -> Self {
|
||||
let r = self % rhs;
|
||||
if r < 0 {
|
||||
@ -2755,12 +2757,8 @@ macro_rules! int_impl {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if `rhs` is zero.
|
||||
///
|
||||
/// ## Overflow behavior
|
||||
///
|
||||
/// On overflow, this function will panic if overflow checks are enabled (default in debug
|
||||
/// mode) and wrap if overflow checks are disabled (default in release mode).
|
||||
/// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is
|
||||
/// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -2780,7 +2778,7 @@ macro_rules! int_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
#[track_caller]
|
||||
pub const fn div_floor(self, rhs: Self) -> Self {
|
||||
let d = self / rhs;
|
||||
let r = self % rhs;
|
||||
@ -2795,12 +2793,8 @@ macro_rules! int_impl {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if `rhs` is zero.
|
||||
///
|
||||
/// ## Overflow behavior
|
||||
///
|
||||
/// On overflow, this function will panic if overflow checks are enabled (default in debug
|
||||
/// mode) and wrap if overflow checks are disabled (default in release mode).
|
||||
/// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is
|
||||
/// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -2820,7 +2814,7 @@ macro_rules! int_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
#[track_caller]
|
||||
pub const fn div_ceil(self, rhs: Self) -> Self {
|
||||
let d = self / rhs;
|
||||
let r = self % rhs;
|
||||
|
@ -1531,6 +1531,10 @@ macro_rules! uint_impl {
|
||||
/// Saturating integer division. Computes `self / rhs`, saturating at the
|
||||
/// numeric bounds instead of overflowing.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if `rhs` is 0.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
@ -1539,16 +1543,12 @@ macro_rules! uint_impl {
|
||||
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".saturating_div(2), 2);")]
|
||||
///
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
#[doc = concat!("let _ = 1", stringify!($SelfT), ".saturating_div(0);")]
|
||||
///
|
||||
/// ```
|
||||
#[stable(feature = "saturating_div", since = "1.58.0")]
|
||||
#[rustc_const_stable(feature = "saturating_div", since = "1.58.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub const fn saturating_div(self, rhs: Self) -> Self {
|
||||
// on unsigned types, there is no overflow in integer division
|
||||
self.wrapping_div(rhs)
|
||||
@ -1683,6 +1683,7 @@ macro_rules! uint_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
#[track_caller]
|
||||
pub const fn wrapping_div(self, rhs: Self) -> Self {
|
||||
self / rhs
|
||||
}
|
||||
@ -1712,6 +1713,7 @@ macro_rules! uint_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
#[track_caller]
|
||||
pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
|
||||
self / rhs
|
||||
}
|
||||
@ -1739,6 +1741,7 @@ macro_rules! uint_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
#[track_caller]
|
||||
pub const fn wrapping_rem(self, rhs: Self) -> Self {
|
||||
self % rhs
|
||||
}
|
||||
@ -1769,6 +1772,7 @@ macro_rules! uint_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
#[track_caller]
|
||||
pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
|
||||
self % rhs
|
||||
}
|
||||
@ -2151,6 +2155,7 @@ macro_rules! uint_impl {
|
||||
#[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[track_caller]
|
||||
pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
|
||||
(self / rhs, false)
|
||||
}
|
||||
@ -2181,6 +2186,7 @@ macro_rules! uint_impl {
|
||||
#[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[track_caller]
|
||||
pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
|
||||
(self / rhs, false)
|
||||
}
|
||||
@ -2208,6 +2214,7 @@ macro_rules! uint_impl {
|
||||
#[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[track_caller]
|
||||
pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
|
||||
(self % rhs, false)
|
||||
}
|
||||
@ -2238,6 +2245,7 @@ macro_rules! uint_impl {
|
||||
#[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[track_caller]
|
||||
pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
|
||||
(self % rhs, false)
|
||||
}
|
||||
@ -2473,7 +2481,7 @@ macro_rules! uint_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
#[track_caller]
|
||||
pub const fn div_euclid(self, rhs: Self) -> Self {
|
||||
self / rhs
|
||||
}
|
||||
@ -2502,7 +2510,7 @@ macro_rules! uint_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
#[track_caller]
|
||||
pub const fn rem_euclid(self, rhs: Self) -> Self {
|
||||
self % rhs
|
||||
}
|
||||
@ -2527,6 +2535,7 @@ macro_rules! uint_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
#[track_caller]
|
||||
pub const fn div_floor(self, rhs: Self) -> Self {
|
||||
self / rhs
|
||||
}
|
||||
@ -2537,11 +2546,6 @@ macro_rules! uint_impl {
|
||||
///
|
||||
/// This function will panic if `rhs` is zero.
|
||||
///
|
||||
/// ## Overflow behavior
|
||||
///
|
||||
/// On overflow, this function will panic if overflow checks are enabled (default in debug
|
||||
/// mode) and wrap if overflow checks are disabled (default in release mode).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
@ -2554,7 +2558,7 @@ macro_rules! uint_impl {
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
#[track_caller]
|
||||
pub const fn div_ceil(self, rhs: Self) -> Self {
|
||||
let d = self / rhs;
|
||||
let r = self % rhs;
|
||||
|
@ -642,7 +642,7 @@ impl<T> Option<T> {
|
||||
/// assert_eq!(x.is_none(), true);
|
||||
/// ```
|
||||
#[must_use = "if you intended to assert that this doesn't have a value, consider \
|
||||
`.and_then(|_| panic!(\"`Option` had a value when expected `None`\"))` instead"]
|
||||
wrapping this in an `assert!()` instead"]
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")]
|
||||
|
@ -449,6 +449,7 @@ pub(crate) fn run_global_ctxt(
|
||||
|
||||
tcx.sess.time("check_lint_expectations", || tcx.check_expectations(Some(sym::rustdoc)));
|
||||
|
||||
// We must include lint errors here.
|
||||
if tcx.dcx().has_errors_or_lint_errors().is_some() {
|
||||
rustc_errors::FatalError.raise();
|
||||
}
|
||||
|
@ -150,6 +150,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
|
||||
|
||||
collector
|
||||
});
|
||||
// We must include lint errors here.
|
||||
if compiler.sess.dcx().has_errors_or_lint_errors().is_some() {
|
||||
FatalError.raise();
|
||||
}
|
||||
|
@ -1721,6 +1721,7 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
|
||||
}
|
||||
currentPointerId = e.pointerId;
|
||||
}
|
||||
window.hideAllModals(false);
|
||||
e.preventDefault();
|
||||
window.addEventListener("pointermove", resize, false);
|
||||
window.addEventListener("pointercancel", stopResize, false);
|
||||
|
@ -796,7 +796,7 @@ fn main_args(
|
||||
|
||||
compiler.enter(|queries| {
|
||||
let mut gcx = abort_on_err(queries.global_ctxt(), sess);
|
||||
if sess.dcx().has_errors_or_lint_errors().is_some() {
|
||||
if sess.dcx().has_errors().is_some() {
|
||||
sess.dcx().fatal("Compilation failed, aborting rustdoc");
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
|
||||
let tcx = cx.tcx;
|
||||
// We need to check if there are errors before running this pass because it would crash when
|
||||
// we try to get auto and blanket implementations.
|
||||
if tcx.dcx().has_errors_or_lint_errors().is_some() {
|
||||
if tcx.dcx().has_errors().is_some() {
|
||||
return krate;
|
||||
}
|
||||
|
||||
|
@ -311,7 +311,7 @@ pub(crate) fn run(
|
||||
|
||||
// The visitor might have found a type error, which we need to
|
||||
// promote to a fatal error
|
||||
if tcx.dcx().has_errors_or_lint_errors().is_some() {
|
||||
if tcx.dcx().has_errors().is_some() {
|
||||
return Err(String::from("Compilation failed, aborting rustdoc"));
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ fn main() {
|
||||
let _ = p_rw;
|
||||
}
|
||||
|
||||
#[allow(let_underscore_lock)]
|
||||
fn uplifted() {
|
||||
// shouldn't lint std locks as they were uplifted as rustc's `let_underscore_lock`
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e -u
|
||||
|
||||
|
20
tests/rustdoc-gui/sidebar-resize-close-popover.goml
Normal file
20
tests/rustdoc-gui/sidebar-resize-close-popover.goml
Normal file
@ -0,0 +1,20 @@
|
||||
// Checks sidebar resizing close the Settings popover
|
||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||
assert-property: (".sidebar", {"clientWidth": "200"})
|
||||
show-text: true
|
||||
click: "#settings-menu"
|
||||
wait-for: "#settings"
|
||||
assert-css: ("#settings", {"display": "block"})
|
||||
// normal resizing
|
||||
drag-and-drop: ((205, 100), (185, 100))
|
||||
assert-property: (".sidebar", {"clientWidth": "182"})
|
||||
assert-css: ("#settings", {"display": "none"})
|
||||
|
||||
// Now same thing, but for source code
|
||||
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
|
||||
click: "#settings-menu"
|
||||
wait-for: "#settings"
|
||||
assert-css: ("#settings", {"display": "block"})
|
||||
assert-property: (".sidebar", {"clientWidth": "49"})
|
||||
drag-and-drop: ((52, 100), (185, 100))
|
||||
assert-css: ("#settings", {"display": "none"})
|
@ -11,4 +11,6 @@ impl Drop for NontrivialDrop {
|
||||
|
||||
fn main() {
|
||||
let _ = NontrivialDrop; //~WARNING non-binding let on a type that implements `Drop`
|
||||
|
||||
let (_, _) = (NontrivialDrop, NontrivialDrop); // This should be ignored.
|
||||
}
|
||||
|
@ -1,7 +1,22 @@
|
||||
// check-fail
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
struct Struct<T> {
|
||||
a: T,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let data = Arc::new(Mutex::new(0));
|
||||
let _ = data.lock().unwrap(); //~ERROR non-binding let on a synchronization lock
|
||||
|
||||
let _ = data.lock(); //~ERROR non-binding let on a synchronization lock
|
||||
|
||||
let (_, _) = (data.lock(), 1); //~ERROR non-binding let on a synchronization lock
|
||||
|
||||
let (_a, Struct { a: _ }) = (0, Struct { a: data.lock() }); //~ERROR non-binding let on a synchronization lock
|
||||
|
||||
(_ , _) = (data.lock(), 1); //~ERROR non-binding let on a synchronization lock
|
||||
|
||||
let _b;
|
||||
(_b, Struct { a: _ }) = (0, Struct { a: data.lock() }); //~ERROR non-binding let on a synchronization lock
|
||||
}
|
||||
|
@ -1,10 +1,8 @@
|
||||
error: non-binding let on a synchronization lock
|
||||
--> $DIR/let_underscore_lock.rs:6:9
|
||||
--> $DIR/let_underscore_lock.rs:10:9
|
||||
|
|
||||
LL | let _ = data.lock().unwrap();
|
||||
| ^ ^^^^^^^^^^^^^^^^^^^^ this binding will immediately drop the value assigned to it
|
||||
| |
|
||||
| this lock is not assigned to a binding and is immediately dropped
|
||||
| ^ this lock is not assigned to a binding and is immediately dropped
|
||||
|
|
||||
= note: `#[deny(let_underscore_lock)]` on by default
|
||||
help: consider binding to an unused variable to avoid immediately dropping the value
|
||||
@ -16,5 +14,70 @@ help: consider immediately dropping the value
|
||||
LL | drop(data.lock().unwrap());
|
||||
| ~~~~~ +
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: non-binding let on a synchronization lock
|
||||
--> $DIR/let_underscore_lock.rs:12:9
|
||||
|
|
||||
LL | let _ = data.lock();
|
||||
| ^ this lock is not assigned to a binding and is immediately dropped
|
||||
|
|
||||
help: consider binding to an unused variable to avoid immediately dropping the value
|
||||
|
|
||||
LL | let _unused = data.lock();
|
||||
| ~~~~~~~
|
||||
help: consider immediately dropping the value
|
||||
|
|
||||
LL | drop(data.lock());
|
||||
| ~~~~~ +
|
||||
|
||||
error: non-binding let on a synchronization lock
|
||||
--> $DIR/let_underscore_lock.rs:14:10
|
||||
|
|
||||
LL | let (_, _) = (data.lock(), 1);
|
||||
| ^ this lock is not assigned to a binding and is immediately dropped
|
||||
|
|
||||
= help: consider immediately dropping the value using `drop(..)` after the `let` statement
|
||||
help: consider binding to an unused variable to avoid immediately dropping the value
|
||||
|
|
||||
LL | let (_unused, _) = (data.lock(), 1);
|
||||
| ~~~~~~~
|
||||
|
||||
error: non-binding let on a synchronization lock
|
||||
--> $DIR/let_underscore_lock.rs:16:26
|
||||
|
|
||||
LL | let (_a, Struct { a: _ }) = (0, Struct { a: data.lock() });
|
||||
| ^ this lock is not assigned to a binding and is immediately dropped
|
||||
|
|
||||
= help: consider immediately dropping the value using `drop(..)` after the `let` statement
|
||||
help: consider binding to an unused variable to avoid immediately dropping the value
|
||||
|
|
||||
LL | let (_a, Struct { a: _unused }) = (0, Struct { a: data.lock() });
|
||||
| ~~~~~~~
|
||||
|
||||
error: non-binding let on a synchronization lock
|
||||
--> $DIR/let_underscore_lock.rs:18:6
|
||||
|
|
||||
LL | (_ , _) = (data.lock(), 1);
|
||||
| ^ this lock is not assigned to a binding and is immediately dropped
|
||||
|
|
||||
help: consider binding to an unused variable to avoid immediately dropping the value
|
||||
--> $DIR/let_underscore_lock.rs:18:6
|
||||
|
|
||||
LL | (_ , _) = (data.lock(), 1);
|
||||
| ^
|
||||
= help: consider immediately dropping the value using `drop(..)` after the `let` statement
|
||||
|
||||
error: non-binding let on a synchronization lock
|
||||
--> $DIR/let_underscore_lock.rs:21:22
|
||||
|
|
||||
LL | (_b, Struct { a: _ }) = (0, Struct { a: data.lock() });
|
||||
| ^ this lock is not assigned to a binding and is immediately dropped
|
||||
|
|
||||
help: consider binding to an unused variable to avoid immediately dropping the value
|
||||
--> $DIR/let_underscore_lock.rs:21:22
|
||||
|
|
||||
LL | (_b, Struct { a: _ }) = (0, Struct { a: data.lock() });
|
||||
| ^
|
||||
= help: consider immediately dropping the value using `drop(..)` after the `let` statement
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
# This file's format is documented at
|
||||
# https://forge.rust-lang.org/triagebot/pr-assignment.html#configuration
|
||||
|
||||
[relabel]
|
||||
allow-unauthenticated = [
|
||||
"A-*",
|
||||
@ -646,6 +649,7 @@ compiler-team = [
|
||||
compiler-team-contributors = [
|
||||
"@TaKO8Ki",
|
||||
"@b-naber",
|
||||
"@nnethercote",
|
||||
]
|
||||
compiler = [
|
||||
"compiler-team",
|
||||
@ -702,6 +706,9 @@ lexer = [
|
||||
"@nnethercote",
|
||||
"@petrochenkov",
|
||||
]
|
||||
arena = [
|
||||
"@nnethercote",
|
||||
]
|
||||
mir = [
|
||||
"@davidtwco",
|
||||
"@oli-obk",
|
||||
@ -735,7 +742,6 @@ style-team = [
|
||||
"@joshtriplett",
|
||||
"@yaahc",
|
||||
]
|
||||
|
||||
project-const-traits = [
|
||||
"@compiler-errors",
|
||||
"@fee1-dead",
|
||||
@ -754,6 +760,7 @@ project-stable-mir = [
|
||||
"/Cargo.lock" = ["@Mark-Simulacrum"]
|
||||
"/Cargo.toml" = ["@Mark-Simulacrum"]
|
||||
"/compiler" = ["compiler"]
|
||||
"/compiler/rustc_arena" = ["compiler", "arena"]
|
||||
"/compiler/rustc_ast" = ["compiler", "parser"]
|
||||
"/compiler/rustc_ast_lowering" = ["compiler", "ast_lowering"]
|
||||
"/compiler/rustc_hir_analysis" = ["compiler", "types"]
|
||||
|
Loading…
Reference in New Issue
Block a user