diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index bbcd509c55869..6783bbf8bf42f 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -800,9 +800,9 @@ pub enum PatKind<'tcx> { }, /// One of the following: - /// * `&str`/`&[u8]` (represented as a valtree), which will be handled as a string/slice pattern - /// and thus exhaustiveness checking will detect if you use the same string/slice twice in - /// different patterns. + /// * `&str` (represented as a valtree), which will be handled as a string pattern and thus + /// exhaustiveness checking will detect if you use the same string twice in different + /// patterns. /// * integer, bool, char or float (represented as a valtree), which will be handled by /// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are /// much simpler. diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index ea341b604e0be..710538ef4b867 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -1326,8 +1326,8 @@ enum TestKind<'tcx> { Eq { value: Const<'tcx>, // Integer types are handled by `SwitchInt`, and constants with ADT - // types are converted back into patterns, so this can only be `&str`, - // `&[T]`, `f32` or `f64`. + // types and `&[T]` types are converted back into patterns, so this can + // only be `&str`, `f32` or `f64`. ty: Ty<'tcx>, }, diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index e5d61bc9e556a..7ef9e48326f63 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -11,7 +11,6 @@ use std::sync::Arc; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::{LangItem, RangeEnd}; use rustc_middle::mir::*; -use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -178,21 +177,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => {} } + assert_eq!(expect_ty, ty); if !ty.is_scalar() { // Use `PartialEq::eq` instead of `BinOp::Eq` // (the binop can only handle primitives) - self.non_scalar_compare( + // Make sure that we do *not* call any user-defined code here. + // The only type that can end up here is string literals, which have their + // comparison defined in `core`. + // (Interestingly this means that exhaustiveness analysis relies, for soundness, + // on the `PartialEq` impl for `str` to b correct!) + match *ty.kind() { + ty::Ref(_, deref_ty, _) if deref_ty == self.tcx.types.str_ => {} + _ => { + span_bug!(source_info.span, "invalid type for non-scalar compare: {ty}") + } + }; + self.string_compare( block, success_block, fail_block, source_info, expect, - expect_ty, Operand::Copy(place), - ty, ); } else { - assert_eq!(expect_ty, ty); self.compare( block, success_block, @@ -370,97 +378,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); } - /// Compare two values using `::eq`. - /// If the values are already references, just call it directly, otherwise - /// take a reference to the values first and then call it. - fn non_scalar_compare( + /// Compare two values of type `&str` using `::eq`. + fn string_compare( &mut self, block: BasicBlock, success_block: BasicBlock, fail_block: BasicBlock, source_info: SourceInfo, - mut expect: Operand<'tcx>, - expect_ty: Ty<'tcx>, - mut val: Operand<'tcx>, - mut ty: Ty<'tcx>, + expect: Operand<'tcx>, + val: Operand<'tcx>, ) { - // If we're using `b"..."` as a pattern, we need to insert an - // unsizing coercion, as the byte string has the type `&[u8; N]`. - // - // We want to do this even when the scrutinee is a reference to an - // array, so we can call `<[u8]>::eq` rather than having to find an - // `<[u8; N]>::eq`. - let unsize = |ty: Ty<'tcx>| match ty.kind() { - ty::Ref(region, rty, _) => match rty.kind() { - ty::Array(inner_ty, n) => Some((region, inner_ty, n)), - _ => None, - }, - _ => None, - }; - let opt_ref_ty = unsize(ty); - let opt_ref_test_ty = unsize(expect_ty); - match (opt_ref_ty, opt_ref_test_ty) { - // nothing to do, neither is an array - (None, None) => {} - (Some((region, elem_ty, _)), _) | (None, Some((region, elem_ty, _))) => { - let tcx = self.tcx; - // make both a slice - ty = Ty::new_imm_ref(tcx, *region, Ty::new_slice(tcx, *elem_ty)); - if opt_ref_ty.is_some() { - let temp = self.temp(ty, source_info.span); - self.cfg.push_assign( - block, - source_info, - temp, - Rvalue::Cast( - CastKind::PointerCoercion( - PointerCoercion::Unsize, - CoercionSource::Implicit, - ), - val, - ty, - ), - ); - val = Operand::Copy(temp); - } - if opt_ref_test_ty.is_some() { - let slice = self.temp(ty, source_info.span); - self.cfg.push_assign( - block, - source_info, - slice, - Rvalue::Cast( - CastKind::PointerCoercion( - PointerCoercion::Unsize, - CoercionSource::Implicit, - ), - expect, - ty, - ), - ); - expect = Operand::Move(slice); - } - } - } - - // Figure out the type on which we are calling `PartialEq`. This involves an extra wrapping - // reference: we can only compare two `&T`, and then compare_ty will be `T`. - // Make sure that we do *not* call any user-defined code here. - // The only types that can end up here are string and byte literals, - // which have their comparison defined in `core`. - // (Interestingly this means that exhaustiveness analysis relies, for soundness, - // on the `PartialEq` impls for `str` and `[u8]` to b correct!) - let compare_ty = match *ty.kind() { - ty::Ref(_, deref_ty, _) - if deref_ty == self.tcx.types.str_ || deref_ty != self.tcx.types.u8 => - { - deref_ty - } - _ => span_bug!(source_info.span, "invalid type for non-scalar compare: {}", ty), - }; - + let str_ty = self.tcx.types.str_; let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span)); - let method = trait_method(self.tcx, eq_def_id, sym::eq, [compare_ty, compare_ty]); + let method = trait_method(self.tcx, eq_def_id, sym::eq, [str_ty, str_ty]); let bool_ty = self.tcx.types.bool; let eq_result = self.temp(bool_ty, source_info.span); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 6056a69ee71f6..1eff824aa624e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -272,7 +272,7 @@ impl RibKind<'_> { /// resolving, the name is looked up from inside out. #[derive(Debug)] pub(crate) struct Rib<'ra, R = Res> { - pub bindings: FxHashMap, + pub bindings: FxIndexMap, pub patterns_with_skipped_bindings: UnordMap)>>, pub kind: RibKind<'ra>, } @@ -1642,8 +1642,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Allow all following defaults to refer to this type parameter. let i = &Ident::with_dummy_span(param.ident.name); - forward_ty_ban_rib.bindings.remove(i); - forward_ty_ban_rib_const_param_ty.bindings.remove(i); + forward_ty_ban_rib.bindings.swap_remove(i); + forward_ty_ban_rib_const_param_ty.bindings.swap_remove(i); } GenericParamKind::Const { ref ty, kw_span: _, ref default } => { // Const parameters can't have param bounds. @@ -1678,8 +1678,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Allow all following defaults to refer to this const parameter. let i = &Ident::with_dummy_span(param.ident.name); - forward_const_ban_rib.bindings.remove(i); - forward_const_ban_rib_const_param_ty.bindings.remove(i); + forward_const_ban_rib.bindings.swap_remove(i); + forward_const_ban_rib_const_param_ty.bindings.swap_remove(i); } } } @@ -2888,7 +2888,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { break; } - #[allow(rustc::potential_query_instability)] // FIXME seen_bindings .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span))); } @@ -4003,7 +4002,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } - fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut FxHashMap { + fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut FxIndexMap { &mut self.ribs[ns].last_mut().unwrap().bindings } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3d666055a94fb..6d95c02c55fc2 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -830,7 +830,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if let Some(rib) = &self.last_block_rib && let RibKind::Normal = rib.kind { - #[allow(rustc::potential_query_instability)] // FIXME for (ident, &res) in &rib.bindings { if let Res::Local(_) = res && path.len() == 1 @@ -1019,7 +1018,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if let Some(err_code) = err.code { if err_code == E0425 { for label_rib in &self.label_ribs { - #[allow(rustc::potential_query_instability)] // FIXME for (label_ident, node_id) in &label_rib.bindings { let ident = path.last().unwrap().ident; if format!("'{ident}") == label_ident.to_string() { @@ -2265,7 +2263,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { }; // Locals and type parameters - #[allow(rustc::potential_query_instability)] // FIXME for (ident, &res) in &rib.bindings { if filter_fn(res) && ident.span.ctxt() == rib_ctxt { names.push(TypoSuggestion::typo_from_ident(*ident, res)); @@ -2793,7 +2790,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let within_scope = self.is_label_valid_from_rib(rib_index); let rib = &self.label_ribs[rib_index]; - #[allow(rustc::potential_query_instability)] // FIXME let names = rib .bindings .iter() @@ -2805,7 +2801,6 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // Upon finding a similar name, get the ident that it was from - the span // contained within helps make a useful diagnostic. In addition, determine // whether this candidate is within scope. - #[allow(rustc::potential_query_instability)] // FIXME let (ident, _) = rib.bindings.iter().find(|(ident, _)| ident.name == symbol).unwrap(); (*ident, within_scope) }) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index e77caad65401b..4644e37f809c1 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1149,9 +1149,8 @@ impl Box { /// /// [memory layout]: self#memory-layout #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { + pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { Box(unsafe { Unique::new_unchecked(raw) }, alloc) } @@ -1203,9 +1202,8 @@ impl Box { /// [memory layout]: self#memory-layout #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const unsafe fn from_non_null_in(raw: NonNull, alloc: A) -> Self { + pub unsafe fn from_non_null_in(raw: NonNull, alloc: A) -> Self { // SAFETY: guaranteed by the caller. unsafe { Box::from_raw_in(raw.as_ptr(), alloc) } } @@ -1550,9 +1548,8 @@ impl Box { /// to call it as `Box::allocator(&b)` instead of `b.allocator()`. This /// is so that there is no conflict with a method on the inner type. #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub const fn allocator(b: &Self) -> &A { + pub fn allocator(b: &Self) -> &A { &b.1 } @@ -1639,8 +1636,7 @@ impl Box { /// let bar = Pin::from(foo); /// ``` #[stable(feature = "box_into_pin", since = "1.63.0")] - #[rustc_const_unstable(feature = "const_box", issue = "92521")] - pub const fn into_pin(boxed: Self) -> Pin + pub fn into_pin(boxed: Self) -> Pin where A: 'static, { diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index 54acd4c27b334..d6ae86bd3d26e 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -1,3 +1,5 @@ +use r_efi::protocols::file; + use crate::ffi::OsString; use crate::fmt; use crate::hash::Hash; @@ -22,7 +24,12 @@ pub struct ReadDir(!); pub struct DirEntry(!); #[derive(Clone, Debug)] -pub struct OpenOptions {} +pub struct OpenOptions { + mode: u64, + append: bool, + truncate: bool, + create_new: bool, +} #[derive(Copy, Clone, Debug, Default)] pub struct FileTimes {} @@ -141,15 +148,58 @@ impl DirEntry { impl OpenOptions { pub fn new() -> OpenOptions { - OpenOptions {} + OpenOptions { mode: 0, append: false, create_new: false, truncate: false } + } + + pub fn read(&mut self, read: bool) { + if read { + self.mode |= file::MODE_READ; + } else { + self.mode &= !file::MODE_READ; + } + } + + pub fn write(&mut self, write: bool) { + if write { + // Valid Combinations: Read, Read/Write, Read/Write/Create + self.read(true); + self.mode |= file::MODE_WRITE; + } else { + self.mode &= !file::MODE_WRITE; + } + } + + pub fn append(&mut self, append: bool) { + // Docs state that `.write(true).append(true)` has the same effect as `.append(true)` + if append { + self.write(true); + } + self.append = append; } - pub fn read(&mut self, _read: bool) {} - pub fn write(&mut self, _write: bool) {} - pub fn append(&mut self, _append: bool) {} - pub fn truncate(&mut self, _truncate: bool) {} - pub fn create(&mut self, _create: bool) {} - pub fn create_new(&mut self, _create_new: bool) {} + pub fn truncate(&mut self, truncate: bool) { + self.truncate = truncate; + } + + pub fn create(&mut self, create: bool) { + if create { + self.mode |= file::MODE_CREATE; + } else { + self.mode &= !file::MODE_CREATE; + } + } + + pub fn create_new(&mut self, create_new: bool) { + self.create_new = create_new; + } + + #[expect(dead_code)] + const fn is_mode_valid(&self) -> bool { + // Valid Combinations: Read, Read/Write, Read/Write/Create + self.mode == file::MODE_READ + || self.mode == (file::MODE_READ | file::MODE_WRITE) + || self.mode == (file::MODE_READ | file::MODE_WRITE | file::MODE_CREATE) + } } impl File { @@ -311,12 +361,12 @@ pub fn stat(_p: &Path) -> io::Result { unsupported() } -pub fn lstat(_p: &Path) -> io::Result { - unsupported() +pub fn lstat(p: &Path) -> io::Result { + stat(p) } -pub fn canonicalize(_p: &Path) -> io::Result { - unsupported() +pub fn canonicalize(p: &Path) -> io::Result { + crate::path::absolute(p) } pub fn copy(_from: &Path, _to: &Path) -> io::Result {