Auto merge of #123628 - matthiaskrgr:rollup-6otgb94, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #115984 (extending filesystem support for Hermit) - #120144 (privacy: Stabilize lint `unnameable_types`) - #122807 (Add consistency with phrases "meantime" and "mean time") - #123089 (Add invariant to VecDeque::pop_* that len < cap if pop successful) - #123595 (Documentation fix) - #123625 (Stop exporting `TypeckRootCtxt` and `FnCtxt`.) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
ab3dba92db
@ -2,7 +2,7 @@ driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
|
|||||||
driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
|
driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
|
||||||
driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly
|
driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly
|
||||||
driver_impl_ice_bug_report_outdated =
|
driver_impl_ice_bug_report_outdated =
|
||||||
it seems that this compiler `{$version}` is outdated, a newer nightly should have been released in the mean time
|
it seems that this compiler `{$version}` is outdated, a newer nightly should have been released in the meantime
|
||||||
.update = please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
|
.update = please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
|
||||||
.url = if the problem still persists, we would appreciate a bug report: {$bug_report_url}
|
.url = if the problem still persists, we would appreciate a bug report: {$bug_report_url}
|
||||||
driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
|
driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
|
||||||
|
@ -355,6 +355,8 @@ declare_features! (
|
|||||||
(accepted, type_alias_enum_variants, "1.37.0", Some(49683)),
|
(accepted, type_alias_enum_variants, "1.37.0", Some(49683)),
|
||||||
/// Allows macros to appear in the type position.
|
/// Allows macros to appear in the type position.
|
||||||
(accepted, type_macros, "1.13.0", Some(27245)),
|
(accepted, type_macros, "1.13.0", Some(27245)),
|
||||||
|
/// Allows using type privacy lints (`private_interfaces`, `private_bounds`, `unnameable_types`).
|
||||||
|
(accepted, type_privacy_lints, "CURRENT_RUSTC_VERSION", Some(48054)),
|
||||||
/// Allows `const _: TYPE = VALUE`.
|
/// Allows `const _: TYPE = VALUE`.
|
||||||
(accepted, underscore_const_names, "1.37.0", Some(54912)),
|
(accepted, underscore_const_names, "1.37.0", Some(54912)),
|
||||||
/// Allows `use path as _;` and `extern crate c as _;`.
|
/// Allows `use path as _;` and `extern crate c as _;`.
|
||||||
|
@ -615,8 +615,6 @@ declare_features! (
|
|||||||
/// Allows creation of instances of a struct by moving fields that have
|
/// Allows creation of instances of a struct by moving fields that have
|
||||||
/// not changed from prior instances of the same struct (RFC #2528)
|
/// not changed from prior instances of the same struct (RFC #2528)
|
||||||
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
|
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
|
||||||
/// Allows using type privacy lints (`private_interfaces`, `private_bounds`, `unnameable_types`).
|
|
||||||
(unstable, type_privacy_lints, "1.72.0", Some(48054)),
|
|
||||||
/// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
|
/// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
|
||||||
(unstable, unix_sigpipe, "1.65.0", Some(97889)),
|
(unstable, unix_sigpipe, "1.65.0", Some(97889)),
|
||||||
/// Allows unnamed fields of struct and union type
|
/// Allows unnamed fields of struct and union type
|
||||||
|
@ -40,17 +40,19 @@ use rustc_middle::mir::Mutability;
|
|||||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||||
use rustc_middle::ty::cast::{CastKind, CastTy};
|
use rustc_middle::ty::cast::{CastKind, CastTy};
|
||||||
use rustc_middle::ty::error::TypeError;
|
use rustc_middle::ty::error::TypeError;
|
||||||
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitableExt, VariantDef};
|
use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitableExt, VariantDef};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
use rustc_span::def_id::{DefId, LOCAL_CRATE};
|
use rustc_span::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
use rustc_span::DUMMY_SP;
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
|
|
||||||
/// Reifies a cast check to be checked once we have full type information for
|
/// Reifies a cast check to be checked once we have full type information for
|
||||||
/// a function context.
|
/// a function context.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CastCheck<'tcx> {
|
pub(crate) struct CastCheck<'tcx> {
|
||||||
/// The expression whose value is being casted
|
/// The expression whose value is being casted
|
||||||
expr: &'tcx hir::Expr<'tcx>,
|
expr: &'tcx hir::Expr<'tcx>,
|
||||||
/// The source type for the cast expression
|
/// The source type for the cast expression
|
||||||
@ -60,8 +62,6 @@ pub struct CastCheck<'tcx> {
|
|||||||
cast_ty: Ty<'tcx>,
|
cast_ty: Ty<'tcx>,
|
||||||
cast_span: Span,
|
cast_span: Span,
|
||||||
span: Span,
|
span: Span,
|
||||||
/// whether the cast is made in a const context or not.
|
|
||||||
pub constness: hir::Constness,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The kind of pointer and associated metadata (thin, length or vtable) - we
|
/// The kind of pointer and associated metadata (thin, length or vtable) - we
|
||||||
@ -194,18 +194,45 @@ fn make_invalid_casting_error<'a, 'tcx>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If a cast from `from_ty` to `to_ty` is valid, returns a `Some` containing the kind
|
||||||
|
/// of the cast.
|
||||||
|
///
|
||||||
|
/// This is a helper used from clippy.
|
||||||
|
pub fn check_cast<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
e: &'tcx hir::Expr<'tcx>,
|
||||||
|
from_ty: Ty<'tcx>,
|
||||||
|
to_ty: Ty<'tcx>,
|
||||||
|
) -> Option<CastKind> {
|
||||||
|
let hir_id = e.hir_id;
|
||||||
|
let local_def_id = hir_id.owner.def_id;
|
||||||
|
|
||||||
|
let root_ctxt = crate::TypeckRootCtxt::new(tcx, local_def_id);
|
||||||
|
let fn_ctxt = FnCtxt::new(&root_ctxt, param_env, local_def_id);
|
||||||
|
|
||||||
|
if let Ok(check) = CastCheck::new(
|
||||||
|
&fn_ctxt, e, from_ty, to_ty,
|
||||||
|
// We won't show any errors to the user, so the span is irrelevant here.
|
||||||
|
DUMMY_SP, DUMMY_SP,
|
||||||
|
) {
|
||||||
|
check.do_check(&fn_ctxt).ok()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> CastCheck<'tcx> {
|
impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
pub fn new(
|
pub(crate) fn new(
|
||||||
fcx: &FnCtxt<'a, 'tcx>,
|
fcx: &FnCtxt<'a, 'tcx>,
|
||||||
expr: &'tcx hir::Expr<'tcx>,
|
expr: &'tcx hir::Expr<'tcx>,
|
||||||
expr_ty: Ty<'tcx>,
|
expr_ty: Ty<'tcx>,
|
||||||
cast_ty: Ty<'tcx>,
|
cast_ty: Ty<'tcx>,
|
||||||
cast_span: Span,
|
cast_span: Span,
|
||||||
span: Span,
|
span: Span,
|
||||||
constness: hir::Constness,
|
|
||||||
) -> Result<CastCheck<'tcx>, ErrorGuaranteed> {
|
) -> Result<CastCheck<'tcx>, ErrorGuaranteed> {
|
||||||
let expr_span = expr.span.find_ancestor_inside(span).unwrap_or(expr.span);
|
let expr_span = expr.span.find_ancestor_inside(span).unwrap_or(expr.span);
|
||||||
let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span, constness };
|
let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span };
|
||||||
|
|
||||||
// For better error messages, check for some obviously unsized
|
// For better error messages, check for some obviously unsized
|
||||||
// cases now. We do a more thorough check at the end, once
|
// cases now. We do a more thorough check at the end, once
|
||||||
@ -644,7 +671,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
/// Checks a cast, and report an error if one exists. In some cases, this
|
/// Checks a cast, and report an error if one exists. In some cases, this
|
||||||
/// can return Ok and create type errors in the fcx rather than returning
|
/// can return Ok and create type errors in the fcx rather than returning
|
||||||
/// directly. coercion-cast is handled in check instead of here.
|
/// directly. coercion-cast is handled in check instead of here.
|
||||||
pub fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
|
fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
|
||||||
use rustc_middle::ty::cast::CastTy::*;
|
use rustc_middle::ty::cast::CastTy::*;
|
||||||
use rustc_middle::ty::cast::IntTy::*;
|
use rustc_middle::ty::cast::IntTy::*;
|
||||||
|
|
||||||
|
@ -1318,6 +1318,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check whether `ty` can be coerced to `output_ty`.
|
||||||
|
/// Used from clippy.
|
||||||
|
pub fn can_coerce<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
body_id: LocalDefId,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
output_ty: Ty<'tcx>,
|
||||||
|
) -> bool {
|
||||||
|
let root_ctxt = crate::typeck_root_ctxt::TypeckRootCtxt::new(tcx, body_id);
|
||||||
|
let fn_ctxt = FnCtxt::new(&root_ctxt, param_env, body_id);
|
||||||
|
fn_ctxt.can_coerce(ty, output_ty)
|
||||||
|
}
|
||||||
|
|
||||||
/// CoerceMany encapsulates the pattern you should use when you have
|
/// CoerceMany encapsulates the pattern you should use when you have
|
||||||
/// many expressions that are all getting coerced to a common
|
/// many expressions that are all getting coerced to a common
|
||||||
/// type. This arises, for example, when you have a match (the result
|
/// type. This arises, for example, when you have a match (the result
|
||||||
|
@ -1390,15 +1390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
// Defer other checks until we're done type checking.
|
// Defer other checks until we're done type checking.
|
||||||
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
|
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
|
||||||
match cast::CastCheck::new(
|
match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
|
||||||
self,
|
|
||||||
e,
|
|
||||||
t_expr,
|
|
||||||
t_cast,
|
|
||||||
t.span,
|
|
||||||
expr.span,
|
|
||||||
hir::Constness::NotConst,
|
|
||||||
) {
|
|
||||||
Ok(cast_check) => {
|
Ok(cast_check) => {
|
||||||
debug!(
|
debug!(
|
||||||
"check_expr_cast: deferring cast from {:?} to {:?}: {:?}",
|
"check_expr_cast: deferring cast from {:?} to {:?}: {:?}",
|
||||||
|
@ -38,7 +38,7 @@ use std::ops::Deref;
|
|||||||
///
|
///
|
||||||
/// [`ItemCtxt`]: rustc_hir_analysis::collect::ItemCtxt
|
/// [`ItemCtxt`]: rustc_hir_analysis::collect::ItemCtxt
|
||||||
/// [`InferCtxt`]: infer::InferCtxt
|
/// [`InferCtxt`]: infer::InferCtxt
|
||||||
pub struct FnCtxt<'a, 'tcx> {
|
pub(crate) struct FnCtxt<'a, 'tcx> {
|
||||||
pub(super) body_id: LocalDefId,
|
pub(super) body_id: LocalDefId,
|
||||||
|
|
||||||
/// The parameter environment used for proving trait obligations
|
/// The parameter environment used for proving trait obligations
|
||||||
|
@ -42,8 +42,9 @@ mod typeck_root_ctxt;
|
|||||||
mod upvar;
|
mod upvar;
|
||||||
mod writeback;
|
mod writeback;
|
||||||
|
|
||||||
pub use fn_ctxt::FnCtxt;
|
pub use coercion::can_coerce;
|
||||||
pub use typeck_root_ctxt::TypeckRootCtxt;
|
use fn_ctxt::FnCtxt;
|
||||||
|
use typeck_root_ctxt::TypeckRootCtxt;
|
||||||
|
|
||||||
use crate::check::check_fn;
|
use crate::check::check_fn;
|
||||||
use crate::coercion::DynamicCoerceMany;
|
use crate::coercion::DynamicCoerceMany;
|
||||||
|
@ -27,7 +27,7 @@ use std::ops::Deref;
|
|||||||
/// `bar()` will each have their own `FnCtxt`, but they will
|
/// `bar()` will each have their own `FnCtxt`, but they will
|
||||||
/// share the inference context, will process obligations together,
|
/// share the inference context, will process obligations together,
|
||||||
/// can access each other's local types (scoping permitted), etc.
|
/// can access each other's local types (scoping permitted), etc.
|
||||||
pub struct TypeckRootCtxt<'tcx> {
|
pub(crate) struct TypeckRootCtxt<'tcx> {
|
||||||
pub(super) infcx: InferCtxt<'tcx>,
|
pub(super) infcx: InferCtxt<'tcx>,
|
||||||
|
|
||||||
pub(super) typeck_results: RefCell<ty::TypeckResults<'tcx>>,
|
pub(super) typeck_results: RefCell<ty::TypeckResults<'tcx>>,
|
||||||
|
@ -1337,8 +1337,9 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// The `unreachable_pub` lint triggers for `pub` items not reachable from
|
/// The `unreachable_pub` lint triggers for `pub` items not reachable from other crates - that
|
||||||
/// the crate root.
|
/// means neither directly accessible, nor reexported, nor leaked through things like return
|
||||||
|
/// types.
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
///
|
///
|
||||||
|
@ -20,7 +20,7 @@ declare_lint! {
|
|||||||
/// This functionality was removed in #97346, but then rolled back in #99860
|
/// This functionality was removed in #97346, but then rolled back in #99860
|
||||||
/// because it caused regressions.
|
/// because it caused regressions.
|
||||||
///
|
///
|
||||||
/// We plan on reintroducing this as a hard error, but in the mean time,
|
/// We plan on reintroducing this as a hard error, but in the meantime,
|
||||||
/// this lint serves to warn and suggest fixes for any use-cases which rely
|
/// this lint serves to warn and suggest fixes for any use-cases which rely
|
||||||
/// on this behavior.
|
/// on this behavior.
|
||||||
///
|
///
|
||||||
|
@ -4311,7 +4311,6 @@ declare_lint! {
|
|||||||
/// ### Example
|
/// ### Example
|
||||||
///
|
///
|
||||||
/// ```rust,compile_fail
|
/// ```rust,compile_fail
|
||||||
/// # #![feature(type_privacy_lints)]
|
|
||||||
/// # #![allow(unused)]
|
/// # #![allow(unused)]
|
||||||
/// #![deny(unnameable_types)]
|
/// #![deny(unnameable_types)]
|
||||||
/// mod m {
|
/// mod m {
|
||||||
@ -4328,10 +4327,14 @@ declare_lint! {
|
|||||||
///
|
///
|
||||||
/// It is often expected that if you can obtain an object of type `T`, then
|
/// It is often expected that if you can obtain an object of type `T`, then
|
||||||
/// you can name the type `T` as well, this lint attempts to enforce this rule.
|
/// you can name the type `T` as well, this lint attempts to enforce this rule.
|
||||||
|
/// The recommended action is to either reexport the type properly to make it nameable,
|
||||||
|
/// or document that users are not supposed to be able to name it for one reason or another.
|
||||||
|
///
|
||||||
|
/// Besides types, this lint applies to traits because traits can also leak through signatures,
|
||||||
|
/// and you may obtain objects of their `dyn Trait` or `impl Trait` types.
|
||||||
pub UNNAMEABLE_TYPES,
|
pub UNNAMEABLE_TYPES,
|
||||||
Allow,
|
Allow,
|
||||||
"effective visibility of a type is larger than the area in which it can be named",
|
"effective visibility of a type is larger than the area in which it can be named",
|
||||||
@feature_gate = sym::type_privacy_lints;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
|
@ -147,7 +147,7 @@ LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef Child, size_t *Size) {
|
|||||||
Expected<StringRef> NameOrErr = Child->getName();
|
Expected<StringRef> NameOrErr = Child->getName();
|
||||||
if (!NameOrErr) {
|
if (!NameOrErr) {
|
||||||
// rustc_codegen_llvm currently doesn't use this error string, but it might be
|
// rustc_codegen_llvm currently doesn't use this error string, but it might be
|
||||||
// useful in the future, and in the mean time this tells LLVM that the
|
// useful in the future, and in the meantime this tells LLVM that the
|
||||||
// error was not ignored and that it shouldn't abort the process.
|
// error was not ignored and that it shouldn't abort the process.
|
||||||
LLVMRustSetLastError(toString(NameOrErr.takeError()).c_str());
|
LLVMRustSetLastError(toString(NameOrErr.takeError()).c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1614,7 +1614,10 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||||||
let old_head = self.head;
|
let old_head = self.head;
|
||||||
self.head = self.to_physical_idx(1);
|
self.head = self.to_physical_idx(1);
|
||||||
self.len -= 1;
|
self.len -= 1;
|
||||||
Some(unsafe { self.buffer_read(old_head) })
|
unsafe {
|
||||||
|
core::hint::assert_unchecked(self.len < self.capacity());
|
||||||
|
Some(self.buffer_read(old_head))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1638,7 +1641,10 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
self.len -= 1;
|
self.len -= 1;
|
||||||
Some(unsafe { self.buffer_read(self.to_physical_idx(self.len)) })
|
unsafe {
|
||||||
|
core::hint::assert_unchecked(self.len < self.capacity());
|
||||||
|
Some(self.buffer_read(self.to_physical_idx(self.len)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +310,7 @@ pub trait FromResidual<R = <Self as Try>::Residual> {
|
|||||||
/// This should be implemented consistently with the `branch` method such
|
/// This should be implemented consistently with the `branch` method such
|
||||||
/// that applying the `?` operator will get back an equivalent residual:
|
/// that applying the `?` operator will get back an equivalent residual:
|
||||||
/// `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`.
|
/// `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`.
|
||||||
/// (It must not be an *identical* residual when interconversion is involved.)
|
/// (The residual is not mandated to be *identical* when interconversion is involved.)
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -48,6 +48,11 @@ impl FileDesc {
|
|||||||
pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> {
|
pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fstat(&self, stat: *mut abi::stat) -> io::Result<()> {
|
||||||
|
cvt(unsafe { abi::fstat(self.fd.as_raw_fd(), stat) })?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Read for &'a FileDesc {
|
impl<'a> Read for &'a FileDesc {
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
use super::abi::{self, O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY};
|
use super::abi::{
|
||||||
|
self, dirent64, stat as stat_struct, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT,
|
||||||
|
O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG,
|
||||||
|
};
|
||||||
use super::fd::FileDesc;
|
use super::fd::FileDesc;
|
||||||
use crate::ffi::{CStr, OsString};
|
use crate::ffi::{CStr, OsStr, OsString};
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::hash::{Hash, Hasher};
|
|
||||||
use crate::io::{self, Error, ErrorKind};
|
use crate::io::{self, Error, ErrorKind};
|
||||||
use crate::io::{BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
|
use crate::io::{BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
|
||||||
|
use crate::mem;
|
||||||
|
use crate::os::hermit::ffi::OsStringExt;
|
||||||
use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||||
use crate::path::{Path, PathBuf};
|
use crate::path::{Path, PathBuf};
|
||||||
|
use crate::sync::Arc;
|
||||||
use crate::sys::common::small_c_string::run_path_with_cstr;
|
use crate::sys::common::small_c_string::run_path_with_cstr;
|
||||||
use crate::sys::cvt;
|
use crate::sys::cvt;
|
||||||
use crate::sys::time::SystemTime;
|
use crate::sys::time::SystemTime;
|
||||||
@ -14,16 +19,53 @@ use crate::sys::unsupported;
|
|||||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||||
|
|
||||||
pub use crate::sys_common::fs::{copy, try_exists};
|
pub use crate::sys_common::fs::{copy, try_exists};
|
||||||
//pub use crate::sys_common::fs::remove_dir_all;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct File(FileDesc);
|
pub struct File(FileDesc);
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct FileAttr {
|
||||||
|
stat_val: stat_struct,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FileAttr(!);
|
impl FileAttr {
|
||||||
|
fn from_stat(stat_val: stat_struct) -> Self {
|
||||||
|
Self { stat_val }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ReadDir(!);
|
// all DirEntry's will have a reference to this struct
|
||||||
|
struct InnerReadDir {
|
||||||
|
root: PathBuf,
|
||||||
|
dir: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DirEntry(!);
|
impl InnerReadDir {
|
||||||
|
pub fn new(root: PathBuf, dir: Vec<u8>) -> Self {
|
||||||
|
Self { root, dir }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ReadDir {
|
||||||
|
inner: Arc<InnerReadDir>,
|
||||||
|
pos: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadDir {
|
||||||
|
fn new(inner: InnerReadDir) -> Self {
|
||||||
|
Self { inner: Arc::new(inner), pos: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DirEntry {
|
||||||
|
/// path to the entry
|
||||||
|
root: PathBuf,
|
||||||
|
/// 64-bit inode number
|
||||||
|
ino: u64,
|
||||||
|
/// File type
|
||||||
|
type_: u32,
|
||||||
|
/// name of the entry
|
||||||
|
name: OsString,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct OpenOptions {
|
pub struct OpenOptions {
|
||||||
@ -41,72 +83,87 @@ pub struct OpenOptions {
|
|||||||
#[derive(Copy, Clone, Debug, Default)]
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
pub struct FileTimes {}
|
pub struct FileTimes {}
|
||||||
|
|
||||||
pub struct FilePermissions(!);
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct FilePermissions {
|
||||||
|
mode: u32,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FileType(!);
|
#[derive(Copy, Clone, Eq, Debug)]
|
||||||
|
pub struct FileType {
|
||||||
|
mode: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
impl PartialEq for FileType {
|
||||||
pub struct DirBuilder {}
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.mode == other.mode
|
||||||
impl FileAttr {
|
|
||||||
pub fn size(&self) -> u64 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn perm(&self) -> FilePermissions {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn file_type(&self) -> FileType {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn created(&self) -> io::Result<SystemTime> {
|
|
||||||
self.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for FileAttr {
|
impl core::hash::Hash for FileType {
|
||||||
fn clone(&self) -> FileAttr {
|
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||||
self.0
|
self.mode.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DirBuilder {
|
||||||
|
mode: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileAttr {
|
||||||
|
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||||
|
Ok(SystemTime::new(
|
||||||
|
self.stat_val.st_mtime.try_into().unwrap(),
|
||||||
|
self.stat_val.st_mtime_nsec.try_into().unwrap(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||||
|
Ok(SystemTime::new(
|
||||||
|
self.stat_val.st_atime.try_into().unwrap(),
|
||||||
|
self.stat_val.st_atime_nsec.try_into().unwrap(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn created(&self) -> io::Result<SystemTime> {
|
||||||
|
Ok(SystemTime::new(
|
||||||
|
self.stat_val.st_ctime.try_into().unwrap(),
|
||||||
|
self.stat_val.st_ctime_nsec.try_into().unwrap(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> u64 {
|
||||||
|
self.stat_val.st_size as u64
|
||||||
|
}
|
||||||
|
pub fn perm(&self) -> FilePermissions {
|
||||||
|
FilePermissions { mode: (self.stat_val.st_mode) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_type(&self) -> FileType {
|
||||||
|
let masked_mode = self.stat_val.st_mode & S_IFMT;
|
||||||
|
let mode = match masked_mode {
|
||||||
|
S_IFDIR => DT_DIR,
|
||||||
|
S_IFLNK => DT_LNK,
|
||||||
|
S_IFREG => DT_REG,
|
||||||
|
_ => DT_UNKNOWN,
|
||||||
|
};
|
||||||
|
FileType { mode: mode }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FilePermissions {
|
impl FilePermissions {
|
||||||
pub fn readonly(&self) -> bool {
|
pub fn readonly(&self) -> bool {
|
||||||
self.0
|
// check if any class (owner, group, others) has write permission
|
||||||
|
self.mode & 0o222 == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_readonly(&mut self, _readonly: bool) {
|
pub fn set_readonly(&mut self, _readonly: bool) {
|
||||||
self.0
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for FilePermissions {
|
#[allow(dead_code)]
|
||||||
fn clone(&self) -> FilePermissions {
|
pub fn mode(&self) -> u32 {
|
||||||
self.0
|
self.mode as u32
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for FilePermissions {
|
|
||||||
fn eq(&self, _other: &FilePermissions) -> bool {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for FilePermissions {}
|
|
||||||
|
|
||||||
impl fmt::Debug for FilePermissions {
|
|
||||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
self.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,49 +174,21 @@ impl FileTimes {
|
|||||||
|
|
||||||
impl FileType {
|
impl FileType {
|
||||||
pub fn is_dir(&self) -> bool {
|
pub fn is_dir(&self) -> bool {
|
||||||
self.0
|
self.mode == DT_DIR
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_file(&self) -> bool {
|
pub fn is_file(&self) -> bool {
|
||||||
self.0
|
self.mode == DT_REG
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_symlink(&self) -> bool {
|
pub fn is_symlink(&self) -> bool {
|
||||||
self.0
|
self.mode == DT_LNK
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for FileType {
|
|
||||||
fn clone(&self) -> FileType {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Copy for FileType {}
|
|
||||||
|
|
||||||
impl PartialEq for FileType {
|
|
||||||
fn eq(&self, _other: &FileType) -> bool {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for FileType {}
|
|
||||||
|
|
||||||
impl Hash for FileType {
|
|
||||||
fn hash<H: Hasher>(&self, _h: &mut H) {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for FileType {
|
|
||||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
self.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for ReadDir {
|
impl fmt::Debug for ReadDir {
|
||||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
self.0
|
// This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
|
||||||
|
// Thus the result will be e.g. 'ReadDir("/home")'
|
||||||
|
fmt::Debug::fmt(&*self.inner.root, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,25 +196,78 @@ impl Iterator for ReadDir {
|
|||||||
type Item = io::Result<DirEntry>;
|
type Item = io::Result<DirEntry>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||||
self.0
|
let mut counter: usize = 0;
|
||||||
|
let mut offset: i64 = 0;
|
||||||
|
|
||||||
|
// loop over all directory entries and search the entry for the current position
|
||||||
|
loop {
|
||||||
|
// leave function, if the loop reaches the of the buffer (with all entries)
|
||||||
|
if offset >= self.inner.dir.len().try_into().unwrap() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dir = unsafe {
|
||||||
|
&*(self.inner.dir.as_ptr().offset(offset.try_into().unwrap()) as *const dirent64)
|
||||||
|
};
|
||||||
|
|
||||||
|
if counter == self.pos.try_into().unwrap() {
|
||||||
|
self.pos += 1;
|
||||||
|
|
||||||
|
// After dirent64, the file name is stored. d_reclen represents the length of the dirent64
|
||||||
|
// plus the length of the file name. Consequently, file name has a size of d_reclen minus
|
||||||
|
// the size of dirent64. The file name is always a C string and terminated by `\0`.
|
||||||
|
// Consequently, we are able to ignore the last byte.
|
||||||
|
let name_bytes = unsafe {
|
||||||
|
core::slice::from_raw_parts(
|
||||||
|
&dir.d_name as *const _ as *const u8,
|
||||||
|
dir.d_reclen as usize - core::mem::size_of::<dirent64>() - 1,
|
||||||
|
)
|
||||||
|
.to_vec()
|
||||||
|
};
|
||||||
|
let entry = DirEntry {
|
||||||
|
root: self.inner.root.clone(),
|
||||||
|
ino: dir.d_ino,
|
||||||
|
type_: dir.d_type as u32,
|
||||||
|
name: OsString::from_vec(name_bytes),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(Ok(entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
counter += 1;
|
||||||
|
|
||||||
|
// move to the next dirent64, which is directly stored after the previous one
|
||||||
|
offset = offset + dir.d_off;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DirEntry {
|
impl DirEntry {
|
||||||
pub fn path(&self) -> PathBuf {
|
pub fn path(&self) -> PathBuf {
|
||||||
self.0
|
self.root.join(self.file_name_os_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_name(&self) -> OsString {
|
pub fn file_name(&self) -> OsString {
|
||||||
self.0
|
self.file_name_os_str().to_os_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||||
self.0
|
let mut path = self.path();
|
||||||
|
path.set_file_name(self.file_name_os_str());
|
||||||
|
lstat(&path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_type(&self) -> io::Result<FileType> {
|
pub fn file_type(&self) -> io::Result<FileType> {
|
||||||
self.0
|
Ok(FileType { mode: self.type_ as u32 })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn ino(&self) -> u64 {
|
||||||
|
self.ino
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_name_os_str(&self) -> &OsStr {
|
||||||
|
self.name.as_os_str()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +370,9 @@ impl File {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||||
Err(Error::from_raw_os_error(22))
|
let mut stat_val: stat_struct = unsafe { mem::zeroed() };
|
||||||
|
self.0.fstat(&mut stat_val)?;
|
||||||
|
Ok(FileAttr::from_stat(stat_val))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fsync(&self) -> io::Result<()> {
|
pub fn fsync(&self) -> io::Result<()> {
|
||||||
@ -357,11 +441,18 @@ impl File {
|
|||||||
|
|
||||||
impl DirBuilder {
|
impl DirBuilder {
|
||||||
pub fn new() -> DirBuilder {
|
pub fn new() -> DirBuilder {
|
||||||
DirBuilder {}
|
DirBuilder { mode: 0o777 }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
|
pub fn mkdir(&self, path: &Path) -> io::Result<()> {
|
||||||
unsupported()
|
run_path_with_cstr(path, &|path| {
|
||||||
|
cvt(unsafe { abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn set_mode(&mut self, mode: u32) {
|
||||||
|
self.mode = mode as u32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,8 +507,43 @@ impl FromRawFd for File {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
|
pub fn readdir(path: &Path) -> io::Result<ReadDir> {
|
||||||
unsupported()
|
let fd_raw = run_path_with_cstr(path, &|path| cvt(unsafe { abi::opendir(path.as_ptr()) }))?;
|
||||||
|
let fd = unsafe { FileDesc::from_raw_fd(fd_raw as i32) };
|
||||||
|
let root = path.to_path_buf();
|
||||||
|
|
||||||
|
// read all director entries
|
||||||
|
let mut vec: Vec<u8> = Vec::new();
|
||||||
|
let mut sz = 512;
|
||||||
|
loop {
|
||||||
|
// reserve memory to receive all directory entries
|
||||||
|
vec.resize(sz, 0);
|
||||||
|
|
||||||
|
let readlen =
|
||||||
|
unsafe { abi::getdents64(fd.as_raw_fd(), vec.as_mut_ptr() as *mut dirent64, sz) };
|
||||||
|
if readlen > 0 {
|
||||||
|
// shrink down to the minimal size
|
||||||
|
vec.resize(readlen.try_into().unwrap(), 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the buffer is too small, getdents64 returns EINVAL
|
||||||
|
// otherwise, getdents64 returns an error number
|
||||||
|
if readlen != (-abi::errno::EINVAL).into() {
|
||||||
|
return Err(Error::from_raw_os_error(readlen.try_into().unwrap()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// we don't have enough memory => try to increase the vector size
|
||||||
|
sz = sz * 2;
|
||||||
|
|
||||||
|
// 1 MB for directory entries should be enough
|
||||||
|
// stop here to avoid an endless loop
|
||||||
|
if sz > 0x100000 {
|
||||||
|
return Err(Error::from(ErrorKind::Uncategorized));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ReadDir::new(InnerReadDir::new(root, vec)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unlink(path: &Path) -> io::Result<()> {
|
pub fn unlink(path: &Path) -> io::Result<()> {
|
||||||
@ -428,17 +554,16 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
|
|||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
|
pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
|
||||||
match perm.0 {}
|
Err(Error::from_raw_os_error(22))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rmdir(_p: &Path) -> io::Result<()> {
|
pub fn rmdir(path: &Path) -> io::Result<()> {
|
||||||
unsupported()
|
run_path_with_cstr(path, &|path| cvt(unsafe { abi::rmdir(path.as_ptr()) }).map(|_| ()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
|
pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
|
||||||
//unsupported()
|
unsupported()
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
|
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
|
||||||
@ -453,12 +578,20 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
|
|||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stat(_p: &Path) -> io::Result<FileAttr> {
|
pub fn stat(path: &Path) -> io::Result<FileAttr> {
|
||||||
unsupported()
|
run_path_with_cstr(path, &|path| {
|
||||||
|
let mut stat_val: stat_struct = unsafe { mem::zeroed() };
|
||||||
|
cvt(unsafe { abi::stat(path.as_ptr(), &mut stat_val) })?;
|
||||||
|
Ok(FileAttr::from_stat(stat_val))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
|
pub fn lstat(path: &Path) -> io::Result<FileAttr> {
|
||||||
unsupported()
|
run_path_with_cstr(path, &|path| {
|
||||||
|
let mut stat_val: stat_struct = unsafe { mem::zeroed() };
|
||||||
|
cvt(unsafe { abi::lstat(path.as_ptr(), &mut stat_val) })?;
|
||||||
|
Ok(FileAttr::from_stat(stat_val))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
|
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
|
||||||
|
@ -18,6 +18,12 @@ impl Timespec {
|
|||||||
Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } }
|
Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fn new(tv_sec: i64, tv_nsec: i64) -> Timespec {
|
||||||
|
assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC as i64);
|
||||||
|
// SAFETY: The assert above checks tv_nsec is within the valid range
|
||||||
|
Timespec { t: timespec { tv_sec: tv_sec, tv_nsec: tv_nsec } }
|
||||||
|
}
|
||||||
|
|
||||||
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
|
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
|
||||||
if self >= other {
|
if self >= other {
|
||||||
Ok(if self.t.tv_nsec >= other.t.tv_nsec {
|
Ok(if self.t.tv_nsec >= other.t.tv_nsec {
|
||||||
@ -195,6 +201,10 @@ pub struct SystemTime(Timespec);
|
|||||||
pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero());
|
pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero());
|
||||||
|
|
||||||
impl SystemTime {
|
impl SystemTime {
|
||||||
|
pub fn new(tv_sec: i64, tv_nsec: i64) -> SystemTime {
|
||||||
|
SystemTime(Timespec::new(tv_sec, tv_nsec))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn now() -> SystemTime {
|
pub fn now() -> SystemTime {
|
||||||
let mut time: Timespec = Timespec::zero();
|
let mut time: Timespec = Timespec::zero();
|
||||||
let _ = unsafe { abi::clock_gettime(CLOCK_REALTIME, core::ptr::addr_of_mut!(time.t)) };
|
let _ = unsafe { abi::clock_gettime(CLOCK_REALTIME, core::ptr::addr_of_mut!(time.t)) };
|
||||||
|
@ -12,7 +12,6 @@ use rustc_errors::Applicability;
|
|||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
|
use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
|
||||||
use rustc_hir_typeck::{FnCtxt, TypeckRootCtxt};
|
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::mir::Mutability;
|
use rustc_middle::mir::Mutability;
|
||||||
@ -437,9 +436,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
|
|||||||
Node::Item(item) => {
|
Node::Item(item) => {
|
||||||
if let ItemKind::Fn(_, _, body_id) = &item.kind
|
if let ItemKind::Fn(_, _, body_id) = &item.kind
|
||||||
&& let output_ty = return_ty(cx, item.owner_id)
|
&& let output_ty = return_ty(cx, item.owner_id)
|
||||||
&& let root_ctxt = TypeckRootCtxt::new(cx.tcx, item.owner_id.def_id)
|
&& rustc_hir_typeck::can_coerce(cx.tcx, cx.param_env, item.owner_id.def_id, ty, output_ty)
|
||||||
&& let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, item.owner_id.def_id)
|
|
||||||
&& fn_ctxt.can_coerce(ty, output_ty)
|
|
||||||
{
|
{
|
||||||
if has_lifetime(output_ty) && has_lifetime(ty) {
|
if has_lifetime(output_ty) && has_lifetime(ty) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -66,7 +66,7 @@ declare_clippy_lint! {
|
|||||||
///
|
///
|
||||||
/// ### Known problems
|
/// ### Known problems
|
||||||
/// The lint does not work properly with desugaring and
|
/// The lint does not work properly with desugaring and
|
||||||
/// macro, it has been allowed in the mean time.
|
/// macro, it has been allowed in the meantime.
|
||||||
///
|
///
|
||||||
/// ### Example
|
/// ### Example
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use super::utils::check_cast;
|
use rustc_hir_typeck::cast::check_cast;
|
||||||
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(
|
|||||||
) -> bool {
|
) -> bool {
|
||||||
use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
|
use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
|
||||||
let mut app = Applicability::MachineApplicable;
|
let mut app = Applicability::MachineApplicable;
|
||||||
let mut sugg = match check_cast(cx, e, from_ty, to_ty) {
|
let mut sugg = match check_cast(cx.tcx, cx.param_env, e, from_ty, to_ty) {
|
||||||
Some(FnPtrAddrCast | PtrAddrCast) if const_context => return false,
|
Some(FnPtrAddrCast | PtrAddrCast) if const_context => return false,
|
||||||
Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
|
Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
|
||||||
Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
|
Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::Expr;
|
|
||||||
use rustc_hir_typeck::{cast, FnCtxt, TypeckRootCtxt};
|
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty::cast::CastKind;
|
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
use rustc_span::DUMMY_SP;
|
|
||||||
|
|
||||||
// check if the component types of the transmuted collection and the result have different ABI,
|
// check if the component types of the transmuted collection and the result have different ABI,
|
||||||
// size or alignment
|
// size or alignment
|
||||||
@ -20,35 +15,3 @@ pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of
|
|
||||||
/// the cast. In certain cases, including some invalid casts from array references
|
|
||||||
/// to pointers, this may cause additional errors to be emitted and/or ICE error
|
|
||||||
/// messages. This function will panic if that occurs.
|
|
||||||
pub(super) fn check_cast<'tcx>(
|
|
||||||
cx: &LateContext<'tcx>,
|
|
||||||
e: &'tcx Expr<'_>,
|
|
||||||
from_ty: Ty<'tcx>,
|
|
||||||
to_ty: Ty<'tcx>,
|
|
||||||
) -> Option<CastKind> {
|
|
||||||
let hir_id = e.hir_id;
|
|
||||||
let local_def_id = hir_id.owner.def_id;
|
|
||||||
|
|
||||||
let root_ctxt = TypeckRootCtxt::new(cx.tcx, local_def_id);
|
|
||||||
let fn_ctxt = FnCtxt::new(&root_ctxt, cx.param_env, local_def_id);
|
|
||||||
|
|
||||||
if let Ok(check) = cast::CastCheck::new(
|
|
||||||
&fn_ctxt,
|
|
||||||
e,
|
|
||||||
from_ty,
|
|
||||||
to_ty,
|
|
||||||
// We won't show any error to the user, so we don't care what the span is here.
|
|
||||||
DUMMY_SP,
|
|
||||||
DUMMY_SP,
|
|
||||||
hir::Constness::NotConst,
|
|
||||||
) {
|
|
||||||
check.do_check(&fn_ctxt).ok()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,7 +4,7 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
|||||||
|
|
||||||
error: the compiler unexpectedly panicked. this is a bug.
|
error: the compiler unexpectedly panicked. this is a bug.
|
||||||
|
|
||||||
note: it seems that this compiler <version> is outdated, a newer nightly should have been released in the mean time
|
note: it seems that this compiler <version> is outdated, a newer nightly should have been released in the meantime
|
||||||
|
|
|
|
||||||
= note: please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
|
= note: please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
|
||||||
= note: if the problem still persists, we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml
|
= note: if the problem still persists, we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml
|
||||||
|
67
tests/codegen/vecdeque_pop_push.rs
Normal file
67
tests/codegen/vecdeque_pop_push.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
//@ compile-flags: -O
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// CHECK-LABEL: @noop_back(
|
||||||
|
pub fn noop_back(v: &mut VecDeque<u8>) {
|
||||||
|
// CHECK-NOT: grow
|
||||||
|
// CHECK: tail call void @llvm.assume
|
||||||
|
// CHECK-NOT: grow
|
||||||
|
// CHECK: ret
|
||||||
|
if let Some(x) = v.pop_back() {
|
||||||
|
v.push_back(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// CHECK-LABEL: @noop_front(
|
||||||
|
pub fn noop_front(v: &mut VecDeque<u8>) {
|
||||||
|
// CHECK-NOT: grow
|
||||||
|
// CHECK: tail call void @llvm.assume
|
||||||
|
// CHECK-NOT: grow
|
||||||
|
// CHECK: ret
|
||||||
|
if let Some(x) = v.pop_front() {
|
||||||
|
v.push_front(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// CHECK-LABEL: @move_byte_front_to_back(
|
||||||
|
pub fn move_byte_front_to_back(v: &mut VecDeque<u8>) {
|
||||||
|
// CHECK-NOT: grow
|
||||||
|
// CHECK: tail call void @llvm.assume
|
||||||
|
// CHECK-NOT: grow
|
||||||
|
// CHECK: ret
|
||||||
|
if let Some(x) = v.pop_front() {
|
||||||
|
v.push_back(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// CHECK-LABEL: @move_byte_back_to_front(
|
||||||
|
pub fn move_byte_back_to_front(v: &mut VecDeque<u8>) {
|
||||||
|
// CHECK-NOT: grow
|
||||||
|
// CHECK: tail call void @llvm.assume
|
||||||
|
// CHECK-NOT: grow
|
||||||
|
// CHECK: ret
|
||||||
|
if let Some(x) = v.pop_back() {
|
||||||
|
v.push_front(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// CHECK-LABEL: @push_back_byte(
|
||||||
|
pub fn push_back_byte(v: &mut VecDeque<u8>) {
|
||||||
|
// CHECK: call {{.*}}grow
|
||||||
|
v.push_back(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// CHECK-LABEL: @push_front_byte(
|
||||||
|
pub fn push_front_byte(v: &mut VecDeque<u8>) {
|
||||||
|
// CHECK: call {{.*}}grow
|
||||||
|
v.push_front(3);
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
//@ check-pass
|
|
||||||
|
|
||||||
#![warn(unnameable_types)] //~ WARN unknown lint
|
|
||||||
fn main() {}
|
|
@ -1,14 +0,0 @@
|
|||||||
warning: unknown lint: `unnameable_types`
|
|
||||||
--> $DIR/feature-gate-type_privacy_lints.rs:3:1
|
|
||||||
|
|
|
||||||
LL | #![warn(unnameable_types)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: the `unnameable_types` lint is unstable
|
|
||||||
= note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
|
|
||||||
= help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
|
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
|
||||||
= note: `#[warn(unknown_lints)]` on by default
|
|
||||||
|
|
||||||
warning: 1 warning emitted
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
|||||||
#![feature(type_privacy_lints)]
|
|
||||||
#![deny(unnameable_types)]
|
#![deny(unnameable_types)]
|
||||||
|
|
||||||
mod m {
|
mod m {
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
error: struct `PubStruct` is reachable but cannot be named
|
error: struct `PubStruct` is reachable but cannot be named
|
||||||
--> $DIR/unnameable_types.rs:5:5
|
--> $DIR/unnameable_types.rs:4:5
|
||||||
|
|
|
|
||||||
LL | pub struct PubStruct(pub i32);
|
LL | pub struct PubStruct(pub i32);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)`
|
| ^^^^^^^^^^^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)`
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/unnameable_types.rs:2:9
|
--> $DIR/unnameable_types.rs:1:9
|
||||||
|
|
|
|
||||||
LL | #![deny(unnameable_types)]
|
LL | #![deny(unnameable_types)]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: enum `PubE` is reachable but cannot be named
|
error: enum `PubE` is reachable but cannot be named
|
||||||
--> $DIR/unnameable_types.rs:7:5
|
--> $DIR/unnameable_types.rs:6:5
|
||||||
|
|
|
|
||||||
LL | pub enum PubE {
|
LL | pub enum PubE {
|
||||||
| ^^^^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)`
|
| ^^^^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)`
|
||||||
|
|
||||||
error: trait `PubTr` is reachable but cannot be named
|
error: trait `PubTr` is reachable but cannot be named
|
||||||
--> $DIR/unnameable_types.rs:11:5
|
--> $DIR/unnameable_types.rs:10:5
|
||||||
|
|
|
|
||||||
LL | pub trait PubTr {
|
LL | pub trait PubTr {
|
||||||
| ^^^^^^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)`
|
| ^^^^^^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user