Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 20 additions & 25 deletions compiler/rustc_builtin_macros/src/eii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,18 @@ fn eii_(
) -> Vec<Annotatable> {
let eii_attr_span = ecx.with_def_site_ctxt(eii_attr_span);

let (item, stmt) = if let Annotatable::Item(item) = item {
(item, false)
let (item, wrap_item): (_, &dyn Fn(_) -> _) = if let Annotatable::Item(item) = item {
(item, &Annotatable::Item)
} else if let Annotatable::Stmt(ref stmt) = item
&& let StmtKind::Item(ref item) = stmt.kind
{
(item.clone(), true)
(item.clone(), &|item| {
Annotatable::Stmt(Box::new(Stmt {
id: DUMMY_NODE_ID,
kind: StmtKind::Item(item),
span: eii_attr_span,
}))
})
} else {
ecx.dcx().emit_err(EiiSharedMacroExpectedFunction {
span: eii_attr_span,
Expand All @@ -74,23 +80,25 @@ fn eii_(
return vec![item];
};

let orig_item = item.clone();

let item = *item;

let ast::Item { attrs, id: _, span: _, vis, kind: ItemKind::Fn(func), tokens: _ } = item else {
let ast::Item { attrs, id: _, span: _, vis, kind: ItemKind::Fn(func), tokens: _ } =
item.as_ref()
else {
ecx.dcx().emit_err(EiiSharedMacroExpectedFunction {
span: eii_attr_span,
name: path_to_string(&meta_item.path),
});
return vec![Annotatable::Item(Box::new(item))];
return vec![wrap_item(item)];
};
// only clone what we need
let attrs = attrs.clone();
let func = (**func).clone();
let vis = vis.clone();

let attrs_from_decl =
filter_attrs_for_multiple_eii_attr(ecx, attrs, eii_attr_span, &meta_item.path);

let Ok(macro_name) = name_for_impl_macro(ecx, &func, &meta_item) else {
return vec![Annotatable::Item(orig_item)];
return vec![wrap_item(item)];
};

// span of the declaring item without attributes
Expand All @@ -115,7 +123,7 @@ fn eii_(
ecx,
eii_attr_span,
item_span,
*func,
func,
vis,
&attrs_from_decl,
)));
Expand All @@ -128,20 +136,7 @@ fn eii_(
decl_span,
)));

if stmt {
return_items
.into_iter()
.map(|i| {
Annotatable::Stmt(Box::new(Stmt {
id: DUMMY_NODE_ID,
kind: StmtKind::Item(i),
span: eii_attr_span,
}))
})
.collect()
} else {
return_items.into_iter().map(|i| Annotatable::Item(i)).collect()
}
return_items.into_iter().map(wrap_item).collect()
}

/// Decide on the name of the macro that can be used to implement the EII.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_graphviz/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ impl<'a> Id<'a> {
/// it in the generated .dot file. They can also provide more
/// elaborate (and non-unique) label text that is used in the graphviz
/// rendered output.
///
/// The graph instance is responsible for providing the DOT compatible
/// identifiers for the nodes and (optionally) rendered labels for the nodes and
/// edges, as well as an identifier for the graph itself.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2654,7 +2654,7 @@ struct InternedInSet<'tcx, T: ?Sized + PointeeSized>(&'tcx T);

impl<'tcx, T: 'tcx + ?Sized + PointeeSized> Clone for InternedInSet<'tcx, T> {
fn clone(&self) -> Self {
InternedInSet(self.0)
*self
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_pattern_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ pub struct MatchArm<'p, Cx: PatCx> {

impl<'p, Cx: PatCx> Clone for MatchArm<'p, Cx> {
fn clone(&self) -> Self {
Self { pat: self.pat, has_guard: self.has_guard, arm_data: self.arm_data }
*self
}
}

Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_pattern_analysis/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,7 @@ pub(crate) enum PatOrWild<'p, Cx: PatCx> {

impl<'p, Cx: PatCx> Clone for PatOrWild<'p, Cx> {
fn clone(&self) -> Self {
match self {
PatOrWild::Wild => PatOrWild::Wild,
PatOrWild::Pat(pat) => PatOrWild::Pat(pat),
}
*self
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_pattern_analysis/src/usefulness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ struct PlaceCtxt<'a, Cx: PatCx> {
impl<'a, Cx: PatCx> Copy for PlaceCtxt<'a, Cx> {}
impl<'a, Cx: PatCx> Clone for PlaceCtxt<'a, Cx> {
fn clone(&self) -> Self {
Self { cx: self.cx, ty: self.ty }
*self
}
}

Expand Down
14 changes: 6 additions & 8 deletions compiler/rustc_thread_pool/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ pub struct Registry {
terminate_count: AtomicUsize,
}

/// ////////////////////////////////////////////////////////////////////////
/// Initialization
///////////////////////////////////////////////////////////////////////////
// Initialization

static mut THE_REGISTRY: Option<Arc<Registry>> = None;
static THE_REGISTRY_SET: Once = Once::new();
Expand Down Expand Up @@ -407,12 +407,12 @@ impl Registry {
}
}

/// ////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
/// MAIN LOOP
///
/// So long as all of the worker threads are hanging out in their
/// top-level loop, there is no work to be done.
///
/// Push a job into the given `registry`. If we are running on a
/// worker thread for the registry, this will push onto the
/// deque. Else, it will inject from the outside (which is slower).
Expand Down Expand Up @@ -668,8 +668,8 @@ impl ThreadInfo {
}
}

/// ////////////////////////////////////////////////////////////////////////
/// WorkerThread identifiers
///////////////////////////////////////////////////////////////////////////
// WorkerThread identifiers

pub(super) struct WorkerThread {
/// the "worker" half of our local deque
Expand Down Expand Up @@ -1019,8 +1019,6 @@ impl WorkerThread {
}
}

/// ////////////////////////////////////////////////////////////////////////
unsafe fn main_loop(thread: ThreadBuilder) {
let worker_thread = &WorkerThread::from(thread);
unsafe { WorkerThread::set_current(worker_thread) };
Expand Down
3 changes: 2 additions & 1 deletion library/core/src/cell/once.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,8 @@ impl<T> OnceCell<T> {
}

#[stable(feature = "once_cell", since = "1.70.0")]
impl<T> Default for OnceCell<T> {
#[rustc_const_unstable(feature = "const_default", issue = "143894")]
impl<T> const Default for OnceCell<T> {
#[inline]
fn default() -> Self {
Self::new()
Expand Down
7 changes: 0 additions & 7 deletions library/core/src/prelude/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,6 @@ pub use crate::macros::builtin::deref;
)]
pub use crate::macros::builtin::define_opaque;

#[unstable(
feature = "derive_from",
issue = "144889",
reason = "`derive(From)` is unstable"
)]
pub use crate::macros::builtin::From;

#[unstable(feature = "extern_item_impls", issue = "125418")]
pub use crate::macros::builtin::{eii, unsafe_eii};

Expand Down
4 changes: 2 additions & 2 deletions library/core/src/sync/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1151,8 +1151,8 @@ impl AtomicBool {
/// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true);
/// assert_eq!(foo.load(Ordering::SeqCst), true);
///
/// let foo = AtomicBool::new(true);
/// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), true);
/// let foo = AtomicBool::new(false);
/// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), false);
/// assert_eq!(foo.load(Ordering::SeqCst), true);
///
/// let foo = AtomicBool::new(false);
Expand Down
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@
#![feature(cfg_sanitizer_cfi)]
#![feature(cfg_target_thread_local)]
#![feature(cfi_encoding)]
#![feature(const_default)]
#![feature(const_trait_impl)]
#![feature(core_float_math)]
#![feature(decl_macro)]
Expand Down
3 changes: 2 additions & 1 deletion library/std/src/sync/once_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,8 @@ impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}

#[stable(feature = "once_cell", since = "1.70.0")]
impl<T> Default for OnceLock<T> {
#[rustc_const_unstable(feature = "const_default", issue = "143894")]
impl<T> const Default for OnceLock<T> {
/// Creates a new uninitialized cell.
///
/// # Example
Expand Down
6 changes: 4 additions & 2 deletions library/test/src/formatters/junit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,10 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
compilation_time: f64,
) -> io::Result<()> {
self.write_message(&format!(
"<report total_time=\"{total_time}\" compilation_time=\"{compilation_time}\"></report>\n",
))
"<report total_time=\"{total_time}\" compilation_time=\"{compilation_time}\"></report>",
))?;
self.out.write_all(b"\n")?;
Ok(())
}
}

