Skip to content

Rollup of 7 pull requests #135682

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

Merged
merged 19 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6ad9c1d
Run clippy for rustc_codegen_gcc
Kobzol Jan 14, 2025
efe8888
Move `std::pipe::*` into `std::io`
NobodyXu Jan 16, 2025
7874ba2
add tidy check on dist src files order
onur-ozkan Jan 17, 2025
fdf4924
include `x` and `x.ps1` scripts in tarball sources
onur-ozkan Jan 17, 2025
0114a97
make `LocalizedConstraintGraph` a struct and not an alias
lqd Jan 9, 2025
dee52a3
encode `Locations::All` typeck constraints as logical edges
lqd Jan 9, 2025
5f49515
ci: mirror buildkit image to ghcr
marcoieni Jan 17, 2025
81d70f9
Fix import of pipe in kernel_copy.rs
NobodyXu Jan 16, 2025
2af4197
Fix use of pipe in tests/run-make/broken-pipe-no-ice/rmake.rs
NobodyXu Jan 17, 2025
366ceca
Stabilize `float_next_up_down`
tgross35 Jan 17, 2025
809f61a
Add references to the IEEE functions for `float_next_up_down`
tgross35 Jan 17, 2025
e1dda10
const-eval: detect more pointers as definitely not-null
RalfJung Dec 1, 2024
b78edd7
Rollup merge of #133700 - RalfJung:const-non-null, r=lcnr
matthiaskrgr Jan 18, 2025
56447d7
Rollup merge of #135290 - lqd:polonius-next-episode-8, r=jackh726
matthiaskrgr Jan 18, 2025
86947bb
Rollup merge of #135478 - Kobzol:gcc-clippy, r=onur-ozkan
matthiaskrgr Jan 18, 2025
508c72b
Rollup merge of #135583 - NobodyXu:move-pipe-to-io, r=joshtriplett
matthiaskrgr Jan 18, 2025
b0d0ec4
Rollup merge of #135612 - onur-ozkan:include-x-scripts-in-tarballs, r…
matthiaskrgr Jan 18, 2025
0553681
Rollup merge of #135624 - marcoieni:mirror-buildkit-image, r=Kobzol
matthiaskrgr Jan 18, 2025
23fb4f2
Rollup merge of #135661 - tgross35:stabilize-float_next_up_down, r=sc…
matthiaskrgr Jan 18, 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
23 changes: 17 additions & 6 deletions .github/workflows/ghcr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,21 @@ jobs:

- name: Mirror DockerHub
run: |
# DockerHub image we want to mirror
image="ubuntu:22.04"
# List of DockerHub images to mirror to ghcr.io
images=(
# Mirrored because used by the mingw-check-tidy, which doesn't cache Docker images
"ubuntu:22.04"
# Mirrored because used by all linux CI jobs, including mingw-check-tidy
"moby/buildkit:buildx-stable-1"
)

# Mirror image from DockerHub to ghcr.io
./crane copy \
docker.io/${image} \
ghcr.io/${{ github.repository_owner }}/${image}
# Mirror each image from DockerHub to ghcr.io
for img in "${images[@]}"; do
echo "Mirroring ${img}..."
# Remove namespace from the image if any.
# E.g. "moby/buildkit:buildx-stable-1" becomes "buildkit:buildx-stable-1"
dest_image=$(echo "${img}" | cut -d'/' -f2-)
./crane copy \
"docker.io/${img}" \
"ghcr.io/${{ github.repository_owner }}/${dest_image}"
done
83 changes: 60 additions & 23 deletions compiler/rustc_borrowck/src/polonius/loan_liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,21 @@ use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_mir_dataflow::points::PointIndex;

use super::{LiveLoans, LocalizedOutlivesConstraintSet};
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};

/// With the full graph of constraints, we can compute loan reachability, stop at kills, and trace
/// loan liveness throughout the CFG.
/// Compute loan reachability, stop at kills, and 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 {
Expand All @@ -29,7 +34,11 @@ pub(super) fn compute_loan_liveness<'tcx>(
// edges when visualizing the constraint graph anyways.
let kills = collect_kills(body, tcx, borrow_set);

let graph = index_constraints(&localized_outlives_constraints);
// 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 =
outlives_constraints.filter(|c| matches!(c.locations, Locations::All(_)));
let graph = LocalizedConstraintGraph::new(&localized_outlives_constraints, logical_constraints);
let mut visited = FxHashSet::default();
let mut stack = Vec::new();

Expand Down Expand Up @@ -108,7 +117,7 @@ pub(super) fn compute_loan_liveness<'tcx>(
let is_loan_killed =
kills.get(&current_location).is_some_and(|kills| kills.contains(&loan_idx));

