Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 4 pull requests #65243

Closed
wants to merge 11 commits into from
10 changes: 10 additions & 0 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -817,12 +817,22 @@ impl<'a> Builder<'a> {

let mut rustflags = Rustflags::new(&target);
if stage != 0 {
if let Ok(s) = env::var("CARGOFLAGS_NOT_BOOTSTRAP") {
cargo.args(s.split_whitespace());
}
rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP");
} else {
if let Ok(s) = env::var("CARGOFLAGS_BOOTSTRAP") {
cargo.args(s.split_whitespace());
}
rustflags.env("RUSTFLAGS_BOOTSTRAP");
rustflags.arg("--cfg=bootstrap");
}

if let Ok(s) = env::var("CARGOFLAGS") {
cargo.args(s.split_whitespace());
}

match mode {
Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {},
Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
Expand Down
15 changes: 12 additions & 3 deletions src/librustc_typeck/check/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => {
debug!("supplied_sig_of_closure: closure is async fn body");
self.deduce_future_output_from_obligations(expr_def_id)
.unwrap_or_else(|| {
// AFAIK, deducing the future output
// always succeeds *except* in error cases
// like #65159. I'd like to return Error
// here, but I can't because I can't
// easily (and locally) prove that we
// *have* reported an
// error. --nikomatsakis
astconv.ty_infer(None, decl.output.span())
})
}

_ => astconv.ty_infer(None, decl.output.span()),
Expand Down Expand Up @@ -645,7 +655,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn deduce_future_output_from_obligations(
&self,
expr_def_id: DefId,
) -> Ty<'tcx> {
) -> Option<Ty<'tcx>> {
debug!("deduce_future_output_from_obligations(expr_def_id={:?})", expr_def_id);

let ret_coercion =
Expand Down Expand Up @@ -688,8 +698,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
None
}
})
.unwrap();
});

debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty);
output_ty
Expand Down
20 changes: 17 additions & 3 deletions src/libstd/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1090,13 +1090,14 @@ impl Metadata {

/// Returns the creation time listed in this metadata.
///
/// The returned value corresponds to the `birthtime` field of `stat` on
/// The returned value corresponds to the `btime` field of `statx` on
/// Linux not prior to 4.11, the `birthtime` field of `stat` on other
/// Unix platforms and the `ftCreationTime` field on Windows platforms.
///
/// # Errors
///
/// This field may not be available on all platforms, and will return an
/// `Err` on platforms where it is not available.
/// `Err` on platforms or filesystems where it is not available.
///
/// # Examples
///
Expand All @@ -1109,7 +1110,7 @@ impl Metadata {
/// if let Ok(time) = metadata.created() {
/// println!("{:?}", time);
/// } else {
/// println!("Not supported on this platform");
/// println!("Not supported on this platform or filesystem");
/// }
/// Ok(())
/// }
Expand Down Expand Up @@ -3443,5 +3444,18 @@ mod tests {
check!(a.created());
check!(b.created());
}

if cfg!(target_os = "linux") {
// Not always available
match (a.created(), b.created()) {
(Ok(t1), Ok(t2)) => assert!(t1 <= t2),
(Err(e1), Err(e2)) if e1.kind() == ErrorKind::Other &&
e2.kind() == ErrorKind::Other => {}
(a, b) => panic!(
"creation time must be always supported or not supported: {:?} {:?}",
a, b,
),
}
}
}
}
8 changes: 4 additions & 4 deletions src/libstd/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1627,7 +1627,7 @@ impl<'a> From<Cow<'a, Path>> for PathBuf {

#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Arc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
/// Converts a `PathBuf` into an `Arc` by moving the `PathBuf` data into a new `Arc` buffer.
#[inline]
fn from(s: PathBuf) -> Arc<Path> {
let arc: Arc<OsStr> = Arc::from(s.into_os_string());
Expand All @@ -1637,7 +1637,7 @@ impl From<PathBuf> for Arc<Path> {

#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<&Path> for Arc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
/// Converts a `Path` into an `Arc` by copying the `Path` data into a new `Arc` buffer.
#[inline]
fn from(s: &Path) -> Arc<Path> {
let arc: Arc<OsStr> = Arc::from(s.as_os_str());
Expand All @@ -1647,7 +1647,7 @@ impl From<&Path> for Arc<Path> {

#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<PathBuf> for Rc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
/// Converts a `PathBuf` into an `Rc` by moving the `PathBuf` data into a new `Rc` buffer.
#[inline]
fn from(s: PathBuf) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.into_os_string());
Expand All @@ -1657,7 +1657,7 @@ impl From<PathBuf> for Rc<Path> {

#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<&Path> for Rc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
/// Converts a `Path` into an `Rc` by copying the `Path` data into a new `Rc` buffer.
#[inline]
fn from(s: &Path) -> Rc<Path> {
let rc: Rc<OsStr> = Rc::from(s.as_os_str());
Expand Down
170 changes: 163 additions & 7 deletions src/libstd/sys/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,83 @@ pub struct File(FileDesc);
#[derive(Clone)]
pub struct FileAttr {
stat: stat64,
#[cfg(target_os = "linux")]
statx_extra_fields: Option<StatxExtraFields>,
}

#[derive(Clone)]
struct StatxExtraFields {
// This is needed to check if btime is supported by the filesystem.
stx_mask: u32,
stx_btime: libc::statx_timestamp,
}

// We prefer `statx` on Linux if available, which contains file creation time.
// Default `stat64` contains no creation time.
#[cfg(target_os = "linux")]
unsafe fn try_statx(
fd: c_int,
path: *const libc::c_char,
flags: i32,
mask: u32,
) -> Option<io::Result<FileAttr>> {
use crate::sync::atomic::{AtomicBool, Ordering};

// Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx`
// We store the availability in a global to avoid unnecessary syscalls
static HAS_STATX: AtomicBool = AtomicBool::new(true);
syscall! {
fn statx(
fd: c_int,
pathname: *const libc::c_char,
flags: c_int,
mask: libc::c_uint,
statxbuf: *mut libc::statx
) -> c_int
}

if !HAS_STATX.load(Ordering::Relaxed) {
return None;
}

let mut buf: libc::statx = mem::zeroed();
let ret = cvt(statx(fd, path, flags, mask, &mut buf));
match ret {
Err(err) => match err.raw_os_error() {
Some(libc::ENOSYS) => {
HAS_STATX.store(false, Ordering::Relaxed);
return None;
}
_ => return Some(Err(err)),
}
Ok(_) => {
// We cannot fill `stat64` exhaustively because of private padding fields.
let mut stat: stat64 = mem::zeroed();
stat.st_dev = libc::makedev(buf.stx_dev_major, buf.stx_dev_minor);
stat.st_ino = buf.stx_ino;
stat.st_nlink = buf.stx_nlink as u64;
stat.st_mode = buf.stx_mode as u32;
stat.st_uid = buf.stx_uid;
stat.st_gid = buf.stx_gid;
stat.st_rdev = libc::makedev(buf.stx_rdev_major, buf.stx_rdev_minor);
stat.st_size = buf.stx_size as i64;
stat.st_blksize = buf.stx_blksize as i64;
stat.st_blocks = buf.stx_blocks as i64;
stat.st_atime = buf.stx_atime.tv_sec;
stat.st_atime_nsec = buf.stx_atime.tv_nsec as i64;
stat.st_mtime = buf.stx_mtime.tv_sec;
stat.st_mtime_nsec = buf.stx_mtime.tv_nsec as i64;
stat.st_ctime = buf.stx_ctime.tv_sec;
stat.st_ctime_nsec = buf.stx_ctime.tv_nsec as i64;

let extra = StatxExtraFields {
stx_mask: buf.stx_mask,
stx_btime: buf.stx_btime,
};

Some(Ok(FileAttr { stat, statx_extra_fields: Some(extra) }))
}
}
}

// all DirEntry's will have a reference to this struct
Expand Down Expand Up @@ -98,6 +175,14 @@ pub struct FileType { mode: mode_t }
pub struct DirBuilder { mode: mode_t }

impl FileAttr {
fn from_stat64(stat: stat64) -> Self {
Self {
stat,
#[cfg(target_os = "linux")]
statx_extra_fields: None,
}
}

pub fn size(&self) -> u64 { self.stat.st_size as u64 }
pub fn perm(&self) -> FilePermissions {
FilePermissions { mode: (self.stat.st_mode as mode_t) }
Expand Down Expand Up @@ -164,6 +249,23 @@ impl FileAttr {
target_os = "macos",
target_os = "ios")))]
pub fn created(&self) -> io::Result<SystemTime> {
#[cfg(target_os = "linux")]
{
if let Some(ext) = &self.statx_extra_fields {
return if (ext.stx_mask & libc::STATX_BTIME) != 0 {
Ok(SystemTime::from(libc::timespec {
tv_sec: ext.stx_btime.tv_sec as libc::time_t,
tv_nsec: ext.stx_btime.tv_nsec as libc::c_long,
}))
} else {
Err(io::Error::new(
io::ErrorKind::Other,
"creation time is not available for the filesystem",
))
};
}
}

Err(io::Error::new(io::ErrorKind::Other,
"creation time is not available on this platform \
currently"))
Expand Down Expand Up @@ -306,12 +408,26 @@ impl DirEntry {

#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
pub fn metadata(&self) -> io::Result<FileAttr> {
let fd = cvt(unsafe {dirfd(self.dir.inner.dirp.0)})?;
let fd = cvt(unsafe { dirfd(self.dir.inner.dirp.0) })?;
let name = self.entry.d_name.as_ptr();

#[cfg(target_os = "linux")]
{
if let Some(ret) = unsafe { try_statx(
fd,
name,
libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
libc::STATX_ALL,
) } {
return ret;
}
}

let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
fstatat64(fd, self.entry.d_name.as_ptr(), &mut stat, libc::AT_SYMLINK_NOFOLLOW)
fstatat64(fd, name, &mut stat, libc::AT_SYMLINK_NOFOLLOW)
})?;
Ok(FileAttr { stat })
Ok(FileAttr::from_stat64(stat))
}

#[cfg(not(any(target_os = "linux", target_os = "emscripten", target_os = "android")))]
Expand Down Expand Up @@ -517,11 +633,25 @@ impl File {
}

pub fn file_attr(&self) -> io::Result<FileAttr> {
let fd = self.0.raw();

#[cfg(target_os = "linux")]
{
if let Some(ret) = unsafe { try_statx(
fd,
b"\0" as *const _ as *const libc::c_char,
libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT,
libc::STATX_ALL,
) } {
return ret;
}
}

let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
fstat64(self.0.raw(), &mut stat)
fstat64(fd, &mut stat)
})?;
Ok(FileAttr { stat })
Ok(FileAttr::from_stat64(stat))
}

pub fn fsync(&self) -> io::Result<()> {
Expand Down Expand Up @@ -798,20 +928,46 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {

pub fn stat(p: &Path) -> io::Result<FileAttr> {
let p = cstr(p)?;

#[cfg(target_os = "linux")]
{
if let Some(ret) = unsafe { try_statx(
libc::AT_FDCWD,
p.as_ptr(),
libc::AT_STATX_SYNC_AS_STAT,
libc::STATX_ALL,
) } {
return ret;
}
}

let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
stat64(p.as_ptr(), &mut stat)
})?;
Ok(FileAttr { stat })
Ok(FileAttr::from_stat64(stat))
}

pub fn lstat(p: &Path) -> io::Result<FileAttr> {
let p = cstr(p)?;

#[cfg(target_os = "linux")]
{
if let Some(ret) = unsafe { try_statx(
libc::AT_FDCWD,
p.as_ptr(),
libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
libc::STATX_ALL,
) } {
return ret;
}
}

let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
lstat64(p.as_ptr(), &mut stat)
})?;
Ok(FileAttr { stat })
Ok(FileAttr::from_stat64(stat))
}

pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/async-await/issues/issue-65159.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Regression test for #65159. We used to ICE.
//
// edition:2018

async fn copy() -> Result<()> //~ ERROR wrong number of type arguments
{
Ok(())
}

fn main() { }
9 changes: 9 additions & 0 deletions src/test/ui/async-await/issues/issue-65159.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0107]: wrong number of type arguments: expected 2, found 1
--> $DIR/issue-65159.rs:5:20
|
LL | async fn copy() -> Result<()>
| ^^^^^^^^^^ expected 2 type arguments

error: aborting due to previous error

For more information about this error, try `rustc --explain E0107`.