Skip to content

Commit

Permalink
Auto merge of rust-lang#120401 - matthiaskrgr:rollup-7740vrx, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 12 pull requests

Successful merges:

 - rust-lang#103522 (stabilise array methods)
 - rust-lang#113489 (impl `From<&[T; N]>` for `Cow<[T]>`)
 - rust-lang#119342 (Emit suggestion when trying to write exclusive ranges as `..<`)
 - rust-lang#119562 (Rename `pointer` field on `Pin`)
 - rust-lang#119800 (Document `rustc_index::vec::IndexVec`)
 - rust-lang#120205 (std: make `HEAP` initializer never inline)
 - rust-lang#120277 (Normalize field types before checking validity)
 - rust-lang#120311 (core: add `From<core::ascii::Char>` implementations)
 - rust-lang#120366 (mark a doctest with UB as no_run)
 - rust-lang#120378 (always normalize `LoweredTy` in the new solver)
 - rust-lang#120382 (Classify closure arguments in refutable pattern in argument error)
 - rust-lang#120389 (Add fmease to the compiler review rotation)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 27, 2024
2 parents c073f56 + 6ce96c0 commit b362939
Show file tree
Hide file tree
Showing 45 changed files with 324 additions and 106 deletions.
23 changes: 14 additions & 9 deletions compiler/rustc_const_eval/src/transform/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,13 +810,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
let adt_def = self.tcx.adt_def(def_id);
assert!(adt_def.is_union());
assert_eq!(idx, FIRST_VARIANT);
let dest = adt_def.non_enum_variant().fields[field].ty(self.tcx, args);
if fields.len() != 1 {
let dest_ty = self.tcx.normalize_erasing_regions(
self.param_env,
adt_def.non_enum_variant().fields[field].ty(self.tcx, args),
);
if fields.len() == 1 {
let src_ty = fields.raw[0].ty(self.body, self.tcx);
if !self.mir_assign_valid_types(src_ty, dest_ty) {
self.fail(location, "union field has the wrong type");
}
} else {
self.fail(location, "unions should have one initialized field");
}
if !self.mir_assign_valid_types(fields.raw[0].ty(self.body, self.tcx), dest) {
self.fail(location, "union field has the wrong type");
}
}
AggregateKind::Adt(def_id, idx, args, _, None) => {
let adt_def = self.tcx.adt_def(def_id);
Expand All @@ -826,10 +831,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail(location, "adt has the wrong number of initialized fields");
}
for (src, dest) in std::iter::zip(fields, &variant.fields) {
if !self.mir_assign_valid_types(
src.ty(self.body, self.tcx),
dest.ty(self.tcx, args),
) {
let dest_ty = self
.tcx
.normalize_erasing_regions(self.param_env, dest.ty(self.tcx, args));
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest_ty) {
self.fail(location, "adt field has the wrong type");
}
}
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,14 @@ pub struct LoweredTy<'tcx> {