for succ in outgoing_edges(&graph, node) {
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 {
Expand All @@ -125,9 +134,17 @@ pub(super) fn compute_loan_liveness<'tcx>(
live_loans
}

/// The localized constraint graph is currently the per-node map of its physical edges. In the
/// future, we'll add logical edges to model constraints that hold at all points in the CFG.
type LocalizedConstraintGraph = FxHashMap<LocalizedNode, FxIndexSet<LocalizedNode>>;
/// The localized constraint graph indexes the physical and logical edges to compute a given node's
/// successors during traversal.
struct LocalizedConstraintGraph {
/// The actual, physical, edges we have recorded for a given node.
edges: FxHashMap<LocalizedNode, FxIndexSet<LocalizedNode>>,

/// The logical edges representing the outlives constraints that hold at all points in the CFG,
/// which we don't localize to avoid creating a lot of unnecessary edges in the graph. Some CFGs
/// can be big, and we don't need to create such a physical edge for every point in the CFG.
logical_edges: FxHashMap<RegionVid, FxIndexSet<RegionVid>>,
}

/// A node in the graph to be traversed, one of the two vertices of a localized outlives constraint.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
Expand All @@ -136,24 +153,44 @@ struct LocalizedNode {
point: PointIndex,
}

/// Traverses the constraints and returns the indexable graph of edges per node.
fn index_constraints(constraints: &LocalizedOutlivesConstraintSet) -> LocalizedConstraintGraph {
let mut edges = LocalizedConstraintGraph::default();
for constraint in &constraints.outlives {
let source = LocalizedNode { region: constraint.source, point: constraint.from };
let target = LocalizedNode { region: constraint.target, point: constraint.to };
edges.entry(source).or_default().insert(target);
}
impl LocalizedConstraintGraph {
/// Traverses the constraints and returns the indexed graph of edges per node.
fn new<'tcx>(
constraints: &LocalizedOutlivesConstraintSet,
logical_constraints: impl Iterator<Item = OutlivesConstraint<'tcx>>,
) -> Self {
let mut edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default();
for constraint in &constraints.outlives {
let source = LocalizedNode { region: constraint.source, point: constraint.from };
let target = LocalizedNode { region: constraint.target, point: constraint.to };
edges.entry(source).or_default().insert(target);
}

edges
}
let mut logical_edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default();
for constraint in logical_constraints {
logical_edges.entry(constraint.sup).or_default().insert(constraint.sub);
}

LocalizedConstraintGraph { edges, logical_edges }
}

/// Returns the outgoing edges of a given node, not its transitive closure.
fn outgoing_edges(
graph: &LocalizedConstraintGraph,
node: LocalizedNode,
) -> impl Iterator<Item = LocalizedNode> + use<'_> {
graph.get(&node).into_iter().flat_map(|edges| edges.iter().copied())
/// Returns the outgoing edges of a given node, not its transitive closure.
fn outgoing_edges(&self, node: LocalizedNode) -> impl Iterator<Item = LocalizedNode> + use<'_> {
// The outgoing edges are:
// - the physical edges present at this node,
// - the materialized logical edges that exist virtually at all points for this node's
// region, localized at this point.
let physical_edges =
self.edges.get(&node).into_iter().flat_map(|targets| targets.iter().copied());
let materialized_edges =
self.logical_edges.get(&node.region).into_iter().flat_map(move |targets| {
targets
.iter()
.copied()
.map(move |target| LocalizedNode { point: node.point, region: target })
});
physical_edges.chain(materialized_edges)
}
}

/// Traverses the MIR and collects kills.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/polonius/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ impl PoloniusContext {
tcx,
body,
regioncx.liveness_constraints(),
regioncx.outlives_constraints(),
borrow_set,
&localized_outlives_constraints,
);
Expand Down
22 changes: 5 additions & 17 deletions compiler/rustc_borrowck/src/polonius/typeck_constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,11 @@ pub(super) fn convert_typeck_constraints<'tcx>(
for outlives_constraint in outlives_constraints {
match outlives_constraint.locations {
Locations::All(_) => {
// For now, turn logical constraints holding at all points into physical edges at
// every point in the graph.
// FIXME: encode this into *traversal* instead.
for (block, bb) in body.basic_blocks.iter_enumerated() {
let statement_count = bb.statements.len();
for statement_index in 0..=statement_count {
let current_location = Location { block, statement_index };
let current_point = liveness.point_from_location(current_location);

localized_outlives_constraints.push(LocalizedOutlivesConstraint {
source: outlives_constraint.sup,
from: current_point,
target: outlives_constraint.sub,
to: current_point,
});
}
}
// We don't turn constraints holding at all points into physical edges at every
// point in the graph. They are encoded into *traversal* instead: a given node's
// successors will combine these logical edges with the regular, physical, localized
// edges.
continue;
}

Locations::Single(location) => {
Expand Down
25 changes: 17 additions & 8 deletions compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1481,22 +1481,31 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Test if this value might be null.
/// If the machine does not support ptr-to-int casts, this is conservative.
pub fn scalar_may_be_null(&self, scalar: Scalar<M::Provenance>) -> InterpResult<'tcx, bool> {
interp_ok(match scalar.try_to_scalar_int() {
Ok(int) => int.is_null(),
match scalar.try_to_scalar_int() {
Ok(int) => interp_ok(int.is_null()),
Err(_) => {
// Can only happen during CTFE.
// We can't cast this pointer to an integer. Can only happen during CTFE.
let ptr = scalar.to_pointer(self)?;
match self.ptr_try_get_alloc_id(ptr, 0) {
Ok((alloc_id, offset, _)) => {
let size = self.get_alloc_info(alloc_id).size;
// If the pointer is out-of-bounds, it may be null.
// Note that one-past-the-end (offset == size) is still inbounds, and never null.
offset > size
let info = self.get_alloc_info(alloc_id);
// If the pointer is in-bounds (including "at the end"), it is definitely not null.
if offset <= info.size {
return interp_ok(false);
}
// If the allocation is N-aligned, and the offset is not divisible by N,
// then `base + offset` has a non-zero remainder after division by `N`,
// which means `base + offset` cannot be null.
if offset.bytes() % info.align.bytes() != 0 {
return interp_ok(false);
}
// We don't know enough, this might be null.
interp_ok(true)
}
Err(_offset) => bug!("a non-int scalar is always a pointer"),
}
}
})
}
}

/// Turning a "maybe pointer" into a proper pointer (and some information
Expand Down
10 changes: 6 additions & 4 deletions library/core/src/num/f128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,6 @@ impl f128 {
///
/// ```rust
/// #![feature(f128)]
/// #![feature(float_next_up_down)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
///
Expand All @@ -516,13 +515,15 @@ impl f128 {
/// # }
/// ```
///
/// This operation corresponds to IEEE-754 `nextUp`.
///
/// [`NEG_INFINITY`]: Self::NEG_INFINITY
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[inline]
#[doc(alias = "nextUp")]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_up(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
Expand Down Expand Up @@ -558,7 +559,6 @@ impl f128 {
///
/// ```rust
/// #![feature(f128)]
/// #![feature(float_next_up_down)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
///
Expand All @@ -570,13 +570,15 @@ impl f128 {
/// # }
/// ```
///
/// This operation corresponds to IEEE-754 `nextDown`.
///
/// [`NEG_INFINITY`]: Self::NEG_INFINITY
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[inline]
#[doc(alias = "nextDown")]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_down(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
Expand Down
10 changes: 6 additions & 4 deletions library/core/src/num/f16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,6 @@ impl f16 {
///
/// ```rust
/// #![feature(f16)]
/// #![feature(float_next_up_down)]
/// # // FIXME(f16_f128): ABI issues on MSVC
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
///
Expand All @@ -509,13 +508,15 @@ impl f16 {
/// # }
/// ```
///
/// This operation corresponds to IEEE-754 `nextUp`.
///
/// [`NEG_INFINITY`]: Self::NEG_INFINITY
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[inline]
#[doc(alias = "nextUp")]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_up(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
Expand Down Expand Up @@ -551,7 +552,6 @@ impl f16 {
///
/// ```rust
/// #![feature(f16)]
/// #![feature(float_next_up_down)]
/// # // FIXME(f16_f128): ABI issues on MSVC
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
///
Expand All @@ -563,13 +563,15 @@ impl f16 {
/// # }
/// ```
///
/// This operation corresponds to IEEE-754 `nextDown`.
///
/// [`NEG_INFINITY`]: Self::NEG_INFINITY
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[inline]
#[doc(alias = "nextDown")]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_down(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
Expand Down
14 changes: 10 additions & 4 deletions library/core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,20 +726,23 @@ impl f32 {
/// is finite `x == x.next_up().next_down()` also holds.
///
/// ```rust
/// #![feature(float_next_up_down)]
/// // f32::EPSILON is the difference between 1.0 and the next number up.
/// assert_eq!(1.0f32.next_up(), 1.0 + f32::EPSILON);
/// // But not for most numbers.
/// assert!(0.1f32.next_up() < 0.1 + f32::EPSILON);
/// assert_eq!(16777216f32.next_up(), 16777218.0);
/// ```
///
/// This operation corresponds to IEEE-754 `nextUp`.
///
/// [`NEG_INFINITY`]: Self::NEG_INFINITY
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[inline]
#[unstable(feature = "float_next_up_down", issue = "91399")]
#[doc(alias = "nextUp")]
#[stable(feature = "float_next_up_down", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "float_next_up_down", since = "CURRENT_RUSTC_VERSION")]
pub const fn next_up(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
Expand Down Expand Up @@ -774,20 +777,23 @@ impl f32 {
/// is finite `x == x.next_down().next_up()` also holds.
///
/// ```rust
/// #![feature(float_next_up_down)]
/// let x = 1.0f32;
/// // Clamp value into range [0, 1).
/// let clamped = x.clamp(0.0, 1.0f32.next_down());
/// assert!(clamped < 1.0);
/// assert_eq!(clamped.next_up(), 1.0);
/// ```
///
/// This operation corresponds to IEEE-754 `nextDown`.
///
/// [`NEG_INFINITY`]: Self::NEG_INFINITY
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[inline]
#[unstable(feature = "float_next_up_down", issue = "91399")]
#[doc(alias = "nextDown")]
#[stable(feature = "float_next_up_down", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "float_next_up_down", since = "CURRENT_RUSTC_VERSION")]
pub const fn next_down(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
Expand Down
Loading
Loading