Skip to content

Rollup of 19 pull requests #145195

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 49 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
30721b0
Add stubs for environment variables; document some of the important ones
jyn514 May 27, 2025
a383fb0
asm: Stabilize loongarch32
heiher Jan 9, 2025
90bb5ca
moved 34 tests to organized locations
Kivooeo Jul 24, 2025
7bd902d
Start reporting future breakage for `ILL_FORMED_ATTRIBUTE_INPUT` in d…
JonathanBrouwer Jul 27, 2025
d9b725a
Improve error output when a command fails in bootstrap
Kobzol Aug 8, 2025
43327b5
switch polonius compare-mode to polonius=next
lqd Feb 14, 2025
f4094ea
update test expectations for boring locals + dropckoutlives interactions
lqd Mar 24, 2025
a5adde8
simplify polonius=next
lqd Aug 8, 2025
1330898
new impl fixes crash test
lqd Jun 16, 2025
d4bbd68
turn expensive assert into debug assertion
lqd Jun 18, 2025
b172980
add some test cases for overlapping yielded items
lqd Jun 26, 2025
48ebae9
add NLL-like imprecision example
lqd Jun 26, 2025
9badbdf
add cursor-like example that works
lqd Jun 26, 2025
b99fe2b
mark polonius=next's NLL imprecisions as known-bugs
lqd Aug 8, 2025
dcc1605
[win][arm64ec] Partial fix for raw-dylib-link-ordinal on Arm64EC
dpaoliello Aug 8, 2025
87a09b2
[win][arm64ec] Add '/machine:arm64ec' when linking LLVM as Arm64EC
dpaoliello Aug 8, 2025
339be84
Use new public libtest `ERROR_EXIT_CODE` constant in rustdoc
GuillaumeGomez Jul 31, 2025
2736d66
rename `TraitRef::from_method` to `from_assoc`
fee1-dead Aug 9, 2025
b5e2ba6
Stabilize feature
Kivooeo Aug 8, 2025
f777067
Port `#[allow_internal_unsafe]` to the new attribute system (attempt 2)
scrabsha Aug 3, 2025
a5ddf5d
Override custom Cargo `build-dir` in bootstrap
Kobzol Aug 9, 2025
1676563
comments
Kivooeo Jul 24, 2025
ca1e464
Change days-threshold to 28 in [behind-upstream]
xizheyin Aug 9, 2025
71f6e53
some `derive_more` refactors
fee1-dead Aug 9, 2025
f4d3dd0
Apply suggestions from code review
jyn514 Aug 9, 2025
6de338b
Enable limit_rdylib_exports on Solaris
bjorn3 Aug 9, 2025
a59842e
improve "Documentation problem" issue template.
lolbinarycat Aug 8, 2025
c0a3e48
`{BTree,Hash}Map`: add "`Entry` API" section heading
ada4a Aug 9, 2025
06e4365
`HashMap`: also add "Usage with custom key types" heading
ada4a Aug 9, 2025
feed41c
Fix an unstable feature comment that wasn't a doc comment
joshtriplett Aug 9, 2025
4dc54f1
Rollup merge of #141624 - jyn514:env-var-stubs, r=BoxyUwU
Zalathar Aug 10, 2025
d6ce399
Rollup merge of #143093 - lqd:polonius-pre-alpha, r=jackh726
Zalathar Aug 10, 2025
450a161
Rollup merge of #144402 - heiher:stabilize-loong32-asm, r=Amanieu
Zalathar Aug 10, 2025
5d85cc2
Rollup merge of #144403 - Kivooeo:issue4, r=jieyouxu
Zalathar Aug 10, 2025
bef70d5
Rollup merge of #144544 - JonathanBrouwer:illformed-in-deps, r=travis…
Zalathar Aug 10, 2025
a10e87c
Rollup merge of #144739 - GuillaumeGomez:rustdoc-test-cleanup, r=fmease
Zalathar Aug 10, 2025
4f744a4
Rollup merge of #145089 - Kobzol:bootstrap-cmd-error, r=jieyouxu
Zalathar Aug 10, 2025
305be1f
Rollup merge of #145112 - dpaoliello:raw-dylib-link-ordinal, r=jieyouxu
Zalathar Aug 10, 2025
b31f255
Rollup merge of #145129 - dpaoliello:arm64eclink, r=wesleywiser
Zalathar Aug 10, 2025
c7abdfc
Rollup merge of #145130 - lolbinarycat:issue-template-docs-update, r=…
Zalathar Aug 10, 2025
2d0fcd7
Rollup merge of #145135 - Kivooeo:stabilize-duration_constructors_lit…
Zalathar Aug 10, 2025
398a365
Rollup merge of #145145 - fee1-dead-contrib:push-qnmpmtmtpkkr, r=jiey…
Zalathar Aug 10, 2025
1bc62da
Rollup merge of #145147 - fee1-dead-contrib:push-mxxpmlpmzmsz, r=comp…
Zalathar Aug 10, 2025
5de397d
Rollup merge of #145155 - scrabsha:push-tkvwkolzooyq, r=jdonszelmann
Zalathar Aug 10, 2025
006c750
Rollup merge of #145156 - Kobzol:cargo-build-dir, r=lqd,jieyouxu
Zalathar Aug 10, 2025
fb0b788
Rollup merge of #145160 - xizheyin:behind-upstream, r=Urgau
Zalathar Aug 10, 2025
296f2ae
Rollup merge of #145162 - ada4a:hash_and_btree_map-add-entry-section,…
Zalathar Aug 10, 2025
d54db8f
Rollup merge of #145175 - bjorn3:solaris_limit_rdylib_exports, r=lqd
Zalathar Aug 10, 2025
d0af528
Rollup merge of #145187 - joshtriplett:fix-unstable-feature-comment, …
Zalathar Aug 10, 2025
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
12 changes: 6 additions & 6 deletions .github/ISSUE_TEMPLATE/documentation.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Documentation problem
description: Create a report for a documentation problem.
description: Report an issue with documentation content.
labels: ["A-docs"]
body:
- type: markdown
Expand All @@ -19,20 +19,20 @@ body:
- [The Rustonomicon](https://github.com/rust-lang/nomicon/issues)
- [The Embedded Book](https://github.com/rust-embedded/book/issues)
All other documentation issues should be filed here.
Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the rustdoc issue template instead.
Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead.
All other documentation issues should be filed here.
- type: textarea
id: location
attributes:
label: Location
label: Location (URL)
validations:
required: true
required: true

- type: textarea
id: summary
attributes:
label: Summary
validations:
required: true
required: true
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
| asm::InlineAsmArch::Arm64EC
| asm::InlineAsmArch::RiscV32
| asm::InlineAsmArch::RiscV64
| asm::InlineAsmArch::LoongArch32
| asm::InlineAsmArch::LoongArch64
| asm::InlineAsmArch::S390x
);
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,11 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser {
Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state })
}
}

pub(crate) struct AllowInternalUnsafeParser;

impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
const PATH: &[Symbol] = &[sym::allow_internal_unsafe];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
}
5 changes: 4 additions & 1 deletion compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ use crate::attributes::lint_helpers::{
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
};
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
use crate::attributes::macro_attrs::{MacroEscapeParser, MacroUseParser};
use crate::attributes::macro_attrs::{
AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser,
};
use crate::attributes::must_use::MustUseParser;
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
use crate::attributes::non_exhaustive::NonExhaustiveParser;
Expand Down Expand Up @@ -178,6 +180,7 @@ attribute_parsers!(
Single<SkipDuringMethodDispatchParser>,
Single<TransparencyParser>,
Single<WithoutArgs<AllowIncoherentImplParser>>,
Single<WithoutArgs<AllowInternalUnsafeParser>>,
Single<WithoutArgs<AsPtrParser>>,
Single<WithoutArgs<AutomaticallyDerivedParser>>,
Single<WithoutArgs<CoherenceIsCoreParser>>,
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_borrowck/src/polonius/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use rustc_mir_dataflow::points::PointIndex;
///
/// This models two sources of constraints:
/// - constraints that traverse the subsets between regions at a given point, `a@p: b@p`. These
/// depend on typeck constraints generated via assignments, calls, etc. (In practice there are
/// subtleties where a statement's effect only starts being visible at the successor point, via
/// the "result" of that statement).
/// depend on typeck constraints generated via assignments, calls, etc.
/// - constraints that traverse the CFG via the same region, `a@p: a@q`, where `p` is a predecessor
/// of `q`. These depend on the liveness of the regions at these points, as well as their
/// variance.
Expand Down
12 changes: 2 additions & 10 deletions compiler/rustc_borrowck/src/polonius/liveness_constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,14 @@ fn propagate_loans_between_points(
});
}

