From 035d854947d5899388f77f6d00fc488caad86b5c Mon Sep 17 00:00:00 2001
From: Lukas Markeffsky <@>
Date: Sun, 1 Jan 2023 18:48:14 +0100
Subject: [PATCH 01/17] reduce spans for `unsafe impl` errors
---
.../src/coherence/unsafety.rs | 6 +++---
.../coherence-default-trait-impl.stderr | 4 ++--
.../dropck-eyepatch-implies-unsafe-impl.stderr | 18 ++++--------------
src/test/ui/error-codes/E0199.stderr | 2 +-
src/test/ui/error-codes/E0200.stderr | 2 +-
src/test/ui/traits/safety-trait-impl-cc.stderr | 8 ++------
src/test/ui/traits/safety-trait-impl.stderr | 4 ++--
7 files changed, 15 insertions(+), 29 deletions(-)
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index a34815b45b3ad..70cc15b2f8c54 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -21,7 +21,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
struct_span_err!(
tcx.sess,
- item.span,
+ tcx.def_span(def_id),
E0199,
"implementing the trait `{}` is not unsafe",
trait_ref.print_only_trait_path()
@@ -38,7 +38,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
(Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
struct_span_err!(
tcx.sess,
- item.span,
+ tcx.def_span(def_id),
E0200,
"the trait `{}` requires an `unsafe impl` declaration",
trait_ref.print_only_trait_path()
@@ -61,7 +61,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
(Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => {
struct_span_err!(
tcx.sess,
- item.span,
+ tcx.def_span(def_id),
E0569,
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
attr_name
diff --git a/src/test/ui/coherence/coherence-default-trait-impl.stderr b/src/test/ui/coherence/coherence-default-trait-impl.stderr
index 6320187827256..7be5b92a7def0 100644
--- a/src/test/ui/coherence/coherence-default-trait-impl.stderr
+++ b/src/test/ui/coherence/coherence-default-trait-impl.stderr
@@ -2,7 +2,7 @@ error[E0199]: implementing the trait `MySafeTrait` is not unsafe
--> $DIR/coherence-default-trait-impl.rs:8:1
|
LL | unsafe impl MySafeTrait for Foo {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: remove `unsafe` from this trait implementation
|
@@ -14,7 +14,7 @@ error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
--> $DIR/coherence-default-trait-impl.rs:13:1
|
LL | impl MyUnsafeTrait for Foo {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `MyUnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
index 82169ee01bedd..5cec2bcb03872 100644
--- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
+++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
@@ -1,13 +1,8 @@
error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
--> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:21:1
|
-LL | / impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt {
-LL | |
-LL | |
-LL | | // (unsafe to access self.1 due to #[may_dangle] on A)
-LL | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
-LL | | }
- | |_^
+LL | impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
@@ -18,13 +13,8 @@ LL | unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt {
error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
--> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:27:1
|
-LL | / impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
-LL | |
-LL | |
-LL | | // (unsafe to access self.1 due to #[may_dangle] on 'a)
-LL | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
-LL | | }
- | |_^
+LL | impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
diff --git a/src/test/ui/error-codes/E0199.stderr b/src/test/ui/error-codes/E0199.stderr
index 99d808c0d4b1e..68c308b15cc08 100644
--- a/src/test/ui/error-codes/E0199.stderr
+++ b/src/test/ui/error-codes/E0199.stderr
@@ -2,7 +2,7 @@ error[E0199]: implementing the trait `Bar` is not unsafe
--> $DIR/E0199.rs:6:1
|
LL | unsafe impl Bar for Foo { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^
|
help: remove `unsafe` from this trait implementation
|
diff --git a/src/test/ui/error-codes/E0200.stderr b/src/test/ui/error-codes/E0200.stderr
index 1fd86aecee177..c70a2d4f3d1f1 100644
--- a/src/test/ui/error-codes/E0200.stderr
+++ b/src/test/ui/error-codes/E0200.stderr
@@ -2,7 +2,7 @@ error[E0200]: the trait `Bar` requires an `unsafe impl` declaration
--> $DIR/E0200.rs:5:1
|
LL | impl Bar for Foo { }
- | ^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
|
= note: the trait `Bar` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
diff --git a/src/test/ui/traits/safety-trait-impl-cc.stderr b/src/test/ui/traits/safety-trait-impl-cc.stderr
index 0b1fb30478ff6..0ca565787f6b6 100644
--- a/src/test/ui/traits/safety-trait-impl-cc.stderr
+++ b/src/test/ui/traits/safety-trait-impl-cc.stderr
@@ -1,12 +1,8 @@
error[E0200]: the trait `Foo` requires an `unsafe impl` declaration
--> $DIR/safety-trait-impl-cc.rs:9:1
|
-LL | / impl lib::Foo for Bar {
-LL | | fn foo(&self) -> isize {
-LL | | panic!();
-LL | | }
-LL | | }
- | |_^
+LL | impl lib::Foo for Bar {
+ | ^^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `Foo` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
diff --git a/src/test/ui/traits/safety-trait-impl.stderr b/src/test/ui/traits/safety-trait-impl.stderr
index 721e2b48b954f..e78e0e3a6baa4 100644
--- a/src/test/ui/traits/safety-trait-impl.stderr
+++ b/src/test/ui/traits/safety-trait-impl.stderr
@@ -2,7 +2,7 @@ error[E0200]: the trait `UnsafeTrait` requires an `unsafe impl` declaration
--> $DIR/safety-trait-impl.rs:14:1
|
LL | impl UnsafeTrait for u16 { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the trait `UnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
@@ -14,7 +14,7 @@ error[E0199]: implementing the trait `SafeTrait` is not unsafe
--> $DIR/safety-trait-impl.rs:16:1
|
LL | unsafe impl SafeTrait for u32 { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: remove `unsafe` from this trait implementation
|
From 5974f6f0a53614e82df9430b95bcb6e9473265fa Mon Sep 17 00:00:00 2001
From: Ralf Jung
Date: Thu, 22 Dec 2022 16:32:08 +0100
Subject: [PATCH 02/17] default OOM handler: use non-unwinding panic (unless
-Zoom=panic is set), to match std handler
---
library/alloc/src/alloc.rs | 15 ++++++++++++++-
library/alloc/src/lib.rs | 1 +
library/core/src/panicking.rs | 23 +++++++++++++++++------
library/std/src/alloc.rs | 2 +-
4 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index e5fbfc55761f4..e1c612c5b3f16 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -402,7 +402,20 @@ pub mod __alloc_error_handler {
// `#[alloc_error_handler]`.
#[rustc_std_internal_symbol]
pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! {
- panic!("memory allocation of {size} bytes failed")
+ extern "Rust" {
+ // This symbol is emitted by rustc next to __rust_alloc_error_handler.
+ // Its value depends on the -Zoom={panic,abort} compiler option.
+ static __rust_alloc_error_handler_should_panic: u8;
+ }
+
+ #[allow(unused_unsafe)]
+ if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
+ panic!("memory allocation of {size} bytes failed")
+ } else {
+ core::panicking::panic_nounwind_fmt(format_args!(
+ "memory allocation of {size} bytes failed"
+ ))
+ }
}
#[cfg(bootstrap)]
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 96960d43f5820..2a7edc2add12d 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -110,6 +110,7 @@
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_refs_to_cell)]
#![feature(core_intrinsics)]
+#![feature(core_panic)]
#![feature(const_eval_select)]
#![feature(const_pin)]
#![feature(const_waker)]
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 9fce78d076bf3..36b43ec2181e5 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -64,13 +64,17 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
unsafe { panic_impl(&pi) }
}
-/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize.
-/// (No `fmt` variant as a `fmt::Arguments` needs more space to be passed.)
+/// Like `panic_fmt`, but for non-unwinding panics.
+///
+/// Has to be a separate function so that it can carry the `rustc_nounwind` attribute.
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
-#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics
+#[track_caller]
+// This attribute has the key side-effect that if the panic handler ignores `can_unwind`
+// and unwinds anyway, we will hit the "unwinding out of nounwind function" guard,
+// which causes a "panic in a function that cannot unwind".
#[rustc_nounwind]
-pub fn panic_nounwind(msg: &'static str) -> ! {
+pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! {
if cfg!(feature = "panic_immediate_abort") {
super::intrinsics::abort()
}
@@ -83,8 +87,6 @@ pub fn panic_nounwind(msg: &'static str) -> ! {
}
// PanicInfo with the `can_unwind` flag set to false forces an abort.
- let pieces = [msg];
- let fmt = fmt::Arguments::new_v1(&pieces, &[]);
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
// SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
@@ -112,6 +114,15 @@ pub const fn panic(expr: &'static str) -> ! {
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
}
+/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize.
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics
+#[rustc_nounwind]
+pub fn panic_nounwind(expr: &'static str) -> ! {
+ panic_nounwind_fmt(fmt::Arguments::new_v1(&[expr], &[]));
+}
+
#[inline]
#[track_caller]
#[rustc_diagnostic_item = "panic_str"]
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 61c1ff578b2ca..c5a5991cc81c4 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -338,7 +338,7 @@ fn default_alloc_error_hook(layout: Layout) {
#[allow(unused_unsafe)]
if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
- panic!("memory allocation of {} bytes failed\n", layout.size());
+ panic!("memory allocation of {} bytes failed", layout.size());
} else {
rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
}
From 2a7d5599706f127c1ebe6e5f992f9245d7f09b8a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?L=C3=A9o=20Lanteri=20Thauvin?=
Date: Mon, 26 Dec 2022 18:49:19 +0100
Subject: [PATCH 03/17] Don't trim path for `unsafe_op_in_unsafe_fn` lints
---
.../rustc_mir_build/src/check_unsafety.rs | 23 +++++++++++--------
src/test/ui/unsafe/auxiliary/issue-106126.rs | 9 ++++++++
.../ui/unsafe/issue-106126-good-path-bug.rs | 12 ++++++++++
3 files changed, 34 insertions(+), 10 deletions(-)
create mode 100644 src/test/ui/unsafe/auxiliary/issue-106126.rs
create mode 100644 src/test/ui/unsafe/issue-106126-good-path-bug.rs
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 3c311729a52aa..03a7f2d70faeb 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -5,6 +5,7 @@ use rustc_middle::thir::visit::{self, Visitor};
use rustc_hir as hir;
use rustc_middle::mir::BorrowKind;
use rustc_middle::thir::*;
+use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
use rustc_session::lint::Level;
@@ -524,17 +525,19 @@ impl UnsafeOpKind {
hir_id: hir::HirId,
span: Span,
) {
+ // FIXME: ideally we would want to trim the def paths, but this is not
+ // feasible with the current lint emission API (see issue #106126).
match self {
- CallToUnsafeFunction(did) if did.is_some() => tcx.emit_spanned_lint(
+ CallToUnsafeFunction(Some(did)) => tcx.emit_spanned_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
span,
- function: &tcx.def_path_str(did.unwrap()),
+ function: &with_no_trimmed_paths!(tcx.def_path_str(*did)),
},
),
- CallToUnsafeFunction(..) => tcx.emit_spanned_lint(
+ CallToUnsafeFunction(None) => tcx.emit_spanned_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -594,7 +597,7 @@ impl UnsafeOpKind {
span,
UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
span,
- function: &tcx.def_path_str(*did),
+ function: &with_no_trimmed_paths!(tcx.def_path_str(*did)),
},
),
}
@@ -607,24 +610,24 @@ impl UnsafeOpKind {
unsafe_op_in_unsafe_fn_allowed: bool,
) {
match self {
- CallToUnsafeFunction(did) if did.is_some() && unsafe_op_in_unsafe_fn_allowed => {
+ CallToUnsafeFunction(Some(did)) if unsafe_op_in_unsafe_fn_allowed => {
tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
span,
- function: &tcx.def_path_str(did.unwrap()),
+ function: &tcx.def_path_str(*did),
});
}
- CallToUnsafeFunction(did) if did.is_some() => {
+ CallToUnsafeFunction(Some(did)) => {
tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafe {
span,
- function: &tcx.def_path_str(did.unwrap()),
+ function: &tcx.def_path_str(*did),
});
}
- CallToUnsafeFunction(..) if unsafe_op_in_unsafe_fn_allowed => {
+ CallToUnsafeFunction(None) if unsafe_op_in_unsafe_fn_allowed => {
tcx.sess.emit_err(
CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span },
);
}
- CallToUnsafeFunction(..) => {
+ CallToUnsafeFunction(None) => {
tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { span });
}
UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => {
diff --git a/src/test/ui/unsafe/auxiliary/issue-106126.rs b/src/test/ui/unsafe/auxiliary/issue-106126.rs
new file mode 100644
index 0000000000000..091a3edb756ad
--- /dev/null
+++ b/src/test/ui/unsafe/auxiliary/issue-106126.rs
@@ -0,0 +1,9 @@
+#[macro_export]
+macro_rules! foo {
+ () => {
+ unsafe fn __unsf() {}
+ unsafe fn __foo() {
+ __unsf();
+ }
+ };
+}
diff --git a/src/test/ui/unsafe/issue-106126-good-path-bug.rs b/src/test/ui/unsafe/issue-106126-good-path-bug.rs
new file mode 100644
index 0000000000000..93f478ee35802
--- /dev/null
+++ b/src/test/ui/unsafe/issue-106126-good-path-bug.rs
@@ -0,0 +1,12 @@
+// Regression test for #106126.
+// check-pass
+// aux-build:issue-106126.rs
+
+#![deny(unsafe_op_in_unsafe_fn)]
+
+#[macro_use]
+extern crate issue_106126;
+
+foo!();
+
+fn main() {}
From 7680b164b00af55e7af64bdc8027b6deb4fb8233 Mon Sep 17 00:00:00 2001
From: Nixon Enraght-Moony
Date: Mon, 2 Jan 2023 19:30:39 +0000
Subject: [PATCH 04/17] jsondoclint: Parse args with clap.
---
Cargo.lock | 18 +++++++++++++++++-
src/tools/jsondoclint/Cargo.toml | 1 +
src/tools/jsondoclint/src/main.rs | 14 ++++++++++----
3 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index f99e58e59b8e5..0483d50fc2a69 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -597,7 +597,7 @@ checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd"
dependencies = [
"atty",
"bitflags",
- "clap_derive",
+ "clap_derive 3.2.18",
"clap_lex 0.2.2",
"indexmap",
"once_cell",
@@ -614,7 +614,9 @@ checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f"
dependencies = [
"atty",
"bitflags",
+ "clap_derive 4.0.13",
"clap_lex 0.3.0",
+ "once_cell",
"strsim",
"termcolor",
]
@@ -641,6 +643,19 @@ dependencies = [
"syn",
]
+[[package]]
+name = "clap_derive"
+version = "4.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "clap_lex"
version = "0.2.2"
@@ -2097,6 +2112,7 @@ name = "jsondoclint"
version = "0.1.0"
dependencies = [
"anyhow",
+ "clap 4.0.15",
"fs-err",
"rustdoc-json-types",
"serde_json",
diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml
index 84a6c7f96c464..0dda3935ed873 100644
--- a/src/tools/jsondoclint/Cargo.toml
+++ b/src/tools/jsondoclint/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
anyhow = "1.0.62"
+clap = { version = "4.0.15", features = ["derive"] }
fs-err = "2.8.1"
rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" }
serde_json = "1.0.85"
diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs
index fc54c421b4b22..91a7aeb063f09 100644
--- a/src/tools/jsondoclint/src/main.rs
+++ b/src/tools/jsondoclint/src/main.rs
@@ -1,6 +1,5 @@
-use std::env;
-
-use anyhow::{anyhow, bail, Result};
+use anyhow::{bail, Result};
+use clap::Parser;
use fs_err as fs;
use rustdoc_json_types::{Crate, Id, FORMAT_VERSION};
use serde_json::Value;
@@ -21,8 +20,15 @@ enum ErrorKind {
Custom(String),
}
+#[derive(Parser)]
+struct Cli {
+ /// The path to the json file to be linted
+ path: String,
+}
+
fn main() -> Result<()> {
- let path = env::args().nth(1).ok_or_else(|| anyhow!("no path given"))?;
+ let Cli { path } = Cli::parse();
+
let contents = fs::read_to_string(&path)?;
let krate: Crate = serde_json::from_str(&contents)?;
assert_eq!(krate.format_version, FORMAT_VERSION);
From 855b7e8cf3963b9f187249f1f38b6bb2baa9c353 Mon Sep 17 00:00:00 2001
From: Nixon Enraght-Moony
Date: Mon, 2 Jan 2023 19:40:00 +0000
Subject: [PATCH 05/17] jsondoclint: Add `--verbose` flag.
Without verbose:
0:61941:36627 not in index or paths, but refered to at '$.index["0:62007"].inner.for.inner.id' and 12 more
With verbose:
0:10808:27206 not in index or paths, but refered to at '$.index["0:10813"].inner.for.inner.id', '$.index["0:52495"].inner.for.inner.id', '$.index["a:0:2666:215-0:10808:27206"].inner.for.inner.id', '$.index["a:0:2680:223-0:10808:27206"].inner.for.inner.id', '$.index["a:0:2730:7845-0:10808:27206"].inner.for.inner.id', '$.index["a:0:7731:21706-0:10808:27206"].inner.for.inner.id', '$.index["a:0:7732:21705-0:10808:27206"].inner.for.inner.id'
---
src/tools/jsondoclint/src/main.rs | 32 +++++++++++++++++++++++++------
1 file changed, 26 insertions(+), 6 deletions(-)
diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs
index 91a7aeb063f09..89965dc24039c 100644
--- a/src/tools/jsondoclint/src/main.rs
+++ b/src/tools/jsondoclint/src/main.rs
@@ -24,10 +24,14 @@ enum ErrorKind {
struct Cli {
/// The path to the json file to be linted
path: String,
+
+ /// Show verbose output
+ #[arg(long)]
+ verbose: bool,
}
fn main() -> Result<()> {
- let Cli { path } = Cli::parse();
+ let Cli { path, verbose } = Cli::parse();
let contents = fs::read_to_string(&path)?;
let krate: Crate = serde_json::from_str(&contents)?;
@@ -53,11 +57,27 @@ fn main() -> Result<()> {
err.id.0,
json_find::to_jsonpath(&sel)
),
- [sel, ..] => eprintln!(
- "{} not in index or paths, but refered to at '{}' and more",
- err.id.0,
- json_find::to_jsonpath(&sel)
- ),
+ [sel, ..] => {
+ if verbose {
+ let sels = sels
+ .iter()
+ .map(json_find::to_jsonpath)
+ .map(|i| format!("'{i}'"))
+ .collect::>()
+ .join(", ");
+ eprintln!(
+ "{} not in index or paths, but refered to at {sels}",
+ err.id.0
+ );
+ } else {
+ eprintln!(
+ "{} not in index or paths, but refered to at '{}' and {} more",
+ err.id.0,
+ json_find::to_jsonpath(&sel),
+ sels.len() - 1,
+ )
+ }
+ }
}
}
ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg),
From 95329080d317f01f22ddce1dec8be693ef4b29f4 Mon Sep 17 00:00:00 2001
From: Nixon Enraght-Moony
Date: Mon, 2 Jan 2023 19:54:08 +0000
Subject: [PATCH 06/17] jsondoclint: Find selector for missing ID when error is
created, not reported.
This is needed for json output, but even without that, it increases
performance massivly. On my machine, in reduces the time to check
core.json from 40.190s to 11.333s.
---
src/tools/jsondoclint/src/main.rs | 73 ++++++++++----------
src/tools/jsondoclint/src/validator.rs | 13 +++-
src/tools/jsondoclint/src/validator/tests.rs | 20 +++++-
3 files changed, 64 insertions(+), 42 deletions(-)
diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs
index 89965dc24039c..266900ea3a22d 100644
--- a/src/tools/jsondoclint/src/main.rs
+++ b/src/tools/jsondoclint/src/main.rs
@@ -16,7 +16,7 @@ struct Error {
#[derive(Debug, PartialEq, Eq)]
enum ErrorKind {
- NotFound,
+ NotFound(Vec),
Custom(String),
}
@@ -37,49 +37,48 @@ fn main() -> Result<()> {
let krate: Crate = serde_json::from_str(&contents)?;
assert_eq!(krate.format_version, FORMAT_VERSION);
- let mut validator = validator::Validator::new(&krate);
+ let krate_json: Value = serde_json::from_str(&contents)?;
+
+ let mut validator = validator::Validator::new(&krate, krate_json);
validator.check_crate();
if !validator.errs.is_empty() {
for err in validator.errs {
match err.kind {
- ErrorKind::NotFound => {
- let krate_json: Value = serde_json::from_str(&contents)?;
-
- let sels =
- json_find::find_selector(&krate_json, &Value::String(err.id.0.clone()));
- match &sels[..] {
- [] => unreachable!(
- "id must be in crate, or it wouldn't be reported as not found"
- ),
- [sel] => eprintln!(
- "{} not in index or paths, but refered to at '{}'",
- err.id.0,
- json_find::to_jsonpath(&sel)
- ),
- [sel, ..] => {
- if verbose {
- let sels = sels
- .iter()
- .map(json_find::to_jsonpath)
- .map(|i| format!("'{i}'"))
- .collect::>()
- .join(", ");
- eprintln!(
- "{} not in index or paths, but refered to at {sels}",
- err.id.0
- );
- } else {
- eprintln!(
- "{} not in index or paths, but refered to at '{}' and {} more",
- err.id.0,
- json_find::to_jsonpath(&sel),
- sels.len() - 1,
- )
- }
+ ErrorKind::NotFound(sels) => match &sels[..] {
+ [] => {
+ unreachable!(
+ "id {:?} must be in crate, or it wouldn't be reported as not found",
+ err.id
+ )
+ }
+ [sel] => eprintln!(
+ "{} not in index or paths, but refered to at '{}'",
+ err.id.0,
+ json_find::to_jsonpath(&sel)
+ ),
+ [sel, ..] => {
+ if verbose {
+ let sels = sels
+ .iter()
+ .map(json_find::to_jsonpath)
+ .map(|i| format!("'{i}'"))
+ .collect::>()
+ .join(", ");
+ eprintln!(
+ "{} not in index or paths, but refered to at {sels}",
+ err.id.0
+ );
+ } else {
+ eprintln!(
+ "{} not in index or paths, but refered to at '{}' and {} more",
+ err.id.0,
+ json_find::to_jsonpath(&sel),
+ sels.len() - 1,
+ )
}
}
- }
+ },
ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg),
}
}
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index 291d02d67bd62..f1b9c1acbaec0 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -7,8 +7,9 @@ use rustdoc_json_types::{
Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding,
TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate,
};
+use serde_json::Value;
-use crate::{item_kind::Kind, Error, ErrorKind};
+use crate::{item_kind::Kind, json_find, Error, ErrorKind};
/// The Validator walks over the JSON tree, and ensures it is well formed.
/// It is made of several parts.
@@ -22,6 +23,7 @@ use crate::{item_kind::Kind, Error, ErrorKind};
pub struct Validator<'a> {
pub(crate) errs: Vec,
krate: &'a Crate,
+ krate_json: Value,
/// Worklist of Ids to check.
todo: HashSet<&'a Id>,
/// Ids that have already been visited, so don't need to be checked again.
@@ -39,9 +41,10 @@ enum PathKind {
}
impl<'a> Validator<'a> {
- pub fn new(krate: &'a Crate) -> Self {
+ pub fn new(krate: &'a Crate, krate_json: Value) -> Self {
Self {
krate,
+ krate_json,
errs: Vec::new(),
seen_ids: HashSet::new(),
todo: HashSet::new(),
@@ -373,7 +376,11 @@ impl<'a> Validator<'a> {
} else {
if !self.missing_ids.contains(id) {
self.missing_ids.insert(id);
- self.fail(id, ErrorKind::NotFound)
+
+ let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone()));
+ assert_ne!(sels.len(), 0);
+
+ self.fail(id, ErrorKind::NotFound(sels))
}
}
}
diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs
index c4aeee9c53b76..37b826153efb1 100644
--- a/src/tools/jsondoclint/src/validator/tests.rs
+++ b/src/tools/jsondoclint/src/validator/tests.rs
@@ -2,11 +2,16 @@ use std::collections::HashMap;
use rustdoc_json_types::{Crate, Item, Visibility};
+use crate::json_find::SelectorPart;
+
use super::*;
#[track_caller]
fn check(krate: &Crate, errs: &[Error]) {
- let mut validator = Validator::new(krate);
+ let krate_string = serde_json::to_string(krate).unwrap();
+ let krate_json = serde_json::from_str(&krate_string).unwrap();
+
+ let mut validator = Validator::new(krate, krate_json);
validator.check_crate();
assert_eq!(errs, &validator.errs[..]);
@@ -46,5 +51,16 @@ fn errors_on_missing_links() {
format_version: rustdoc_json_types::FORMAT_VERSION,
};
- check(&k, &[Error { kind: ErrorKind::NotFound, id: id("1") }]);
+ check(
+ &k,
+ &[Error {
+ kind: ErrorKind::NotFound(vec![vec![
+ SelectorPart::Field("index".to_owned()),
+ SelectorPart::Field("0".to_owned()),
+ SelectorPart::Field("links".to_owned()),
+ SelectorPart::Field("Not Found".to_owned()),
+ ]]),
+ id: id("1"),
+ }],
+ );
}
From 226ab7fd759d94e81d6831f869e41502a7f183c7 Mon Sep 17 00:00:00 2001
From: Nixon Enraght-Moony
Date: Mon, 2 Jan 2023 20:15:45 +0000
Subject: [PATCH 07/17] jsondoclint: Add option to dump errors as json.
The output looks like:
{
"errors": [
{
"id": "2:2017:1833",
"kind": {
"NotFound": [
[
{"Field": "index"},
{"Field": "0:0:1571"},
{"Field": "links"},
{"Field": "pointer::read"}
]
]
}
}
],
"path": "/home/nixon/dev/rust/rust/build/x86_64-unknown-linux-gnu/test/rustdoc-json/intra-doc-links/pointer_method/pointer_method.json"
}
---
Cargo.lock | 1 +
src/tools/jsondoclint/Cargo.toml | 1 +
src/tools/jsondoclint/src/json_find.rs | 3 ++-
src/tools/jsondoclint/src/main.rs | 25 ++++++++++++++++++++++---
4 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 0483d50fc2a69..bb438f288f2e9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2115,6 +2115,7 @@ dependencies = [
"clap 4.0.15",
"fs-err",
"rustdoc-json-types",
+ "serde",
"serde_json",
]
diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml
index 0dda3935ed873..8990310a4f474 100644
--- a/src/tools/jsondoclint/Cargo.toml
+++ b/src/tools/jsondoclint/Cargo.toml
@@ -10,4 +10,5 @@ anyhow = "1.0.62"
clap = { version = "4.0.15", features = ["derive"] }
fs-err = "2.8.1"
rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" }
+serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.85"
diff --git a/src/tools/jsondoclint/src/json_find.rs b/src/tools/jsondoclint/src/json_find.rs
index 70e7440f73085..a183c4068ce85 100644
--- a/src/tools/jsondoclint/src/json_find.rs
+++ b/src/tools/jsondoclint/src/json_find.rs
@@ -1,8 +1,9 @@
use std::fmt::Write;
+use serde::Serialize;
use serde_json::Value;
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub enum SelectorPart {
Field(String),
Index(usize),
diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs
index 266900ea3a22d..05e938f4f7df4 100644
--- a/src/tools/jsondoclint/src/main.rs
+++ b/src/tools/jsondoclint/src/main.rs
@@ -1,25 +1,34 @@
+use std::io::{BufWriter, Write};
+
use anyhow::{bail, Result};
use clap::Parser;
use fs_err as fs;
use rustdoc_json_types::{Crate, Id, FORMAT_VERSION};
+use serde::Serialize;
use serde_json::Value;
pub(crate) mod item_kind;
mod json_find;
mod validator;
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq, Serialize, Clone)]
struct Error {
kind: ErrorKind,
id: Id,
}
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq, Serialize, Clone)]
enum ErrorKind {
NotFound(Vec),
Custom(String),
}
+#[derive(Debug, Serialize)]
+struct JsonOutput {
+ path: String,
+ errors: Vec,
+}
+
#[derive(Parser)]
struct Cli {
/// The path to the json file to be linted
@@ -28,10 +37,13 @@ struct Cli {
/// Show verbose output
#[arg(long)]
verbose: bool,
+
+ #[arg(long)]
+ json_output: Option,
}
fn main() -> Result<()> {
- let Cli { path, verbose } = Cli::parse();
+ let Cli { path, verbose, json_output } = Cli::parse();
let contents = fs::read_to_string(&path)?;
let krate: Crate = serde_json::from_str(&contents)?;
@@ -42,6 +54,13 @@ fn main() -> Result<()> {
let mut validator = validator::Validator::new(&krate, krate_json);
validator.check_crate();
+ if let Some(json_output) = json_output {
+ let output = JsonOutput { path: path.clone(), errors: validator.errs.clone() };
+ let mut f = BufWriter::new(fs::File::create(json_output)?);
+ serde_json::to_writer(&mut f, &output)?;
+ f.flush()?;
+ }
+
if !validator.errs.is_empty() {
for err in validator.errs {
match err.kind {
From 4fe2bd567536719e556d7fc9a4b571042b7807f9 Mon Sep 17 00:00:00 2001
From: Michael Howell
Date: Tue, 3 Jan 2023 10:23:55 -0700
Subject: [PATCH 08/17] rustdoc: remove legacy font-feature-settings CSS
According to [caniuse], these vendor prefixes aren't needed in any supported
web browsers as defined in [RFC 1985].
* The last version of Chrome that required a vendor prefix was version 47.
The current version is 108.
* Firefox 33 is the last version that required a vendor prefix. The
[current Firefox ESR] is version 102.
* The last version of Safari that required a vendor prefix was version 9.1.
The current version is 16.
* The last version of Safari/iOS that required a vendor prefix was version
9.3. The current version is 16.
* Edge never required vendor prefixes.
* UCAndroid never required vendor prefixes.
[caniuse]: https://caniuse.com/?search=font-feature-settings
[RFC 1985]: https://rust-lang.github.io/rfcs/1985-tiered-browser-support.html
[current Firefox ESR]: https://wiki.mozilla.org/Releases
---
src/librustdoc/html/static/css/rustdoc.css | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index bc0458bcd28f2..f4c9cea5935fa 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -110,11 +110,7 @@ body {
/* Then override it with `anywhere`, which is required to make non-Safari browsers break
more aggressively when we want them to. */
overflow-wrap: anywhere;
-
- -webkit-font-feature-settings: "kern", "liga";
- -moz-font-feature-settings: "kern", "liga";
font-feature-settings: "kern", "liga";
-
background-color: var(--main-background-color);
color: var(--main-color);
}
From 9914a8924e651bd013d86ae6254a2283b7afc583 Mon Sep 17 00:00:00 2001
From: Josh Stone
Date: Tue, 3 Jan 2023 09:47:03 -0800
Subject: [PATCH 09/17] Add cuviper to the review rotation for libs
---
triagebot.toml | 1 +
1 file changed, 1 insertion(+)
diff --git a/triagebot.toml b/triagebot.toml
index 0da9fcddad8d7..58108dac496b6 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -479,6 +479,7 @@ compiler = [
"compiler-team-contributors",
]
libs = [
+ "@cuviper",
"@joshtriplett",
"@Mark-Simulacrum",
"@m-ou-se",
From 6eb205d591863f03e661f79ea3cb993f69eff844 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9my=20Rakic?=
Date: Wed, 23 Nov 2022 18:20:57 +0000
Subject: [PATCH 10/17] bootstrap dist: ensure LLD's step
---
src/bootstrap/dist.rs | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 340aa78ebf9b5..479bfeb8e8565 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -2067,6 +2067,12 @@ impl Step for RustDev {
builder.ensure(crate::native::Llvm { target });
+ // If the config has LLD enabled, ensure its step. We'll we want to package it, and use it
+ // in download-ci-llvm.
+ if builder.config.lld_enabled {
+ builder.ensure(crate::native::Lld { target });
+ }
+
let src_bindir = builder.llvm_out(target).join("bin");
// If updating this list, you likely want to change
// src/bootstrap/download-ci-llvm-stamp as well, otherwise local users
From 835b58d61971890c3134f1d7a6a23d32f3ae7479 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9my=20Rakic?=
Date: Wed, 23 Nov 2022 18:08:15 +0000
Subject: [PATCH 11/17] make the `native::LLD` step able to use an already
built lld
Makes the lld step avoid building it from source when possible: when
dist has packaged it along the other LLVM binaries for the rust-dev
component.
---
src/bootstrap/native.rs | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 4e503dfe864e2..0f92c81e4d970 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -826,6 +826,20 @@ impl Step for Lld {
let LlvmResult { llvm_config, llvm_cmake_dir } =
builder.ensure(Llvm { target: self.target });
+ // The `dist` step packages LLD next to LLVM's binaries for download-ci-llvm. The root path
+ // we usually expect here is `./build/$triple/ci-llvm/`, with the binaries in its `bin`
+ // subfolder. We check if that's the case, and if LLD's binary already exists there next to
+ // `llvm-config`: if so, we can use it instead of building LLVM/LLD from source.
+ let ci_llvm_bin = llvm_config.parent().unwrap();
+ if ci_llvm_bin.is_dir() && ci_llvm_bin.file_name().unwrap() == "bin" {
+ let lld_path = ci_llvm_bin.join(exe("lld", target));
+ if lld_path.exists() {
+ // The following steps copying `lld` as `rust-lld` to the sysroot, expect it in the
+ // `bin` subfolder of this step's out dir.
+ return ci_llvm_bin.parent().unwrap().to_path_buf();
+ }
+ }
+
let out_dir = builder.lld_out(target);
let done_stamp = out_dir.join("lld-finished-building");
if done_stamp.exists() {
From 4e4658f0aafbf559a2c3e8674f10a06cadbfc737 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9my=20Rakic?=
Date: Wed, 23 Nov 2022 18:12:58 +0000
Subject: [PATCH 12/17] slight cleanup
---
src/bootstrap/native.rs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 0f92c81e4d970..48158d51e004c 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -823,8 +823,7 @@ impl Step for Lld {
}
let target = self.target;
- let LlvmResult { llvm_config, llvm_cmake_dir } =
- builder.ensure(Llvm { target: self.target });
+ let LlvmResult { llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target });
// The `dist` step packages LLD next to LLVM's binaries for download-ci-llvm. The root path
// we usually expect here is `./build/$triple/ci-llvm/`, with the binaries in its `bin`
From f635f9d4e4448bbccca28a93e42ca52043edeb41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9my=20Rakic?=
Date: Wed, 23 Nov 2022 18:16:37 +0000
Subject: [PATCH 13/17] turn a comment into an actual doc comment
---
src/bootstrap/native.rs | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 48158d51e004c..781a738a81196 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -63,13 +63,13 @@ impl LdFlags {
}
}
-// This returns whether we've already previously built LLVM.
-//
-// It's used to avoid busting caches during x.py check -- if we've already built
-// LLVM, it's fine for us to not try to avoid doing so.
-//
-// This will return the llvm-config if it can get it (but it will not build it
-// if not).
+/// This returns whether we've already previously built LLVM.
+///
+/// It's used to avoid busting caches during x.py check -- if we've already built
+/// LLVM, it's fine for us to not try to avoid doing so.
+///
+/// This will return the llvm-config if it can get it (but it will not build it
+/// if not).
pub fn prebuilt_llvm_config(
builder: &Builder<'_>,
target: TargetSelection,
From c73a46c6bff445230a922e6b5e3018f87443bcbe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9my=20Rakic?=
Date: Tue, 22 Nov 2022 22:38:53 +0000
Subject: [PATCH 14/17] bump download-ci-llvm-stamp
---
src/bootstrap/download-ci-llvm-stamp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index d19a1ae95cf14..94630e40f3c4c 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
Change this file to make users of the `download-ci-llvm` configuration download
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
-Last change is for: https://github.com/rust-lang/rust/pull/102790
+Last change is for: https://github.com/rust-lang/rust/pull/104748
From e0f5c6da1df52a64b80753bf33bae3176729ae52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9my=20Rakic?=
Date: Tue, 3 Jan 2023 20:21:49 +0000
Subject: [PATCH 15/17] ensure lld's step unconditionally for RustDev component
---
src/bootstrap/dist.rs | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 479bfeb8e8565..68215790bed17 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -2067,11 +2067,8 @@ impl Step for RustDev {
builder.ensure(crate::native::Llvm { target });
- // If the config has LLD enabled, ensure its step. We'll we want to package it, and use it
- // in download-ci-llvm.
- if builder.config.lld_enabled {
- builder.ensure(crate::native::Lld { target });
- }
+ // We want to package `lld` to use it with `download-ci-llvm`.
+ builder.ensure(crate::native::Lld { target });
let src_bindir = builder.llvm_out(target).join("bin");
// If updating this list, you likely want to change
From 7690fe3bc66cae219301368650317936f0d4e3a9 Mon Sep 17 00:00:00 2001
From: Michael Goulet
Date: Sat, 10 Dec 2022 20:31:01 +0000
Subject: [PATCH 16/17] Simplify some iterator combinators
---
.../src/diagnostics/conflict_errors.rs | 23 ++---
.../src/diagnostics/region_errors.rs | 50 +++++-----
compiler/rustc_codegen_gcc/src/builder.rs | 2 +-
compiler/rustc_codegen_gcc/src/context.rs | 2 +-
compiler/rustc_hir_typeck/src/lib.rs | 9 +-
.../src/method/prelude2021.rs | 3 +-
compiler/rustc_hir_typeck/src/method/probe.rs | 3 +-
.../rustc_hir_typeck/src/method/suggest.rs | 4 +-
.../nice_region_error/static_impl_trait.rs | 91 ++++++++-----------
compiler/rustc_lint/src/unused.rs | 27 +++---
compiler/rustc_macros/src/symbols/tests.rs | 3 +-
compiler/rustc_resolve/src/ident.rs | 9 +-
12 files changed, 91 insertions(+), 135 deletions(-)
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 3c3cb8c6b9c2a..6d6ad199be35c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -527,26 +527,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// that are *partially* initialized by assigning to a field of an uninitialized
// binding. We differentiate between them for more accurate wording here.
"isn't fully initialized"
- } else if spans
- .iter()
- .filter(|i| {
- // We filter these to avoid misleading wording in cases like the following,
- // where `x` has an `init`, but it is in the same place we're looking at:
- // ```
- // let x;
- // x += 1;
- // ```
- !i.contains(span)
+ } else if !spans.iter().any(|i| {
+ // We filter these to avoid misleading wording in cases like the following,
+ // where `x` has an `init`, but it is in the same place we're looking at:
+ // ```
+ // let x;
+ // x += 1;
+ // ```
+ !i.contains(span)
// We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs`
&& !visitor
.errors
.iter()
.map(|(sp, _)| *sp)
.any(|sp| span < sp && !sp.contains(span))
- })
- .count()
- == 0
- {
+ }) {
show_assign_sugg = true;
"isn't initialized"
} else {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index bcc8afbfd952d..631e147ce8c5f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -316,35 +316,29 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// obligation comes from the `impl`. Find that `impl` so that we can point
// at it in the suggestion.
let trait_did = trait_did.to_def_id();
- match tcx
- .hir()
- .trait_impls(trait_did)
- .iter()
- .filter_map(|&impl_did| {
- match tcx.hir().get_if_local(impl_did.to_def_id()) {
- Some(Node::Item(Item {
- kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
- ..
- })) if trait_objects.iter().all(|did| {
- // FIXME: we should check `self_ty` against the receiver
- // type in the `UnifyReceiver` context, but for now, use
- // this imperfect proxy. This will fail if there are
- // multiple `impl`s for the same trait like
- // `impl Foo for Box` and `impl Foo for dyn Bar`.
- // In that case, only the first one will get suggestions.
- let mut traits = vec![];
- let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
- hir_v.visit_ty(self_ty);
- !traits.is_empty()
- }) =>
- {
- Some(self_ty)
- }
- _ => None,
+ match tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| {
+ match tcx.hir().get_if_local(impl_did.to_def_id()) {
+ Some(Node::Item(Item {
+ kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
+ ..
+ })) if trait_objects.iter().all(|did| {
+ // FIXME: we should check `self_ty` against the receiver
+ // type in the `UnifyReceiver` context, but for now, use
+ // this imperfect proxy. This will fail if there are
+ // multiple `impl`s for the same trait like
+ // `impl Foo for Box` and `impl Foo for dyn Bar`.
+ // In that case, only the first one will get suggestions.
+ let mut traits = vec![];
+ let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
+ hir_v.visit_ty(self_ty);
+ !traits.is_empty()
+ }) =>
+ {
+ Some(self_ty)
}
- })
- .next()
- {
+ _ => None,
+ }
+ }) {
Some(self_ty) => Some((trait_item.ident, self_ty)),
_ => None,
}
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index effb2de482751..a92242b2615c1 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1244,7 +1244,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
) -> RValue<'gcc> {
// FIXME(antoyo): remove when having a proper API.
let gcc_func = unsafe { std::mem::transmute(func) };
- let call = if self.functions.borrow().values().find(|value| **value == gcc_func).is_some() {
+ let call = if self.functions.borrow().values().any(|value| *value == gcc_func) {
self.function_call(func, args, funclet)
}
else {
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 837708aeb0ea9..4424b31c0542c 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -253,7 +253,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
let function: Function<'gcc> = unsafe { std::mem::transmute(value) };
- debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(),
+ debug_assert!(self.functions.borrow().values().any(|value| *value == function),
"{:?} ({:?}) is not a function", value, value.get_type());
function
}
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index b06927f9662be..cecf3d3f1e064 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -240,10 +240,8 @@ fn typeck_with_fallback<'tcx>(
}),
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
- let operand_ty = asm
- .operands
- .iter()
- .filter_map(|(op, _op_sp)| match op {
+ let operand_ty =
+ asm.operands.iter().find_map(|(op, _op_sp)| match op {
hir::InlineAsmOperand::Const { anon_const }
if anon_const.hir_id == id =>
{
@@ -259,8 +257,7 @@ fn typeck_with_fallback<'tcx>(
}))
}
_ => None,
- })
- .next();
+ });
operand_ty.unwrap_or_else(fallback)
}
_ => fallback(),
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index dea14dd93d6ac..3d6c2119bea33 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -341,8 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Find an identifier with which this trait was imported (note that `_` doesn't count).
let any_id = import_items
.iter()
- .filter_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None })
- .next();
+ .find_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None });
if let Some(any_id) = any_id {
if any_id.name == Empty {
// Glob import, so just use its name.
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 1afaae0e0209d..2daf1979ee5e6 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1111,7 +1111,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// a raw pointer
!step.self_ty.references_error() && !step.from_unsafe_deref
})
- .flat_map(|step| {
+ .find_map(|step| {
let InferOk { value: self_ty, obligations: _ } = self
.fcx
.probe_instantiate_query_response(
@@ -1147,7 +1147,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
})
})
})
- .next()
}
/// For each type `T` in the step list, this attempts to find a method where
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 71c3803e64fa2..b04ef55a994ea 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -257,9 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx
.inherent_impls(adt_def.did())
.iter()
- .filter_map(|def_id| self.associated_value(*def_id, item_name))
- .count()
- >= 1
+ .any(|def_id| self.associated_value(*def_id, item_name).is_some())
} else {
false
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 9bd2202d2601e..58be91bc276a9 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -309,19 +309,12 @@ pub fn suggest_new_region_bound(
let did = item_id.owner_id.to_def_id();
let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did));
- if let Some(span) = opaque
- .bounds
- .iter()
- .filter_map(|arg| match arg {
- GenericBound::Outlives(Lifetime {
- res: LifetimeName::Static,
- ident,
- ..
- }) => Some(ident.span),
- _ => None,
- })
- .next()
- {
+ if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg {
+ GenericBound::Outlives(Lifetime {
+ res: LifetimeName::Static, ident, ..
+ }) => Some(ident.span),
+ _ => None,
+ }) {
if let Some(explicit_static) = &explicit_static {
err.span_suggestion_verbose(
span,
@@ -338,20 +331,14 @@ pub fn suggest_new_region_bound(
Applicability::MaybeIncorrect,
);
}
- } else if opaque
- .bounds
- .iter()
- .filter_map(|arg| match arg {
- GenericBound::Outlives(Lifetime { ident, .. })
- if ident.name.to_string() == lifetime_name =>
- {
- Some(ident.span)
- }
- _ => None,
- })
- .next()
- .is_some()
- {
+ } else if opaque.bounds.iter().any(|arg| match arg {
+ GenericBound::Outlives(Lifetime { ident, .. })
+ if ident.name.to_string() == lifetime_name =>
+ {
+ true
+ }
+ _ => false,
+ }) {
} else {
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
@@ -428,35 +415,29 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
// obligation comes from the `impl`. Find that `impl` so that we can point
// at it in the suggestion.
let trait_did = trait_did.to_def_id();
- match tcx
- .hir()
- .trait_impls(trait_did)
- .iter()
- .filter_map(|&impl_did| {
- match tcx.hir().get_if_local(impl_did.to_def_id()) {
- Some(Node::Item(Item {
- kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
- ..
- })) if trait_objects.iter().all(|did| {
- // FIXME: we should check `self_ty` against the receiver
- // type in the `UnifyReceiver` context, but for now, use
- // this imperfect proxy. This will fail if there are
- // multiple `impl`s for the same trait like
- // `impl Foo for Box` and `impl Foo for dyn Bar`.
- // In that case, only the first one will get suggestions.
- let mut traits = vec![];
- let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
- hir_v.visit_ty(self_ty);
- !traits.is_empty()
- }) =>
- {
- Some(self_ty)
- }
- _ => None,
+ match tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| {
+ match tcx.hir().get_if_local(impl_did.to_def_id()) {
+ Some(Node::Item(Item {
+ kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
+ ..
+ })) if trait_objects.iter().all(|did| {
+ // FIXME: we should check `self_ty` against the receiver
+ // type in the `UnifyReceiver` context, but for now, use
+ // this imperfect proxy. This will fail if there are
+ // multiple `impl`s for the same trait like
+ // `impl Foo for Box` and `impl Foo for dyn Bar`.
+ // In that case, only the first one will get suggestions.
+ let mut traits = vec![];
+ let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
+ hir_v.visit_ty(self_ty);
+ !traits.is_empty()
+ }) =>
+ {
+ Some(self_ty)
}
- })
- .next()
- {
+ _ => None,
+ }
+ }) {
Some(self_ty) => Some((trait_item.ident, self_ty)),
_ => None,
}
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index a7a5234049fe6..bf1f150fc3b47 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -256,7 +256,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
cx.tcx,
cx.tcx.explicit_item_bounds(def).iter().cloned(),
)
- .filter_map(|obligation| {
+ .find_map(|obligation| {
// We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateKind::Clause(ty::Clause::Trait(
ref poly_trait_predicate,
@@ -270,22 +270,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
}
})
.map(|inner| MustUsePath::Opaque(Box::new(inner)))
- .next()
}
- ty::Dynamic(binders, _, _) => binders
- .iter()
- .filter_map(|predicate| {
- if let ty::ExistentialPredicate::Trait(ref trait_ref) =
- predicate.skip_binder()
- {
- let def_id = trait_ref.def_id;
- is_def_must_use(cx, def_id, span)
- } else {
- None
- }
- .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
- })
- .next(),
+ ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| {
+ if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
+ {
+ let def_id = trait_ref.def_id;
+ is_def_must_use(cx, def_id, span)
+ } else {
+ None
+ }
+ .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
+ }),
ty::Tuple(tys) => {
let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind {
debug_assert_eq!(elem_exprs.len(), tys.len());
diff --git a/compiler/rustc_macros/src/symbols/tests.rs b/compiler/rustc_macros/src/symbols/tests.rs
index 842d2a977189d..bd0c08a53c4f2 100644
--- a/compiler/rustc_macros/src/symbols/tests.rs
+++ b/compiler/rustc_macros/src/symbols/tests.rs
@@ -16,14 +16,13 @@ fn test_symbols() {
let m: &syn::ItemMacro = file
.items
.iter()
- .filter_map(|i| {
+ .find_map(|i| {
if let syn::Item::Macro(m) = i {
if m.mac.path == symbols_path { Some(m) } else { None }
} else {
None
}
})
- .next()
.expect("did not find `symbols!` macro invocation.");
let body_tokens = m.mac.tokens.clone();
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 0c4b35b88335a..e41fe325b811c 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -820,13 +820,12 @@ impl<'a> Resolver<'a> {
// binding if it exists. What we really want here is having two separate scopes in
// a module - one for non-globs and one for globs, but until that's done use this
// hack to avoid inconsistent resolution ICEs during import validation.
- let binding = [resolution.binding, resolution.shadowed_glob]
- .into_iter()
- .filter_map(|binding| match (binding, ignore_binding) {
+ let binding = [resolution.binding, resolution.shadowed_glob].into_iter().find_map(
+ |binding| match (binding, ignore_binding) {
(Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None,
_ => binding,
- })
- .next();
+ },
+ );
let Some(binding) = binding else {
return Err((Determined, Weak::No));
};
From 2baee88bdb6ebbfda067818f5f4194083c2a77c1 Mon Sep 17 00:00:00 2001
From: Michael Goulet
Date: Tue, 27 Dec 2022 17:53:29 +0000
Subject: [PATCH 17/17] Address comments
---
.../src/diagnostics/conflict_errors.rs | 12 +--
.../src/diagnostics/region_errors.rs | 63 +------------
.../nice_region_error/static_impl_trait.rs | 92 +++++++++----------
compiler/rustc_lint/src/unused.rs | 2 +-
4 files changed, 52 insertions(+), 117 deletions(-)
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 6d6ad199be35c..50cd13a2ccc8a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -535,12 +535,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// x += 1;
// ```
!i.contains(span)
- // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs`
- && !visitor
- .errors
- .iter()
- .map(|(sp, _)| *sp)
- .any(|sp| span < sp && !sp.contains(span))
+ // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs`
+ && !visitor
+ .errors
+ .iter()
+ .map(|(sp, _)| *sp)
+ .any(|sp| span < sp && !sp.contains(span))
}) {
show_assign_sugg = true;
"isn't initialized"
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 631e147ce8c5f..567a9814fccbf 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -4,9 +4,9 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
+use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
-use rustc_hir::{self as hir, Item, ItemKind, Node};
use rustc_infer::infer::{
error_reporting::nice_region_error::{
self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
@@ -291,65 +291,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
outlives_suggestion.add_suggestion(self);
}
- fn get_impl_ident_and_self_ty_from_trait(
- &self,
- def_id: DefId,
- trait_objects: &FxIndexSet,
- ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
- let tcx = self.infcx.tcx;
- match tcx.hir().get_if_local(def_id) {
- Some(Node::ImplItem(impl_item)) => {
- match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id)
- {
- Some(Node::Item(Item {
- kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
- ..
- })) => Some((impl_item.ident, self_ty)),
- _ => None,
- }
- }
- Some(Node::TraitItem(trait_item)) => {
- let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
- match tcx.hir().find_by_def_id(trait_did.def_id) {
- Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
- // The method being called is defined in the `trait`, but the `'static`
- // obligation comes from the `impl`. Find that `impl` so that we can point
- // at it in the suggestion.
- let trait_did = trait_did.to_def_id();
- match tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| {
- match tcx.hir().get_if_local(impl_did.to_def_id()) {
- Some(Node::Item(Item {
- kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
- ..
- })) if trait_objects.iter().all(|did| {
- // FIXME: we should check `self_ty` against the receiver
- // type in the `UnifyReceiver` context, but for now, use
- // this imperfect proxy. This will fail if there are
- // multiple `impl`s for the same trait like
- // `impl Foo for Box` and `impl Foo for dyn Bar`.
- // In that case, only the first one will get suggestions.
- let mut traits = vec![];
- let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
- hir_v.visit_ty(self_ty);
- !traits.is_empty()
- }) =>
- {
- Some(self_ty)
- }
- _ => None,
- }
- }) {
- Some(self_ty) => Some((trait_item.ident, self_ty)),
- _ => None,
- }
- }
- _ => None,
- }
- }
- _ => None,
- }
- }
-
/// Report an error because the universal region `fr` was required to outlive
/// `outlived_fr` but it is not known to do so. For example:
///
@@ -844,7 +785,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
visitor.visit_ty(param.param_ty);
let Some((ident, self_ty)) =
- self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &visitor.0) else {return};
+ NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &visitor.0) else { return; };
self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty);
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 58be91bc276a9..d9cdfa9dd4fc9 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -239,7 +239,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let mut v = TraitObjectVisitor(FxIndexSet::default());
v.visit_ty(param.param_ty);
if let Some((ident, self_ty)) =
- self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0)
+ NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, item_def_id, &v.0)
&& self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty)
{
override_error_code = Some(ident.name);
@@ -390,60 +390,54 @@ pub fn suggest_new_region_bound(
}
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
- fn get_impl_ident_and_self_ty_from_trait(
- &self,
+ pub fn get_impl_ident_and_self_ty_from_trait(
+ tcx: TyCtxt<'tcx>,
def_id: DefId,
trait_objects: &FxIndexSet,
) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
- let tcx = self.tcx();
- match tcx.hir().get_if_local(def_id) {
- Some(Node::ImplItem(impl_item)) => {
- match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id)
+ match tcx.hir().get_if_local(def_id)? {
+ Node::ImplItem(impl_item) => {
+ let impl_did = tcx.hir().get_parent_item(impl_item.hir_id());
+ if let hir::OwnerNode::Item(Item {
+ kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
+ ..
+ }) = tcx.hir().owner(impl_did)
{
- Some(Node::Item(Item {
- kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
- ..
- })) => Some((impl_item.ident, self_ty)),
- _ => None,
+ Some((impl_item.ident, self_ty))
+ } else {
+ None
}
}
- Some(Node::TraitItem(trait_item)) => {
- let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
- match tcx.hir().find_by_def_id(trait_did.def_id) {
- Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
- // The method being called is defined in the `trait`, but the `'static`
- // obligation comes from the `impl`. Find that `impl` so that we can point
- // at it in the suggestion.
- let trait_did = trait_did.to_def_id();
- match tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| {
- match tcx.hir().get_if_local(impl_did.to_def_id()) {
- Some(Node::Item(Item {
- kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
- ..
- })) if trait_objects.iter().all(|did| {
- // FIXME: we should check `self_ty` against the receiver
- // type in the `UnifyReceiver` context, but for now, use
- // this imperfect proxy. This will fail if there are
- // multiple `impl`s for the same trait like
- // `impl Foo for Box` and `impl Foo for dyn Bar`.
- // In that case, only the first one will get suggestions.
- let mut traits = vec![];
- let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
- hir_v.visit_ty(self_ty);
- !traits.is_empty()
- }) =>
- {
- Some(self_ty)
- }
- _ => None,
- }
- }) {
- Some(self_ty) => Some((trait_item.ident, self_ty)),
- _ => None,
- }
+ Node::TraitItem(trait_item) => {
+ let trait_id = tcx.hir().get_parent_item(trait_item.hir_id());
+ debug_assert_eq!(tcx.def_kind(trait_id.def_id), hir::def::DefKind::Trait);
+ // The method being called is defined in the `trait`, but the `'static`
+ // obligation comes from the `impl`. Find that `impl` so that we can point
+ // at it in the suggestion.
+ let trait_did = trait_id.to_def_id();
+ tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| {
+ if let Node::Item(Item {
+ kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
+ ..
+ }) = tcx.hir().find_by_def_id(impl_did)?
+ && trait_objects.iter().all(|did| {
+ // FIXME: we should check `self_ty` against the receiver
+ // type in the `UnifyReceiver` context, but for now, use
+ // this imperfect proxy. This will fail if there are
+ // multiple `impl`s for the same trait like
+ // `impl Foo for Box` and `impl Foo for dyn Bar`.
+ // In that case, only the first one will get suggestions.
+ let mut traits = vec![];
+ let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
+ hir_v.visit_ty(self_ty);
+ !traits.is_empty()
+ })
+ {
+ Some((trait_item.ident, *self_ty))
+ } else {
+ None
}
- _ => None,
- }
+ })
}
_ => None,
}
@@ -474,7 +468,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
// Get the `Ident` of the method being called and the corresponding `impl` (to point at
// `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
- let Some((ident, self_ty)) = self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0) else {
+ let Some((ident, self_ty)) = NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &v.0) else {
return false;
};
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index bf1f150fc3b47..525079681ca5c 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -276,10 +276,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
{
let def_id = trait_ref.def_id;
is_def_must_use(cx, def_id, span)
+ .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
} else {
None
}
- .map(|inner| MustUsePath::TraitObject(Box::new(inner)))
}),
ty::Tuple(tys) => {
let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind {