]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #98617 - ChrisDenton:const-unwrap, r=Mark-Simulacrum
authorMatthias Krüger <matthias.krueger@famsik.de>
Tue, 28 Jun 2022 16:34:33 +0000 (18:34 +0200)
committerGitHub <noreply@github.com>
Tue, 28 Jun 2022 16:34:33 +0000 (18:34 +0200)
Remove feature `const_option` from std

This is part of the effort to reduce the number of unstable features used by std. This one is easy as it's only used in one place.

64 files changed:
.gitignore
Cargo.lock
RELEASES.md
compiler/rustc_borrowck/src/borrowck_errors.rs
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_builtin_macros/src/assert/context.rs
compiler/rustc_data_structures/src/profiling.rs
compiler/rustc_error_messages/locales/en-US/privacy.ftl [new file with mode: 0644]
compiler/rustc_error_messages/src/lib.rs
compiler/rustc_errors/src/emitter.rs
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/lib.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_lint/src/internal.rs
compiler/rustc_parse/src/lib.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_privacy/Cargo.toml
compiler/rustc_privacy/src/errors.rs [new file with mode: 0644]
compiler/rustc_privacy/src/lib.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/source_map.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_typeck/src/impl_wf_check.rs
compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
library/alloc/src/boxed/thin.rs
library/core/src/iter/adapters/chain.rs
library/core/src/iter/adapters/flatten.rs
library/core/src/iter/adapters/fuse.rs
library/std/src/sys/hermit/condvar.rs
library/std/src/sys/hermit/mutex.rs
library/std/src/sys/hermit/rwlock.rs
src/librustdoc/clean/types.rs
src/librustdoc/json/conversions.rs
src/test/rustdoc-json/assoc_type.rs [new file with mode: 0644]
src/test/rustdoc-json/glob_import.rs [new file with mode: 0644]
src/test/ui/associated-item/associated-item-duplicate-names-2.stderr
src/test/ui/consts/const-eval/issue-85907.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/issue-85907.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0201.stderr
src/test/ui/extern/auxiliary/issue-80074-macro.rs [new file with mode: 0644]
src/test/ui/extern/issue-80074.rs [new file with mode: 0644]
src/test/ui/generics/issue-98432.rs [new file with mode: 0644]
src/test/ui/generics/issue-98432.stderr [new file with mode: 0644]
src/test/ui/impl-duplicate-methods.stderr
src/test/ui/impl-trait/nested-return-type2.rs
src/test/ui/impl-trait/nested-return-type2.stderr [new file with mode: 0644]
src/test/ui/issues/issue-4265.stderr
src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs [deleted file]
src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout [deleted file]
src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs [new file with mode: 0644]
src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout [new file with mode: 0644]
src/test/ui/methods/method-macro-backtrace.stderr
src/test/ui/traits/issue-8153.stderr
src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
src/tools/clippy/clippy_utils/src/diagnostics.rs
src/tools/clippy/tests/ui/map_flatten.stderr
src/tools/clippy/tests/ui/map_flatten_fixable.fixed
src/tools/clippy/tests/ui/map_flatten_fixable.stderr
src/tools/clippy/tests/ui/or_fun_call.fixed
src/tools/clippy/tests/ui/or_fun_call.stderr
src/tools/compiletest/src/main.rs
src/tools/rust-analyzer

index ec6cb6ed2e4d3fdeb3ca5ff9d1274076f208ff1a..a6625ac2ac4a172d08c081090e5cfba5597cea00 100644 (file)
@@ -46,8 +46,6 @@ no_llvm_build
 /unicode-downloads
 /target
 /src/tools/x/target
-# Generated by compiletest for incremental
-/tmp/
 # Created by default with `src/ci/docker/run.sh`
 /obj/
 
index 347341b5ff7e2a39fa1f280dd62e86708446247e..96d9449db57c076c5db7f44fa8c9dc92c12a479d 100644 (file)
@@ -4280,6 +4280,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
+ "rustc_macros",
  "rustc_middle",
  "rustc_session",
  "rustc_span",