let Some(current_live_regions) = live_regions.row(current_point) else {
// There are no constraints to add: there are no live regions at the current point.
return;
};
let Some(next_live_regions) = live_regions.row(next_point) else {
// There are no constraints to add: there are no live regions at the next point.
return;
};

for region in next_live_regions.iter() {
if !current_live_regions.contains(region) {
continue;
}

// `region` is indeed live at both points, add a constraint between them, according to
// variance.
// `region` could be live at the current point, and is live at the next point: add a
// constraint between them, according to variance.
if let Some(&direction) = live_region_variances.get(&region) {
add_liveness_constraint(
region,
Expand Down
191 changes: 22 additions & 169 deletions compiler/rustc_borrowck/src/polonius/loan_liveness.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,25 @@
use std::collections::{BTreeMap, BTreeSet};

use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{
Body, Local, Location, Place, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
};
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_middle::ty::RegionVid;
use rustc_mir_dataflow::points::PointIndex;

use super::{LiveLoans, LocalizedOutlivesConstraintSet};
use crate::BorrowSet;
use crate::constraints::OutlivesConstraint;
use crate::dataflow::BorrowIndex;
use crate::region_infer::values::LivenessValues;
use crate::type_check::Locations;
use crate::{BorrowSet, PlaceConflictBias, places_conflict};

/// Compute loan reachability, stop at kills, and trace loan liveness throughout the CFG, by
/// Compute loan reachability to approximately trace loan liveness throughout the CFG, by
/// traversing the full graph of constraints that combines:
/// - the localized constraints (the physical edges),
/// - with the constraints that hold at all points (the logical edges).
pub(super) fn compute_loan_liveness<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
liveness: &LivenessValues,
outlives_constraints: impl Iterator<Item = OutlivesConstraint<'tcx>>,
borrow_set: &BorrowSet<'tcx>,
localized_outlives_constraints: &LocalizedOutlivesConstraintSet,
) -> LiveLoans {
let mut live_loans = LiveLoans::new(borrow_set.len());

// FIXME: it may be preferable for kills to be encoded in the edges themselves, to simplify and
// likely make traversal (and constraint generation) more efficient. We also display kills on
// edges when visualizing the constraint graph anyways.
let kills = collect_kills(body, tcx, borrow_set);

// Create the full graph with the physical edges we've localized earlier, and the logical edges
// of constraints that hold at all points.
let logical_constraints =
Expand All @@ -59,15 +45,15 @@ pub(super) fn compute_loan_liveness<'tcx>(
continue;
}

// Record the loan as being live on entry to this point.
live_loans.insert(node.point, loan_idx);

// Here, we have a conundrum. There's currently a weakness in our theory, in that
// we're using a single notion of reachability to represent what used to be _two_
// different transitive closures. It didn't seem impactful when coming up with the
// single-graph and reachability through space (regions) + time (CFG) concepts, but in
// practice the combination of time-traveling with kills is more impactful than
// initially anticipated.
// Record the loan as being live on entry to this point if it reaches a live region
// there.
//
// This is an approximation of liveness (which is the thing we want), in that we're
// using a single notion of reachability to represent what used to be _two_ different
// transitive closures. It didn't seem impactful when coming up with the single-graph
// and reachability through space (regions) + time (CFG) concepts, but in practice the
// combination of time-traveling with kills is more impactful than initially
// anticipated.
//
// Kills should prevent a loan from reaching its successor points in the CFG, but not
// while time-traveling: we're not actually at that CFG point, but looking for
Expand All @@ -92,40 +78,20 @@ pub(super) fn compute_loan_liveness<'tcx>(
// two-step traversal described above: only kills encountered on exit via a backward
// edge are ignored.
//
// In our test suite, there are a couple of cases where kills are encountered while
// time-traveling, however as far as we can tell, always in cases where they would be
// unreachable. We have reason to believe that this is a property of the single-graph
// approach (but haven't proved it yet):
// - reachable kills while time-traveling would also be encountered via regular
// traversal
// - it makes _some_ sense to ignore unreachable kills, but subtleties around dead code
// in general need to be better thought through (like they were for NLLs).
// - ignoring kills is a conservative approximation: the loan is still live and could
// cause false positive errors at another place access. Soundness issues in this
// domain should look more like the absence of reachability instead.
//
// This is enough in practice to pass tests, and therefore is what we have implemented
// for now.
// This version of the analysis, however, is enough in practice to pass the tests that
// we care about and NLLs reject, without regressions on crater, and is an actionable
// subset of the full analysis. It also naturally points to areas of improvement that we
// wish to explore later, namely handling kills appropriately during traversal, instead
// of continuing traversal to all the reachable nodes.
//
// FIXME: all of the above. Analyze potential unsoundness, possibly in concert with a
// borrowck implementation in a-mir-formality, fuzzing, or manually crafting
// counter-examples.
// FIXME: analyze potential unsoundness, possibly in concert with a borrowck
// implementation in a-mir-formality, fuzzing, or manually crafting counter-examples.

// Continuing traversal will depend on whether the loan is killed at this point, and
// whether we're time-traveling.
let current_location = liveness.location_from_point(node.point);
let is_loan_killed =
kills.get(&current_location).is_some_and(|kills| kills.contains(&loan_idx));
if liveness.is_live_at(node.region, liveness.location_from_point(node.point)) {
live_loans.insert(node.point, loan_idx);
}

for succ in graph.outgoing_edges(node) {
// If the loan is killed at this point, it is killed _on exit_. But only during
// forward traversal.
if is_loan_killed {
let destination = liveness.location_from_point(succ.point);
if current_location.is_predecessor_of(destination, body) {
continue;
}
}
stack.push(succ);
}
}
Expand Down Expand Up @@ -192,116 +158,3 @@ impl LocalizedConstraintGraph {
physical_edges.chain(materialized_edges)
}
}

