Skip to content

Commit cf7e3ed

Browse files
authored
Merge branch 'rust-lang:master' into patch-7
2 parents e07e70a + b22856d commit cf7e3ed

File tree

99 files changed

+1509
-371
lines changed

Some content is hidden

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

99 files changed

+1509
-371
lines changed

Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,9 @@ version = "0.1.0"
405405

406406
[[package]]
407407
name = "cc"
408-
version = "1.2.0"
408+
version = "1.2.5"
409409
source = "registry+https://github.com/rust-lang/crates.io-index"
410-
checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
410+
checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e"
411411
dependencies = [
412412
"shlex",
413413
]

compiler/rustc_ast_pretty/src/pprust/state.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1204,8 +1204,10 @@ impl<'a> State<'a> {
12041204
}
12051205
ast::TyKind::Path(Some(qself), path) => self.print_qpath(path, qself, false),
12061206
ast::TyKind::TraitObject(bounds, syntax) => {
1207-
if *syntax == ast::TraitObjectSyntax::Dyn {
1208-
self.word_nbsp("dyn");
1207+
match syntax {
1208+
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
1209+
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
1210+
ast::TraitObjectSyntax::None => {}
12091211
}
12101212
self.print_type_bounds(bounds);
12111213
}

compiler/rustc_borrowck/src/lib.rs

+11
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ fn do_mir_borrowck<'tcx>(
202202
polonius_output,
203203
opt_closure_req,
204204
nll_errors,
205+
localized_outlives_constraints,
205206
} = nll::compute_regions(
206207
&infcx,
207208
free_regions,
@@ -315,6 +316,16 @@ fn do_mir_borrowck<'tcx>(
315316

316317
mbcx.report_move_errors();
317318

319+
// If requested, dump polonius MIR.
320+
polonius::dump_polonius_mir(
321+
&infcx,
322+
body,
323+
&regioncx,
324+
&borrow_set,
325+
localized_outlives_constraints,
326+
&opt_closure_req,
327+
);
328+
318329
// For each non-user used mutable variable, check if it's been assigned from
319330
// a user-declared local. If so, then put that local into the used_mut set.
320331
// Note that this set is expected to be small - only upvars from closures

compiler/rustc_borrowck/src/nll.rs

+60-34
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use crate::consumers::ConsumerOptions;
2929
use crate::diagnostics::RegionErrors;
3030
use crate::facts::{AllFacts, AllFactsExt, RustcFacts};
3131
use crate::location::LocationTable;
32+
use crate::polonius::LocalizedOutlivesConstraintSet;
3233
use crate::region_infer::RegionInferenceContext;
3334
use crate::type_check::{self, MirTypeckResults};
3435
use crate::universal_regions::UniversalRegions;
@@ -45,6 +46,9 @@ pub(crate) struct NllOutput<'tcx> {
4546
pub polonius_output: Option<Box<PoloniusOutput>>,
4647
pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
4748
pub nll_errors: RegionErrors<'tcx>,
49+
50+
/// When using `-Zpolonius=next`: the localized typeck and liveness constraints.
51+
pub localized_outlives_constraints: Option<LocalizedOutlivesConstraintSet>,
4852
}
4953

5054
/// Rewrites the regions in the MIR to use NLL variables, also scraping out the set of universal
@@ -135,6 +139,15 @@ pub(crate) fn compute_regions<'a, 'tcx>(
135139
elements,
136140
);
137141