index 3d88891ad215c22dc6972d906149be8e7e381204..7479735012cc9dfca34b858d5fb720b93e4b5eb3 100644 (file)
@@ -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/
index a1233d62cb02ea2ecb832d05bd30975ccb2e4629..708fe8719a1ebc84d3f0bb5b51f2dc434960831f 100644 (file)
@@ -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 @@ pub(crate) fn temporary_value_borrowed_for_too_long(
         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)
index 8ef2974c372322323dd25fbe8d7459742094abff..a2df072aa31195f63964f71d9d45bc4e4dfdb08c 100644 (file)
@@ -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)]
index cad301812123b07f56c1371600148c992064cda8..9e50d33486cf2f51dca7e3c8d9ceafdc6f81d5de 100644 (file)
@@ -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;
 };
 
 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 @@ pub(super) fn build(mut self, mut cond_expr: P<Expr>, panic_path: Path) -> P<Exp
         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))
     }
 
@@ -115,6 +132,16 @@ fn build_initial_imports(&self) -> Stmt {
         )
     }
 
+    /// 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 @@ fn build_panic(&self, expr_str: &str, panic_path: Path) -> P<Expr> {
     /// 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 @@ fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
                     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 @@ fn manage_try_capture(&mut self, capture: Ident, curr_capture_idx: usize, expr:
             ))
             .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;
     }
 }
 
index 88ff33b4d09a15989eeab46ab316431a238149f9..d8b26f9840b63e9ed9891b7f524f51aa782efd20 100644 (file)
@@ -826,6 +826,24 @@ pub fn get_resident_set_size() -> Option<usize> {
                 }
             }
         }
+    } 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;
diff --git a/compiler/rustc_error_messages/locales/en-US/privacy.ftl b/compiler/rustc_error_messages/locales/en-US/privacy.ftl
new file mode 100644 (file)
index 0000000..2b0778f
--- /dev/null
@@ -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}
index 673e160cc1e74d589ce19aa110f647b92e22c590..90eb5ef54462d87181a41f1d0549746d9ca37360 100644 (file)
@@ -32,6 +32,7 @@
 // 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",
 }
index a4cbc73978d5b6a356eab7842acd3467e9e4038d..8b2a995f1c58ebf974d0d1f903f934565af8016b 100644 (file)
@@ -656,11 +656,6 @@ fn emit_diagnostic(&mut self, d: &Diagnostic) {
     }
 }
 
-/// 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
index 245719bff120216eae37a08b0a1ee051375a8e85..1e57d66dd9f5619dd8558574b74a3900cea5771f 100644 (file)
@@ -1077,6 +1077,7 @@ pub fn expansion_cause(&self) -> Option<Span> {
         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 @@ pub fn emit_err(&self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
     ///
     /// 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);
     }
index 86ff110eec183f954910fdabc1a0813a5fe44d76..c18147592dc7022b449379f876b88237dc3bb67f 100644 (file)
@@ -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"]
 
index 7684d861f3c9394595c9ab3ec0a167fd67116686..ebb8d4434215fef29a0c9928c12a144262b3ce84 100644 (file)
@@ -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,
index fadb1c87933989d788250739603e74f4708fd5af..56c8635a189e1be10e7d1562d680eab630cb81ce 100644 (file)
@@ -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;
         }
 
index f3bdd63ee6dd44325de216f324e5e49bd8907164..113af328a91fa39bbcdedb97885d0f55f0caaee6 100644 (file)
@@ -6,6 +6,7 @@
 #![feature(let_chains)]
 #![feature(let_else)]
 #![feature(never_type)]
+#![feature(rustc_attrs)]
 #![recursion_limit = "256"]
 
 #[macro_use]
index 58d5d43cfbfa83ff4e32cb38f294a9dfaa9ae149..0869ed65ad2f3db915f7bbe8c4fb56895f55993c 100644 (file)
@@ -357,6 +357,7 @@ fn deref_mut(&mut self) -> &mut Self::Target {
 }
 
 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 @@ pub(super) fn span_err<S: Into<MultiSpan>>(
         err.span_err(sp, self.diagnostic())
     }
 
+    #[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
index d952e288a6477c46864dde961e2999dca16bf557..5785921fb1eda3b14f6d517700aa05c9ab01daa8 100644 (file)
@@ -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"
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
new file mode 100644 (file)
index 0000000..482721d
--- /dev/null
@@ -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,
+}
index b27c986d0f9da2bc1d0cb9e1bfe929f3ef0c4c08..238c917bbc33f63fc989f6e7df632d076f7c3d3b 100644 (file)
@@ -1,15 +1,19 @@
 #![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.
 ////////////////////////////////////////////////////////////////////////////////
@@ -935,23 +944,17 @@ fn check_field(
         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 @@ fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
     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 @@ fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: S
                     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 @@ fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
                     }
                 }
             };
-            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 @@ fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
                     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();
                     },
                 );
             }
index f1814eebfa6fd1f8edcc70deb6adbc495a7db659..b5058fd699aca0c900847c7a414081ff973c8ab1 100644 (file)
@@ -280,6 +280,7 @@ pub fn init_crate_types(&self, crate_types: Vec<CrateType>) {
         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 @@ pub fn struct_span_warn<S: Into<MultiSpan>>(
     ) -> 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 @@ pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>(
     ) -> 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 @@ pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
     ) -> 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 @@ pub fn struct_warn_with_expectation(
     ) -> 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 @@ pub fn struct_span_allow<S: Into<MultiSpan>>(
     ) -> 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 @@ pub fn struct_expect(
     ) -> 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 @@ pub fn struct_span_err<S: Into<MultiSpan>>(
     ) -> 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 @@ pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
         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 @@ pub fn struct_err_with_code(
     ) -> 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 @@ pub fn struct_warn_with_code(
     ) -> 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 @@ pub fn struct_span_fatal<S: Into<MultiSpan>>(
     ) -> 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 @@ pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
     ) -> 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 @@ pub fn span_fatal_with_code<S: Into<MultiSpan>>(
     ) -> ! {
         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 @@ pub fn span_err_or_warn<S: Into<MultiSpan>>(
             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 @@ pub fn span_err<S: Into<MultiSpan>>(
     ) -> 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 @@ pub fn span_err_with_code<S: Into<MultiSpan>>(
     ) {
         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)
     }
index 95ea7029617014715e25efe520be80e6ae7aa9fc..227127aed50d71b8feca779b1a71149b6709ef5b 100644 (file)
@@ -956,7 +956,7 @@ pub fn count_lines(&self) -> usize {
     }
 
     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={:?}",
index 82c54291a5d5ef6a3055e39a5d1ed125a2e8a388..aba4f144d4bcc7db0871fb19216c7b3e3dea4bf9 100644 (file)
@@ -28,7 +28,6 @@
 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)
index e968d73e95f98923ba471fcbd05b1474b5f480ea..981c35e184bece0d744a4a8e979eaa0dd718d3bd 100644 (file)
@@ -13,7 +13,6 @@
 
 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;
@@ -59,13 +58,10 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     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);
             }
         }
     }
@@ -75,11 +71,7 @@ pub fn provide(providers: &mut Providers) {
     *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() {
@@ -107,9 +99,9 @@ fn enforce_impl_params_are_constrained(
     );
 
     // 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 {
@@ -209,33 +201,32 @@ impl trait, self type, or predicates",
 }
 
 /// 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);
             }
         }
     }
index 0ecc28e6054d505e147b282d99a7381707493567..f07396ce74ffb2aa3881be836d9b6615de337b0b 100644 (file)
 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);
@@ -103,15 +103,8 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: DefId) -> Option<No
 }
 
 /// 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)",
@@ -126,17 +119,10 @@ fn check_always_applicable(
             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);
     }
 }
 
@@ -152,20 +138,21 @@ fn check_always_applicable(
 /// 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;
     };