/// Traverses the MIR and collects kills.
fn collect_kills<'tcx>(
body: &Body<'tcx>,
tcx: TyCtxt<'tcx>,
borrow_set: &BorrowSet<'tcx>,
) -> BTreeMap<Location, BTreeSet<BorrowIndex>> {
let mut collector = KillsCollector { borrow_set, tcx, body, kills: BTreeMap::default() };
for (block, data) in body.basic_blocks.iter_enumerated() {
collector.visit_basic_block_data(block, data);
}
collector.kills
}

struct KillsCollector<'a, 'tcx> {
body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
borrow_set: &'a BorrowSet<'tcx>,

/// The set of loans killed at each location.
kills: BTreeMap<Location, BTreeSet<BorrowIndex>>,
}

// This visitor has a similar structure to the `Borrows` dataflow computation with respect to kills,
// and the datalog polonius fact generation for the `loan_killed_at` relation.
impl<'tcx> KillsCollector<'_, 'tcx> {
/// Records the borrows on the specified place as `killed`. For example, when assigning to a
/// local, or on a call's return destination.
fn record_killed_borrows_for_place(&mut self, place: Place<'tcx>, location: Location) {
// For the reasons described in graph traversal, we also filter out kills
// unreachable from the loan's introduction point, as they would stop traversal when
// e.g. checking for reachability in the subset graph through invariance constraints
// higher up.
let filter_unreachable_kills = |loan| {
let introduction = self.borrow_set[loan].reserve_location;
let reachable = introduction.is_predecessor_of(location, self.body);
reachable
};

let other_borrows_of_local = self
.borrow_set
.local_map
.get(&place.local)
.into_iter()
.flat_map(|bs| bs.iter())
.copied();

// If the borrowed place is a local with no projections, all other borrows of this
// local must conflict. This is purely an optimization so we don't have to call
// `places_conflict` for every borrow.
if place.projection.is_empty() {
if !self.body.local_decls[place.local].is_ref_to_static() {
self.kills
.entry(location)
.or_default()
.extend(other_borrows_of_local.filter(|&loan| filter_unreachable_kills(loan)));
}
return;
}

// By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given
// pair of array indices are not equal, so that when `places_conflict` returns true, we
// will be assured that two places being compared definitely denotes the same sets of
// locations.
let definitely_conflicting_borrows = other_borrows_of_local
.filter(|&i| {
places_conflict(
self.tcx,
self.body,
self.borrow_set[i].borrowed_place,
place,
PlaceConflictBias::NoOverlap,
)
})
.filter(|&loan| filter_unreachable_kills(loan));

self.kills.entry(location).or_default().extend(definitely_conflicting_borrows);
}