142+
// If requested for `-Zpolonius=next`, convert NLL constraints to localized outlives
143+
// constraints.
144+
let localized_outlives_constraints =
145+
if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
146+
Some(polonius::create_localized_constraints(&mut regioncx, body))
147+
} else {
148+
None
149+
};
150+
138151
// If requested: dump NLL facts, and run legacy polonius analysis.
139152
let polonius_output = all_facts.as_ref().and_then(|all_facts| {
140153
if infcx.tcx.sess.opts.unstable_opts.nll_facts {
@@ -175,6 +188,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
175188
polonius_output,
176189
opt_closure_req: closure_region_requirements,
177190
nll_errors,
191+
localized_outlives_constraints,
178192
}
179193
}
180194

@@ -215,40 +229,7 @@ pub(super) fn dump_nll_mir<'tcx>(
215229
&0,
216230
body,
217231
|pass_where, out| {
218-
match pass_where {
219-
// Before the CFG, dump out the values for each region variable.
220-
PassWhere::BeforeCFG => {
221-
regioncx.dump_mir(tcx, out)?;
222-
writeln!(out, "|")?;
223-
224-
if let Some(closure_region_requirements) = closure_region_requirements {
225-
writeln!(out, "| Free Region Constraints")?;
226-
for_each_region_constraint(tcx, closure_region_requirements, &mut |msg| {
227-
writeln!(out, "| {msg}")
228-
})?;
229-
writeln!(out, "|")?;
230-
}
231-
232-
if borrow_set.len() > 0 {
233-
writeln!(out, "| Borrows")?;
234-
for (borrow_idx, borrow_data) in borrow_set.iter_enumerated() {
235-
writeln!(
236-
out,
237-
"| {:?}: issued at {:?} in {:?}",
238-
borrow_idx, borrow_data.reserve_location, borrow_data.region
239-
)?;
240-
}
241-
writeln!(out, "|")?;
242-
}
243-
}
244-
245-
PassWhere::BeforeLocation(_) => {}
246-
247-
PassWhere::AfterTerminator(_) => {}
248-
249-
PassWhere::BeforeBlock(_) | PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
250-
}
251-
Ok(())
232+
emit_nll_mir(tcx, regioncx, closure_region_requirements, borrow_set, pass_where, out)
252233
},
253234
options,
254235
);
@@ -266,6 +247,51 @@ pub(super) fn dump_nll_mir<'tcx>(
266247
};
267248
}
268249

