Skip to content

Commit 505292d

Browse files
committed
Auto merge of rust-lang#136050 - matthiaskrgr:rollup-t77sm1i, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#133631 (Support QNX 7.1 with `io-sock`+libstd and QNX 8.0 (`no_std` only)) - rust-lang#133951 (Make the wasm_c_abi future compat warning a hard error) - rust-lang#134283 (fix(libtest): Deprecate '--logfile') - rust-lang#134679 (Windows: remove readonly files) - rust-lang#135635 (Move `std::io::pipe` code into its own file) - rust-lang#135842 (TRPL: more backward-compatible Edition changes) - rust-lang#135953 (ci.py: check the return code in `run-local`) - rust-lang#136031 (Expand polonius MIR dump) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 203e6c1 + 30a7740 commit 505292d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+864
-504
lines changed

compiler/rustc_borrowck/src/polonius/dump.rs

+170-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::io;
22

3-
use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
4-
use rustc_middle::mir::{Body, ClosureRegionRequirements, PassWhere};
3+
use rustc_middle::mir::pretty::{
4+
PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer,
5+
};
6+
use rustc_middle::mir::{Body, ClosureRegionRequirements};
57
use rustc_middle::ty::TyCtxt;
68
use rustc_session::config::MirIncludeSpans;
79

@@ -10,9 +12,6 @@ use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSe
1012
use crate::{BorrowckInferCtxt, RegionInferenceContext};
1113

1214
/// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information.
13-
// Note: this currently duplicates most of NLL MIR, with some additions for the localized outlives
14-
// constraints. This is ok for now as this dump will change in the near future to an HTML file to
15-
// become more useful.
1615
pub(crate) fn dump_polonius_mir<'tcx>(
1716
infcx: &BorrowckInferCtxt<'tcx>,
1817
body: &Body<'tcx>,
@@ -26,25 +25,113 @@ pub(crate) fn dump_polonius_mir<'tcx>(
2625
return;
2726
}
2827

28+
if !dump_enabled(tcx, "polonius", body.source.def_id()) {
29+
return;
30+
}
31+
2932
let localized_outlives_constraints = localized_outlives_constraints
3033
.expect("missing localized constraints with `-Zpolonius=next`");
3134