impl<'tcx> LoweredTy<'tcx> {
pub fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> {
LoweredTy { raw, normalized: fcx.normalize(span, raw) }
// FIXME(-Znext-solver): We're still figuring out how to best handle
// normalization and this doesn't feel too great. We should look at this
// code again before stabilizing it.
let normalized = if fcx.next_trait_solver() {
fcx.try_structurally_resolve_type(span, raw)
} else {
fcx.normalize(span, raw)
};
LoweredTy { raw, normalized }
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2040,7 +2040,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let field_is_local = sole_field.did.is_local();
let field_is_accessible =
sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
// Skip suggestions for unstable public fields (for example `Pin::pointer`)
// Skip suggestions for unstable public fields (for example `Pin::__pointer`)
&& matches!(self.tcx.eval_stability(sole_field.did, None, expr.span, None), EvalResult::Allow | EvalResult::Unmarked);

if !field_is_local && !field_is_accessible {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_index/src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ use std::vec;
use crate::{Idx, IndexSlice};

/// An owned contiguous collection of `T`s, indexed by `I` rather than by `usize`.
/// Its purpose is to avoid mixing indexes.
///
/// While it's possible to use `u32` or `usize` directly for `I`,
/// you almost certainly want to use a [`newtype_index!`]-generated type instead.
///
/// This allows to index the IndexVec with the new index type.
///
/// [`newtype_index!`]: ../macro.newtype_index.html
#[derive(Clone, PartialEq, Eq, Hash)]
#[repr(transparent)]
Expand All @@ -25,11 +28,13 @@ pub struct IndexVec<I: Idx, T> {
}

impl<I: Idx, T> IndexVec<I, T> {
/// Constructs a new, empty `IndexVec<I, T>`.
#[inline]
pub const fn new() -> Self {
IndexVec::from_raw(Vec::new())
}

/// Constructs a new `IndexVec<I, T>` from a `Vec<T>`.
#[inline]
pub const fn from_raw(raw: Vec<T>) -> Self {
IndexVec { raw, _marker: PhantomData }
Expand Down Expand Up @@ -59,6 +64,7 @@ impl<I: Idx, T> IndexVec<I, T> {
IndexVec::from_raw(vec![elem; universe.len()])
}

/// Creates a new IndexVec with n copies of the `elem`.
#[inline]
pub fn from_elem_n(elem: T, n: usize) -> Self
where
Expand All @@ -85,6 +91,7 @@ impl<I: Idx, T> IndexVec<I, T> {
IndexSlice::from_raw_mut(&mut self.raw)
}

/// Pushes an element to the array returning the index where it was pushed to.
#[inline]
pub fn push(&mut self, d: T) -> I {
let idx = self.next_index();
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,18 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err
};
visitor.visit_expr(&thir[expr]);

let origin = match tcx.def_kind(def_id) {
DefKind::AssocFn | DefKind::Fn => "function argument",
DefKind::Closure => "closure argument",
// other types of MIR don't have function parameters, and we don't need to
// categorize those for the irrefutable check.
_ if thir.params.is_empty() => "",
kind => bug!("unexpected function parameters in THIR: {kind:?} {def_id:?}"),
};

for param in thir.params.iter() {
if let Some(box ref pattern) = param.pat {
visitor.check_binding_is_irrefutable(pattern, "function argument", None, None);
visitor.check_binding_is_irrefutable(pattern, origin, None, None);
}
}
visitor.error
Expand Down
25 changes: 20 additions & 5 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::parser;
use crate::parser::attr::InnerAttrPolicy;
use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind};
use rustc_ast::tokenstream::AttrTokenTree;
use rustc_ast::util::parser::AssocOp;
use rustc_ast::{
Expand Down Expand Up @@ -448,12 +448,11 @@ impl<'a> Parser<'a> {
})
}

let mut expected = edible
self.expected_tokens.extend(edible.iter().chain(inedible).cloned().map(TokenType::Token));
let mut expected = self
.expected_tokens
.iter()
.chain(inedible)
.cloned()
.map(TokenType::Token)
.chain(self.expected_tokens.iter().cloned())
.filter(|token| {
// Filter out suggestions that suggest the same token which was found and deemed incorrect.
fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
Expand Down Expand Up @@ -2927,6 +2926,22 @@ impl<'a> Parser<'a> {
Ok(())
}

/// Check for exclusive ranges written as `..<`
pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: PErr<'a>) -> PErr<'a> {
if maybe_lt == token::Lt
&& (self.expected_tokens.contains(&TokenType::Token(token::Gt))
|| matches!(self.token.kind, token::Literal(..)))
{
err.span_suggestion(
maybe_lt.span,
"remove the `<` to write an exclusive range",
"",
Applicability::MachineApplicable,
);
}
err
}

pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool {
(0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
&& self.look_ahead(3, |tok| tok == short_kind)
Expand Down
10 changes: 8 additions & 2 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,11 @@ impl<'a> Parser<'a> {
cur_op_span: Span,
) -> PResult<'a, P<Expr>> {
let rhs = if self.is_at_start_of_range_notation_rhs() {
Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?)
let maybe_lt = self.token.clone();
Some(
self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)
.map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?,
)
} else {
None
};
Expand Down Expand Up @@ -531,11 +535,13 @@ impl<'a> Parser<'a> {
let attrs = self.parse_or_use_outer_attributes(attrs)?;
self.collect_tokens_for_expr(attrs, |this, attrs| {
let lo = this.token.span;
let maybe_lt = this.look_ahead(1, |t| t.clone());
this.bump();
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
// RHS must be parsed with more associativity than the dots.
this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
.map(|x| (lo.to(x.span), Some(x)))?
.map(|x| (lo.to(x.span), Some(x)))
.map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
} else {
(lo, None)
};
Expand Down
1 change: 0 additions & 1 deletion library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@
#![feature(allocator_api)]
#![feature(array_chunks)]
#![feature(array_into_iter_constructors)]
#![feature(array_methods)]
#![feature(array_windows)]
#![feature(ascii_char)]
#![feature(assert_matches)]
Expand Down
13 changes: 13 additions & 0 deletions library/alloc/src/vec/cow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
}
}

#[stable(feature = "cow_from_array_ref", since = "CURRENT_RUSTC_VERSION")]
impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> {
/// Creates a [`Borrowed`] variant of [`Cow`]
/// from a reference to an array.
///
/// This conversion does not allocate or clone the data.
///
/// [`Borrowed`]: crate::borrow::Cow::Borrowed
fn from(s: &'a [T; N]) -> Cow<'a, [T]> {
Cow::Borrowed(s as &[_])
}
}

#[stable(feature = "cow_from_vec", since = "1.8.0")]
impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> {
/// Creates an [`Owned`] variant of [`Cow`]
Expand Down
9 changes: 2 additions & 7 deletions library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,6 @@ impl<T, const N: usize> [T; N] {
/// # Example
///
/// ```
/// #![feature(array_methods)]
///
/// let floats = [3.1, 2.7, -1.0];
/// let float_refs: [&f64; 3] = floats.each_ref();
/// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]);
Expand All @@ -571,16 +569,14 @@ impl<T, const N: usize> [T; N] {
/// array if its elements are not [`Copy`].
///
/// ```
/// #![feature(array_methods)]
///
/// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
/// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
/// assert_eq!(is_ascii, [true, false, true]);
///
/// // We can still access the original array: it has not been moved.
/// assert_eq!(strings.len(), 3);
/// ```
#[unstable(feature = "array_methods", issue = "76118")]
#[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")]
pub fn each_ref(&self) -> [&T; N] {
from_trusted_iterator(self.iter())
}
Expand All @@ -592,15 +588,14 @@ impl<T, const N: usize> [T; N] {
/// # Example
///
/// ```
/// #![feature(array_methods)]
///
/// let mut floats = [3.1, 2.7, -1.0];
/// let float_refs: [&mut f64; 3] = floats.each_mut();
/// *float_refs[0] = 0.0;
/// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]);
/// assert_eq!(floats, [0.0, 2.7, -1.0]);
/// ```
#[unstable(feature = "array_methods", issue = "76118")]
#[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")]
pub fn each_mut(&mut self) -> [&mut T; N] {
from_trusted_iterator(self.iter_mut())
}
Expand Down
16 changes: 16 additions & 0 deletions library/core/src/ascii/ascii_char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,22 @@ impl AsciiChar {
}
}

macro_rules! into_int_impl {
($($ty:ty)*) => {
$(
#[unstable(feature = "ascii_char", issue = "110998")]
impl From<AsciiChar> for $ty {
#[inline]
fn from(chr: AsciiChar) -> $ty {
chr as u8 as $ty
}
}
)*
}
}

into_int_impl!(u8 u16 u32 u64 u128 char);

impl [AsciiChar] {
/// Views this slice of ASCII characters as a UTF-8 `str`.
#[unstable(feature = "ascii_char", issue = "110998")]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2531,7 +2531,7 @@ extern "rust-intrinsic" {
/// or `false`, and the caller has to ensure sound behavior for both cases.
/// In other words, the following code has *Undefined Behavior*:
///
/// ```
/// ```no_run
/// #![feature(is_val_statically_known)]
/// #![feature(core_intrinsics)]
/// # #![allow(internal_features)]
Expand Down
Loading

0 comments on commit b362939

Please sign in to comment.