From d49d136b3a0e9749e4aa517b7aa6490752444cf7 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Tue, 19 Mar 2024 12:58:23 -0400 Subject: [PATCH 01/11] conditionally ignore fatal diagnostic in the SilentEmitter This change is primarily meant to allow rustfmt to ignore all diagnostics when using the `SilentEmitter`. Back in PR 121301 the `SilentEmitter` was shared between rustc and rustfmt. This changed rustfmt's behavior from ignoring all diagnostic to emitting fatal diagnostics. These changes allow rustfmt to maintain it's previous behaviour when using the SilentEmitter, while allowing rustc code to still emit fatal diagnostics. --- compiler/rustc_errors/src/emitter.rs | 3 ++- compiler/rustc_errors/src/lib.rs | 8 +++++++- compiler/rustc_interface/src/interface.rs | 2 ++ compiler/rustc_session/src/parse.rs | 7 ++++++- src/tools/rustfmt/src/parse/session.rs | 3 ++- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 4f033e3fefa..f5d275fc452 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -541,6 +541,7 @@ pub struct SilentEmitter { pub fallback_bundle: LazyFallbackBundle, pub fatal_dcx: DiagCtxt, pub fatal_note: Option, + pub emit_fatal_diagnostic: bool, } impl Translate for SilentEmitter { @@ -561,7 +562,7 @@ impl Emitter for SilentEmitter { } fn emit_diagnostic(&mut self, mut diag: DiagInner) { - if diag.level == Level::Fatal { + if self.emit_fatal_diagnostic && diag.level == Level::Fatal { if let Some(fatal_note) = &self.fatal_note { diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new()); } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 723f13dbe8d..ff5e1948db8 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -613,12 +613,18 @@ impl DiagCtxt { Self { inner: Lock::new(DiagCtxtInner::new(emitter)) } } - pub fn make_silent(&mut self, fallback_bundle: LazyFallbackBundle, fatal_note: Option) { + pub fn make_silent( + &mut self, + fallback_bundle: LazyFallbackBundle, + fatal_note: Option, + emit_fatal_diagnostic: bool, + ) { self.wrap_emitter(|old_dcx| { Box::new(emitter::SilentEmitter { fallback_bundle, fatal_dcx: DiagCtxt { inner: Lock::new(old_dcx) }, fatal_note, + emit_fatal_diagnostic, }) }); } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 1a82e6c6910..edf52fe8c34 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -48,6 +48,7 @@ pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec) -> Cfg { let psess = ParseSess::with_silent_emitter( vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE], format!("this error occurred on the command line: `--cfg={s}`"), + true, ); let filename = FileName::cfg_spec_source_code(&s); @@ -111,6 +112,7 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { let psess = ParseSess::with_silent_emitter( vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE], format!("this error occurred on the command line: `--check-cfg={s}`"), + true, ); let filename = FileName::cfg_spec_source_code(&s); diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 5434bbe0b98..f6053f43fbd 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -269,7 +269,11 @@ impl ParseSess { } } - pub fn with_silent_emitter(locale_resources: Vec<&'static str>, fatal_note: String) -> Self { + pub fn with_silent_emitter( + locale_resources: Vec<&'static str>, + fatal_note: String, + emit_fatal_diagnostic: bool, + ) -> Self { let fallback_bundle = fallback_fluent_bundle(locale_resources, false); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new(HumanEmitter::new( @@ -281,6 +285,7 @@ impl ParseSess { fallback_bundle, fatal_dcx, fatal_note: Some(fatal_note), + emit_fatal_diagnostic, })) .disable_warnings(); ParseSess::with_dcx(dcx, sm) diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index cb46e65999d..1a39d212386 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -121,6 +121,7 @@ fn default_dcx( fallback_bundle, fatal_dcx: DiagCtxt::new(emitter), fatal_note: None, + emit_fatal_diagnostic: false, }) } else { emitter @@ -209,7 +210,7 @@ impl ParseSess { rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false, ); - self.raw_psess.dcx.make_silent(fallback_bundle, None); + self.raw_psess.dcx.make_silent(fallback_bundle, None, false); } pub(crate) fn span_to_filename(&self, span: Span) -> FileName { From 92325a95b3830e693e11c3575254d133f6dd7c5b Mon Sep 17 00:00:00 2001 From: h1467792822 <1467792822@qq.com> Date: Tue, 19 Mar 2024 19:50:07 +0800 Subject: [PATCH 02/11] Fixed the `private-dependency` bug: If the directly dependent crate is loaded last and is not configured with `--extern`, it may be incorrectly set to `private-dependency` --- compiler/rustc_metadata/src/creader.rs | 27 +++++++++++-------- .../ui/privacy/pub-priv-dep/auxiliary/bar.rs | 6 +++++ .../ui/privacy/pub-priv-dep/auxiliary/foo.rs | 2 ++ .../pub-priv-dep/priv-dep-issue-122756.rs | 12 +++++++++ 4 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 tests/ui/privacy/pub-priv-dep/auxiliary/bar.rs create mode 100644 tests/ui/privacy/pub-priv-dep/auxiliary/foo.rs create mode 100644 tests/ui/privacy/pub-priv-dep/priv-dep-issue-122756.rs diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 72757d90e42..f61248aa731 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -388,6 +388,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { None } + // The `dependency` type is determined by the command line arguments(`--extern`) and + // `private_dep`. However, sometimes the directly dependent crate is not specified by + // `--extern`, in this case, `private-dep` is none during loading. This is equivalent to the + // scenario where the command parameter is set to `public-dependency` + fn is_private_dep(&self, name: &str, private_dep: Option) -> bool { + self.sess.opts.externs.get(name).map_or(private_dep.unwrap_or(false), |e| e.is_private_dep) + && private_dep.unwrap_or(true) + } + fn register_crate( &mut self, host_lib: Option, @@ -402,14 +411,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - - let private_dep = self - .sess - .opts - .externs - .get(name.as_str()) - .map_or(private_dep.unwrap_or(false), |e| e.is_private_dep) - && private_dep.unwrap_or(true); + let private_dep = self.is_private_dep(name.as_str(), private_dep); // Claim this crate number and cache it let cnum = self.cstore.intern_stable_crate_id(&crate_root)?; @@ -599,14 +601,17 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { match result { (LoadResult::Previous(cnum), None) => { + // When `private_dep` is none, it indicates the directly dependent crate. If it is + // not specified by `--extern` on command line parameters, it may be + // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to + // `public-dependency` here. + let private_dep = self.is_private_dep(name.as_str(), private_dep); let data = self.cstore.get_crate_data_mut(cnum); if data.is_proc_macro_crate() { dep_kind = CrateDepKind::MacrosOnly; } data.set_dep_kind(cmp::max(data.dep_kind(), dep_kind)); - if let Some(private_dep) = private_dep { - data.update_and_private_dep(private_dep); - } + data.update_and_private_dep(private_dep); Ok(cnum) } (LoadResult::Loaded(library), host_library) => { diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/bar.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/bar.rs new file mode 100644 index 00000000000..58297c92693 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/bar.rs @@ -0,0 +1,6 @@ +//@ aux-crate:priv:foo=foo.rs +//@ compile-flags: -Zunstable-options + +#![crate_type = "rlib"] +extern crate foo; +pub struct Bar(pub i32); diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/foo.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/foo.rs new file mode 100644 index 00000000000..6fd950619e6 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/foo.rs @@ -0,0 +1,2 @@ +#![crate_type = "rlib"] +pub struct Foo(pub i32); diff --git a/tests/ui/privacy/pub-priv-dep/priv-dep-issue-122756.rs b/tests/ui/privacy/pub-priv-dep/priv-dep-issue-122756.rs new file mode 100644 index 00000000000..d7ade7f0e96 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/priv-dep-issue-122756.rs @@ -0,0 +1,12 @@ +//@ aux-build: bar.rs +//@ aux-build: foo.rs +//@ build-pass + +#![deny(exported_private_dependencies)] + +// Ensure the libbar.rlib is loaded first. If the command line parameter `--extern foo` does not +// exist, previus version would fail to compile +#![crate_type = "rlib"] +extern crate bar; +extern crate foo; +pub fn baz() -> (Option, Option) { (None, None) } From ab92699f4a4bce54675012112693e9919ab19f54 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 23 Mar 2024 19:13:52 +1100 Subject: [PATCH 03/11] Unbox and unwrap the contents of `StatementKind::Coverage` The payload of coverage statements was historically a structure with several fields, so it was boxed to avoid bloating `StatementKind`. Now that the payload is a single relatively-small enum, we can replace `Box` with just `CoverageKind`. This patch also adds a size assertion for `StatementKind`, to avoid accidentally bloating it in the future. --- .../rustc_codegen_gcc/src/coverageinfo.rs | 4 +-- .../src/coverageinfo/mod.rs | 4 +-- .../rustc_codegen_ssa/src/mir/coverageinfo.rs | 6 ++-- .../rustc_codegen_ssa/src/mir/statement.rs | 4 +-- .../src/traits/coverageinfo.rs | 4 +-- .../src/transform/validate.rs | 3 +- compiler/rustc_middle/src/mir/pretty.rs | 4 +-- compiler/rustc_middle/src/mir/syntax.rs | 9 ++--- compiler/rustc_middle/src/mir/visit.rs | 6 ++-- compiler/rustc_mir_build/src/build/cfg.rs | 4 +-- .../rustc_mir_build/src/build/coverageinfo.rs | 4 +-- .../src/cleanup_post_borrowck.rs | 9 +++-- .../rustc_mir_transform/src/coverage/mod.rs | 7 ++-- .../rustc_mir_transform/src/coverage/query.rs | 10 +++--- .../src/coverage/spans/from_mir.rs | 34 ++++++++----------- 15 files changed, 44 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/coverageinfo.rs b/compiler/rustc_codegen_gcc/src/coverageinfo.rs index 849e9886ef3..4e44f78f23c 100644 --- a/compiler/rustc_codegen_gcc/src/coverageinfo.rs +++ b/compiler/rustc_codegen_gcc/src/coverageinfo.rs @@ -1,11 +1,11 @@ use rustc_codegen_ssa::traits::CoverageInfoBuilderMethods; -use rustc_middle::mir::Coverage; +use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::Instance; use crate::builder::Builder; impl<'a, 'gcc, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { - fn add_coverage(&mut self, _instance: Instance<'tcx>, _coverage: &Coverage) { + fn add_coverage(&mut self, _instance: Instance<'tcx>, _kind: &CoverageKind) { // TODO(antoyo) } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 54f4bc06340..85277db6d53 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -14,7 +14,6 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_llvm::RustString; use rustc_middle::bug; use rustc_middle::mir::coverage::CoverageKind; -use rustc_middle::mir::Coverage; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::Instance; @@ -75,7 +74,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { #[instrument(level = "debug", skip(self))] - fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) { + fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind) { // Our caller should have already taken care of inlining subtleties, // so we can assume that counter/expression IDs in this coverage // statement are meaningful for the given instance. @@ -98,7 +97,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { .entry(instance) .or_insert_with(|| FunctionCoverageCollector::new(instance, function_coverage_info)); - let Coverage { kind } = coverage; match *kind { CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!( "marker statement {kind:?} should have been removed by CleanupPostBorrowck" diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index ee70465966d..72187277228 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -1,12 +1,12 @@ use crate::traits::*; -use rustc_middle::mir::Coverage; +use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::SourceScope; use super::FunctionCx; impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { - pub fn codegen_coverage(&self, bx: &mut Bx, coverage: &Coverage, scope: SourceScope) { + pub fn codegen_coverage(&self, bx: &mut Bx, kind: &CoverageKind, scope: SourceScope) { // Determine the instance that coverage data was originally generated for. let instance = if let Some(inlined) = scope.inlined_instance(&self.mir.source_scopes) { self.monomorphize(inlined) @@ -15,6 +15,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; // Handle the coverage info in a backend-specific way. - bx.add_coverage(instance, coverage); + bx.add_coverage(instance, kind); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index ac7dfbb261d..2188eeae426 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -64,8 +64,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_indirect_place.storage_dead(bx); } } - mir::StatementKind::Coverage(box ref coverage) => { - self.codegen_coverage(bx, coverage, statement.source_info.scope); + mir::StatementKind::Coverage(ref kind) => { + self.codegen_coverage(bx, kind, statement.source_info.scope); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) { diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index 7e8de0ddc5b..d1d813bd389 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -1,5 +1,5 @@ use super::BackendTypes; -use rustc_middle::mir::Coverage; +use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::Instance; pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { @@ -7,5 +7,5 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { /// /// This can potentially be a no-op in backends that don't support /// coverage instrumentation. - fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage); + fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind); } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 4bc49f90607..00dac1343c8 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -346,8 +346,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.fail(location, format!("explicit `{kind:?}` is forbidden")); } } - StatementKind::Coverage(coverage) => { - let kind = &coverage.kind; + StatementKind::Coverage(kind) => { if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) && let CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. } = kind { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 94751c44761..7dcaacfc5e6 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -13,7 +13,7 @@ use rustc_middle::mir::interpret::{ Provenance, }; use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{self, *}; +use rustc_middle::mir::*; use rustc_target::abi::Size; const INDENT: &str = " "; @@ -711,7 +711,7 @@ impl Debug for Statement<'_> { AscribeUserType(box (ref place, ref c_ty), ref variance) => { write!(fmt, "AscribeUserType({place:?}, {variance:?}, {c_ty:?})") } - Coverage(box mir::Coverage { ref kind }) => write!(fmt, "Coverage::{kind:?}"), + Coverage(ref kind) => write!(fmt, "Coverage::{kind:?}"), Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"), ConstEvalCounter => write!(fmt, "ConstEvalCounter"), Nop => write!(fmt, "nop"), diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 752f5845afb..1dde65b1bae 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -373,7 +373,7 @@ pub enum StatementKind<'tcx> { /// /// Interpreters and codegen backends that don't support coverage instrumentation /// can usually treat this as a no-op. - Coverage(Box), + Coverage(CoverageKind), /// Denotes a call to an intrinsic that does not require an unwind path and always returns. /// This avoids adding a new block and a terminator for simple intrinsics. @@ -517,12 +517,6 @@ pub enum FakeReadCause { ForIndex, } -#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct Coverage { - pub kind: CoverageKind, -} - #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] #[derive(TypeFoldable, TypeVisitable)] pub struct CopyNonOverlapping<'tcx> { @@ -1465,5 +1459,6 @@ mod size_asserts { static_assert_size!(Place<'_>, 16); static_assert_size!(PlaceElem<'_>, 24); static_assert_size!(Rvalue<'_>, 40); + static_assert_size!(StatementKind<'_>, 16); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index be960669ff4..3835bd371d9 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -156,10 +156,10 @@ macro_rules! make_mir_visitor { fn visit_coverage( &mut self, - coverage: & $($mutability)? Coverage, + kind: & $($mutability)? coverage::CoverageKind, location: Location, ) { - self.super_coverage(coverage, location); + self.super_coverage(kind, location); } fn visit_retag( @@ -803,7 +803,7 @@ macro_rules! make_mir_visitor { } fn super_coverage(&mut self, - _coverage: & $($mutability)? Coverage, + _kind: & $($mutability)? coverage::CoverageKind, _location: Location) { } diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs index 2bd0e289731..18e45291e9a 100644 --- a/compiler/rustc_mir_build/src/build/cfg.rs +++ b/compiler/rustc_mir_build/src/build/cfg.rs @@ -107,9 +107,7 @@ impl<'tcx> CFG<'tcx> { /// This results in more accurate coverage reports for certain kinds of /// syntax (e.g. `continue` or `if !`) that would otherwise not appear in MIR. pub(crate) fn push_coverage_span_marker(&mut self, block: BasicBlock, source_info: SourceInfo) { - let kind = StatementKind::Coverage(Box::new(Coverage { - kind: coverage::CoverageKind::SpanMarker, - })); + let kind = StatementKind::Coverage(coverage::CoverageKind::SpanMarker); let stmt = Statement { source_info, kind }; self.push(block, stmt); } diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs index 0b8ec234dda..ab0043906b1 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -127,9 +127,7 @@ impl Builder<'_, '_> { let marker_statement = mir::Statement { source_info, - kind: mir::StatementKind::Coverage(Box::new(mir::Coverage { - kind: CoverageKind::BlockMarker { id }, - })), + kind: mir::StatementKind::Coverage(CoverageKind::BlockMarker { id }), }; self.cfg.push(block, marker_statement); diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index aaf2035fc21..da82f8de781 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -18,7 +18,7 @@ use crate::MirPass; use rustc_middle::mir::coverage::CoverageKind; -use rustc_middle::mir::{Body, BorrowKind, Coverage, Rvalue, StatementKind, TerminatorKind}; +use rustc_middle::mir::{Body, BorrowKind, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::TyCtxt; pub struct CleanupPostBorrowck; @@ -30,12 +30,11 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck { match statement.kind { StatementKind::AscribeUserType(..) | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake, _))) - | StatementKind::Coverage(box Coverage { + | StatementKind::Coverage( // These kinds of coverage statements are markers inserted during // MIR building, and are not needed after InstrumentCoverage. - kind: CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. }, - .. - }) + CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. }, + ) | StatementKind::FakeRead(..) => statement.make_nop(), _ => (), } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 83189c6a50a..ae3b1a3d1af 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -15,7 +15,7 @@ use crate::MirPass; use rustc_middle::mir::coverage::*; use rustc_middle::mir::{ - self, BasicBlock, BasicBlockData, Coverage, SourceInfo, Statement, StatementKind, Terminator, + self, BasicBlock, BasicBlockData, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::TyCtxt; @@ -230,10 +230,7 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb debug!(" injecting statement {counter_kind:?} for {bb:?}"); let data = &mut mir_body[bb]; let source_info = data.terminator().source_info; - let statement = Statement { - source_info, - kind: StatementKind::Coverage(Box::new(Coverage { kind: counter_kind })), - }; + let statement = Statement { source_info, kind: StatementKind::Coverage(counter_kind) }; data.statements.insert(0, statement); } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 1de7b6f66a7..b5dd9dcc7b4 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,7 +1,7 @@ use rustc_data_structures::captures::Captures; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::{CounterId, CoverageKind}; -use rustc_middle::mir::{Body, Coverage, CoverageIdsInfo, Statement, StatementKind}; +use rustc_middle::mir::{Body, CoverageIdsInfo, Statement, StatementKind}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::util::Providers; @@ -54,7 +54,7 @@ fn coverage_ids_info<'tcx>( let mir_body = tcx.instance_mir(instance_def); let max_counter_id = all_coverage_in_mir_body(mir_body) - .filter_map(|coverage| match coverage.kind { + .filter_map(|kind| match *kind { CoverageKind::CounterIncrement { id } => Some(id), _ => None, }) @@ -66,12 +66,10 @@ fn coverage_ids_info<'tcx>( fn all_coverage_in_mir_body<'a, 'tcx>( body: &'a Body<'tcx>, -) -> impl Iterator + Captures<'tcx> { +) -> impl Iterator + Captures<'tcx> { body.basic_blocks.iter().flat_map(|bb_data| &bb_data.statements).filter_map(|statement| { match statement.kind { - StatementKind::Coverage(box ref coverage) if !is_inlined(body, statement) => { - Some(coverage) - } + StatementKind::Coverage(ref kind) if !is_inlined(body, statement) => Some(kind), _ => None, } }) diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 3f6a4156044..adb0c9f1929 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -187,9 +187,7 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option { // for their parent `BasicBlock`. StatementKind::StorageLive(_) | StatementKind::StorageDead(_) - // Ignore `ConstEvalCounter`s | StatementKind::ConstEvalCounter - // Ignore `Nop`s | StatementKind::Nop => None, // FIXME(#78546): MIR InstrumentCoverage - Can the source_info.span for `FakeRead` @@ -211,30 +209,28 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option { StatementKind::FakeRead(box (FakeReadCause::ForGuardBinding, _)) => None, // Retain spans from most other statements. - StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding` + StatementKind::FakeRead(_) | StatementKind::Intrinsic(..) - | StatementKind::Coverage(box mir::Coverage { + | StatementKind::Coverage( // The purpose of `SpanMarker` is to be matched and accepted here. - kind: CoverageKind::SpanMarker - }) + CoverageKind::SpanMarker, + ) | StatementKind::Assign(_) | StatementKind::SetDiscriminant { .. } | StatementKind::Deinit(..) | StatementKind::Retag(_, _) | StatementKind::PlaceMention(..) - | StatementKind::AscribeUserType(_, _) => { - Some(statement.source_info.span) - } + | StatementKind::AscribeUserType(_, _) => Some(statement.source_info.span), - StatementKind::Coverage(box mir::Coverage { - // Block markers are used for branch coverage, so ignore them here. - kind: CoverageKind::BlockMarker {..} - }) => None, + // Block markers are used for branch coverage, so ignore them here. + StatementKind::Coverage(CoverageKind::BlockMarker { .. }) => None, - StatementKind::Coverage(box mir::Coverage { - // These coverage statements should not exist prior to coverage instrumentation. - kind: CoverageKind::CounterIncrement { .. } | CoverageKind::ExpressionUsed { .. } - }) => bug!("Unexpected coverage statement found during coverage instrumentation: {statement:?}"), + // These coverage statements should not exist prior to coverage instrumentation. + StatementKind::Coverage( + CoverageKind::CounterIncrement { .. } | CoverageKind::ExpressionUsed { .. }, + ) => bug!( + "Unexpected coverage statement found during coverage instrumentation: {statement:?}" + ), } } @@ -382,9 +378,7 @@ pub(super) fn extract_branch_mappings( // Fill out the mapping from block marker IDs to their enclosing blocks. for (bb, data) in mir_body.basic_blocks.iter_enumerated() { for statement in &data.statements { - if let StatementKind::Coverage(coverage) = &statement.kind - && let CoverageKind::BlockMarker { id } = coverage.kind - { + if let StatementKind::Coverage(CoverageKind::BlockMarker { id }) = statement.kind { block_markers[id] = Some(bb); } } From 37dbe40a7e54a873d047ae530b3a70e52ec8c030 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sat, 23 Mar 2024 23:51:27 +0900 Subject: [PATCH 04/11] Add a regression test for #117310 --- .../tait-param-inference-issue-117310.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/tait-param-inference-issue-117310.rs diff --git a/tests/ui/type-alias-impl-trait/tait-param-inference-issue-117310.rs b/tests/ui/type-alias-impl-trait/tait-param-inference-issue-117310.rs new file mode 100644 index 00000000000..be743e8e270 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/tait-param-inference-issue-117310.rs @@ -0,0 +1,28 @@ +//@ check-pass + +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +use std::ops::Deref; + +trait Trait {} +impl Trait for (A, B, u8) where A: Deref, B: Deref, {} +impl Trait for (A, B, i8) {} + +type TaitSized = impl Sized; +fn def_tait1() -> TaitSized {} + +type TaitCopy = impl Copy; +fn def_tait2() -> TaitCopy {} + +fn impl_trait () {} + +fn test() { + impl_trait::<(&TaitSized, &TaitCopy, _)>(); + impl_trait::<(&TaitCopy, &TaitSized, _)>(); + + impl_trait::<(&TaitCopy, &String, _)>(); + impl_trait::<(&TaitSized, &String, _)>(); +} + +fn main() {} From 894555ff8ed077a7bf3d9738888a456c6c763163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sat, 23 Mar 2024 20:09:51 +0000 Subject: [PATCH 05/11] Track run-make-support lib in common inputs stamp --- src/tools/compiletest/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index ef02e7fcb4a..b791b38379f 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -609,6 +609,8 @@ fn common_inputs_stamp(config: &Config) -> Stamp { stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py")); } + stamp.add_dir(&rust_src_dir.join("src/tools/run-make-support")); + // Compiletest itself. stamp.add_dir(&rust_src_dir.join("src/tools/compiletest/")); From b67ad8f626a8848eb568a528d31b32d65fddccb5 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 23 Mar 2024 21:49:29 -0700 Subject: [PATCH 06/11] Rename `Arguments::as_const_str` to `as_statically_known_str` While `const` has a particular meaning about language guarantees, here we need a fuzzier notion like whether constant propagation was effective, and `statically_known` is the best term we have for now. --- library/core/src/fmt/mod.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 4016167d05c..e880d5758ec 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -201,7 +201,7 @@ pub trait Write { impl SpecWriteFmt for &mut W { #[inline] default fn spec_write_fmt(mut self, args: Arguments<'_>) -> Result { - if let Some(s) = args.as_const_str() { + if let Some(s) = args.as_statically_known_str() { self.write_str(s) } else { write(&mut self, args) @@ -212,7 +212,7 @@ pub trait Write { impl SpecWriteFmt for &mut W { #[inline] fn spec_write_fmt(self, args: Arguments<'_>) -> Result { - if let Some(s) = args.as_const_str() { + if let Some(s) = args.as_statically_known_str() { self.write_str(s) } else { write(self, args) @@ -442,7 +442,7 @@ impl<'a> Arguments<'a> { /// Same as [`Arguments::as_str`], but will only return `Some(s)` if it can be determined at compile time. #[must_use] #[inline] - fn as_const_str(&self) -> Option<&'static str> { + fn as_statically_known_str(&self) -> Option<&'static str> { let s = self.as_str(); if core::intrinsics::is_val_statically_known(s.is_some()) { s } else { None } } @@ -1617,7 +1617,11 @@ impl<'a> Formatter<'a> { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result { - if let Some(s) = fmt.as_const_str() { self.buf.write_str(s) } else { write(self.buf, fmt) } + if let Some(s) = fmt.as_statically_known_str() { + self.buf.write_str(s) + } else { + write(self.buf, fmt) + } } /// Flags for formatting @@ -2308,7 +2312,7 @@ impl Write for Formatter<'_> { #[inline] fn write_fmt(&mut self, args: Arguments<'_>) -> Result { - if let Some(s) = args.as_const_str() { + if let Some(s) = args.as_statically_known_str() { self.buf.write_str(s) } else { write(self.buf, args) From fc5085d5709df1cc6e409d60216c6a1f5380aa48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 22 Mar 2024 16:45:15 +0100 Subject: [PATCH 07/11] add test for #90192 Fixes #90192 --- .../ice-poly-with-mir-opts-90192.rs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs diff --git a/tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs b/tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs new file mode 100644 index 00000000000..4557c7e517c --- /dev/null +++ b/tests/ui/polymorphization/ice-poly-with-mir-opts-90192.rs @@ -0,0 +1,20 @@ +// issue: rust-lang/rust#90192 +// ICE assertion failed: matches!(ty.kind(), ty :: Param(_)) +//@ compile-flags:-Zpolymorphize=on -Zmir-opt-level=3 +//@ build-pass + +fn test() { + std::mem::size_of::(); +} + +pub fn foo(_: T) -> &'static fn() { + &(test:: as fn()) +} + +fn outer() { + foo(|| ()); +} + +fn main() { + outer::(); +} From 7aa76a7ac31d978bf0a80e304b39e43bd1b34547 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 24 Mar 2024 17:26:48 +0900 Subject: [PATCH 08/11] Fix build failure on ARM/AArch64/PowerPC/RISC-V FreeBSD/NetBSD --- library/std/src/sys/pal/unix/net.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs index 1f140f7844f..9a0a1b18aee 100644 --- a/library/std/src/sys/pal/unix/net.rs +++ b/library/std/src/sys/pal/unix/net.rs @@ -459,7 +459,7 @@ impl Socket { const AF_NAME_MAX: usize = 16; let mut buf = [0; AF_NAME_MAX]; for (src, dst) in name.to_bytes().iter().zip(&mut buf[..AF_NAME_MAX - 1]) { - *dst = *src as i8; + *dst = *src as libc::c_char; } let mut arg: libc::accept_filter_arg = unsafe { mem::zeroed() }; arg.af_name = buf; From 0727b6ad0db5876910291f9e20cc66b730cde6e1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 24 Mar 2024 09:40:07 +0100 Subject: [PATCH 09/11] panic-in-panic-hook: formatting a message that's just a string is risk-free --- library/std/src/lib.rs | 1 + library/std/src/panicking.rs | 14 +++++++++----- tests/ui/panics/panic-in-message-fmt.run.stderr | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index c457c39e0c1..dc5a8704498 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -328,6 +328,7 @@ #![feature(float_gamma)] #![feature(float_minimum_maximum)] #![feature(float_next_up_down)] +#![feature(fmt_internals)] #![feature(generic_nonzero)] #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index e6e1d32fa54..31dbe86b66c 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -391,6 +391,7 @@ pub mod panic_count { pub fn increase(run_panic_hook: bool) -> Option { let global_count = GLOBAL_PANIC_COUNT.fetch_add(1, Ordering::Relaxed); if global_count & ALWAYS_ABORT_FLAG != 0 { + // Do *not* access thread-local state, we might be after a `fork`. return Some(MustAbort::AlwaysAbort); } @@ -744,11 +745,14 @@ fn rust_panic_with_hook( if let Some(must_abort) = must_abort { match must_abort { panic_count::MustAbort::PanicInHook => { - // Don't try to print the message in this case - // - perhaps that is causing the recursive panics. + // Don't try to format the message in this case, perhaps that is causing the + // recursive panics. However if the message is just a string, no user-defined + // code is involved in printing it, so that is risk-free. + let msg_str = message.and_then(|m| m.as_str()).map(|m| [m]); + let message = msg_str.as_ref().map(|m| fmt::Arguments::new_const(m)); let panicinfo = PanicInfo::internal_constructor( - None, // no message - location, // but we want to show the location! + message.as_ref(), + location, can_unwind, force_no_backtrace, ); @@ -756,7 +760,7 @@ fn rust_panic_with_hook( } panic_count::MustAbort::AlwaysAbort => { // Unfortunately, this does not print a backtrace, because creating - // a `Backtrace` will allocate, which we must to avoid here. + // a `Backtrace` will allocate, which we must avoid here. let panicinfo = PanicInfo::internal_constructor( message, location, diff --git a/tests/ui/panics/panic-in-message-fmt.run.stderr b/tests/ui/panics/panic-in-message-fmt.run.stderr index c3a5733c8ae..46829c33a54 100644 --- a/tests/ui/panics/panic-in-message-fmt.run.stderr +++ b/tests/ui/panics/panic-in-message-fmt.run.stderr @@ -1,2 +1,3 @@ panicked at $DIR/panic-in-message-fmt.rs:18:9: +not yet implemented thread panicked while processing panic. aborting. From 4b84df9ea398fd3b3da55968d021906fc2346ce8 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 24 Mar 2024 10:57:17 +0000 Subject: [PATCH 10/11] std::thread: refine available_parallelism for solaris/illumos. Rather than the system-wide available cpus fallback solution, we fetch the cpus bound to the current process. --- library/std/src/sys/pal/unix/thread.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 6520ca9fc48..9befcb0e3e6 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -483,6 +483,12 @@ pub fn available_parallelism() -> io::Result> { .ok_or(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")) } } + } else if #[cfg(any(target_os = "solaris", target_os = "illumos"))] { + let mut cpus = 0u32; + if unsafe { libc::pset_info(libc::PS_MYID, core::ptr::null_mut(), &mut cpus, core::ptr::null_mut()) } == 0 { + NonZero::new(cpus as usize) + .ok_or(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")) + } } else if #[cfg(target_os = "haiku")] { // system_info cpu_count field gets the static data set at boot time with `smp_set_num_cpus` // `get_system_info` calls then `smp_get_num_cpus` From 1871ea5710cdead66b1dfa3621f3727026185fa4 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 24 Mar 2024 16:02:02 +0000 Subject: [PATCH 11/11] fix build. --- library/std/src/sys/pal/unix/thread.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 9befcb0e3e6..a3e1b6782e8 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -355,8 +355,6 @@ pub fn available_parallelism() -> io::Result> { target_os = "tvos", target_os = "linux", target_os = "macos", - target_os = "solaris", - target_os = "illumos", target_os = "aix", ))] { #[allow(unused_assignments)] @@ -485,10 +483,10 @@ pub fn available_parallelism() -> io::Result> { } } else if #[cfg(any(target_os = "solaris", target_os = "illumos"))] { let mut cpus = 0u32; - if unsafe { libc::pset_info(libc::PS_MYID, core::ptr::null_mut(), &mut cpus, core::ptr::null_mut()) } == 0 { - NonZero::new(cpus as usize) - .ok_or(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")) + if unsafe { libc::pset_info(libc::PS_MYID, core::ptr::null_mut(), &mut cpus, core::ptr::null_mut()) } != 0 { + return Err(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")); } + Ok(unsafe { NonZero::new_unchecked(cpus as usize) }) } else if #[cfg(target_os = "haiku")] { // system_info cpu_count field gets the static data set at boot time with `smp_set_num_cpus` // `get_system_info` calls then `smp_get_num_cpus`