Skip to content
Closed
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`.