Skip to content

Commit

Permalink
Auto merge of #120187 - Nadrieril:rollup-xfwrb0c, r=Nadrieril
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - #116090 (Implement strict integer operations that panic on overflow)
 - #118811 (Use `bool` instead of `PartiolOrd` as return value of the comparison closure in `{slice,Iteraotr}::is_sorted_by`)
 - #119081 (Add Ipv6Addr::is_ipv4_mapped)
 - #119461 (Use an interpreter in MIR jump threading)
 - #119996 (Move OS String implementation into `sys`)
 - #120015 (coverage: Format all coverage tests with `rustfmt`)
 - #120027 (pattern_analysis: Remove `Ty: Copy` bound)
 - #120084 (fix(rust-analyzer): use new pkgid spec to compare)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 21, 2024
2 parents 867d39c + 01669d2 commit cb25c5b
Show file tree
Hide file tree
Showing 111 changed files with 1,687 additions and 421 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1130,7 +1130,7 @@ fn collect_non_exhaustive_tys<'tcx>(
non_exhaustive_tys.insert(pat.ty().inner());
}
if let Constructor::IntRange(range) = pat.ctor() {
if cx.is_range_beyond_boundaries(range, pat.ty()) {
if cx.is_range_beyond_boundaries(range, *pat.ty()) {
// The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`.
non_exhaustive_tys.insert(pat.ty().inner());
}
Expand Down
262 changes: 155 additions & 107 deletions compiler/rustc_mir_transform/src/jump_threading.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions compiler/rustc_monomorphize/src/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ where
}

// Ensure CGUs are sorted by name, so that we get deterministic results.
if !codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))) {
if !codegen_units.is_sorted_by(|a, b| a.name().as_str() <= b.name().as_str()) {
let mut names = String::new();
for cgu in codegen_units.iter() {
names += &format!("- {}\n", cgu.name());
Expand Down Expand Up @@ -317,7 +317,7 @@ fn merge_codegen_units<'tcx>(
assert!(cx.tcx.sess.codegen_units().as_usize() >= 1);

// A sorted order here ensures merging is deterministic.
assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))));
assert!(codegen_units.is_sorted_by(|a, b| a.name().as_str() <= b.name().as_str()));

// This map keeps track of what got merged into what.
let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_pattern_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl<'a, T: ?Sized> Captures<'a> for T {}
/// Most of the crate is parameterized on a type that implements this trait.
pub trait TypeCx: Sized + fmt::Debug {
/// The type of a pattern.
type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy
type Ty: Clone + fmt::Debug;
/// Errors that can abort analysis.
type Error: fmt::Debug;
/// The index of an enum variant.
Expand All @@ -97,16 +97,16 @@ pub trait TypeCx: Sized + fmt::Debug {
fn is_exhaustive_patterns_feature_on(&self) -> bool;

/// The number of fields for this constructor.
fn ctor_arity(&self, ctor: &Constructor<Self>, ty: Self::Ty) -> usize;
fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;

/// The types of the fields for this constructor. The result must have a length of
/// `ctor_arity()`.
fn ctor_sub_tys(&self, ctor: &Constructor<Self>, ty: Self::Ty) -> &[Self::Ty];
fn ctor_sub_tys(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> &[Self::Ty];

/// The set of all the constructors for `ty`.
///
/// This must follow the invariants of `ConstructorSet`
fn ctors_for_ty(&self, ty: Self::Ty) -> Result<ConstructorSet<Self>, Self::Error>;
fn ctors_for_ty(&self, ty: &Self::Ty) -> Result<ConstructorSet<Self>, Self::Error>;

/// Best-effort `Debug` implementation.
fn debug_pat(f: &mut fmt::Formatter<'_>, pat: &DeconstructedPat<'_, Self>) -> fmt::Result;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_pattern_analysis/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
}

fn head_ty(&self) -> Option<RevealedTy<'tcx>> {
self.patterns.first().map(|pat| pat.ty())
self.patterns.first().map(|pat| *pat.ty())
}

/// Do constructor splitting on the constructors of the column.
Expand Down Expand Up @@ -101,7 +101,7 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
let Some(ty) = column.head_ty() else {
return Ok(Vec::new());
};
let pcx = &PlaceCtxt::new_dummy(cx, ty);
let pcx = &PlaceCtxt::new_dummy(cx, &ty);

let set = column.analyze_ctors(pcx)?;
if set.present.is_empty() {
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_pattern_analysis/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
pub fn ctor(&self) -> &Constructor<Cx> {
&self.ctor
}
pub fn ty(&self) -> Cx::Ty {
self.ty
pub fn ty(&self) -> &Cx::Ty {
&self.ty
}
/// Returns the extra data stored in a pattern. Returns `None` if the pattern is a wildcard that
/// does not correspond to a user-supplied pattern.
Expand Down Expand Up @@ -242,15 +242,15 @@ impl<Cx: TypeCx> WitnessPat<Cx> {
/// `Some(_)`.
pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor<Cx>) -> Self {
let field_tys = pcx.ctor_sub_tys(&ctor);
let fields = field_tys.iter().map(|ty| Self::wildcard(*ty)).collect();
Self::new(ctor, fields, pcx.ty)
let fields = field_tys.iter().cloned().map(|ty| Self::wildcard(ty)).collect();
Self::new(ctor, fields, pcx.ty.clone())
}

pub fn ctor(&self) -> &Constructor<Cx> {
&self.ctor
}
pub fn ty(&self) -> Cx::Ty {
self.ty
pub fn ty(&self) -> &Cx::Ty {
&self.ty
}

pub fn iter_fields(&self) -> impl Iterator<Item = &WitnessPat<Cx>> {
Expand Down
20 changes: 10 additions & 10 deletions compiler/rustc_pattern_analysis/src/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
let mut subpatterns = pat.iter_fields().map(|p| Box::new(cx.hoist_witness_pat(p)));
let kind = match pat.ctor() {
Bool(b) => PatKind::Constant { value: mir::Const::from_bool(cx.tcx, *b) },
IntRange(range) => return self.hoist_pat_range(range, pat.ty()),
IntRange(range) => return self.hoist_pat_range(range, *pat.ty()),
Struct | Variant(_) | UnionField => match pat.ty().kind() {
ty::Tuple(..) => PatKind::Leaf {
subpatterns: subpatterns
Expand All @@ -785,7 +785,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
RustcMatchCheckCtxt::variant_index_for_adt(&pat.ctor(), *adt_def);
let variant = &adt_def.variant(variant_index);
let subpatterns = cx
.list_variant_nonhidden_fields(pat.ty(), variant)
.list_variant_nonhidden_fields(*pat.ty(), variant)
.zip(subpatterns)
.map(|((field, _ty), pattern)| FieldPat { field, pattern })
.collect();
Expand All @@ -796,7 +796,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
PatKind::Leaf { subpatterns }
}
}
_ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), pat.ty()),
_ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), *pat.ty()),
},
// Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
// be careful to reconstruct the correct constant pattern here. However a string
Expand Down Expand Up @@ -961,21 +961,21 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
self.tcx.features().exhaustive_patterns
}

fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: Self::Ty) -> usize {
self.ctor_arity(ctor, ty)
fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize {
self.ctor_arity(ctor, *ty)
}
fn ctor_sub_tys(
&self,
ctor: &crate::constructor::Constructor<Self>,
ty: Self::Ty,
ty: &Self::Ty,
) -> &[Self::Ty] {
self.ctor_sub_tys(ctor, ty)
self.ctor_sub_tys(ctor, *ty)
}
fn ctors_for_ty(
&self,
ty: Self::Ty,
ty: &Self::Ty,
) -> Result<crate::constructor::ConstructorSet<Self>, Self::Error> {
self.ctors_for_ty(ty)
self.ctors_for_ty(*ty)
}

fn debug_pat(
Expand All @@ -994,7 +994,7 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
overlaps_on: IntRange,
overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>],
) {
let overlap_as_pat = self.hoist_pat_range(&overlaps_on, pat.ty());
let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty());
let overlaps: Vec<_> = overlaps_with
.iter()
.map(|pat| pat.data().unwrap().span)
Expand Down
17 changes: 9 additions & 8 deletions compiler/rustc_pattern_analysis/src/usefulness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,13 +736,14 @@ pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> {
#[derivative(Debug = "ignore")]
pub(crate) mcx: MatchCtxt<'a, Cx>,
/// Type of the place under investigation.
pub(crate) ty: Cx::Ty,
#[derivative(Clone(clone_with = "Clone::clone"))] // See rust-derivative#90
pub(crate) ty: &'a Cx::Ty,
}

impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> {
/// A `PlaceCtxt` when code other than `is_useful` needs one.
#[cfg_attr(not(feature = "rustc"), allow(dead_code))]
pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: Cx::Ty) -> Self {
pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: &'a Cx::Ty) -> Self {
PlaceCtxt { mcx, ty }
}

Expand Down Expand Up @@ -1023,8 +1024,8 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
matrix
}