index 807c035fdbd0db099ca3ecc0ff943bb4463b2233..203e5dff0c77fad78eac07b673ab97306098f550 100644 (file)
@@ -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
index 53e48500e3b4d6061976069176168529932bb24b..60eb3a6da3a4bf93147a7a5cd103ed380eef6954 100644 (file)
@@ -37,33 +37,6 @@ pub(in super::super) fn new(a: A, b: 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 @@ impl<A, B> Iterator for Chain<A, B>
 
     #[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 @@ fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
             self.a = None;
         }
 
-        maybe!(self.b.nth(n))
+        self.b.as_mut()?.nth(n)
     }
 
     #[inline]
@@ -169,23 +139,15 @@ fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
     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 @@ impl<A, B> DoubleEndedIterator for Chain<A, B>
 {
     #[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 @@ fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
             self.b = None;
         }
 
-        maybe!(self.a.nth_back(n))
+        self.a.as_mut()?.nth_back(n)
     }
 
     #[inline]
@@ -271,10 +230,8 @@ fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
     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 @@ unsafe impl<A, B> TrustedLen for Chain<A, B>
     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
+}
index 351fd569d8acf98d99d2cfcef4ec2d4c8900ec05..15a120e35a2fa16c75562b84eaed6e60ed79045e 100644 (file)
@@ -290,20 +290,11 @@ impl<I, U> Iterator for FlattenCompat<I, U>
     #[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 @@ impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
     #[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 @@ pub unsafe trait TrustedConstSize: IntoIterator {}
 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
+}
index 8adb53c6714284c1d6376c3114c6f15c92e1d243..c931445420342bf16c9585ab145d1ca73ab0c910 100644 (file)
@@ -29,33 +29,6 @@ pub(in crate::iter) fn new(iter: 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 @@ impl<I> FuseImpl<I> for Fuse<I>
 
     #[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 @@ impl<I> FuseImpl<I> for Fuse<I>
     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 @@ impl<I> FuseImpl<I> for Fuse<I>
     where
         I: DoubleEndedIterator,
     {
-        fuse!(self.iter.next_back())
+        and_then_or_clear(&mut self.iter, |iter| iter.next_back())
     }
 
     #[inline]
@@ -324,7 +297,7 @@ impl<I> FuseImpl<I> for Fuse<I>
     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 @@ impl<I> FuseImpl<I> for Fuse<I>
         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 @@ impl<I> FuseImpl<I> for Fuse<I>
 {
     #[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 @@ fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
     where
         P: FnMut(&Self::Item) -> bool,
     {
-        spec!(self.iter.find(predicate))
+        self.iter.as_mut()?.find(predicate)
     }
 
     #[inline]
@@ -395,7 +368,7 @@ fn next_back(&mut self) -> Option<<I as Iterator>::Item>
     where
         I: DoubleEndedIterator,
     {
-        spec!(self.iter.next_back())
+        self.iter.as_mut()?.next_back()
     }
 
     #[inline]
@@ -403,7 +376,7 @@ fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
     where
         I: DoubleEndedIterator,
     {
-        spec!(self.iter.nth_back(n))
+        self.iter.as_mut()?.nth_back(n)
     }
 
     #[inline]
@@ -426,6 +399,15 @@ fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
         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
 }
index 3f00160e55a257cbfc257c1081c8d20e9160aedd..22059ca0dbe107ec24b6f64c3bf5c6f60f6d1bec 100644 (file)
@@ -3,6 +3,7 @@
 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) {
index ef44bf411fba5c0bdf3845f1d8eabdd93489de52..eb15a04ffcffbf7056c77d5db09effab82eac595 100644 (file)
@@ -175,9 +175,7 @@ pub const fn new() -> 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) {
index d43fa08a17150418700c6e481463dafba6c77880..9701bab1f660be75a09848c0d4117567d4f649a6 100644 (file)
@@ -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]
index 2762d5e8502b2cf373da340f7b5b27664e837e46..352803855a4e75284db48a8df03f60d42282f166 100644 (file)
@@ -2161,8 +2161,12 @@ pub(crate) fn def_id(&self) -> DefId {
         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 {
index 428519dbc16b31df8814af4fc89460d93f66c9b2..54dc1b4fdeeac5d7f59f8ca270a19f5205ac38e9 100644 (file)
@@ -666,7 +666,12 @@ fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self {
             },
             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,
             },
diff --git a/src/test/rustdoc-json/assoc_type.rs b/src/test/rustdoc-json/assoc_type.rs
new file mode 100644 (file)
index 0000000..716bb3d
--- /dev/null
@@ -0,0 +1,22 @@
+// 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;
diff --git a/src/test/rustdoc-json/glob_import.rs b/src/test/rustdoc-json/glob_import.rs
new file mode 100644 (file)
index 0000000..d7ac952
--- /dev/null
@@ -0,0 +1,24 @@
+// 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 *;
+}
index ea475ffc5547a4d709fbeedc93f4bd0ed82d261a..ad21b38d07eb98813ad0ded877fd1b1aaf48dbd1 100644 (file)
@@ -4,7 +4,7 @@ error[E0201]: duplicate definitions with name `bar`:
 LL |     const bar: bool = true;
    |     ----------------------- previous definition of `bar` here
 LL |     fn bar() {}