32-
// We want the NLL extra comments printed by default in NLL MIR dumps (they were removed in
33-
// #112346). Specifying `-Z mir-include-spans` on the CLI still has priority: for example,
34-
// they're always disabled in mir-opt tests to make working with blessed dumps easier.
35+
let _: io::Result<()> = try {
36+
let mut file = create_dump_file(tcx, "html", false, "polonius", &0, body)?;
37+
emit_polonius_dump(
38+
tcx,
39+
body,
40+
regioncx,
41+
borrow_set,
42+
localized_outlives_constraints,
43+
closure_region_requirements,
44+
&mut file,
45+
)?;
46+
};
47+
}
48+
49+
/// The polonius dump consists of:
50+
/// - the NLL MIR
51+
/// - the list of polonius localized constraints
52+
/// - a mermaid graph of the CFG
53+
fn emit_polonius_dump<'tcx>(
54+
tcx: TyCtxt<'tcx>,
55+
body: &Body<'tcx>,
56+
regioncx: &RegionInferenceContext<'tcx>,
57+
borrow_set: &BorrowSet<'tcx>,
58+
localized_outlives_constraints: LocalizedOutlivesConstraintSet,
59+
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
60+
out: &mut dyn io::Write,
61+
) -> io::Result<()> {
62+
// Prepare the HTML dump file prologue.
63+
writeln!(out, "<!DOCTYPE html>")?;
64+
writeln!(out, "<html>")?;
65+
writeln!(out, "<head><title>Polonius MIR dump</title></head>")?;
66+
writeln!(out, "<body>")?;
67+
68+
// Section 1: the NLL + Polonius MIR.
69+
writeln!(out, "<div>")?;
70+
writeln!(out, "Raw MIR dump")?;
71+
writeln!(out, "<code><pre>")?;
72+
emit_html_mir(
73+
tcx,
74+
body,
75+
regioncx,
76+
borrow_set,
77+
localized_outlives_constraints,
78+
closure_region_requirements,
79+
out,
80+
)?;
81+
writeln!(out, "</pre></code>")?;
82+
writeln!(out, "</div>")?;
83+
84+
// Section 2: mermaid visualization of the CFG.
85+
writeln!(out, "<div>")?;
86+
writeln!(out, "Control-flow graph")?;
87+
writeln!(out, "<code><pre class='mermaid'>")?;
88+
emit_mermaid_cfg(body, out)?;
89+
writeln!(out, "</pre></code>")?;
90+
writeln!(out, "</div>")?;
91+
92+
// Finalize the dump with the HTML epilogue.
93+
writeln!(
94+
out,
95+
"<script src='https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js'></script>"
96+
)?;
97+
writeln!(out, "<script>")?;
98+
writeln!(out, "mermaid.initialize({{ startOnLoad: false, maxEdges: 100 }});")?;
99+
writeln!(out, "mermaid.run({{ querySelector: '.mermaid' }})")?;
100+
writeln!(out, "</script>")?;
101+
writeln!(out, "</body>")?;
102+
writeln!(out, "</html>")?;
103+
104+
Ok(())
105+
}
106+
107+
/// Emits the polonius MIR, as escaped HTML.
108+
fn emit_html_mir<'tcx>(
109+
tcx: TyCtxt<'tcx>,
110+
body: &Body<'tcx>,
111+
regioncx: &RegionInferenceContext<'tcx>,
112+
borrow_set: &BorrowSet<'tcx>,
113+
localized_outlives_constraints: LocalizedOutlivesConstraintSet,
114+
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
115+
out: &mut dyn io::Write,
116+
) -> io::Result<()> {
117+
// Buffer the regular MIR dump to be able to escape it.
118+
let mut buffer = Vec::new();
119+
120+
// We want the NLL extra comments printed by default in NLL MIR dumps. Specifying `-Z
121+
// mir-include-spans` on the CLI still has priority.
35122
let options = PrettyPrintMirOptions {
36123
include_extra_comments: matches!(
37124
tcx.sess.opts.unstable_opts.mir_include_spans,
38125
MirIncludeSpans::On | MirIncludeSpans::Nll
39126
),
40127
};
41128

42-
dump_mir_with_options(
129+
dump_mir_to_writer(
43130
tcx,
44-
false,
45131
"polonius",
46132
&0,
47133
body,
134+
&mut buffer,
48135
|pass_where, out| {
49136
emit_polonius_mir(
50137
tcx,
@@ -57,7 +144,27 @@ pub(crate) fn dump_polonius_mir<'tcx>(
57144
)
58145
},
59146
options,
60-
);
147+
)?;
148+
149+
// Escape the handful of characters that need it. We don't need to be particularly efficient:
150+
// we're actually writing into a buffered writer already. Note that MIR dumps are valid UTF-8.
151+
let buffer = String::from_utf8_lossy(&buffer);
152+
for ch in buffer.chars() {
153+
let escaped = match ch {
154+
'>' => "&gt;",
155+
'<' => "&lt;",
156+
'&' => "&amp;",
157+
'\'' => "&#39;",
158+
'"' => "&quot;",
159+
_ => {
160+
// The common case, no escaping needed.
161+
write!(out, "{}", ch)?;
162+
continue;
163+
}
164+
};
165+
write!(out, "{}", escaped)?;
166+
}
167+
Ok(())
61168
}
62169

63170
/// Produces the actual NLL + Polonius MIR sections to emit during the dumping process.
@@ -102,3 +209,55 @@ fn emit_polonius_mir<'tcx>(
102209

103210
Ok(())
104211
}
212+
213+
/// Emits a mermaid flowchart of the CFG blocks and edges, similar to the graphviz version.
214+
fn emit_mermaid_cfg(body: &Body<'_>, out: &mut dyn io::Write) -> io::Result<()> {
215+
use rustc_middle::mir::{TerminatorEdges, TerminatorKind};
216+
217+
// The mermaid chart type: a top-down flowchart.
218+
writeln!(out, "flowchart TD")?;
219+
220+
// Emit the block nodes.
221+
for (block_idx, block) in body.basic_blocks.iter_enumerated() {
222+
let block_idx = block_idx.as_usize();
223+
let cleanup = if block.is_cleanup { " (cleanup)" } else { "" };
224+
writeln!(out, "{block_idx}[\"bb{block_idx}{cleanup}\"]")?;
225+
}
226+
227+
// Emit the edges between blocks, from the terminator edges.
228+
for (block_idx, block) in body.basic_blocks.iter_enumerated() {
229+
let block_idx = block_idx.as_usize();
230+
let terminator = block.terminator();
231+
match terminator.edges() {
232+
TerminatorEdges::None => {}
233+
TerminatorEdges::Single(bb) => {
234+
writeln!(out, "{block_idx} --> {}", bb.as_usize())?;
235+
}
236+
TerminatorEdges::Double(bb1, bb2) => {
237+
if matches!(terminator.kind, TerminatorKind::FalseEdge { .. }) {
238+
writeln!(out, "{block_idx} --> {}", bb1.as_usize())?;
239+
writeln!(out, "{block_idx} -- imaginary --> {}", bb2.as_usize())?;
240+
} else {
241+
writeln!(out, "{block_idx} --> {}", bb1.as_usize())?;
242+
writeln!(out, "{block_idx} -- unwind --> {}", bb2.as_usize())?;
243+
}
244+
}
245+
TerminatorEdges::AssignOnReturn { return_, cleanup, .. } => {
246+
for to_idx in return_ {
247+
writeln!(out, "{block_idx} --> {}", to_idx.as_usize())?;
248+
}
249+
250+
if let Some(to_idx) = cleanup {
251+
writeln!(out, "{block_idx} -- unwind --> {}", to_idx.as_usize())?;
252+
}
253+
}
254+
TerminatorEdges::SwitchInt { targets, .. } => {
255+
for to_idx in targets.all_targets() {
256+
writeln!(out, "{block_idx} --> {}", to_idx.as_usize())?;
257+
}
258+
}
259+
}
260+
}
261+
262+
Ok(())
263+
}

compiler/rustc_lint/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,3 @@ lint_uses_power_alignment = repr(C) does not follow the power alignment rule. Th
976976
977977
lint_variant_size_differences =
978978
enum variant is more than three times larger ({$largest} bytes) than the next largest
979-
980-
lint_wasm_c_abi =
981-
older versions of the `wasm-bindgen` crate will be incompatible with future versions of Rust; please update to `wasm-bindgen` v0.2.88

compiler/rustc_lint/src/early/diagnostics.rs