fn head_ty(&self) -> Option<Cx::Ty> {
self.place_ty.first().copied()
fn head_ty(&self) -> Option<&Cx::Ty> {
self.place_ty.first()
}
fn column_count(&self) -> usize {
self.place_ty.len()
Expand Down Expand Up @@ -1058,7 +1059,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
let ctor_sub_tys = pcx.ctor_sub_tys(ctor);
let arity = ctor_sub_tys.len();
let specialized_place_ty =
ctor_sub_tys.iter().chain(self.place_ty[1..].iter()).copied().collect();
ctor_sub_tys.iter().chain(self.place_ty[1..].iter()).cloned().collect();
let ctor_sub_validity = self.place_validity[0].specialize(ctor);
let specialized_place_validity = std::iter::repeat(ctor_sub_validity)
.take(arity)
Expand Down Expand Up @@ -1214,7 +1215,7 @@ impl<Cx: TypeCx> WitnessStack<Cx> {
let len = self.0.len();
let arity = ctor.arity(pcx);
let fields = self.0.drain((len - arity)..).rev().collect();
let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty);
let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone());
self.0.push(pat);
}
}
Expand Down Expand Up @@ -1410,7 +1411,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
return Ok(WitnessMatrix::empty());
}

let Some(ty) = matrix.head_ty() else {
let Some(ty) = matrix.head_ty().cloned() else {
// The base case: there are no columns in the matrix. We are morally pattern-matching on ().
// A row is useful iff it has no (unguarded) rows above it.
let mut useful = true; // Whether the next row is useful.
Expand All @@ -1431,7 +1432,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
};

debug!("ty: {ty:?}");
let pcx = &PlaceCtxt { mcx, ty };
let pcx = &PlaceCtxt { mcx, ty: &ty };
let ctors_for_ty = pcx.ctors_for_ty()?;

// Whether the place/column we are inspecting is known to contain valid data.
Expand Down
26 changes: 13 additions & 13 deletions library/core/src/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4033,42 +4033,42 @@ pub trait Iterator {
Self: Sized,
Self::Item: PartialOrd,
{
self.is_sorted_by(PartialOrd::partial_cmp)
self.is_sorted_by(|a, b| a <= b)
}

/// Checks if the elements of this iterator are sorted using the given comparator function.
///
/// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare`
/// function to determine the ordering of two elements. Apart from that, it's equivalent to
/// [`is_sorted`]; see its documentation for more information.
/// function to determine whether two elements are to be considered in sorted order.
///
/// # Examples
///
/// ```
/// #![feature(is_sorted)]
///
/// assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// assert!(![1, 3, 2, 4].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// assert!([0].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| a.partial_cmp(b)));
/// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// ```
/// assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a <= b));
/// assert!(![1, 2, 2, 9].iter().is_sorted_by(|a, b| a < b));
///
/// [`is_sorted`]: Iterator::is_sorted
/// assert!([0].iter().is_sorted_by(|a, b| true));
/// assert!([0].iter().is_sorted_by(|a, b| false));
///
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| false));
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| true));
/// ```
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
#[rustc_do_not_const_check]
fn is_sorted_by<F>(mut self, compare: F) -> bool
where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>,
F: FnMut(&Self::Item, &Self::Item) -> bool,
{
#[inline]
fn check<'a, T>(
last: &'a mut T,
mut compare: impl FnMut(&T, &T) -> Option<Ordering> + 'a,
mut compare: impl FnMut(&T, &T) -> bool + 'a,
) -> impl FnMut(T) -> bool + 'a {
move |curr| {
if let Some(Ordering::Greater) | None = compare(&last, &curr) {
if !compare(&last, &curr) {
return false;
}
*last = curr;
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
#![feature(const_slice_ptr_len)]
#![feature(const_slice_split_at_mut)]
#![feature(const_str_from_utf8_unchecked_mut)]
#![feature(const_strict_overflow_ops)]
#![feature(const_swap)]
#![feature(const_try)]
#![feature(const_type_id)]
Expand Down
25 changes: 25 additions & 0 deletions library/core/src/net/ip_addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1785,6 +1785,31 @@ impl Ipv6Addr {
(self.segments()[0] & 0xff00) == 0xff00
}

/// Returns [`true`] if the address is an IPv4-mapped address (`::ffff:0:0/96`).
///
/// IPv4-mapped addresses can be converted to their canonical IPv4 address with
/// [`to_ipv4_mapped`](Ipv6Addr::to_ipv4_mapped).
///
/// # Examples
/// ```
/// #![feature(ip)]
///
/// use std::net::{Ipv4Addr, Ipv6Addr};
///
/// let ipv4_mapped = Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped();
/// assert_eq!(ipv4_mapped.is_ipv4_mapped(), true);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff).is_ipv4_mapped(), true);
///
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_ipv4_mapped(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
#[unstable(feature = "ip", issue = "27709")]
#[must_use]
#[inline]
pub const fn is_ipv4_mapped(&self) -> bool {
matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
}

/// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address,
/// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
///
Expand Down
Loading

0 comments on commit cb25c5b

Please sign in to comment.