Expand Down
1 change: 1 addition & 0 deletions tests/run-make/doctests-junit/doctest-2021.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="test" package="test" id="0" errors="0" failures="0" tests="3" skipped="0" ><testcase classname="doctest.rs" name="add (line 1)" time="$TIME"/><testcase classname="doctest.rs" name="add (line 5)" time="$TIME"/><testcase classname="doctest.rs" name="add (line 9)" time="$TIME"/><system-out/><system-err/></testsuite></testsuites>
3 changes: 3 additions & 0 deletions tests/run-make/doctests-junit/doctest-2024.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="test" package="test" id="0" errors="0" failures="0" tests="2" skipped="0" ><testcase classname="doctest.rs" name="add (line 1)" time="$TIME"/><testcase classname="doctest.rs" name="add (line 5)" time="$TIME"/><system-out/><system-err/></testsuite></testsuites>
<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="test" package="test" id="0" errors="0" failures="0" tests="1" skipped="0" ><testcase classname="doctest.rs" name="add (line 9)" time="$TIME"/><system-out/><system-err/></testsuite></testsuites>
<report total_time="$TIME" compilation_time="$TIME"></report>
14 changes: 14 additions & 0 deletions tests/run-make/doctests-junit/doctest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/// ```
/// assert_eq!(doctest::add(2, 2), 4);
/// ```
///
/// ```should_panic
/// assert_eq!(doctest::add(2, 2), 5);
/// ```
///
/// ```compile_fail
/// assert_eq!(doctest::add(2, 2), "banana");
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
45 changes: 45 additions & 0 deletions tests/run-make/doctests-junit/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Check rustdoc's test JUnit (XML) output against snapshots.

