Skip to content

Commit d465f99

Browse files
committed
Auto merge of #150500 - jhpratt:rollup-ei77kqi, r=jhpratt
Rollup of 3 pull requests Successful merges: - #146792 (Implement `TryFrom<char>` for `usize`.) - #150484 (Mark set_times as unavailable for RTEMS target) - #150498 (mir_build: Remove several remnants of `#![feature(inline_const_pat)]`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents d874dce + 50e6224 commit d465f99

7 files changed

Lines changed: 93 additions & 50 deletions

File tree

compiler/rustc_middle/src/thir.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -832,18 +832,18 @@ pub enum PatKind<'tcx> {
832832
value: ty::Value<'tcx>,
833833
},
834834

835-
/// Pattern obtained by converting a constant (inline or named) to its pattern
836-
/// representation using `const_to_pat`. This is used for unsafety checking.
835+
/// Wrapper node representing a named constant that was lowered to a pattern
836+
/// using `const_to_pat`.
837+
///
838+
/// This is used by some diagnostics for non-exhaustive matches, to map
839+
/// the pattern node back to the `DefId` of its original constant.
840+
///
841+
/// FIXME(#150498): Can we make this an `Option<DefId>` field on `Pat`
842+
/// instead, so that non-diagnostic code can ignore it more easily?
837843
ExpandedConstant {
838844
/// [DefId] of the constant item.
839845
def_id: DefId,
840846
/// The pattern that the constant lowered to.
841-
///
842-
/// HACK: we need to keep the `DefId` of inline constants around for unsafety checking;
843-
/// therefore when a range pattern contains inline constants, we re-wrap the range pattern
844-
/// with the `ExpandedConstant` nodes that correspond to the range endpoints. Hence
845-
/// `subpattern` may actually be a range pattern, and `def_id` be the constant for one of
846-
/// its endpoints.
847847
subpattern: Box<Pat<'tcx>>,
848848
},
849849

compiler/rustc_mir_build/src/check_unsafety.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -410,14 +410,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
410410
visit::walk_pat(self, pat);
411411
self.inside_adt = old_inside_adt;
412412
}
413-
PatKind::ExpandedConstant { def_id, .. } => {
414-
if let Some(def) = def_id.as_local()
415-
&& matches!(self.tcx.def_kind(def_id), DefKind::InlineConst)
416-
{
417-
self.visit_inner_body(def);
418-
}
419-
visit::walk_pat(self, pat);
420-
}
421413
_ => {
422414
visit::walk_pat(self, pat);
423415
}

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
55
use rustc_errors::codes::*;
66
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_err};
77
use rustc_hir::def::*;
8-
use rustc_hir::def_id::LocalDefId;
8+
use rustc_hir::def_id::{DefId, LocalDefId};
99
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, MatchSource};
1010
use rustc_infer::infer::TyCtxtInferExt;
1111
use rustc_lint::Level;
@@ -687,12 +687,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
687687
unpeeled_pat = subpattern;
688688
}
689689