250+
/// Produces the actual NLL MIR sections to emit during the dumping process.
251+
pub(crate) fn emit_nll_mir<'tcx>(
252+
tcx: TyCtxt<'tcx>,
253+
regioncx: &RegionInferenceContext<'tcx>,
254+
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
255+
borrow_set: &BorrowSet<'tcx>,
256+
pass_where: PassWhere,
257+
out: &mut dyn io::Write,
258+
) -> io::Result<()> {
259+
match pass_where {
260+
// Before the CFG, dump out the values for each region variable.
261+
PassWhere::BeforeCFG => {
262+
regioncx.dump_mir(tcx, out)?;
263+
writeln!(out, "|")?;
264+
265+
if let Some(closure_region_requirements) = closure_region_requirements {
266+
writeln!(out, "| Free Region Constraints")?;
267+
for_each_region_constraint(tcx, closure_region_requirements, &mut |msg| {
268+
writeln!(out, "| {msg}")
269+
})?;
270+
writeln!(out, "|")?;
271+
}
272+
273+
if borrow_set.len() > 0 {
274+
writeln!(out, "| Borrows")?;
275+
for (borrow_idx, borrow_data) in borrow_set.iter_enumerated() {
276+
writeln!(
277+
out,
278+
"| {:?}: issued at {:?} in {:?}",
279+
borrow_idx, borrow_data.reserve_location, borrow_data.region
280+
)?;
281+
}
282+
writeln!(out, "|")?;
283+
}
284+
}
285+
286+
PassWhere::BeforeLocation(_) => {}
287+
288+
PassWhere::AfterTerminator(_) => {}
289+
290+
PassWhere::BeforeBlock(_) | PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
291+
}
292+
Ok(())
293+
}
294+
269295
#[allow(rustc::diagnostic_outside_of_impl)]
270296
#[allow(rustc::untranslatable_diagnostic)]
271297
pub(super) fn dump_annotation<'tcx, 'infcx>(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use rustc_middle::ty::RegionVid;
2+
use rustc_mir_dataflow::points::PointIndex;
3+
4+
/// A localized outlives constraint reifies the CFG location where the outlives constraint holds,
5+
/// within the origins themselves as if they were different from point to point: from `a: b`
6+
/// outlives constraints to `a@p: b@p`, where `p` is the point in the CFG.
7+
///
8+
/// This models two sources of constraints:
9+
/// - constraints that traverse the subsets between regions at a given point, `a@p: b@p`. These
10+
/// depend on typeck constraints generated via assignments, calls, etc. (In practice there are
11+
/// subtleties where a statement's effect only starts being visible at the successor point, via
12+
/// the "result" of that statement).
13+
/// - constraints that traverse the CFG via the same region, `a@p: a@q`, where `p` is a predecessor
14+
/// of `q`. These depend on the liveness of the regions at these points, as well as their
15+
/// variance.
16+
///
17+
/// The `source` origin at `from` flows into the `target` origin at `to`.
18+
///
19+
/// This dual of NLL's [crate::constraints::OutlivesConstraint] therefore encodes the
20+
/// position-dependent outlives constraints used by Polonius, to model the flow-sensitive loan
21+
/// propagation via reachability within a graph of localized constraints.
22+
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
23+
pub(crate) struct LocalizedOutlivesConstraint {
24+
pub source: RegionVid,
25+
pub from: PointIndex,
26+
pub target: RegionVid,
27+
pub to: PointIndex,
28+
}
29+
30+
/// A container of [LocalizedOutlivesConstraint]s that can be turned into a traversable
31+
/// `rustc_data_structures` graph.
32+
#[derive(Clone, Default, Debug)]
33+
pub(crate) struct LocalizedOutlivesConstraintSet {
34+
pub outlives: Vec<LocalizedOutlivesConstraint>,
35+
}
36+
37+
impl LocalizedOutlivesConstraintSet {
38+
pub(crate) fn push(&mut self, constraint: LocalizedOutlivesConstraint) {
39+
if constraint.source == constraint.target && constraint.from == constraint.to {
40+
// 'a@p: 'a@p is pretty uninteresting
41+
return;
42+
}
43+
self.outlives.push(constraint);
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
use std::io;
2+
3+
use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
4+
use rustc_middle::mir::{Body, ClosureRegionRequirements, PassWhere};
5+
use rustc_middle::ty::TyCtxt;
6+
use rustc_session::config::MirIncludeSpans;
7+
8+
use crate::borrow_set::BorrowSet;
9+
use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet};
10+
use crate::{BorrowckInferCtxt, RegionInferenceContext};
11+
12+
/// `-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.
16+
pub(crate) fn dump_polonius_mir<'tcx>(
17+
infcx: &BorrowckInferCtxt<'tcx>,
18+
body: &Body<'tcx>,
19+
regioncx: &RegionInferenceContext<'tcx>,
20+
borrow_set: &BorrowSet<'tcx>,
21+
localized_outlives_constraints: Option<LocalizedOutlivesConstraintSet>,
22+
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
23+
) {
24+
let tcx = infcx.tcx;
25+
if !tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
26+
return;
27+
}
28+
29+
let localized_outlives_constraints = localized_outlives_constraints
30+
.expect("missing localized constraints with `-Zpolonius=next`");
31+
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 options = PrettyPrintMirOptions {
36+
include_extra_comments: matches!(
37+
tcx.sess.opts.unstable_opts.mir_include_spans,
38+
MirIncludeSpans::On | MirIncludeSpans::Nll
39+
),
40+
};
41+
42+
dump_mir_with_options(
43+
tcx,
44+
false,
45+
"polonius",
46+
&0,
47+
body,
48+
|pass_where, out| {
49+
emit_polonius_mir(
50+
tcx,
51+
regioncx,
52+
closure_region_requirements,
53+
borrow_set,
54+
&localized_outlives_constraints,
55+
pass_where,
56+
out,
57+
)
58+
},
59+
options,
60+
);
61+
}
62+
63+
/// Produces the actual NLL + Polonius MIR sections to emit during the dumping process.
64+
fn emit_polonius_mir<'tcx>(
65+
tcx: TyCtxt<'tcx>,
66+
regioncx: &RegionInferenceContext<'tcx>,
67+
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
68+
borrow_set: &BorrowSet<'tcx>,
69+
localized_outlives_constraints: &LocalizedOutlivesConstraintSet,
70+
pass_where: PassWhere,
71+
out: &mut dyn io::Write,
72+
) -> io::Result<()> {
73+
// Emit the regular NLL front-matter
74+
crate::nll::emit_nll_mir(
75+
tcx,
76+
regioncx,
77+
closure_region_requirements,
78+
borrow_set,
79+
pass_where.clone(),
80+
out,
81+
)?;
82+
83+
let liveness = regioncx.liveness_constraints();
84+
85+
// Add localized outlives constraints
86+
match pass_where {
87+
PassWhere::BeforeCFG => {
88+
if localized_outlives_constraints.outlives.len() > 0 {
89+
writeln!(out, "| Localized constraints")?;
90+
91+
for constraint in &localized_outlives_constraints.outlives {
92+
let LocalizedOutlivesConstraint { source, from, target, to } = constraint;
93+
let from = liveness.location_from_point(*from);
94+
let to = liveness.location_from_point(*to);
95+
writeln!(out, "| {source:?} at {from:?} -> {target:?} at {to:?}")?;
96+
}
97+
writeln!(out, "|")?;
98+
}
99+
}
100+
_ => {}
101+
}
102+
103+
Ok(())
104+
}

0 commit comments

Comments
 (0)