//@ ignore-cross-compile (running doctests)
//@ ignore-stage1 (rustdoc depends on a fix in libtest)
//@ needs-unwind (test file contains `should_panic` test)

use std::path::Path;

use run_make_support::{cwd, diff, python_command, rustc, rustdoc};

fn main() {
let rlib = cwd().join("libdoctest.rlib");
rustc().input("doctest.rs").crate_type("rlib").output(&rlib).run();

run_doctests(&rlib, "2021", "doctest-2021.xml");
run_doctests(&rlib, "2024", "doctest-2024.xml");
}

#[track_caller]
fn run_doctests(rlib: &Path, edition: &str, expected_xml: &str) {
let rustdoc_out = rustdoc()
.input("doctest.rs")
.args(&[
"--test",
"--test-args=-Zunstable-options",
"--test-args=--test-threads=1",
"--test-args=--format=junit",
])
.edition(edition)
.env("RUST_BACKTRACE", "0")
.extern_("doctest", rlib.display().to_string())
.run();
let rustdoc_stdout = &rustdoc_out.stdout_utf8();

// FIXME: merged output of compile_fail tests is broken
if edition != "2024" {
python_command().arg("validate_junit.py").stdin_buf(rustdoc_stdout).run();
}

diff()
.expected_file(expected_xml)
.actual_text("output", rustdoc_stdout)
.normalize(r#"\b(time|total_time|compilation_time)="[0-9.]+""#, r#"$1="$$TIME""#)
.run();
}
22 changes: 22 additions & 0 deletions tests/run-make/doctests-junit/validate_junit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python

# Trivial Python script that reads lines from stdin, and checks that each line
# is a well-formed XML document.
#
# This takes advantage of the fact that Python has a built-in XML parser,
# whereas doing the same check in Rust would require us to pull in an XML
# crate just for this relatively-minor test.
#
# If you're trying to remove Python scripts from the test suite, think twice
# before removing this one. You could do so, but it's probably not worth it.

import sys
import xml.etree.ElementTree as ET

# Read the entire output and try to decode it as XML.
junit = sys.stdin.read()
try:
ET.fromstring(junit)
except ET.ParseError:
print("Invalid xml: %r" % junit)
raise
14 changes: 7 additions & 7 deletions tests/run-make/libtest-junit/validate_junit.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
import sys
import xml.etree.ElementTree as ET

# Try to decode line in order to ensure it is a valid XML document
for line in sys.stdin:
try:
ET.fromstring(line)
except ET.ParseError:
print("Invalid xml: %r" % line)
raise
# Read the entire output and try to decode it as XML.
junit = sys.stdin.read()
try:
ET.fromstring(junit)
except ET.ParseError:
print("Invalid xml: %r" % junit)
raise
16 changes: 16 additions & 0 deletions tests/ui/eii/error_statement_position.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![feature(extern_item_impls)]
// EIIs can, despite not being super useful, be declared in statement position
// nested inside items. Items in statement position, when expanded as part of a macro,
// need to be wrapped slightly differently (in an `ast::Statement`).
// We did this on the happy path (no errors), but when there was an error, we'd
// replace it with *just* an `ast::Item` not wrapped in an `ast::Statement`.
// This caused an ICE (https://github.com/rust-lang/rust/issues/149980).
// this test fails to build, but demonstrates that no ICE is produced.

fn main() {
struct Bar;

#[eii]
//~^ ERROR `#[eii]` is only valid on functions
impl Bar {}
}
8 changes: 8 additions & 0 deletions tests/ui/eii/error_statement_position.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: `#[eii]` is only valid on functions
--> $DIR/error_statement_position.rs:13:5
|
LL | #[eii]
| ^^^^^^

error: aborting due to 1 previous error

Loading