/// Records the borrows on the specified local as `killed`.
fn record_killed_borrows_for_local(&mut self, local: Local, location: Location) {
if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
self.kills.entry(location).or_default().extend(borrow_indices.iter());
}
}
}

impl<'tcx> Visitor<'tcx> for KillsCollector<'_, 'tcx> {
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
// Make sure there are no remaining borrows for locals that have gone out of scope.
if let StatementKind::StorageDead(local) = statement.kind {
self.record_killed_borrows_for_local(local, location);
}

self.super_statement(statement, location);
}

fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
// When we see `X = ...`, then kill borrows of `(*X).foo` and so forth.
self.record_killed_borrows_for_place(*place, location);
self.super_assign(place, rvalue, location);
}

fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
// A `Call` terminator's return value can be a local which has borrows, so we need to record
// those as killed as well.
if let TerminatorKind::Call { destination, .. } = terminator.kind {
self.record_killed_borrows_for_place(destination, location);
}

self.super_terminator(terminator, location);
}
}
6 changes: 2 additions & 4 deletions compiler/rustc_borrowck/src/polonius/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ impl PoloniusContext {
/// - converting NLL typeck constraints to be localized
/// - encoding liveness constraints
///
/// Then, this graph is traversed, and combined with kills, reachability is recorded as loan
/// liveness, to be used by the loan scope and active loans computations.
/// Then, this graph is traversed, reachability is recorded as loan liveness, to be used by the
/// loan scope and active loans computations.
///
/// The constraint data will be used to compute errors and diagnostics.
pub(crate) fn compute_loan_liveness<'tcx>(
Expand Down Expand Up @@ -182,8 +182,6 @@ impl PoloniusContext {
// Now that we have a complete graph, we can compute reachability to trace the liveness of
// loans for the next step in the chain, the NLL loan scope and active loans computations.
let live_loans = compute_loan_liveness(
tcx,
body,
regioncx.liveness_constraints(),
regioncx.outlives_constraints(),
borrow_set,
Expand Down
Loading
Loading