-   |     ^^^^^^^^^^^ duplicate definition
+   |     ^^^^^^^^ duplicate definition
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/issue-85907.rs b/src/test/ui/consts/const-eval/issue-85907.rs
new file mode 100644 (file)
index 0000000..6ae40ae
--- /dev/null
@@ -0,0 +1,7 @@
+const fn hey() -> usize {
+    panic!(123); //~ ERROR argument to `panic!()` in a const context must have type `&str`
+}
+
+fn main() {
+    let _: [u8; hey()] = todo!();
+}
diff --git a/src/test/ui/consts/const-eval/issue-85907.stderr b/src/test/ui/consts/const-eval/issue-85907.stderr
new file mode 100644 (file)
index 0000000..381f2fd
--- /dev/null
@@ -0,0 +1,10 @@
+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
+
index 89cfd4024230b3a693328083ed40642efcdc59e6..af029603fa17a4988a67d221be9f85975dba85ba 100644 (file)
@@ -2,17 +2,17 @@ error[E0201]: duplicate definitions with name `bar`:
   --> $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
diff --git a/src/test/ui/extern/auxiliary/issue-80074-macro.rs b/src/test/ui/extern/auxiliary/issue-80074-macro.rs
new file mode 100644 (file)
index 0000000..30e0f19
--- /dev/null
@@ -0,0 +1,4 @@
+// edition:2018
+
+macro_rules! foo_ { () => {}; }
+use foo_ as foo;
diff --git a/src/test/ui/extern/issue-80074.rs b/src/test/ui/extern/issue-80074.rs
new file mode 100644 (file)
index 0000000..f83027d
--- /dev/null
@@ -0,0 +1,10 @@
+// edition:2018
+// build-pass
+// aux-crate:issue_80074=issue-80074-macro.rs
+
+#[macro_use]
+extern crate issue_80074;
+
+fn main() {
+    foo!();
+}
diff --git a/src/test/ui/generics/issue-98432.rs b/src/test/ui/generics/issue-98432.rs
new file mode 100644 (file)
index 0000000..780c50d
--- /dev/null
@@ -0,0 +1,9 @@
+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() {}
diff --git a/src/test/ui/generics/issue-98432.stderr b/src/test/ui/generics/issue-98432.stderr
new file mode 100644 (file)
index 0000000..afa67b6
--- /dev/null
@@ -0,0 +1,14 @@
+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`.
index b6dc4882fc8f3827e8f1c67efe2abc03d38d6eec..c19702a5bf0cf26c13e7d27e6bbcfd24a0b3312b 100644 (file)
@@ -2,9 +2,9 @@ error[E0201]: duplicate definitions with name `orange`:
   --> $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
 
index 39928d543e15d79a2d0e74d1c5b7affdb5ae2bf0..279641a46c3d0fd32402b7d9576d7247bf05c151 100644 (file)
@@ -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() {}
diff --git a/src/test/ui/impl-trait/nested-return-type2.stderr b/src/test/ui/impl-trait/nested-return-type2.stderr
new file mode 100644 (file)
index 0000000..f996e99
--- /dev/null
@@ -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`.
index acdf963ed3bd7af476cea4d328c62addd21c49d4..27e83d495749371618a6a7277556147a0246af92 100644 (file)
@@ -1,14 +1,11 @@
 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
 
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.rs
deleted file mode 100644 (file)
index 1db9d33..0000000
+++ /dev/null
@@ -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);
-}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout b/src/test/ui/macros/rfc-2011-nicer-assert-messages/codegen.stdout
deleted file mode 100644 (file)
index a590eb3..0000000
+++ /dev/null
@@ -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)]))
-                }
-            }
-    };
-}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs
new file mode 100644 (file)
index 0000000..5ec84b0
--- /dev/null
@@ -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() {
+}
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/src/test/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
new file mode 100644 (file)
index 0000000..90f858f
--- /dev/null
@@ -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() {}
index 7860365476a310d1649cb99131966bb2a63dd645..7ae00835c965d3b74680aa969ced7252c2364698 100644 (file)
@@ -2,9 +2,9 @@ error[E0201]: duplicate definitions with name `bar`:
   --> $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
 