-1
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,6 @@ pub(super) fn decorate_lint(
430430
BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => {
431431
lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag)
432432
}
433-
BuiltinLintDiag::WasmCAbi => lints::WasmCAbi.decorate_lint(diag),
434433
BuiltinLintDiag::IllFormedAttributeInput { suggestions } => {
435434
lints::IllFormedAttributeInput {
436435
num_suggestions: suggestions.len(),

compiler/rustc_lint/src/lints.rs

-4
Original file line numberDiff line numberDiff line change
@@ -2566,10 +2566,6 @@ pub(crate) struct UnusedCrateDependency {
25662566
pub local_crate: Symbol,
25672567
}
25682568

2569-
#[derive(LintDiagnostic)]
2570-
#[diag(lint_wasm_c_abi)]
2571-
pub(crate) struct WasmCAbi;
2572-
25732569
#[derive(LintDiagnostic)]
25742570
#[diag(lint_ill_formed_attribute_input)]
25752571
pub(crate) struct IllFormedAttributeInput {

compiler/rustc_lint_defs/src/builtin.rs

-39
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ declare_lint_pass! {
143143
UNUSED_VARIABLES,
144144
USELESS_DEPRECATED,
145145
WARNINGS,
146-
WASM_C_ABI,
147146
// tidy-alphabetical-end
148147
]
149148
}
@@ -4647,44 +4646,6 @@ declare_lint! {
46474646
};
46484647
}
46494648

4650-
declare_lint! {
4651-
/// The `wasm_c_abi` lint detects crate dependencies that are incompatible
4652-
/// with future versions of Rust that will emit spec-compliant C ABI.
4653-
///
4654-
/// ### Example
4655-
///
4656-
/// ```rust,ignore (needs extern crate)
4657-
/// #![deny(wasm_c_abi)]
4658-
/// ```
4659-
///
4660-
/// This will produce:
4661-
///
4662-
/// ```text
4663-
/// error: the following packages contain code that will be rejected by a future version of Rust: wasm-bindgen v0.2.87
4664-
/// |
4665-
/// note: the lint level is defined here
4666-
/// --> src/lib.rs:1:9
4667-
/// |
4668-
/// 1 | #![deny(wasm_c_abi)]
4669-
/// | ^^^^^^^^^^
4670-
/// ```
4671-
///
4672-
/// ### Explanation
4673-
///
4674-
/// Rust has historically emitted non-spec-compliant C ABI. This has caused
4675-
/// incompatibilities between other compilers and Wasm targets. In a future
4676-
/// version of Rust this will be fixed and therefore dependencies relying
4677-
/// on the non-spec-compliant C ABI will stop functioning.
4678-
pub WASM_C_ABI,
4679-
Deny,
4680-
"detects dependencies that are incompatible with the Wasm C ABI",
4681-
@future_incompatible = FutureIncompatibleInfo {
4682-
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
4683-
reference: "issue #71871 <https://github.com/rust-lang/rust/issues/71871>",
4684-
};
4685-
crate_level_only
4686-
}
4687-
46884649
declare_lint! {
46894650
/// The `uncovered_param_in_projection` lint detects a violation of one of Rust's orphan rules for
46904651
/// foreign trait implementations that concerns the use of type parameters inside trait associated

compiler/rustc_lint_defs/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,6 @@ pub enum BuiltinLintDiag {
783783
extern_crate: Symbol,
784784
local_crate: Symbol,
785785
},
786-
WasmCAbi,
787786
IllFormedAttributeInput {
788787
suggestions: Vec<String>,
789788
},

compiler/rustc_metadata/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@ metadata_unsupported_abi =
290290
metadata_unsupported_abi_i686 =
291291
ABI not supported by `#[link(kind = "raw-dylib")]` on i686
292292
293+
metadata_wasm_c_abi =
294+
older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88
295+
293296
metadata_wasm_import_form =
294297
wasm import module must be of the form `wasm_import_module = "string"`
295298

compiler/rustc_metadata/src/creader.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -1076,12 +1076,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
10761076
// Make a point span rather than covering the whole file
10771077
let span = krate.spans.inner_span.shrink_to_lo();
10781078

1079-
self.sess.psess.buffer_lint(
1080-
lint::builtin::WASM_C_ABI,
1081-
span,
1082-
ast::CRATE_NODE_ID,
1083-
BuiltinLintDiag::WasmCAbi,
1084-
);
1079+
self.sess.dcx().emit_err(errors::WasmCAbi { span });
10851080
}
10861081
}
10871082

compiler/rustc_metadata/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -732,3 +732,10 @@ pub struct ImportNameTypeRaw {
732732
#[primary_span]
733733
pub span: Span,
734734
}
735+
736+
#[derive(Diagnostic)]
737+
#[diag(metadata_wasm_c_abi)]
738+
pub(crate) struct WasmCAbi {
739+
#[primary_span]
740+
pub span: Span,
741+
}

0 commit comments

Comments
 (0)