mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #98612 - Dylan-DPC:rollup-7tasikc, r=Dylan-DPC
Rollup of 9 pull requests Successful merges: - #97346 (Remove a back-compat hack on lazy TAIT) - #98261 (Remove `MAX_SUGGESTION_HIGHLIGHT_LINES`) - #98337 ([RFC 2011] Optimize non-consuming operators) - #98384 (Fix RSS reporting on macOS) - #98420 (translation: lint fix + more migration) - #98430 (Refactor iter adapters with less macros) - #98555 (Hermit: Fix initializing lazy locks) - #98595 (Implement `Send` and `Sync` for `ThinBox<T>`) - #98597 (Remove unstable CStr/CString change from 1.62 release note) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
00ebeb87ac
@ -4280,6 +4280,7 @@ dependencies = [
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_hir",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
|
@ -29,7 +29,6 @@ Compiler
|
||||
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]
|
||||
@ -90,7 +89,6 @@ and related tools.
|
||||
|
||||
[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/
|
||||
|
@ -1,4 +1,6 @@
|
||||
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;
|
||||
|
||||
@ -476,10 +478,11 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||
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)
|
||||
|
@ -6,6 +6,7 @@
|
||||
#![feature(let_else)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(trusted_step)]
|
||||
#![feature(try_blocks)]
|
||||
|
@ -1,11 +1,10 @@
|
||||
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;
|
||||
@ -16,11 +15,19 @@ use rustc_span::{
|
||||
};
|
||||
|
||||
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
|
||||
@ -36,9 +43,11 @@ pub(super) struct Context<'cx, 'a> {
|
||||
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,
|
||||
@ -69,14 +78,22 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
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 { capture_decls, cx, local_bind_decls, span, .. } = self;
|
||||
let Self { best_case_captures, 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))
|
||||
}
|
||||
|
||||
@ -115,6 +132,16 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
)
|
||||
}
|
||||
|
||||
/// 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!(
|
||||
@ -167,17 +194,39 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
/// 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 {
|
||||
@ -228,8 +277,11 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
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.
|
||||
//
|
||||
@ -337,9 +389,23 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
))
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -826,6 +826,24 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
|
12
compiler/rustc_error_messages/locales/en-US/privacy.ftl
Normal file
12
compiler/rustc_error_messages/locales/en-US/privacy.ftl
Normal file
@ -0,0 +1,12 @@
|
||||
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}
|
@ -32,6 +32,7 @@ pub use unic_langid::{langid, LanguageIdentifier};
|
||||
// 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",
|
||||
}
|
||||
|
@ -656,11 +656,6 @@ impl Emitter for SilentEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -1077,6 +1077,7 @@ impl<'a> ExtCtxt<'a> {
|
||||
self.current_expansion.id.expansion_cause()
|
||||
}
|
||||
|
||||
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
|
||||
pub fn struct_span_err<S: Into<MultiSpan>>(
|
||||
&self,
|
||||
sp: S,
|
||||
@ -1101,9 +1102,11 @@ impl<'a> ExtCtxt<'a> {
|
||||
///
|
||||
/// 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);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#![feature(proc_macro_diagnostic)]
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(proc_macro_span)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(try_blocks)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
|
@ -39,21 +39,19 @@ pub struct OpaqueTypeDecl<'tcx> {
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -406,9 +406,12 @@ impl LateLintPass<'_> for Diagnostics {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#![feature(let_chains)]
|
||||
#![feature(let_else)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
|
@ -357,6 +357,7 @@ impl<'a> DerefMut for SnapshotParser<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
|
||||
pub(super) fn span_err<S: Into<MultiSpan>>(
|
||||
&self,
|
||||
sp: S,
|
||||
@ -365,6 +366,7 @@ impl<'a> Parser<'a> {
|
||||
err.span_err(sp, self.diagnostic())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
|
||||
pub fn struct_span_err<S: Into<MultiSpan>>(
|
||||
&self,
|
||||
sp: S,
|
||||
|
@ -4,14 +4,15 @@ version = "0.0.0"
|
||||
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"
|
||||
|
75
compiler/rustc_privacy/src/errors.rs
Normal file
75
compiler/rustc_privacy/src/errors.rs
Normal file
@ -0,0 +1,75 @@
|
||||
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,
|
||||
}
|
@ -1,15 +1,19 @@
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(try_blocks)]
|
||||
#![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};
|
||||
@ -34,6 +38,11 @@ use std::marker::PhantomData;
|
||||
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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -935,23 +944,17 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
|
||||
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 }
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1075,11 +1078,11 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
|
||||
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
|
||||
}
|
||||
@ -1250,13 +1253,10 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1753,22 +1753,31 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
|
||||
}
|
||||
}
|
||||
};
|
||||
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(
|
||||
@ -1776,7 +1785,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
|
||||
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();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -280,6 +280,7 @@ impl Session {
|
||||
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,
|
||||
@ -287,6 +288,7 @@ impl Session {
|
||||
) -> 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,
|
||||
@ -295,6 +297,7 @@ impl Session {
|
||||
) -> 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,
|
||||
@ -303,9 +306,11 @@ impl Session {
|
||||
) -> 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>,
|
||||
@ -313,6 +318,7 @@ impl Session {
|
||||
) -> 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,
|
||||
@ -320,9 +326,11 @@ impl Session {
|
||||
) -> 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>,
|
||||
@ -330,6 +338,7 @@ impl Session {
|
||||
) -> 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,
|
||||
@ -337,6 +346,7 @@ impl Session {
|
||||
) -> 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,
|
||||
@ -346,12 +356,14 @@ impl Session {
|
||||
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>,
|
||||
@ -359,6 +371,7 @@ impl Session {
|
||||
) -> 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>,
|
||||
@ -366,6 +379,7 @@ impl Session {
|
||||
) -> 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,
|
||||
@ -373,6 +387,7 @@ impl Session {
|
||||
) -> 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,
|
||||
@ -381,13 +396,16 @@ impl Session {
|
||||
) -> 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,
|
||||
@ -396,9 +414,11 @@ impl Session {
|
||||
) -> ! {
|
||||
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,
|
||||
@ -411,6 +431,7 @@ impl Session {
|
||||
self.span_err(sp, msg);
|
||||
}
|
||||
}
|
||||
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
|
||||
pub fn span_err<S: Into<MultiSpan>>(
|
||||
&self,
|
||||
sp: S,
|
||||
@ -418,6 +439,7 @@ impl Session {
|
||||
) -> 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,
|
||||
@ -426,6 +448,7 @@ impl Session {
|
||||
) {
|
||||
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)
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ use rustc_hir::def::DefKind;
|
||||
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;
|
||||
@ -252,22 +251,10 @@ fn project_and_unify_type<'cx, 'tcx>(
|
||||
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)
|
||||
|
@ -33,6 +33,14 @@ pub struct ThinBox<T: ?Sized> {
|
||||
_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
|
||||
|
@ -37,33 +37,6 @@ impl<A, B> Chain<A, B> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
@ -74,10 +47,7 @@ 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]
|
||||
@ -161,7 +131,7 @@ where
|
||||
self.a = None;
|
||||
}
|
||||
|
||||
maybe!(self.b.nth(n))
|
||||
self.b.as_mut()?.nth(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -169,23 +139,15 @@ where
|
||||
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)
|
||||
}
|
||||
|
||||
@ -220,10 +182,7 @@ where
|
||||
{
|
||||
#[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]
|
||||
@ -263,7 +222,7 @@ where
|
||||
self.b = None;
|
||||
}
|
||||
|
||||
maybe!(self.a.nth_back(n))
|
||||
self.a.as_mut()?.nth_back(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -271,10 +230,8 @@ where
|
||||
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
|
||||
@ -324,3 +281,12 @@ where
|
||||
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
|
||||
}
|
||||
|
@ -290,20 +290,11 @@ where
|
||||
#[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()),
|
||||
}
|
||||
}
|
||||
@ -436,21 +427,12 @@ where
|
||||
#[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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -606,3 +588,12 @@ unsafe impl<T, const N: usize> TrustedConstSize for [T; N] {}
|
||||
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
|
||||
}
|
||||
|
@ -29,33 +29,6 @@ impl<I> Fuse<I> {
|
||||
#[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")]
|
||||
@ -281,12 +254,12 @@ where
|
||||
|
||||
#[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]
|
||||
@ -308,7 +281,7 @@ where
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
fuse!(self.iter.find(predicate))
|
||||
and_then_or_clear(&mut self.iter, |iter| iter.find(predicate))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -316,7 +289,7 @@ where
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
fuse!(self.iter.next_back())
|
||||
and_then_or_clear(&mut self.iter, |iter| iter.next_back())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -324,7 +297,7 @@ where
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
fuse!(self.iter.nth_back(n))
|
||||
and_then_or_clear(&mut self.iter, |iter| iter.nth_back(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -348,7 +321,7 @@ where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
fuse!(self.iter.rfind(predicate))
|
||||
and_then_or_clear(&mut self.iter, |iter| iter.rfind(predicate))
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,12 +334,12 @@ where
|
||||
{
|
||||
#[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]
|
||||
@ -387,7 +360,7 @@ where
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
spec!(self.iter.find(predicate))
|
||||
self.iter.as_mut()?.find(predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -395,7 +368,7 @@ where
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
spec!(self.iter.next_back())
|
||||
self.iter.as_mut()?.next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -403,7 +376,7 @@ where
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
spec!(self.iter.nth_back(n))
|
||||
self.iter.as_mut()?.nth_back(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -426,6 +399,15 @@ where
|
||||
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
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ use crate::ptr;
|
||||
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
|
||||
@ -14,14 +15,26 @@ pub struct Condvar {
|
||||
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) {
|
||||
|
@ -175,9 +175,7 @@ impl Mutex {
|
||||
}
|
||||
|
||||
#[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) {
|
||||
|
@ -1,9 +1,10 @@
|
||||
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>,
|
||||
}
|
||||
|
||||
@ -28,7 +29,11 @@ unsafe impl Sync for RwLock {}
|
||||
|
||||
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]
|
||||
|
@ -1,5 +1,3 @@
|
||||
// check-pass
|
||||
|
||||
trait Duh {}
|
||||
|
||||
impl Duh for i32 {}
|
||||
@ -20,11 +18,9 @@ impl<R: Duh, F: FnMut() -> R> Trait for F {
|
||||
// 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() {}
|
||||
|
16
src/test/ui/impl-trait/nested-return-type2.stderr
Normal file
16
src/test/ui/impl-trait/nested-return-type2.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
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`.
|
@ -1,9 +0,0 @@
|
||||
// check-pass
|
||||
// compile-flags: -Z unpretty=expanded
|
||||
|
||||
#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
|
||||
|
||||
fn main() {
|
||||
let elem = 1i32;
|
||||
assert!(elem == 1);
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
#![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)]))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
// 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() {
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
#![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() {}
|
@ -1,4 +1,4 @@
|
||||
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;
|
||||
@ -14,17 +14,14 @@ use super::MAP_FLATTEN;
|
||||
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,
|
||||
);
|
||||
|
@ -4,7 +4,6 @@ use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_mac
|
||||
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;
|
||||
@ -33,7 +32,6 @@ pub(super) fn check<'tcx>(
|
||||
arg: &hir::Expr<'_>,
|
||||
or_has_args: bool,
|
||||
span: Span,
|
||||
method_span: Span,
|
||||
) -> bool {
|
||||
let is_default_default = || is_trait_item(cx, fun, sym::Default);
|
||||
|
||||
@ -56,19 +54,14 @@ pub(super) fn check<'tcx>(
|
||||
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,
|
||||
@ -178,7 +171,7 @@ pub(super) fn check<'tcx>(
|
||||
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);
|
||||
}
|
||||
|
@ -112,7 +112,6 @@ const LINT_EMISSION_FUNCTIONS: [&[&str]; 8] = [
|
||||
&["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),
|
||||
|
@ -8,7 +8,7 @@
|
||||
//! 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;
|
||||
@ -219,95 +219,6 @@ pub fn span_lint_and_sugg<'a, T: LintContext>(
|
||||
});
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -12,14 +12,12 @@ LL | | .flatten();
|
||||
| |__________________^
|
||||
|
|
||||
= 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 ~ });
|
||||
@ -38,14 +36,12 @@ 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 ~ });
|
||||
@ -64,14 +60,13 @@ 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 ~ });
|
||||
@ -90,14 +85,12 @@ 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 + })
|
||||
|
@ -59,8 +59,6 @@ fn issue8878() {
|
||||
.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
|
||||
|
@ -2,79 +2,45 @@ error: called `map(..).flatten()` on `Iterator`
|
||||
--> $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
|
||||
@ -89,14 +55,12 @@ LL | | })
|
||||
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 ~ });
|
||||
|
@ -185,8 +185,7 @@ mod issue8239 {
|
||||
.reduce(|mut acc, f| {
|
||||
acc.push_str(&f);
|
||||
acc
|
||||
})
|
||||
.unwrap_or_default();
|
||||
}).unwrap_or_default();
|
||||
}
|
||||
|
||||
fn more_to_max_suggestion_highest_lines_1() {
|
||||
@ -198,8 +197,7 @@ mod issue8239 {
|
||||
let _ = "";
|
||||
acc.push_str(&f);
|
||||
acc
|
||||
})
|
||||
.unwrap_or_default();
|
||||
}).unwrap_or_default();
|
||||
}
|
||||
|
||||
fn equal_to_max_suggestion_highest_lines() {
|
||||
|
@ -109,16 +109,50 @@ LL | None.unwrap_or( unsafe { ptr_to_ref(s) } );
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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
|
||||
|
Loading…
Reference in New Issue
Block a user