index 4389c3dc288f6790fcbbabc44c94e36b889a6fa1..b76bbc0235fde49ea047997505c603416c53ed21 100644 (file)
@@ -2,9 +2,9 @@ error[E0201]: duplicate definitions with name `bar`:
   --> $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
 
index f447940ea3b5aaa84a2845c7ff8bbffc1e08fc1b..8ae84dbb3dcf432b056e9c9649db60c5a543bfb7 100644 (file)
@@ -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;
 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,
         );
index 448dc4e6147ffb97470ad021a674bab68c8ed432..3d1208824fa34c10e187f873322b462746105104 100644 (file)
@@ -4,7 +4,6 @@
 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 @@ fn check_unwrap_or_default(
         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 @@ fn check_unwrap_or_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,
@@ -178,7 +171,7 @@ fn check_general_case<'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);
                 }
index 99e9e3275ab53e631bc7c99741e1d0ba359f4870..2564099f4dbcac56a0d6e78859b255ce531968e7 100644 (file)
@@ -112,7 +112,6 @@ macro_rules! RENAME_VALUE_TEMPLATE {
     &["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),
index 39595f589c70be77c832047d11c4e655a8d893a0..7f55db3b31f7070cdfd74801d2608ec4d6f00f6e 100644 (file)
@@ -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
index c9c60df838f67bf07bd70cc38fb0f3b238a7d44e..4b2630d6858479b2bafe70e637f53f3ff18ef638 100644 (file)
@@ -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 +         })
index 928e5bd509c3fbf6c358883647b747beba2abdc1..e9b41354c58fa50599e93f2b39a5dc015f61646d 100644 (file)
@@ -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
index 828e24acaad6c71ce4de550f0f3bb2c02418d8ff..f3b82ad08d0fc3c61c31cb53e46c035c06789440 100644 (file)
@@ -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 ~         });
index 3208048e0d53c82e87407376138c0d0923db3bef..123aed40251e2a639a63a6b630fc6a084944e02c 100644 (file)
@@ -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() {
index 549b00ae3c45980c75ac3b229d2139e7375e7ccb..dfe15654bc32c05db6992bfde425b6ba40915883 100644 (file)
@@ -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
index e23cccf6cd1294320f0aa9ead725fb2e1318fe89..4e8e5afd4bbe279bbfeb4d2e994435e26db403b8 100644 (file)
@@ -351,11 +351,6 @@ pub fn opt_str2(maybestr: Option<String>) -> String {
 }
 
 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.
index 427061da19723f2206fe4dcb175c9c43b9a6193d..b74e96f509baf0be70281c55f14cb18fefbc6b22 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 427061da19723f2206fe4dcb175c9c43b9a6193d
+Subproject commit b74e96f509baf0be70281c55f14cb18fefbc6b22