Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions compiler/rustc_hir_analysis/src/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,14 +202,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
Some((normalized_ty, ocx.into_pending_obligations()))
}

/// Returns the final type we ended up with, which may be an inference
/// variable (we will resolve it first, if we want).
pub fn final_ty(&self, resolve: bool) -> Ty<'tcx> {
if resolve {
self.infcx.resolve_vars_if_possible(self.state.cur_ty)
} else {
self.state.cur_ty
}
/// Returns the final type we ended up with, which may be an unresolved
/// inference variable.
pub fn final_ty(&self) -> Ty<'tcx> {
self.state.cur_ty
}

pub fn step_count(&self) -> usize {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let mut obligations = PredicateObligations::new();
let targets =
steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false)));
steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty()));
let steps: Vec<_> = steps
.iter()
.map(|&(source, kind)| {
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef);
}

match autoderef.final_ty(false).kind() {
match autoderef.final_ty().kind() {
ty::FnDef(def_id, _) => {
let abi = self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi;
self.check_call_abi(abi, call_expr.span);
Expand Down Expand Up @@ -200,8 +200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>],
autoderef: &Autoderef<'a, 'tcx>,
) -> Option<CallStep<'tcx>> {
let adjusted_ty =
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty());

// If the callee is a function pointer or a closure, then we're all set.
match *adjusted_ty.kind() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2918,7 +2918,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Emits an error if we deref an infer variable, like calling `.field` on a base type
// of `&_`. We can also use this to suppress unnecessary "missing field" errors that
// will follow ambiguity errors.
let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty());
if let ty::Error(_) = final_ty.kind() {
return final_ty;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ pub(crate) fn method_autoderef_steps<'tcx>(
.collect();
(steps, autoderef_via_deref.reached_recursion_limit())
};
let final_ty = autoderef_via_deref.final_ty(true);
let final_ty = autoderef_via_deref.final_ty();
let opt_bad_ty = match final_ty.kind() {
ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
reached_raw_pointer,
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_hir_typeck/src/place_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
index_ty: Ty<'tcx>,
index_expr: &hir::Expr<'_>,
) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> {
let adjusted_ty =
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
let adjusted_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty());
debug!(
"try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \
index_ty={:?})",
Expand Down
21 changes: 7 additions & 14 deletions library/core/src/sync/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2199,7 +2199,6 @@ impl<T> AtomicPtr<T> {
/// # Examples
///
/// ```
/// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
Expand All @@ -2209,7 +2208,7 @@ impl<T> AtomicPtr<T> {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
#[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
#[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T {
self.fetch_byte_add(val.wrapping_mul(size_of::<T>()), order)
Expand Down Expand Up @@ -2240,7 +2239,6 @@ impl<T> AtomicPtr<T> {
/// # Examples
///
/// ```
/// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let array = [1i32, 2i32];
Expand All @@ -2254,7 +2252,7 @@ impl<T> AtomicPtr<T> {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
#[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
#[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T {
self.fetch_byte_sub(val.wrapping_mul(size_of::<T>()), order)
Expand All @@ -2279,7 +2277,6 @@ impl<T> AtomicPtr<T> {
/// # Examples
///
/// ```
/// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
Expand All @@ -2289,7 +2286,7 @@ impl<T> AtomicPtr<T> {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
#[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
#[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
// SAFETY: data races are prevented by atomic intrinsics.
Expand All @@ -2315,7 +2312,6 @@ impl<T> AtomicPtr<T> {
/// # Examples
///
/// ```
/// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let mut arr = [0i64, 1];
Expand All @@ -2325,7 +2321,7 @@ impl<T> AtomicPtr<T> {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
#[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
#[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T {
// SAFETY: data races are prevented by atomic intrinsics.
Expand Down Expand Up @@ -2361,7 +2357,6 @@ impl<T> AtomicPtr<T> {
/// # Examples
///
/// ```
/// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let pointer = &mut 3i64 as *mut i64;
Expand All @@ -2376,7 +2371,7 @@ impl<T> AtomicPtr<T> {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
#[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
#[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T {
// SAFETY: data races are prevented by atomic intrinsics.
Expand Down Expand Up @@ -2412,7 +2407,6 @@ impl<T> AtomicPtr<T> {
/// # Examples
///
/// ```
/// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let pointer = &mut 3i64 as *mut i64;
Expand All @@ -2426,7 +2420,7 @@ impl<T> AtomicPtr<T> {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
#[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
#[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T {
// SAFETY: data races are prevented by atomic intrinsics.
Expand Down Expand Up @@ -2462,7 +2456,6 @@ impl<T> AtomicPtr<T> {
/// # Examples
///
/// ```
/// #![feature(strict_provenance_atomic_ptr)]
/// use core::sync::atomic::{AtomicPtr, Ordering};
///
/// let pointer = &mut 3i64 as *mut i64;
Expand All @@ -2474,7 +2467,7 @@ impl<T> AtomicPtr<T> {
/// ```
#[inline]
#[cfg(target_has_atomic = "ptr")]
#[unstable(feature = "strict_provenance_atomic_ptr", issue = "99108")]
#[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T {
// SAFETY: data races are prevented by atomic intrinsics.
Expand Down
1 change: 0 additions & 1 deletion library/coretests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@
#![feature(std_internals)]
#![feature(step_trait)]
#![feature(str_internals)]
#![feature(strict_provenance_atomic_ptr)]
#![feature(strict_provenance_lints)]
#![feature(test)]
#![feature(trusted_len)]
Expand Down
7 changes: 6 additions & 1 deletion library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,10 @@ impl OpenOptions {
/// See also [`std::fs::write()`][self::write] for a simple function to
/// create a file with some given data.
///
/// # Errors
///
/// If `.create(true)` is set without `.write(true)` or `.append(true)`,
/// calling [`open`](Self::open) will fail with [`InvalidInput`](io::ErrorKind::InvalidInput) error.
/// # Examples
///
/// ```no_run
Expand Down Expand Up @@ -1685,7 +1689,8 @@ impl OpenOptions {
/// * [`AlreadyExists`]: `create_new` was specified and the file already
/// exists.
/// * [`InvalidInput`]: Invalid combinations of open options (truncate
/// without write access, no access mode set, etc.).
/// without write access, create without write or append access,
/// no access mode set, etc.).
///
/// The following errors don't match any existing [`io::ErrorKind`] at the moment:
/// * One of the directory components of the specified file path
Expand Down
38 changes: 32 additions & 6 deletions library/std/src/fs/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1265,12 +1265,7 @@ fn open_flavors() {
let mut ra = OO::new();
ra.read(true).append(true);

#[cfg(windows)]
let invalid_options = 87; // ERROR_INVALID_PARAMETER
#[cfg(all(unix, not(target_os = "vxworks")))]
let invalid_options = "Invalid argument";
#[cfg(target_os = "vxworks")]
let invalid_options = "invalid argument";
let invalid_options = "creating or truncating a file requires write or append access";

// Test various combinations of creation modes and access modes.
//
Expand Down Expand Up @@ -2084,3 +2079,34 @@ fn test_rename_junction() {
// Junction links are always absolute so we just check the file name is correct.
assert_eq!(fs::read_link(&dest).unwrap().file_name(), Some(not_exist.as_os_str()));
}

#[test]
fn test_open_options_invalid_combinations() {
use crate::fs::OpenOptions as OO;

let test_cases: &[(fn() -> OO, &str)] = &[
(|| OO::new().create(true).read(true).clone(), "create without write"),
(|| OO::new().create_new(true).read(true).clone(), "create_new without write"),
(|| OO::new().truncate(true).read(true).clone(), "truncate without write"),
(|| OO::new().truncate(true).append(true).clone(), "truncate with append"),
];

for (make_opts, desc) in test_cases {
let opts = make_opts();
let result = opts.open("nonexistent.txt");
assert!(result.is_err(), "{desc} should fail");
let err = result.unwrap_err();
assert_eq!(err.kind(), ErrorKind::InvalidInput, "{desc} - wrong error kind");
assert_eq!(
err.to_string(),
"creating or truncating a file requires write or append access",
"{desc} - wrong error message"
);
}

let result = OO::new().open("nonexistent.txt");
assert!(result.is_err(), "no access mode should fail");
let err = result.unwrap_err();
assert_eq!(err.kind(), ErrorKind::InvalidInput);
assert_eq!(err.to_string(), "must specify at least one of read, write, or append access");
}
1 change: 0 additions & 1 deletion library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,6 @@
#![feature(slice_range)]
#![feature(std_internals)]
#![feature(str_internals)]
#![feature(strict_provenance_atomic_ptr)]
#![feature(sync_unsafe_cell)]
#![feature(temporary_niche_types)]
#![feature(ub_checks)]
Expand Down
26 changes: 23 additions & 3 deletions library/std/src/sys/fs/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,21 @@ impl OpenOptions {
(true, true, false) => Ok(libc::O_RDWR),
(false, _, true) => Ok(libc::O_WRONLY | libc::O_APPEND),
(true, _, true) => Ok(libc::O_RDWR | libc::O_APPEND),
(false, false, false) => Err(Error::from_raw_os_error(libc::EINVAL)),
(false, false, false) => {
// If no access mode is set, check if any creation flags are set
// to provide a more descriptive error message
if self.create || self.create_new || self.truncate {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"creating or truncating a file requires write or append access",
))
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"must specify at least one of read, write, or append access",
))
}
}
}
}

Expand All @@ -1132,12 +1146,18 @@ impl OpenOptions {
(true, false) => {}
(false, false) => {
if self.truncate || self.create || self.create_new {
return Err(Error::from_raw_os_error(libc::EINVAL));
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"creating or truncating a file requires write or append access",
));
}
}
(_, true) => {
if self.truncate && !self.create_new {
return Err(Error::from_raw_os_error(libc::EINVAL));
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"creating or truncating a file requires write or append access",
));
}
}
}
Expand Down
24 changes: 21 additions & 3 deletions library/std/src/sys/fs/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,19 @@ impl OpenOptions {
Ok(c::GENERIC_READ | (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA))
}
(false, false, false, None) => {
Err(Error::from_raw_os_error(c::ERROR_INVALID_PARAMETER as i32))
// If no access mode is set, check if any creation flags are set
// to provide a more descriptive error message
if self.create || self.create_new || self.truncate {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"creating or truncating a file requires write or append access",
))
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"must specify at least one of read, write, or append access",
))
}
}
}
}
Expand All @@ -268,12 +280,18 @@ impl OpenOptions {
(true, false) => {}
(false, false) => {
if self.truncate || self.create || self.create_new {
return Err(Error::from_raw_os_error(c::ERROR_INVALID_PARAMETER as i32));
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"creating or truncating a file requires write or append access",
));
}
}
(_, true) => {
if self.truncate && !self.create_new {
return Err(Error::from_raw_os_error(c::ERROR_INVALID_PARAMETER as i32));
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"creating or truncating a file requires write or append access",
));
}
}
}
Expand Down
Loading
Loading