/unicode-downloads
/target
/src/tools/x/target
-# Generated by compiletest for incremental
-/tmp/
# Created by default with `src/ci/docker/run.sh`
/obj/
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
+ "rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
Libraries
---------
-- [Move `CStr` to libcore, and `CString` to liballoc][94079]
- [Windows: Use a pipe relay for chaining pipes][95841]
- [Replace Linux Mutex and Condvar with futex based ones.][95035]
- [Replace RwLock by a futex based one on Linux][95801]
[93313]: https://github.com/rust-lang/rust/pull/93313/
[93969]: https://github.com/rust-lang/rust/pull/93969/
-[94079]: https://github.com/rust-lang/rust/pull/94079/
[94206]: https://github.com/rust-lang/rust/pull/94206/
[94457]: https://github.com/rust-lang/rust/pull/94457/
[94775]: https://github.com/rust-lang/rust/pull/94775/
-use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{
+ struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
+};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
fn struct_span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
- msg: &str,
+ msg: impl Into<DiagnosticMessage>,
code: DiagnosticId,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code)
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(never_type)]
+#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![feature(trusted_step)]
#![feature(try_blocks)]
-use crate::assert::expr_if_not;
use rustc_ast::{
attr,
ptr::P,
token,
tokenstream::{DelimSpan, TokenStream, TokenTree},
- BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability, Path,
- PathSegment, Stmt, StructRest, UseTree, UseTreeKind, DUMMY_NODE_ID,
+ BinOpKind, BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability,
+ Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
};
pub(super) struct Context<'cx, 'a> {
+ // An optimization.
+ //
+ // Elements that aren't consumed (PartialEq, PartialOrd, ...) can be copied **after** the
+ // `assert!` expression fails rather than copied on-the-fly.
+ best_case_captures: Vec<Stmt>,
// Top-level `let captureN = Capture::new()` statements
capture_decls: Vec<Capture>,
cx: &'cx ExtCtxt<'a>,
// Formatting string used for debugging
fmt_string: String,
+ // If the current expression being visited consumes itself. Used to construct
+ // `best_case_captures`.
+ is_consumed: bool,
// Top-level `let __local_bindN = &expr` statements
local_bind_decls: Vec<Stmt>,
// Used to avoid capturing duplicated paths
impl<'cx, 'a> Context<'cx, 'a> {
pub(super) fn new(cx: &'cx ExtCtxt<'a>, span: Span) -> Self {
Self {
+ best_case_captures: <_>::default(),
capture_decls: <_>::default(),
cx,
fmt_string: <_>::default(),
+ is_consumed: true,
local_bind_decls: <_>::default(),
paths: <_>::default(),
span,
self.manage_cond_expr(&mut cond_expr);
let initial_imports = self.build_initial_imports();
let panic = self.build_panic(&expr_str, panic_path);
+ let cond_expr_with_unlikely = self.build_unlikely(cond_expr);
+
+ let Self { best_case_captures, capture_decls, cx, local_bind_decls, span, .. } = self;
- let Self { capture_decls, cx, local_bind_decls, span, .. } = self;
+ let mut assert_then_stmts = Vec::with_capacity(2);
+ assert_then_stmts.extend(best_case_captures);
+ assert_then_stmts.push(self.cx.stmt_expr(panic));
+ let assert_then = self.cx.block(span, assert_then_stmts);
let mut stmts = Vec::with_capacity(4);
stmts.push(initial_imports);
stmts.extend(capture_decls.into_iter().map(|c| c.decl));
stmts.extend(local_bind_decls);
- stmts.push(cx.stmt_expr(expr_if_not(cx, span, cond_expr, panic, None)));
+ stmts.push(
+ cx.stmt_expr(cx.expr(span, ExprKind::If(cond_expr_with_unlikely, assert_then, None))),
+ );
cx.expr_block(cx.block(span, stmts))
}
)
}
+ /// Takes the conditional expression of `assert!` and then wraps it inside `unlikely`
+ fn build_unlikely(&self, cond_expr: P<Expr>) -> P<Expr> {
+ let unlikely_path = self.cx.std_path(&[sym::intrinsics, sym::unlikely]);
+ self.cx.expr_call(
+ self.span,
+ self.cx.expr_path(self.cx.path(self.span, unlikely_path)),
+ vec![self.cx.expr(self.span, ExprKind::Unary(UnOp::Not, cond_expr))],
+ )
+ }
+
/// The necessary custom `panic!(...)` expression.
///
/// panic!(
/// See [Self::manage_initial_capture] and [Self::manage_try_capture]
fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
match (*expr).kind {
- ExprKind::AddrOf(_, _, ref mut local_expr) => {
- self.manage_cond_expr(local_expr);
+ ExprKind::AddrOf(_, mutability, ref mut local_expr) => {
+ self.with_is_consumed_management(
+ matches!(mutability, Mutability::Mut),
+ |this| this.manage_cond_expr(local_expr)
+ );
}
ExprKind::Array(ref mut local_exprs) => {
for local_expr in local_exprs {
self.manage_cond_expr(local_expr);
}
}
- ExprKind::Binary(_, ref mut lhs, ref mut rhs) => {
- self.manage_cond_expr(lhs);
- self.manage_cond_expr(rhs);
+ ExprKind::Binary(ref op, ref mut lhs, ref mut rhs) => {
+ self.with_is_consumed_management(
+ matches!(
+ op.node,
+ BinOpKind::Add
+ | BinOpKind::And
+ | BinOpKind::BitAnd
+ | BinOpKind::BitOr
+ | BinOpKind::BitXor
+ | BinOpKind::Div
+ | BinOpKind::Mul
+ | BinOpKind::Or
+ | BinOpKind::Rem
+ | BinOpKind::Shl
+ | BinOpKind::Shr
+ | BinOpKind::Sub
+ ),
+ |this| {
+ this.manage_cond_expr(lhs);
+ this.manage_cond_expr(rhs);
+ }
+ );
}
ExprKind::Call(_, ref mut local_exprs) => {
for local_expr in local_exprs {
self.manage_cond_expr(local_expr);
}
}
- ExprKind::Unary(_, ref mut local_expr) => {
- self.manage_cond_expr(local_expr);
+ ExprKind::Unary(un_op, ref mut local_expr) => {
+ self.with_is_consumed_management(
+ matches!(un_op, UnOp::Neg | UnOp::Not),
+ |this| this.manage_cond_expr(local_expr)
+ );
}
// Expressions that are not worth or can not be captured.
//
))
.add_trailing_semicolon();
let local_bind_path = self.cx.expr_path(Path::from_ident(local_bind));
- let ret = self.cx.stmt_expr(local_bind_path);
- let block = self.cx.expr_block(self.cx.block(self.span, vec![try_capture_call, ret]));
- *expr = self.cx.expr_deref(self.span, block);
+ let rslt = if self.is_consumed {
+ let ret = self.cx.stmt_expr(local_bind_path);
+ self.cx.expr_block(self.cx.block(self.span, vec![try_capture_call, ret]))
+ } else {
+ self.best_case_captures.push(try_capture_call);
+ local_bind_path
+ };
+ *expr = self.cx.expr_deref(self.span, rslt);
+ }
+
+ // Calls `f` with the internal `is_consumed` set to `curr_is_consumed` and then
+ // sets the internal `is_consumed` back to its original value.
+ fn with_is_consumed_management(&mut self, curr_is_consumed: bool, f: impl FnOnce(&mut Self)) {
+ let prev_is_consumed = self.is_consumed;
+ self.is_consumed = curr_is_consumed;
+ f(self);
+ self.is_consumed = prev_is_consumed;
}
}
}
}
}
+ } else if #[cfg(target_os = "macos")] {
+ pub fn get_resident_set_size() -> Option<usize> {
+ use libc::{c_int, c_void, getpid, proc_pidinfo, proc_taskinfo, PROC_PIDTASKINFO};
+ use std::mem;
+ const PROC_TASKINFO_SIZE: c_int = mem::size_of::<proc_taskinfo>() as c_int;
+
+ unsafe {
+ let mut info: proc_taskinfo = mem::zeroed();
+ let info_ptr = &mut info as *mut proc_taskinfo as *mut c_void;
+ let pid = getpid() as c_int;
+ let ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, info_ptr, PROC_TASKINFO_SIZE);
+ if ret == PROC_TASKINFO_SIZE {
+ Some(info.pti_resident_size as usize)
+ } else {
+ None
+ }
+ }
+ }
} else if #[cfg(unix)] {
pub fn get_resident_set_size() -> Option<usize> {
let field = 1;
--- /dev/null
+privacy-field-is-private = field `{$field_name}` of {$variant_descr} `{$def_path_str}` is private
+privacy-field-is-private-is-update-syntax-label = field `{$field_name}` is private
+privacy-field-is-private-label = private field
+
+privacy-item-is-private = {$kind} `{$descr}` is private
+ .label = private {$kind}
+privacy-unnamed-item-is-private = {$kind} is private
+ .label = private {$kind}
+
+privacy-in-public-interface = {$vis_descr} {$kind} `{$descr}` in public interface
+ .label = can't leak {$vis_descr} {$kind}
+ .visibility-label = `{$descr}` declared as {$vis_descr}
// Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
fluent_messages! {
parser => "../locales/en-US/parser.ftl",
+ privacy => "../locales/en-US/privacy.ftl",
typeck => "../locales/en-US/typeck.ftl",
builtin_macros => "../locales/en-US/builtin_macros.ftl",
}
}
}
-/// Maximum number of lines we will print for a multiline suggestion; arbitrary.
-///
-/// This should be replaced with a more involved mechanism to output multiline suggestions that
-/// more closely mimics the regular diagnostic output, where irrelevant code lines are elided.
-pub const MAX_SUGGESTION_HIGHLIGHT_LINES: usize = 6;
/// Maximum number of suggestions to be shown
///
/// Arbitrary, but taken from trait import suggestion limit
self.current_expansion.id.expansion_cause()
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
///
/// Compilation will be stopped in the near future (at the end of
/// the macro expansion phase).
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.sess.parse_sess.span_diagnostic.span_err(sp, msg);
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
}
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_internals)]
#![feature(proc_macro_span)]
+#![feature(rustc_attrs)]
#![feature(try_blocks)]
#![recursion_limit = "256"]
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
- /// This is a backwards compatibility hack to prevent breaking changes from
- /// lazy TAIT around RPIT handling.
- pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<'tcx>>(
+ pub fn replace_opaque_types_with_inference_vars(
&self,
- value: T,
+ ty: Ty<'tcx>,
body_id: HirId,
span: Span,
code: ObligationCauseCode<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- ) -> InferOk<'tcx, T> {
- if !value.has_opaque_types() {
- return InferOk { value, obligations: vec![] };
+ ) -> InferOk<'tcx, Ty<'tcx>> {
+ if !ty.has_opaque_types() {
+ return InferOk { value: ty, obligations: vec![] };
}
let mut obligations = vec![];
- let value = value.fold_with(&mut ty::fold::BottomUpFolder {
+ let value = ty.fold_with(&mut ty::fold::BottomUpFolder {
tcx: self.tcx,
lt_op: |lt| lt,
ct_op: |ct| ct,
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
let Some((span, def_id, substs)) = typeck_results_of_method_fn(cx, expr) else { return };
debug!(?span, ?def_id, ?substs);
- if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) &&
- !cx.tcx.has_attr(instance.def_id(), sym::rustc_lint_diagnostics)
- {
+ let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs)
+ .ok()
+ .and_then(|inst| inst)
+ .map(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics))
+ .unwrap_or(false);
+ if !has_attr {
return;
}
#![feature(let_chains)]
#![feature(let_else)]
#![feature(never_type)]
+#![feature(rustc_attrs)]
#![recursion_limit = "256"]
#[macro_use]
}
impl<'a> Parser<'a> {
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub(super) fn span_err<S: Into<MultiSpan>>(
&self,
sp: S,
err.span_err(sp, self.diagnostic())
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
edition = "2021"
[dependencies]
-rustc_middle = { path = "../rustc_middle" }
rustc_ast = { path = "../rustc_ast" }
rustc_attr = { path = "../rustc_attr" }
+rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-rustc_data_structures = { path = "../rustc_data_structures" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
+rustc_typeck = { path = "../rustc_typeck" }
tracing = "0.1"
--- /dev/null
+use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_span::{Span, Symbol};
+
+#[derive(SessionDiagnostic)]
+#[error(privacy::field_is_private, code = "E0451")]
+pub struct FieldIsPrivate {
+ #[primary_span]
+ pub span: Span,
+ pub field_name: Symbol,
+ pub variant_descr: &'static str,
+ pub def_path_str: String,
+ #[subdiagnostic]
+ pub label: FieldIsPrivateLabel,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub enum FieldIsPrivateLabel {
+ #[label(privacy::field_is_private_is_update_syntax_label)]
+ IsUpdateSyntax {
+ #[primary_span]
+ span: Span,
+ field_name: Symbol,
+ },
+ #[label(privacy::field_is_private_label)]
+ Other {
+ #[primary_span]
+ span: Span,
+ },
+}
+
+#[derive(SessionDiagnostic)]
+#[error(privacy::item_is_private)]
+pub struct ItemIsPrivate<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub kind: &'a str,
+ pub descr: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(privacy::unnamed_item_is_private)]
+pub struct UnnamedItemIsPrivate {
+ #[primary_span]
+ pub span: Span,
+ pub kind: &'static str,
+}
+
+// Duplicate of `InPublicInterface` but with a different error code, shares the same slug.
+#[derive(SessionDiagnostic)]
+#[error(privacy::in_public_interface, code = "E0445")]
+pub struct InPublicInterfaceTraits<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub vis_descr: &'static str,
+ pub kind: &'a str,
+ pub descr: String,
+ #[label(privacy::visibility_label)]
+ pub vis_span: Span,
+}
+
+// Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug.
+#[derive(SessionDiagnostic)]
+#[error(privacy::in_public_interface, code = "E0446")]
+pub struct InPublicInterface<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub vis_descr: &'static str,
+ pub kind: &'a str,
+ pub descr: String,
+ #[label(privacy::visibility_label)]
+ pub vis_span: Span,
+}
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(associated_type_defaults)]
#![feature(control_flow_enum)]
+#![feature(rustc_private)]
#![feature(try_blocks)]
-#![feature(associated_type_defaults)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
+#![cfg_attr(not(bootstrap), deny(rustc::untranslatable_diagnostic))]
+#![cfg_attr(not(bootstrap), deny(rustc::diagnostic_outside_of_impl))]
+
+mod errors;
use rustc_ast::MacroDef;
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::intern::Interned;
-use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
use std::ops::ControlFlow;
use std::{cmp, fmt, mem};
+use errors::{
+ FieldIsPrivate, FieldIsPrivateLabel, InPublicInterface, InPublicInterfaceTraits, ItemIsPrivate,
+ UnnamedItemIsPrivate,
+};
+
////////////////////////////////////////////////////////////////////////////////
/// Generic infrastructure used to implement specific visitors below.
////////////////////////////////////////////////////////////////////////////////
let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.current_item);
let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1;
if !field.vis.is_accessible_from(def_id, self.tcx) {
- let label = if in_update_syntax {
- format!("field `{}` is private", field.name)
- } else {
- "private field".to_string()
- };
-
- struct_span_err!(
- self.tcx.sess,
+ self.tcx.sess.emit_err(FieldIsPrivate {
span,
- E0451,
- "field `{}` of {} `{}` is private",
- field.name,
- def.variant_descr(),
- self.tcx.def_path_str(def.did())
- )
- .span_label(span, label)
- .emit();
+ field_name: field.name,
+ variant_descr: def.variant_descr(),
+ def_path_str: self.tcx.def_path_str(def.did()),
+ label: if in_update_syntax {
+ FieldIsPrivateLabel::IsUpdateSyntax { span, field_name: field.name }
+ } else {
+ FieldIsPrivateLabel::Other { span }
+ },
+ });
}
}
}
fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
let is_error = !self.item_is_accessible(def_id);
if is_error {
- self.tcx
- .sess
- .struct_span_err(self.span, &format!("{} `{}` is private", kind, descr))
- .span_label(self.span, &format!("private {}", kind))
- .emit();
+ self.tcx.sess.emit_err(ItemIsPrivate {
+ span: self.span,
+ kind,
+ descr: descr.to_string(),
+ });
}
is_error
}
hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
};
let kind = kind.descr(def_id);
- let msg = match name {
- Some(name) => format!("{} `{}` is private", kind, name),
- None => format!("{} is private", kind),
+ let _ = match name {
+ Some(name) => sess.emit_err(ItemIsPrivate { span, kind, descr: name }),
+ None => sess.emit_err(UnnamedItemIsPrivate { span, kind }),
};
- sess.struct_span_err(span, &msg)
- .span_label(span, &format!("private {}", kind))
- .emit();
return;
}
}
}
}
};
- let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr);
let span = self.tcx.def_span(self.item_def_id.to_def_id());
if self.has_old_errors
|| self.in_assoc_ty
|| self.tcx.resolutions(()).has_pub_restricted
{
- let mut err = if kind == "trait" {
- struct_span_err!(self.tcx.sess, span, E0445, "{}", make_msg())
- } else {
- struct_span_err!(self.tcx.sess, span, E0446, "{}", make_msg())
- };
+ let descr = descr.to_string();
let vis_span =
self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id));
- err.span_label(span, format!("can't leak {} {}", vis_descr, kind));
- err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr));
- err.emit();
+ if kind == "trait" {
+ self.tcx.sess.emit_err(InPublicInterfaceTraits {
+ span,
+ vis_descr,
+ kind,
+ descr,
+ vis_span,
+ });
+ } else {
+ self.tcx.sess.emit_err(InPublicInterface {
+ span,
+ vis_descr,
+ kind,
+ descr,
+ vis_span,
+ });
+ }
} else {
let err_code = if kind == "trait" { "E0445" } else { "E0446" };
self.tcx.struct_span_lint_hir(
hir_id,
span,
|lint| {
- lint.build(&format!("{} (error {})", make_msg(), err_code)).emit();
+ lint.build(&format!(
+ "{} (error {})",
+ format!("{} {} `{}` in public interface", vis_descr, kind, descr),
+ err_code
+ ))
+ .emit();
},
);
}
self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_warn<S: Into<MultiSpan>>(
&self,
sp: S,
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_warn(sp, msg)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>(
&self,
sp: S,
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_warn_with_expectation(sp, msg, id)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_warn_with_code(sp, msg, code)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn(msg)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_warn_with_expectation(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn_with_expectation(msg, id)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_allow<S: Into<MultiSpan>>(
&self,
sp: S,
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_allow(sp, msg)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_allow(msg)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_expect(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_expect(msg, id)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
self.diagnostic().struct_span_err(sp, msg)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
self.diagnostic().struct_span_err_with_code(sp, msg, code)
}
// FIXME: This method should be removed (every error should have an associated error code).
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
self.parse_sess.struct_err(msg)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_err_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
self.diagnostic().struct_err_with_code(msg, code)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_warn_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn_with_code(msg, code)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_fatal<S: Into<MultiSpan>>(
&self,
sp: S,
) -> DiagnosticBuilder<'_, !> {
self.diagnostic().struct_span_fatal(sp, msg)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
) -> DiagnosticBuilder<'_, !> {
self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
self.diagnostic().struct_fatal(msg)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
self.diagnostic().span_fatal(sp, msg)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_fatal_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
) -> ! {
self.diagnostic().span_fatal_with_code(sp, msg, code)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! {
self.diagnostic().fatal(msg).raise()
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_err_or_warn<S: Into<MultiSpan>>(
&self,
is_warning: bool,
self.span_err(sp, msg);
}
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_err<S: Into<MultiSpan>>(
&self,
sp: S,
) -> ErrorGuaranteed {
self.diagnostic().span_err(sp, msg)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
) {
self.diagnostic().span_err_with_code(sp, msg, code)
}
+ #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
self.diagnostic().err(msg)
}
}
pub fn generate_fn_name_span(&self, span: Span) -> Option<Span> {
- let prev_span = self.span_extend_to_prev_str(span, "fn", true, true).unwrap_or(span);
+ let prev_span = self.span_extend_to_prev_str(span, "fn", true, true)?;
if let Ok(snippet) = self.span_to_snippet(prev_span) {
debug!(
"generate_fn_name_span: span={:?}, prev_span={:?}, snippet={:?}",
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
-use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::fold::{MaxUniverse, TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::subst::Subst;
Err(InProgress) => return ProjectAndUnifyResult::Recursive,
};
debug!(?normalized, ?obligations, "project_and_unify_type result");
- let actual = obligation.predicate.term;
- // HACK: lazy TAIT would regress src/test/ui/impl-trait/nested-return-type2.rs, so we add
- // a back-compat hack hat converts the RPITs into inference vars, just like they were before
- // lazy TAIT.
- // This does not affect TAITs in general, as tested in the nested-return-type-tait* tests.
- let InferOk { value: actual, obligations: new } =
- selcx.infcx().replace_opaque_types_with_inference_vars(
- actual,
- obligation.cause.body_id,
- obligation.cause.span,
- ObligationCauseCode::MiscObligation,
- obligation.param_env,
- );
- obligations.extend(new);
-
- match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) {
+ match infcx
+ .at(&obligation.cause, obligation.param_env)
+ .eq(normalized, obligation.predicate.term)
+ {
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
obligations.extend(inferred_obligations);
ProjectAndUnifyResult::Holds(obligations)
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::struct_span_err;
-use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::query::Providers;
let module = tcx.hir_module_items(module_def_id);
for id in module.items() {
if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
- let item = tcx.hir().item(id);
- if let hir::ItemKind::Impl(ref impl_) = item.kind {
- enforce_impl_params_are_constrained(tcx, item.def_id, impl_.items);
- enforce_impl_items_are_distinct(tcx, impl_.items);
- if min_specialization {
- check_min_specialization(tcx, item.def_id.to_def_id(), item.span);
- }
+ enforce_impl_params_are_constrained(tcx, id.def_id);
+ enforce_impl_items_are_distinct(tcx, id.def_id);
+ if min_specialization {
+ check_min_specialization(tcx, id.def_id);
}
}
}
*providers = Providers { check_mod_impl_wf, ..*providers };
}
-fn enforce_impl_params_are_constrained(
- tcx: TyCtxt<'_>,
- impl_def_id: LocalDefId,
- impl_item_refs: &[hir::ImplItemRef],
-) {
+fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
// Every lifetime used in an associated type must be constrained.
let impl_self_ty = tcx.type_of(impl_def_id);
if impl_self_ty.references_error() {
);
// Disallow unconstrained lifetimes, but only if they appear in assoc types.
- let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs
+ let lifetimes_in_associated_types: FxHashSet<_> = tcx
+ .associated_item_def_ids(impl_def_id)
.iter()
- .map(|item_ref| item_ref.id.def_id)
.flat_map(|def_id| {
let item = tcx.associated_item(def_id);
match item.kind {
}
/// Enforce that we do not have two items in an impl with the same name.
-fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef]) {
+fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
let mut seen_type_items = FxHashMap::default();
let mut seen_value_items = FxHashMap::default();
- for impl_item_ref in impl_item_refs {
- let impl_item = tcx.hir().impl_item(impl_item_ref.id);
+ for &impl_item_ref in tcx.associated_item_def_ids(impl_def_id) {
+ let impl_item = tcx.associated_item(impl_item_ref);
let seen_items = match impl_item.kind {
- hir::ImplItemKind::TyAlias(_) => &mut seen_type_items,
+ ty::AssocKind::Type => &mut seen_type_items,
_ => &mut seen_value_items,
};
- match seen_items.entry(impl_item.ident.normalize_to_macros_2_0()) {
+ let span = tcx.def_span(impl_item_ref);
+ let ident = impl_item.ident(tcx);
+ match seen_items.entry(ident.normalize_to_macros_2_0()) {
Occupied(entry) => {
let mut err = struct_span_err!(
tcx.sess,
- impl_item.span,
+ span,
E0201,
"duplicate definitions with name `{}`:",
- impl_item.ident
- );
- err.span_label(
- *entry.get(),
- format!("previous definition of `{}` here", impl_item.ident),
+ ident
);
- err.span_label(impl_item.span, "duplicate definition");
+ err.span_label(*entry.get(), format!("previous definition of `{}` here", ident));
+ err.span_label(span, "duplicate definition");
err.emit();
}
Vacant(entry) => {
- entry.insert(impl_item.span);
+ entry.insert(span);
}
}
}
use rustc_span::Span;
use rustc_trait_selection::traits::{self, translate_substs, wf};
-pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: DefId, span: Span) {
+pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
tcx.infer_ctxt().enter(|infcx| {
- check_always_applicable(&infcx, impl_def_id, node, span);
+ check_always_applicable(&infcx, impl_def_id, node);
});
}
}
-fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: DefId) -> Option<Node> {
+fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option<Node> {
let trait_ref = tcx.impl_trait_ref(impl1_def_id)?;
let trait_def = tcx.trait_def(trait_ref.def_id);
- let impl2_node = trait_def.ancestors(tcx, impl1_def_id).ok()?.nth(1)?;
+ let impl2_node = trait_def.ancestors(tcx, impl1_def_id.to_def_id()).ok()?.nth(1)?;
let always_applicable_trait =
matches!(trait_def.specialization_kind, TraitSpecializationKind::AlwaysApplicable);
}
/// Check that `impl1` is a sound specialization
-fn check_always_applicable(
- infcx: &InferCtxt<'_, '_>,
- impl1_def_id: DefId,
- impl2_node: Node,
- span: Span,
-) {
- if let Some((impl1_substs, impl2_substs)) =
- get_impl_substs(infcx, impl1_def_id, impl2_node, span)
- {
+fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId, impl2_node: Node) {
+ if let Some((impl1_substs, impl2_substs)) = get_impl_substs(infcx, impl1_def_id, impl2_node) {
let impl2_def_id = impl2_node.def_id();
debug!(
"check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)",
unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs)
};
+ let span = tcx.def_span(impl1_def_id);
check_static_lifetimes(tcx, &parent_substs, span);
check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
-
- check_predicates(
- infcx,
- impl1_def_id.expect_local(),
- impl1_substs,
- impl2_node,
- impl2_substs,
- span,
- );
+ check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
}
}
/// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
fn get_impl_substs<'tcx>(
infcx: &InferCtxt<'_, 'tcx>,
- impl1_def_id: DefId,
+ impl1_def_id: LocalDefId,
impl2_node: Node,
- span: Span,
) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> {
let tcx = infcx.tcx;
let param_env = tcx.param_env(impl1_def_id);
- let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
- let impl2_substs = translate_substs(infcx, param_env, impl1_def_id, impl1_substs, impl2_node);
+ let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
+ let impl2_substs =
+ translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
// Conservatively use an empty `ParamEnv`.
let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
- infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
+ infcx.resolve_regions_and_report_errors(impl1_def_id.to_def_id(), &outlives_env);
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
+ let span = tcx.def_span(impl1_def_id);
tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
return None;
};
_marker: PhantomData<T>,
}
+/// `ThinBox<T>` is `Send` if `T` is `Send` because the data is owned.
+#[unstable(feature = "thin_box", issue = "92791")]
+unsafe impl<T: ?Sized + Send> Send for ThinBox<T> {}
+
+/// `ThinBox<T>` is `Sync` if `T` is `Sync` because the data is owned.
+#[unstable(feature = "thin_box", issue = "92791")]
+unsafe impl<T: ?Sized + Sync> Sync for ThinBox<T> {}
+
#[unstable(feature = "thin_box", issue = "92791")]
impl<T> ThinBox<T> {
/// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on
}
}
-/// Fuse the iterator if the expression is `None`.
-macro_rules! fuse {
- ($self:ident . $iter:ident . $($call:tt)+) => {
- match $self.$iter {
- Some(ref mut iter) => match iter.$($call)+ {
- None => {
- $self.$iter = None;
- None
- }
- item => item,
- },
- None => None,
- }
- };
-}
-
-/// Try an iterator method without fusing,
-/// like an inline `.as_mut().and_then(...)`
-macro_rules! maybe {
- ($self:ident . $iter:ident . $($call:tt)+) => {
- match $self.$iter {
- Some(ref mut iter) => iter.$($call)+,
- None => None,
- }
- };
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<A, B> Iterator for Chain<A, B>
where
#[inline]
fn next(&mut self) -> Option<A::Item> {
- match fuse!(self.a.next()) {
- None => maybe!(self.b.next()),
- item => item,
- }
+ and_then_or_clear(&mut self.a, Iterator::next).or_else(|| self.b.as_mut()?.next())
}
#[inline]
self.a = None;
}
- maybe!(self.b.nth(n))
+ self.b.as_mut()?.nth(n)
}
#[inline]
where
P: FnMut(&Self::Item) -> bool,
{
- match fuse!(self.a.find(&mut predicate)) {
- None => maybe!(self.b.find(predicate)),
- item => item,
- }
+ and_then_or_clear(&mut self.a, |a| a.find(&mut predicate))
+ .or_else(|| self.b.as_mut()?.find(predicate))
}
#[inline]
fn last(self) -> Option<A::Item> {
// Must exhaust a before b.
- let a_last = match self.a {
- Some(a) => a.last(),
- None => None,
- };
- let b_last = match self.b {
- Some(b) => b.last(),
- None => None,
- };
+ let a_last = self.a.and_then(Iterator::last);
+ let b_last = self.b.and_then(Iterator::last);
b_last.or(a_last)
}
{
#[inline]
fn next_back(&mut self) -> Option<A::Item> {
- match fuse!(self.b.next_back()) {
- None => maybe!(self.a.next_back()),
- item => item,
- }
+ and_then_or_clear(&mut self.b, |b| b.next_back()).or_else(|| self.a.as_mut()?.next_back())
}
#[inline]
self.b = None;
}
- maybe!(self.a.nth_back(n))
+ self.a.as_mut()?.nth_back(n)
}
#[inline]
where
P: FnMut(&Self::Item) -> bool,
{
- match fuse!(self.b.rfind(&mut predicate)) {
- None => maybe!(self.a.rfind(predicate)),
- item => item,
- }
+ and_then_or_clear(&mut self.b, |b| b.rfind(&mut predicate))
+ .or_else(|| self.a.as_mut()?.rfind(predicate))
}
fn try_rfold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
B: TrustedLen<Item = A::Item>,
{
}
+
+#[inline]
+fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
+ let x = f(opt.as_mut()?);
+ if x.is_none() {
+ *opt = None;
+ }
+ x
+}
#[inline]
fn next(&mut self) -> Option<U::Item> {
loop {
- if let Some(ref mut inner) = self.frontiter {
- match inner.next() {
- None => self.frontiter = None,
- elt @ Some(_) => return elt,
- }
+ if let elt @ Some(_) = and_then_or_clear(&mut self.frontiter, Iterator::next) {
+ return elt;
}
match self.iter.next() {
- None => match self.backiter.as_mut()?.next() {
- None => {
- self.backiter = None;
- return None;
- }
- elt @ Some(_) => return elt,
- },
+ None => return and_then_or_clear(&mut self.backiter, Iterator::next),
Some(inner) => self.frontiter = Some(inner.into_iter()),
}
}
#[inline]
fn next_back(&mut self) -> Option<U::Item> {
loop {
- if let Some(ref mut inner) = self.backiter {
- match inner.next_back() {
- None => self.backiter = None,
- elt @ Some(_) => return elt,
- }
+ if let elt @ Some(_) = and_then_or_clear(&mut self.backiter, |b| b.next_back()) {
+ return elt;
}
match self.iter.next_back() {
- None => match self.frontiter.as_mut()?.next_back() {
- None => {
- self.frontiter = None;
- return None;
- }
- elt @ Some(_) => return elt,
- },
- next => self.backiter = next.map(IntoIterator::into_iter),
+ None => return and_then_or_clear(&mut self.frontiter, |f| f.next_back()),
+ Some(inner) => self.backiter = Some(inner.into_iter()),
}
}
}
unsafe impl<T, const N: usize> TrustedConstSize for &'_ [T; N] {}
#[unstable(feature = "std_internals", issue = "none")]
unsafe impl<T, const N: usize> TrustedConstSize for &'_ mut [T; N] {}
+
+#[inline]
+fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
+ let x = f(opt.as_mut()?);
+ if x.is_none() {
+ *opt = None;
+ }
+ x
+}
#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Fuse<I> where I: Iterator {}
-/// Fuse the iterator if the expression is `None`.
-macro_rules! fuse {
- ($self:ident . iter . $($call:tt)+) => {
- match $self.iter {
- Some(ref mut iter) => match iter.$($call)+ {
- None => {
- $self.iter = None;
- None
- }
- item => item,
- },
- None => None,
- }
- };
-}
-
-/// Specialized macro that doesn't check if the expression is `None`.
-/// (We trust that a `FusedIterator` will fuse itself.)
-macro_rules! spec {
- ($self:ident . iter . $($call:tt)+) => {
- match $self.iter {
- Some(ref mut iter) => iter.$($call)+,
- None => None,
- }
- };
-}
-
// Any specialized implementation here is made internal
// to avoid exposing default fns outside this trait.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
default fn next(&mut self) -> Option<<I as Iterator>::Item> {
- fuse!(self.iter.next())
+ and_then_or_clear(&mut self.iter, Iterator::next)
}
#[inline]
default fn nth(&mut self, n: usize) -> Option<I::Item> {
- fuse!(self.iter.nth(n))
+ and_then_or_clear(&mut self.iter, |iter| iter.nth(n))
}
#[inline]
where
P: FnMut(&Self::Item) -> bool,
{
- fuse!(self.iter.find(predicate))
+ and_then_or_clear(&mut self.iter, |iter| iter.find(predicate))
}
#[inline]
where
I: DoubleEndedIterator,
{
- fuse!(self.iter.next_back())
+ and_then_or_clear(&mut self.iter, |iter| iter.next_back())
}
#[inline]
where
I: DoubleEndedIterator,
{
- fuse!(self.iter.nth_back(n))
+ and_then_or_clear(&mut self.iter, |iter| iter.nth_back(n))
}
#[inline]
P: FnMut(&Self::Item) -> bool,
I: DoubleEndedIterator,
{
- fuse!(self.iter.rfind(predicate))
+ and_then_or_clear(&mut self.iter, |iter| iter.rfind(predicate))
}
}
{
#[inline]
fn next(&mut self) -> Option<<I as Iterator>::Item> {
- spec!(self.iter.next())
+ self.iter.as_mut()?.next()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<I::Item> {
- spec!(self.iter.nth(n))
+ self.iter.as_mut()?.nth(n)
}
#[inline]
where
P: FnMut(&Self::Item) -> bool,
{
- spec!(self.iter.find(predicate))
+ self.iter.as_mut()?.find(predicate)
}
#[inline]
where
I: DoubleEndedIterator,
{
- spec!(self.iter.next_back())
+ self.iter.as_mut()?.next_back()
}
#[inline]
where
I: DoubleEndedIterator,
{
- spec!(self.iter.nth_back(n))
+ self.iter.as_mut()?.nth_back(n)
}
#[inline]
P: FnMut(&Self::Item) -> bool,
I: DoubleEndedIterator,
{
- spec!(self.iter.rfind(predicate))
+ self.iter.as_mut()?.rfind(predicate)
+ }
+}
+
+#[inline]
+fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
+ let x = f(opt.as_mut()?);
+ if x.is_none() {
+ *opt = None;
}
+ x
}
use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
use crate::sys::hermit::abi;
use crate::sys::locks::Mutex;
+use crate::sys_common::lazy_box::{LazyBox, LazyInit};
use crate::time::Duration;
// The implementation is inspired by Andrew D. Birrell's paper
sem2: *const c_void,
}
-pub type MovableCondvar = Condvar;
+pub(crate) type MovableCondvar = LazyBox<Condvar>;
+
+impl LazyInit for Condvar {
+ fn init() -> Box<Self> {
+ Box::new(Self::new())
+ }
+}
unsafe impl Send for Condvar {}
unsafe impl Sync for Condvar {}
impl Condvar {
- pub const fn new() -> Condvar {
- Condvar { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() }
+ pub fn new() -> Self {
+ let mut condvar =
+ Self { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() };
+ unsafe {
+ let _ = abi::sem_init(&mut condvar.sem1, 0);
+ let _ = abi::sem_init(&mut condvar.sem2, 0);
+ }
+ condvar
}
pub unsafe fn notify_one(&self) {
}
#[inline]
- pub unsafe fn init(&mut self) {
- self.inner = Spinlock::new(MutexInner::new());
- }
+ pub unsafe fn init(&mut self) {}
#[inline]
pub unsafe fn lock(&self) {
use crate::cell::UnsafeCell;
-use crate::sys::locks::{Condvar, Mutex};
+use crate::sys::locks::{MovableCondvar, Mutex};
+use crate::sys_common::lazy_box::{LazyBox, LazyInit};
pub struct RwLock {
lock: Mutex,
- cond: Condvar,
+ cond: MovableCondvar,
state: UnsafeCell<State>,
}
impl RwLock {
pub const fn new() -> RwLock {
- RwLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) }
+ RwLock {
+ lock: Mutex::new(),
+ cond: MovableCondvar::new(),
+ state: UnsafeCell::new(State::Unlocked),
+ }
}
#[inline]
self.res.def_id()
}
+ pub(crate) fn last_opt(&self) -> Option<Symbol> {
+ self.segments.last().map(|s| s.name)
+ }
+
pub(crate) fn last(&self) -> Symbol {
- self.segments.last().expect("segments were empty").name
+ self.last_opt().expect("segments were empty")
}
pub(crate) fn whole_name(&self) -> String {
},
Glob => Import {
source: import.source.path.whole_name(),
- name: import.source.path.last().to_string(),
+ name: import
+ .source
+ .path
+ .last_opt()
+ .unwrap_or_else(|| Symbol::intern("*"))
+ .to_string(),
id: import.source.did.map(ItemId::from).map(|i| from_item_id(i, tcx)),
glob: true,
},
--- /dev/null
+// Regression test for <https://github.com/rust-lang/rust/issues/98547>.
+
+// @has assoc_type.json
+// @has - "$.index[*][?(@.name=='Trait')]"
+// @has - "$.index[*][?(@.name=='AssocType')]"
+// @has - "$.index[*][?(@.name=='S')]"
+// @has - "$.index[*][?(@.name=='S2')]"
+
+pub trait Trait {
+ type AssocType;
+}
+
+impl<T> Trait for T {
+ type AssocType = Self;
+}
+
+pub struct S;
+
+/// Not needed for the #98547 ICE to occur, but added to maximize the chance of
+/// getting an ICE in the future. See
+/// <https://github.com/rust-lang/rust/pull/98548#discussion_r908219164>
+pub struct S2;
--- /dev/null
+// This is a regression test for <https://github.com/rust-lang/rust/issues/98003>.
+
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+
+// @has glob_import.json
+// @has - "$.index[*][?(@.name=='glob')]"
+// @has - "$.index[*][?(@.kind=='import')].inner.name" \"*\"
+
+
+mod m1 {
+ pub fn f() {}
+}
+mod m2 {
+ pub fn f(_: u8) {}
+}
+
+pub use m1::*;
+pub use m2::*;
+
+pub mod glob {
+ pub use *;
+}
LL | const bar: bool = true;
| ----------------------- previous definition of `bar` here
LL | fn bar() {}
- | ^^^^^^^^^^^ duplicate definition
+ | ^^^^^^^^ duplicate definition
error: aborting due to previous error
--- /dev/null
+const fn hey() -> usize {
+ panic!(123); //~ ERROR argument to `panic!()` in a const context must have type `&str`
+}
+
+fn main() {
+ let _: [u8; hey()] = todo!();
+}
--- /dev/null
+error: argument to `panic!()` in a const context must have type `&str`
+ --> $DIR/issue-85907.rs:2:5
+ |
+LL | panic!(123);
+ | ^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
--> $DIR/E0201.rs:5:5
|
LL | fn bar(&self) -> bool { self.0 > 5 }
- | ------------------------------------ previous definition of `bar` here
+ | --------------------- previous definition of `bar` here
LL | fn bar() {}
- | ^^^^^^^^^^^ duplicate definition
+ | ^^^^^^^^ duplicate definition
error[E0201]: duplicate definitions with name `baz`:
--> $DIR/E0201.rs:17:5
|
LL | fn baz(&self) -> bool { true }
- | ------------------------------ previous definition of `baz` here
+ | --------------------- previous definition of `baz` here
LL | fn baz(&self) -> bool { self.0 > 5 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^^^^^^^^^ duplicate definition
error[E0201]: duplicate definitions with name `Quux`:
--> $DIR/E0201.rs:18:5
--- /dev/null
+// edition:2018
+
+macro_rules! foo_ { () => {}; }
+use foo_ as foo;
--- /dev/null
+// edition:2018
+// build-pass
+// aux-crate:issue_80074=issue-80074-macro.rs
+
+#[macro_use]
+extern crate issue_80074;
+
+fn main() {
+ foo!();
+}
--- /dev/null
+struct Struct<T>(T);
+
+impl<T> Struct<T> {
+ const CONST: fn() = || {
+ struct _Obligation where T:; //~ ERROR can't use generic parameters from outer function
+ };
+}
+
+fn main() {}
--- /dev/null
+error[E0401]: can't use generic parameters from outer function
+ --> $DIR/issue-98432.rs:5:34
+ |
+LL | impl<T> Struct<T> {
+ | - type parameter from outer function
+LL | const CONST: fn() = || {
+LL | struct _Obligation where T:;
+ | ^ use of generic parameter from outer function
+ |
+ = help: try using a local generic parameter instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
--> $DIR/impl-duplicate-methods.rs:5:5
|
LL | fn orange(&self) {}
- | ------------------- previous definition of `orange` here
+ | ---------------- previous definition of `orange` here
LL | fn orange(&self) {}
- | ^^^^^^^^^^^^^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^^^^ duplicate definition
error: aborting due to previous error
-// check-pass
-
trait Duh {}
impl Duh for i32 {}
// the hidden type. We already have obligations registered on the inference
// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
// type does not implement `Duh`, even if its hidden type does.
-// Lazy TAIT would error out, but we inserted a hack to make it work again,
-// keeping backwards compatibility.
fn foo() -> impl Trait<Assoc = impl Send> {
+ //~^ ERROR `impl Send: Duh` is not satisfied
|| 42
}
-fn main() {
-}
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `impl Send: Duh` is not satisfied
+ --> $DIR/nested-return-type2.rs:21:13
+ |
+LL | fn foo() -> impl Trait<Assoc = impl Send> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `impl Send`
+ |
+ = help: the trait `Duh` is implemented for `i32`
+note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2.rs:23:5: 23:10]`
+ --> $DIR/nested-return-type2.rs:12:31
+ |
+LL | impl<R: Duh, F: FnMut() -> R> Trait for F {
+ | ^^^^^ ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
error[E0201]: duplicate definitions with name `bar`:
--> $DIR/issue-4265.rs:10:5
|
-LL | / fn bar() {
-LL | | Foo { baz: 0 }.bar();
-LL | | }
- | |_____- previous definition of `bar` here
-LL |
-LL | / fn bar() {
-LL | | }
- | |_____^ duplicate definition
+LL | fn bar() {
+ | -------- previous definition of `bar` here
+...
+LL | fn bar() {
+ | ^^^^^^^^ duplicate definition
error: aborting due to previous error
+++ /dev/null
-// check-pass
-// compile-flags: -Z unpretty=expanded
-
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
-
-fn main() {
- let elem = 1i32;
- assert!(elem == 1);
-}
+++ /dev/null
-#![feature(prelude_import)]
-#![no_std]
-// check-pass
-// compile-flags: -Z unpretty=expanded
-
-#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
-#[prelude_import]
-use ::std::prelude::rust_2015::*;
-#[macro_use]
-extern crate std;
-
-fn main() {
- let elem = 1i32;
- {
- #[allow(unused_imports)]
- use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
- let mut __capture0 = ::core::asserting::Capture::new();
- let __local_bind0 = &elem;
- if !(*{
- (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
- __local_bind0
- } == 1) {
- {
- ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n elem = ",
- "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
- }
- }
- };
-}
--- /dev/null
+// check-pass
+// compile-flags: -Z unpretty=expanded
+
+#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+
+fn arbitrary_consuming_method_for_demonstration_purposes() {
+ let elem = 1i32;
+ assert!(elem as usize);
+}
+
+fn addr_of() {
+ let elem = 1i32;
+ assert!(&elem);
+}
+
+fn binary() {
+ let elem = 1i32;
+ assert!(elem == 1);
+ assert!(elem >= 1);
+ assert!(elem > 0);
+ assert!(elem < 3);
+ assert!(elem <= 3);
+ assert!(elem != 3);
+}
+
+fn unary() {
+ let elem = &1i32;
+ assert!(*elem);
+}
+
+fn main() {
+}
--- /dev/null
+#![feature(prelude_import)]
+#![no_std]
+// check-pass
+// compile-flags: -Z unpretty=expanded
+
+#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+fn arbitrary_consuming_method_for_demonstration_purposes() {
+ let elem = 1i32;
+ {
+ #[allow(unused_imports)]
+ use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+ let mut __capture0 = ::core::asserting::Capture::new();
+ let __local_bind0 = &elem;
+ if ::core::intrinsics::unlikely(!(*{
+ (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+ __local_bind0
+ } as usize)) {
+
+
+
+
+ {
+ ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem as usize\nWith captures:\n elem = ",
+ "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ }
+ }
+ };
+}
+fn addr_of() {
+ let elem = 1i32;
+ {
+ #[allow(unused_imports)]
+ use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+ let mut __capture0 = ::core::asserting::Capture::new();
+ let __local_bind0 = &elem;
+ if ::core::intrinsics::unlikely(!&*__local_bind0) {
+ (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+ {
+ ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: &elem\nWith captures:\n elem = ",
+ "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ }
+ }
+ };
+}
+fn binary() {
+ let elem = 1i32;
+ {
+ #[allow(unused_imports)]
+ use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+ let mut __capture0 = ::core::asserting::Capture::new();
+ let __local_bind0 = &elem;
+ if ::core::intrinsics::unlikely(!(*__local_bind0 == 1)) {
+ (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+ {
+ ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n elem = ",
+ "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ }
+ }
+ };
+ {
+ #[allow(unused_imports)]
+ use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+ let mut __capture0 = ::core::asserting::Capture::new();
+ let __local_bind0 = &elem;
+ if ::core::intrinsics::unlikely(!(*__local_bind0 >= 1)) {
+ (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+ {
+ ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem >= 1\nWith captures:\n elem = ",
+ "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ }
+ }
+ };
+ {
+ #[allow(unused_imports)]
+ use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+ let mut __capture0 = ::core::asserting::Capture::new();
+ let __local_bind0 = &elem;
+ if ::core::intrinsics::unlikely(!(*__local_bind0 > 0)) {
+ (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+ {
+ ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem > 0\nWith captures:\n elem = ",
+ "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ }
+ }
+ };
+ {
+ #[allow(unused_imports)]
+ use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+ let mut __capture0 = ::core::asserting::Capture::new();
+ let __local_bind0 = &elem;
+ if ::core::intrinsics::unlikely(!(*__local_bind0 < 3)) {
+ (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+ {
+ ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem < 3\nWith captures:\n elem = ",
+ "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ }
+ }
+ };
+ {
+ #[allow(unused_imports)]
+ use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+ let mut __capture0 = ::core::asserting::Capture::new();
+ let __local_bind0 = &elem;
+ if ::core::intrinsics::unlikely(!(*__local_bind0 <= 3)) {
+ (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+ {
+ ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem <= 3\nWith captures:\n elem = ",
+ "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ }
+ }
+ };
+ {
+ #[allow(unused_imports)]
+ use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+ let mut __capture0 = ::core::asserting::Capture::new();
+ let __local_bind0 = &elem;
+ if ::core::intrinsics::unlikely(!(*__local_bind0 != 3)) {
+ (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+ {
+ ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem != 3\nWith captures:\n elem = ",
+ "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ }
+ }
+ };
+}
+fn unary() {
+ let elem = &1i32;
+ {
+ #[allow(unused_imports)]
+ use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable};
+ let mut __capture0 = ::core::asserting::Capture::new();
+ let __local_bind0 = &elem;
+ if ::core::intrinsics::unlikely(!**__local_bind0) {
+ (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
+ {
+ ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: *elem\nWith captures:\n elem = ",
+ "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ }
+ }
+ };
+}
+fn main() {}
--> $DIR/method-macro-backtrace.rs:22:5
|
LL | fn bar(&self) { }
- | ----------------- previous definition of `bar` here
+ | ------------- previous definition of `bar` here
LL | fn bar(&self) { }
- | ^^^^^^^^^^^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^ duplicate definition
error: aborting due to previous error
--> $DIR/issue-8153.rs:11:5
|
LL | fn bar(&self) -> isize {1}
- | -------------------------- previous definition of `bar` here
+ | ---------------------- previous definition of `bar` here
LL | fn bar(&self) -> isize {2}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
error: aborting due to previous error
-use clippy_utils::diagnostics::span_lint_and_sugg_for_edges;
+use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_trait_method;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, map_arg: &Expr<'_>, map_span: Span) {
if let Some((caller_ty_name, method_to_use)) = try_get_caller_ty_name_and_method_name(cx, expr, recv, map_arg) {
let mut applicability = Applicability::MachineApplicable;
- let help_msgs = [
- &format!("try replacing `map` with `{}`", method_to_use),
- "and remove the `.flatten()`",
- ];
+
let closure_snippet = snippet_with_applicability(cx, map_arg.span, "..", &mut applicability);
- span_lint_and_sugg_for_edges(
+ span_lint_and_sugg(
cx,
MAP_FLATTEN,
expr.span.with_lo(map_span.lo()),
&format!("called `map(..).flatten()` on `{}`", caller_ty_name),
- &help_msgs,
+ &format!("try replacing `map` with `{}` and remove the `.flatten()`", method_to_use),
format!("{}({})", method_to_use, closure_snippet),
applicability,
);
use clippy_utils::ty::{implements_trait, match_type};
use clippy_utils::{contains_return, is_trait_item, last_path_segment, paths};
use if_chain::if_chain;
-use rustc_errors::emitter::MAX_SUGGESTION_HIGHLIGHT_LINES;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
arg: &hir::Expr<'_>,
or_has_args: bool,
span: Span,
- method_span: Span,
) -> bool {
let is_default_default = || is_trait_item(cx, fun, sym::Default);
then {
let mut applicability = Applicability::MachineApplicable;
let hint = "unwrap_or_default()";
- let mut sugg_span = span;
+ let sugg_span = span;
- let mut sugg: String = format!(
+ let sugg: String = format!(
"{}.{}",
snippet_with_applicability(cx, self_expr.span, "..", &mut applicability),
hint
);
- if sugg.lines().count() > MAX_SUGGESTION_HIGHLIGHT_LINES {
- sugg_span = method_span.with_hi(span.hi());
- sugg = hint.to_string();
- }
-
span_lint_and_sugg(
cx,
OR_FUN_CALL,
match inner_arg.kind {
hir::ExprKind::Call(fun, or_args) => {
let or_has_args = !or_args.is_empty();
- if !check_unwrap_or_default(cx, name, fun, self_arg, arg, or_has_args, expr.span, method_span) {
+ if !check_unwrap_or_default(cx, name, fun, self_arg, arg, or_has_args, expr.span) {
let fun_span = if or_has_args { None } else { Some(fun.span) };
check_general_case(cx, name, method_span, self_arg, arg, expr.span, fun_span);
}
&["clippy_utils", "diagnostics", "span_lint_and_sugg"],
&["clippy_utils", "diagnostics", "span_lint_and_then"],
&["clippy_utils", "diagnostics", "span_lint_hir_and_then"],
- &["clippy_utils", "diagnostics", "span_lint_and_sugg_for_edges"],
];
const SUGGESTION_DIAGNOSTIC_BUILDER_METHODS: [(&str, bool); 9] = [
("span_suggestion", false),
//! Thank you!
//! ~The `INTERNAL_METADATA_COLLECTOR` lint
-use rustc_errors::{emitter::MAX_SUGGESTION_HIGHLIGHT_LINES, Applicability, Diagnostic, MultiSpan};
+use rustc_errors::{Applicability, Diagnostic, MultiSpan};
use rustc_hir::HirId;
use rustc_lint::{LateContext, Lint, LintContext};
use rustc_span::source_map::Span;
});
}
-/// Like [`span_lint_and_sugg`] with a focus on the edges. The output will either
-/// emit single span or multispan suggestion depending on the number of its lines.
-///
-/// If the given suggestion string has more lines than the maximum display length defined by
-/// [`MAX_SUGGESTION_HIGHLIGHT_LINES`][`rustc_errors::emitter::MAX_SUGGESTION_HIGHLIGHT_LINES`],
-/// this function will split the suggestion and span to showcase the change for the top and
-/// bottom edge of the code. For normal suggestions, in one display window, the help message
-/// will be combined with a colon.
-///
-/// Multipart suggestions like the one being created here currently cannot be
-/// applied by rustfix (See [rustfix#141](https://github.com/rust-lang/rustfix/issues/141)).
-/// Testing rustfix with this lint emission function might require a file with
-/// suggestions that can be fixed and those that can't. See
-/// [clippy#8520](https://github.com/rust-lang/rust-clippy/pull/8520/files) for
-/// an example and of this.
-///
-/// # Example for a long suggestion
-///
-/// ```text
-/// error: called `map(..).flatten()` on `Option`
-/// --> $DIR/map_flatten.rs:8:10
-/// |
-/// LL | .map(|x| {
-/// | __________^
-/// LL | | if x <= 5 {
-/// LL | | Some(x)
-/// LL | | } else {
-/// ... |
-/// LL | | })
-/// LL | | .flatten();
-/// | |__________________^
-/// |
-/// = note: `-D clippy::map-flatten` implied by `-D warnings`
-/// help: try replacing `map` with `and_then`
-/// |
-/// LL ~ .and_then(|x| {
-/// LL + if x <= 5 {
-/// LL + Some(x)
-/// |
-/// help: and remove the `.flatten()`
-/// |
-/// LL + None
-/// LL + }
-/// LL ~ });
-/// |
-/// ```
-pub fn span_lint_and_sugg_for_edges(
- cx: &LateContext<'_>,
- lint: &'static Lint,
- sp: Span,
- msg: &str,
- helps: &[&str; 2],
- sugg: String,
- applicability: Applicability,
-) {
- span_lint_and_then(cx, lint, sp, msg, |diag| {
- let sugg_lines_count = sugg.lines().count();
- if sugg_lines_count > MAX_SUGGESTION_HIGHLIGHT_LINES {
- let sm = cx.sess().source_map();
- if let (Ok(line_upper), Ok(line_bottom)) =
- (sm.lookup_line(sp.lo()), sm.lookup_line(sp.hi()))
- {
- let split_idx = MAX_SUGGESTION_HIGHLIGHT_LINES / 2;
- let span_upper = sm.span_until_char(
- sp.with_hi(line_upper.sf.lines(|lines| lines[line_upper.line + split_idx])),
- '\n',
- );
- let span_bottom = sp.with_lo(line_bottom.sf.lines(|lines| lines[line_bottom.line - split_idx]));
-
- let sugg_lines_vec = sugg.lines().collect::<Vec<&str>>();
- let sugg_upper = sugg_lines_vec[..split_idx].join("\n");
- let sugg_bottom = sugg_lines_vec[sugg_lines_count - split_idx..].join("\n");
-
- diag.span_suggestion(span_upper, helps[0], sugg_upper, applicability);
- diag.span_suggestion(span_bottom, helps[1], sugg_bottom, applicability);
-
- return;
- }
- }
- diag.span_suggestion_with_style(
- sp,
- &helps.join(", "),
- sugg,
- applicability,
- rustc_errors::SuggestionStyle::ShowAlways,
- );
- });
-}
-
/// Create a suggestion made from several `span → replacement`.
///
/// Note: in the JSON format (used by `compiletest_rs`), the help message will
| |__________________^
|
= note: `-D clippy::map-flatten` implied by `-D warnings`
-help: try replacing `map` with `and_then`
+help: try replacing `map` with `and_then` and remove the `.flatten()`
|
LL ~ .and_then(|x| {
LL + if x <= 5 {
LL + Some(x)
- |
-help: and remove the `.flatten()`
- |
+LL + } else {
LL + None
LL + }
LL ~ });
LL | | .flatten();
| |__________________^
|
-help: try replacing `map` with `and_then`
+help: try replacing `map` with `and_then` and remove the `.flatten()`
|
LL ~ .and_then(|x| {
LL + if x == 1 {
LL + Ok(x)
- |
-help: and remove the `.flatten()`
- |
+LL + } else {
LL + Err(0)
LL + }
LL ~ });
LL | | .flatten();
| |__________________^
|
-help: try replacing `map` with `and_then`
+help: try replacing `map` with `and_then` and remove the `.flatten()`
|
LL ~ .and_then(|res| {
LL + if res > 0 {
LL + do_something();
- |
-help: and remove the `.flatten()`
- |
+LL + Ok(res)
+LL + } else {
LL + Err(0)
LL + }
LL ~ });
LL | | .flatten()
| |__________________^
|
-help: try replacing `map` with `filter_map`
+help: try replacing `map` with `filter_map` and remove the `.flatten()`
|
LL ~ .filter_map(|some_value| {
LL + if some_value > 3 {
LL + Some(some_value)
- |
-help: and remove the `.flatten()`
- |
+LL + } else {
LL + None
LL + }
LL + })
.and_then(|_| {
// we need some newlines
// so that the span is big enough
-// we need some newlines
-// so that the span is big enough
// for a splitted output of the diagnostic
Some("")
// whitespace beforehand is important as well
--> $DIR/map_flatten_fixable.rs:18:47
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)`
|
= note: `-D clippy::map-flatten` implied by `-D warnings`
-help: try replacing `map` with `filter_map`, and remove the `.flatten()`
- |
-LL | let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id).collect();
- | ~~~~~~~~~~~~~~~~~~~~~
error: called `map(..).flatten()` on `Iterator`
--> $DIR/map_flatten_fixable.rs:19:47
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-help: try replacing `map` with `filter_map`, and remove the `.flatten()`
- |
-LL | let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id_ref).collect();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)`
error: called `map(..).flatten()` on `Iterator`
--> $DIR/map_flatten_fixable.rs:20:47
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-help: try replacing `map` with `filter_map`, and remove the `.flatten()`
- |
-LL | let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(option_id_closure).collect();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)`
error: called `map(..).flatten()` on `Iterator`
--> $DIR/map_flatten_fixable.rs:21:47
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-help: try replacing `map` with `filter_map`, and remove the `.flatten()`
- |
-LL | let _: Vec<_> = vec![5_i8; 6].into_iter().filter_map(|x| x.checked_add(1)).collect();
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))`
error: called `map(..).flatten()` on `Iterator`
--> $DIR/map_flatten_fixable.rs:24:47
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
- | ^^^^^^^^^^^^^^^^^^^^^^^
- |
-help: try replacing `map` with `flat_map`, and remove the `.flatten()`
- |
-LL | let _: Vec<_> = vec![5_i8; 6].into_iter().flat_map(|x| 0..x).collect();
- | ~~~~~~~~~~~~~~~~~~
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)`
error: called `map(..).flatten()` on `Option`
--> $DIR/map_flatten_fixable.rs:27:40
|
LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
- | ^^^^^^^^^^^^^^^^^^^^
- |
-help: try replacing `map` with `and_then`, and remove the `.flatten()`
- |
-LL | let _: Option<_> = (Some(Some(1))).and_then(|x| x);
- | ~~~~~~~~~~~~~~~
+ | ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
error: called `map(..).flatten()` on `Result`
--> $DIR/map_flatten_fixable.rs:30:42
|
LL | let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
- | ^^^^^^^^^^^^^^^^^^^^
- |
-help: try replacing `map` with `and_then`, and remove the `.flatten()`
- |
-LL | let _: Result<_, &str> = (Ok(Ok(1))).and_then(|x| x);
- | ~~~~~~~~~~~~~~~
+ | ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
error: called `map(..).flatten()` on `Option`
--> $DIR/map_flatten_fixable.rs:59:10
LL | | .flatten();
| |__________________^
|
-help: try replacing `map` with `and_then`
+help: try replacing `map` with `and_then` and remove the `.flatten()`
|
LL ~ .and_then(|_| {
LL + // we need some newlines
LL + // so that the span is big enough
- |
-help: and remove the `.flatten()`
- |
+LL + // for a splitted output of the diagnostic
LL + Some("")
LL + // whitespace beforehand is important as well
LL ~ });
.reduce(|mut acc, f| {
acc.push_str(&f);
acc
- })
- .unwrap_or_default();
+ }).unwrap_or_default();
}
fn more_to_max_suggestion_highest_lines_1() {
let _ = "";
acc.push_str(&f);
acc
- })
- .unwrap_or_default();
+ }).unwrap_or_default();
}
fn equal_to_max_suggestion_highest_lines() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:189:14
+ --> $DIR/or_fun_call.rs:182:9
+ |
+LL | / frames
+LL | | .iter()
+LL | | .map(|f: &String| f.to_lowercase())
+LL | | .reduce(|mut acc, f| {
+... |
+LL | | })
+LL | | .unwrap_or(String::new());
+ | |_____________________________________^
+ |
+help: try this
+ |
+LL ~ frames
+LL + .iter()
+LL + .map(|f: &String| f.to_lowercase())
+LL + .reduce(|mut acc, f| {
+LL + acc.push_str(&f);
+LL + acc
+LL ~ }).unwrap_or_default();
|
-LL | .unwrap_or(String::new());
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:202:14
+ --> $DIR/or_fun_call.rs:195:9
+ |
+LL | / iter.map(|f: &String| f.to_lowercase())
+LL | | .reduce(|mut acc, f| {
+LL | | let _ = "";
+LL | | let _ = "";
+... |
+LL | | })
+LL | | .unwrap_or(String::new());
+ | |_____________________________________^
+ |
+help: try this
+ |
+LL ~ iter.map(|f: &String| f.to_lowercase())
+LL + .reduce(|mut acc, f| {
+LL + let _ = "";
+LL + let _ = "";
+LL + acc.push_str(&f);
+LL + acc
+LL ~ }).unwrap_or_default();
|
-LL | .unwrap_or(String::new());
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a call to `new`
--> $DIR/or_fun_call.rs:208:9
}
pub fn run_tests(config: Config) {
- // FIXME(#33435) Avoid spurious failures in codegen-units/partitioning tests.
- if let Mode::CodegenUnits = config.mode {
- let _ = fs::remove_dir_all("tmp/partitioning-tests");
- }
-
// If we want to collect rustfix coverage information,
// we first make sure that the coverage file does not exist.
// It will be created later on.
-Subproject commit 427061da19723f2206fe4dcb175c9c43b9a6193d
+Subproject commit b74e96f509baf0be70281c55f14cb18fefbc6b22