Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 1fc46f3

Browse files
committed
Auto merge of rust-lang#120365 - matthiaskrgr:rollup-ly2w0d5, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#107464 (Add `str::Lines::remainder`) - rust-lang#118803 (Add the `min_exhaustive_patterns` feature gate) - rust-lang#119466 (Initial implementation of `str::from_raw_parts[_mut]`) - rust-lang#120053 (Specialize `Bytes` on `StdinLock<'_>`) - rust-lang#120124 (Split assembly tests for ELF and MachO) - rust-lang#120204 (Builtin macros effectively have implicit #[collapse_debuginfo(yes)]) - rust-lang#120322 (Don't manually resolve async closures in `rustc_resolve`) - rust-lang#120356 (Fix broken markdown in csky-unknown-linux-gnuabiv2.md) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 69db514 + ee2a2a3 commit 1fc46f3

File tree

21 files changed

+999
-245
lines changed

21 files changed

+999
-245
lines changed

compiler/rustc_expand/src/base.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,9 +796,15 @@ impl SyntaxExtension {
796796
/// | external | no | if-ext | if-ext | yes |
797797
/// | yes | yes | yes | yes | yes |
798798
fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool {
799-
let collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
799+
let mut collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
800800
.map(|v| Self::collapse_debuginfo_by_name(sess, v))
801801
.unwrap_or(CollapseMacroDebuginfo::Unspecified);
802+
if collapse_debuginfo_attr == CollapseMacroDebuginfo::Unspecified
803+
&& attr::contains_name(attrs, sym::rustc_builtin_macro)
804+
{
805+
collapse_debuginfo_attr = CollapseMacroDebuginfo::Yes;
806+
}
807+
802808
let flag = sess.opts.unstable_opts.collapse_macro_debuginfo;
803809
let attr = collapse_debuginfo_attr;
804810
let ext = !is_local;

compiler/rustc_feature/src/unstable.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,9 @@ declare_features! (
516516
(unstable, macro_metavar_expr, "1.61.0", Some(83527)),
517517
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
518518
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
519+
/// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are
520+
/// unambiguously sound.
521+
(incomplete, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)),
519522
/// A minimal, sound subset of specialization intended to be used by the
520523
/// standard library until the soundness issues with specialization
521524
/// are fixed.

compiler/rustc_pattern_analysis/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub trait TypeCx: Sized + fmt::Debug {
9595
type PatData: Clone;
9696

9797
fn is_exhaustive_patterns_feature_on(&self) -> bool;
98+
fn is_min_exhaustive_patterns_feature_on(&self) -> bool;
9899

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

compiler/rustc_pattern_analysis/src/rustc.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
181181
// `field.ty()` doesn't normalize after substituting.
182182
let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
183183
let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
184-
let is_uninhabited = cx.tcx.features().exhaustive_patterns && cx.is_uninhabited(ty);
184+
let is_uninhabited = (cx.tcx.features().exhaustive_patterns
185+
|| cx.tcx.features().min_exhaustive_patterns)
186+
&& cx.is_uninhabited(ty);
185187

186188
if is_uninhabited && (!is_visible || is_non_exhaustive) {
187189
None
@@ -863,6 +865,9 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
863865
fn is_exhaustive_patterns_feature_on(&self) -> bool {
864866
self.tcx.features().exhaustive_patterns
865867
}
868+
fn is_min_exhaustive_patterns_feature_on(&self) -> bool {
869+
self.tcx.features().min_exhaustive_patterns
870+
}
866871

867872
fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize {
868873
self.ctor_arity(ctor, *ty)

compiler/rustc_pattern_analysis/src/usefulness.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -548,11 +548,12 @@
548548
//! [`ValidityConstraint::specialize`].
549549
//!
550550
//! Having said all that, in practice we don't fully follow what's been presented in this section.
551-
//! Under `exhaustive_patterns`, we allow omitting empty arms even in `!known_valid` places, for
552-
//! backwards-compatibility until we have a better alternative. Without `exhaustive_patterns`, we
553-
//! mostly treat empty types as inhabited, except specifically a non-nested `!` or empty enum. In
554-
//! this specific case we also allow the empty match regardless of place validity, for
555-
//! backwards-compatibility. Hopefully we can eventually deprecate this.
551+
//! Let's call "toplevel exception" the case where the match scrutinee itself has type `!` or
552+
//! `EmptyEnum`. First, on stable rust, we require `_` patterns for empty types in all cases apart
553+
//! from the toplevel exception. The `exhaustive_patterns` and `min_exaustive_patterns` allow
554+
//! omitting patterns in the cases described above. There's a final detail: in the toplevel
555+
//! exception or with the `exhaustive_patterns` feature, we ignore place validity when checking
556+
//! whether a pattern is required for exhaustiveness. I (Nadrieril) hope to deprecate this behavior.
556557
//!
557558
//!
558559
//!
@@ -1442,10 +1443,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
14421443
// We treat match scrutinees of type `!` or `EmptyEnum` differently.
14431444
let is_toplevel_exception =
14441445
is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors);
1445-
// Whether empty patterns can be omitted for exhaustiveness.
1446-
let can_omit_empty_arms = is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on();
1447-
// Whether empty patterns are counted as useful or not.
1448-
let empty_arms_are_unreachable = place_validity.is_known_valid() && can_omit_empty_arms;
1446+
// Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if
1447+
// it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`).
1448+
let empty_arms_are_unreachable = place_validity.is_known_valid()
1449+
&& (is_toplevel_exception
1450+
|| mcx.tycx.is_exhaustive_patterns_feature_on()
1451+
|| mcx.tycx.is_min_exhaustive_patterns_feature_on());
1452+
// Whether empty patterns can be omitted for exhaustiveness. We ignore place validity in the
1453+
// toplevel exception and `exhaustive_patterns` cases for backwards compatibility.
1454+
let can_omit_empty_arms = empty_arms_are_unreachable
1455+
|| is_toplevel_exception
1456+
|| mcx.tycx.is_exhaustive_patterns_feature_on();
14491457

14501458
// Analyze the constructors present in this column.
14511459
let ctors = matrix.heads().map(|p| p.ctor());

compiler/rustc_resolve/src/late.rs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4424,35 +4424,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
44244424
ExprKind::Type(ref _type_expr, ref _ty) => {
44254425
visit::walk_expr(self, expr);
44264426
}
4427-
// `async |x| ...` gets desugared to `|x| async {...}`, so we need to
4428-
// resolve the arguments within the proper scopes so that usages of them inside the
4429-
// closure are detected as upvars rather than normal closure arg usages.
4430-
//
4431-
// Similarly, `gen |x| ...` gets desugared to `|x| gen {...}`, so we handle that too.
4432-
ExprKind::Closure(box ast::Closure {
4433-
coroutine_kind: Some(_),
4434-
ref fn_decl,
4435-
ref body,
4436-
..
4437-
}) => {
4438-
self.with_rib(ValueNS, RibKind::Normal, |this| {
4439-
this.with_label_rib(RibKind::FnOrCoroutine, |this| {
4440-
// Resolve arguments:
4441-
this.resolve_params(&fn_decl.inputs);
4442-
// No need to resolve return type --
4443-
// the outer closure return type is `FnRetTy::Default`.
4444-
4445-
// Now resolve the inner closure
4446-
{
4447-
// No need to resolve arguments: the inner closure has none.
4448-
// Resolve the return type:
4449-
visit::walk_fn_ret_ty(this, &fn_decl.output);
4450-
// Resolve the body
4451-
this.visit_expr(body);
4452-
}
4453-
})
4454-
});
4455-
}
44564427
// For closures, RibKind::FnOrCoroutine is added in visit_fn
44574428
ExprKind::Closure(box ast::Closure {
44584429
binder: ClosureBinder::For { ref generic_params, span },

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,7 @@ symbols! {
10291029
min_const_fn,
10301030
min_const_generics,
10311031
min_const_unsafe_fn,
1032+
min_exhaustive_patterns,
10321033
min_specialization,
10331034
min_type_alias_impl_trait,
10341035
minnumf32,

library/alloc/src/str.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub use core::str::SplitAsciiWhitespace;
3030
pub use core::str::SplitInclusive;
3131
#[stable(feature = "rust1", since = "1.0.0")]
3232
pub use core::str::SplitWhitespace;
33+
#[unstable(feature = "str_from_raw_parts", issue = "119206")]
34+
pub use core::str::{from_raw_parts, from_raw_parts_mut};
3335
#[stable(feature = "rust1", since = "1.0.0")]
3436
pub use core::str::{from_utf8, from_utf8_mut, Bytes, CharIndices, Chars};
3537
#[stable(feature = "rust1", since = "1.0.0")]

library/core/src/str/converts.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Ways to create a `str` from bytes slice.
22
3-
use crate::mem;
3+
use crate::{mem, ptr};
44

55
use super::validations::run_utf8_validation;
66
use super::Utf8Error;
@@ -205,3 +205,41 @@ pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
205205
// comes from a reference which is guaranteed to be valid for writes.
206206
unsafe { &mut *(v as *mut [u8] as *mut str) }
207207
}
208+
209+
/// Creates an `&str` from a pointer and a length.
210+
///
211+
/// The pointed-to bytes must be valid UTF-8.
212+
/// If this might not be the case, use `str::from_utf8(slice::from_raw_parts(ptr, len))`,
213+
/// which will return an `Err` if the data isn't valid UTF-8.
214+
///
215+
/// This function is the `str` equivalent of [`slice::from_raw_parts`](crate::slice::from_raw_parts).
216+
/// See that function's documentation for safety concerns and examples.
217+
///
218+
/// The mutable version of this function is [`from_raw_parts_mut`].
219+
#[inline]
220+
#[must_use]
221+
#[unstable(feature = "str_from_raw_parts", issue = "119206")]
222+
#[rustc_const_unstable(feature = "str_from_raw_parts", issue = "119206")]
223+
pub const unsafe fn from_raw_parts<'a>(ptr: *const u8, len: usize) -> &'a str {
224+
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
225+
unsafe { &*ptr::from_raw_parts(ptr.cast(), len) }
226+
}
227+
228+
/// Creates an `&mut str` from a pointer and a length.
229+
///
230+
/// The pointed-to bytes must be valid UTF-8.
231+
/// If this might not be the case, use `str::from_utf8_mut(slice::from_raw_parts_mut(ptr, len))`,
232+
/// which will return an `Err` if the data isn't valid UTF-8.
233+
///
234+
/// This function is the `str` equivalent of [`slice::from_raw_parts_mut`](crate::slice::from_raw_parts_mut).
235+
/// See that function's documentation for safety concerns and examples.
236+
///
237+
/// The immutable version of this function is [`from_raw_parts`].
238+
#[inline]
239+
#[must_use]
240+
#[unstable(feature = "str_from_raw_parts", issue = "119206")]
241+
#[rustc_const_unstable(feature = "const_str_from_raw_parts_mut", issue = "119206")]
242+
pub const unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a str {
243+
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
244+
unsafe { &mut *ptr::from_raw_parts_mut(ptr.cast(), len) }
245+
}

library/core/src/str/iter.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,31 @@ impl<'a> DoubleEndedIterator for Lines<'a> {
11871187
#[stable(feature = "fused", since = "1.26.0")]
11881188
impl FusedIterator for Lines<'_> {}
11891189

1190+
impl<'a> Lines<'a> {
1191+
/// Returns the remaining lines of the split string.
1192+
///
1193+
/// # Examples
1194+
///
1195+
/// ```
1196+
/// #![feature(str_lines_remainder)]
1197+
///
1198+
/// let mut lines = "a\nb\nc\nd".lines();
1199+
/// assert_eq!(lines.remainder(), Some("a\nb\nc\nd"));
1200+
///
1201+
/// lines.next();
1202+
/// assert_eq!(lines.remainder(), Some("b\nc\nd"));
1203+
///
1204+
/// lines.by_ref().for_each(drop);
1205+
/// assert_eq!(lines.remainder(), None);
1206+
/// ```
1207+
#[inline]
1208+
#[must_use]
1209+
#[unstable(feature = "str_lines_remainder", issue = "77998")]
1210+
pub fn remainder(&self) -> Option<&'a str> {
1211+
self.0.iter.remainder()
1212+
}
1213+
}
1214+
11901215
/// Created with the method [`lines_any`].
11911216
///
11921217
/// [`lines_any`]: str::lines_any

0 commit comments

Comments
 (0)