690-
if let PatKind::ExpandedConstant { def_id, .. } = unpeeled_pat.kind
691-
&& let DefKind::Const = self.tcx.def_kind(def_id)
692-
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
693-
// We filter out paths with multiple path::segments.
694-
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
695-
{
690+
if let Some(def_id) = is_const_pat_that_looks_like_binding(self.tcx, unpeeled_pat) {
696691
let span = self.tcx.def_span(def_id);
697692
let variable = self.tcx.item_name(def_id).to_string();
698693
// When we encounter a constant as the binding name, point at the `const` definition.
@@ -1209,6 +1204,26 @@ fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool {
12091204
}
12101205
}
12111206

1207+
/// If the given pattern is a named constant that looks like it could have been
1208+
/// intended to be a binding, returns the `DefId` of the named constant.
1209+
///
1210+
/// Diagnostics use this to give more detailed suggestions for non-exhaustive
1211+
/// matches.
1212+
fn is_const_pat_that_looks_like_binding<'tcx>(tcx: TyCtxt<'tcx>, pat: &Pat<'tcx>) -> Option<DefId> {
1213+
// The pattern must be a named constant, and the name that appears in
1214+
// the pattern's source text must resemble a plain identifier without any
1215+
// `::` namespace separators or other non-identifier characters.
1216+
if let PatKind::ExpandedConstant { def_id, .. } = pat.kind
1217+
&& matches!(tcx.def_kind(def_id), DefKind::Const)
1218+
&& let Ok(snippet) = tcx.sess.source_map().span_to_snippet(pat.span)
1219+
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
1220+
{
1221+
Some(def_id)
1222+
} else {
1223+
None
1224+
}
1225+
}
1226+
12121227
/// Report that a match is not exhaustive.
12131228
fn report_non_exhaustive_match<'p, 'tcx>(
12141229
cx: &PatCtxt<'p, 'tcx>,
@@ -1303,12 +1318,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
13031318

13041319
for &arm in arms {
13051320
let arm = &thir.arms[arm];
1306-
if let PatKind::ExpandedConstant { def_id, .. } = arm.pattern.kind
1307-
&& !matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst)
1308-
&& let Ok(snippet) = cx.tcx.sess.source_map().span_to_snippet(arm.pattern.span)
1309-
// We filter out paths with multiple path::segments.
1310-
&& snippet.chars().all(|c| c.is_alphanumeric() || c == '_')
1311-
{
1321+
if let Some(def_id) = is_const_pat_that_looks_like_binding(cx.tcx, &arm.pattern) {
13121322
let const_name = cx.tcx.item_name(def_id);
13131323
err.span_label(
13141324
arm.pattern.span,

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ impl<'tcx> ConstToPat<'tcx> {
187187
}
188188

189189
// Wrap the pattern in a marker node to indicate that it is the result of lowering a
190-
// constant. This is used for diagnostics, and for unsafety checking of inline const blocks.
190+
// constant. This is used for diagnostics.
191191
let kind = PatKind::ExpandedConstant { subpattern: inlined_const_as_pat, def_id: uv.def };
192192
Box::new(Pat { kind, ty, span: self.span })
193193
}

compiler/rustc_mir_build/src/thir/pattern/mod.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment};
2121
use rustc_middle::ty::layout::IntegerExt;
2222
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
2323
use rustc_middle::{bug, span_bug};
24-
use rustc_span::def_id::DefId;
2524
use rustc_span::{ErrorGuaranteed, Span};
2625
use tracing::{debug, instrument};
2726

@@ -131,9 +130,8 @@ impl<'tcx> PatCtxt<'tcx> {
131130
fn lower_pattern_range_endpoint(
132131
&mut self,
133132
expr: Option<&'tcx hir::PatExpr<'tcx>>,
134-
// Out-parameters collecting extra data to be reapplied by the caller
133+
// Out-parameter collecting extra data to be reapplied by the caller
135134
ascriptions: &mut Vec<Ascription<'tcx>>,
136-
expanded_consts: &mut Vec<DefId>,
137135
) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
138136
let Some(expr) = expr else { return Ok(None) };
139137

@@ -148,8 +146,10 @@ impl<'tcx> PatCtxt<'tcx> {
148146
ascriptions.push(ascription);
149147
kind = subpattern.kind;
150148
}
151-
PatKind::ExpandedConstant { def_id, subpattern } => {
152-
expanded_consts.push(def_id);
149+
PatKind::ExpandedConstant { def_id: _, subpattern } => {
150+
// Expanded-constant nodes are currently only needed by
151+
// diagnostics that don't apply to range patterns, so we
152+
// can just discard them here.
153153
kind = subpattern.kind;
154154
}
155155
_ => break,
@@ -227,10 +227,7 @@ impl<'tcx> PatCtxt<'tcx> {
227227

228228
// Collect extra data while lowering the endpoints, to be reapplied later.
229229
let mut ascriptions = vec![];
230-
let mut expanded_consts = vec![];
231-
232-
let mut lower_endpoint =
233-
|expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut expanded_consts);
230+
let mut lower_endpoint = |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions);
234231

235232
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
236233
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
@@ -282,10 +279,11 @@ impl<'tcx> PatCtxt<'tcx> {
282279
let subpattern = Box::new(Pat { span, ty, kind });
283280
kind = PatKind::AscribeUserType { ascription, subpattern };
284281
}
285-
for def_id in expanded_consts {
286-
let subpattern = Box::new(Pat { span, ty, kind });
287-
kind = PatKind::ExpandedConstant { def_id, subpattern };
288-
}
282+
// `PatKind::ExpandedConstant` wrappers from range endpoints used to
283+
// also be preserved here, but that was only needed for unsafeck of
284+
// inline `const { .. }` patterns, which were removed by
285+
// <https://github.com/rust-lang/rust/pull/138492>.
286+
289287
Ok(kind)
290288
}
291289

library/core/src/char/convert.rs

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ impl const From<char> for u32 {
4545
/// ```
4646
/// let c = 'c';
4747
/// let u = u32::from(c);
48+
///
4849
/// assert!(4 == size_of_val(&u))
4950
/// ```
5051
#[inline]
@@ -63,6 +64,7 @@ impl const From<char> for u64 {
6364
/// ```
6465
/// let c = '👤';
6566
/// let u = u64::from(c);
67+
///
6668
/// assert!(8 == size_of_val(&u))
6769
/// ```
6870
#[inline]
@@ -83,6 +85,7 @@ impl const From<char> for u128 {
8385
/// ```
8486
/// let c = '⚙';
8587
/// let u = u128::from(c);
88+
///
8689
/// assert!(16 == size_of_val(&u))
8790
/// ```
8891
#[inline]
@@ -93,8 +96,8 @@ impl const From<char> for u128 {
9396
}
9497
}
9598

96-
/// Maps a `char` with code point in U+0000..=U+00FF to a byte in 0x00..=0xFF with same value,
97-
/// failing if the code point is greater than U+00FF.
99+
/// Maps a `char` with a code point from U+0000 to U+00FF (inclusive) to a byte in `0x00..=0xFF` with
100+
/// the same value, failing if the code point is greater than U+00FF.
98101
///
99102
/// See [`impl From<u8> for char`](char#impl-From<u8>-for-char) for details on the encoding.
100103
#[stable(feature = "u8_from_char", since = "1.59.0")]
@@ -109,6 +112,7 @@ impl const TryFrom<char> for u8 {
109112
/// ```
110113
/// let a = 'ÿ'; // U+00FF
111114
/// let b = 'Ā'; // U+0100
115+
///
112116
/// assert_eq!(u8::try_from(a), Ok(0xFF_u8));
113117
/// assert!(u8::try_from(b).is_err());
114118
/// ```
@@ -122,8 +126,8 @@ impl const TryFrom<char> for u8 {
122126
}
123127
}
124128

125-
/// Maps a `char` with code point in U+0000..=U+FFFF to a `u16` in 0x0000..=0xFFFF with same value,
126-
/// failing if the code point is greater than U+FFFF.
129+
/// Maps a `char` with a code point from U+0000 to U+FFFF (inclusive) to a `u16` in `0x0000..=0xFFFF`
130+
/// with the same value, failing if the code point is greater than U+FFFF.
127131
///
128132
/// This corresponds to the UCS-2 encoding, as specified in ISO/IEC 10646:2003.
129133
#[stable(feature = "u16_from_char", since = "1.74.0")]
@@ -138,6 +142,7 @@ impl const TryFrom<char> for u16 {
138142
/// ```
139143
/// let trans_rights = '⚧'; // U+26A7
140144
/// let ninjas = '🥷'; // U+1F977
145+
///
141146
/// assert_eq!(u16::try_from(trans_rights), Ok(0x26A7_u16));
142147
/// assert!(u16::try_from(ninjas).is_err());
143148
/// ```
@@ -151,7 +156,45 @@ impl const TryFrom<char> for u16 {
151156
}
152157
}
153158

154-
/// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
159+
/// Maps a `char` with a code point from U+0000 to U+10FFFF (inclusive) to a `usize` in
160+
/// `0x0000..=0x10FFFF` with the same value, failing if the final value is unrepresentable by
161+
/// `usize`.
162+
///
163+
/// Generally speaking, this conversion can be seen as obtaining the character's corresponding
164+
/// UTF-32 code point to the extent representable by pointer addresses.
165+
#[stable(feature = "usize_try_from_char", since = "CURRENT_RUSTC_VERSION")]
166+
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
167+
impl const TryFrom<char> for usize {
168+
type Error = TryFromCharError;
169+
170+
/// Tries to convert a [`char`] into a [`usize`].
171+
///
172+
/// # Examples
173+
///
174+
/// ```
175+
/// let a = '\u{FFFF}'; // Always succeeds.
176+
/// let b = '\u{10FFFF}'; // Conditionally succeeds.
177+
///
178+
/// assert_eq!(usize::try_from(a), Ok(0xFFFF));
179+
///
180+
/// if size_of::<usize>() >= size_of::<u32>() {
181+
/// assert_eq!(usize::try_from(b), Ok(0x10FFFF));
182+
/// } else {
183+
/// assert!(matches!(usize::try_from(b), Err(_)));
184+
/// }
185+
/// ```
186+
#[inline]
187+
fn try_from(c: char) -> Result<usize, Self::Error> {
188+
// FIXME(const-hack): this should use map_err instead
189+
match usize::try_from(u32::from(c)) {
190+
Ok(x) => Ok(x),
191+
Err(_) => Err(TryFromCharError(())),
192+
}
193+
}
194+
}
195+
196+
/// Maps a byte in `0x00..=0xFF` to a `char` whose code point has the same value from U+0000 to U+00FF
197+
/// (inclusive).
155198
///
156199
/// Unicode is designed such that this effectively decodes bytes
157200
/// with the character encoding that IANA calls ISO-8859-1.
@@ -179,6 +222,7 @@ impl const From<u8> for char {
179222
/// ```
180223
/// let u = 32 as u8;
181224
/// let c = char::from(u);
225+
///
182226
/// assert!(4 == size_of_val(&c))
183227
/// ```
184228
#[inline]
@@ -246,7 +290,6 @@ const fn char_try_from_u32(i: u32) -> Result<char, CharTryFromError> {
246290
// Subtracting 0x800 causes 0x0000..0x0800 to wrap, meaning that a single
247291
// unsigned comparison against 0x110000 - 0x800 will detect both the wrapped
248292
// surrogate range as well as the numbers originally larger than 0x110000.
249-
//
250293
if (i ^ 0xD800).wrapping_sub(0x800) >= 0x110000 - 0x800 {
251294
Err(CharTryFromError(()))
252295
} else {

library/std/src/sys/fs/unix.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2166,7 +2166,7 @@ fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)>
21662166

21672167
fn set_times_impl(p: &CStr, times: FileTimes, follow_symlinks: bool) -> io::Result<()> {
21682168
cfg_select! {
2169-
any(target_os = "redox", target_os = "espidf", target_os = "horizon", target_os = "nuttx", target_os = "vita") => {
2169+
any(target_os = "redox", target_os = "espidf", target_os = "horizon", target_os = "nuttx", target_os = "vita", target_os = "rtems") => {
21702170
let _ = (p, times, follow_symlinks);
21712171
Err(io::const_error!(
21722172
io::ErrorKind::Unsupported,

0 commit comments

Comments
 (0)