Auto merge of #129443 - matthiaskrgr:rollup-tbgdj0p, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #127623 (fix: fs::remove_dir_all: treat internal ENOENT as success)
 - #128876 (Ship MinGW-w64 runtime DLLs along with `rust-lld.exe` for `-pc-windows-gnu` targets)
 - #129055 (Migrate `x86_64-fortanix-unknown-sgx-lvi` `run-make` test to rmake)
 - #129386 (Use a LocalDefId in ResolvedArg.)
 - #129400 (Update `compiler_builtins` to `0.1.120`)
 - #129414 (Fix extern crates not being hidden with `doc(hidden)`)
 - #129417 (Don't trigger refinement lint if predicates reference errors)
 - #129433 (Fix a missing import in a doc in run-make-support)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-08-23 08:31:26 +00:00
commit c8b14ba7b6
35 changed files with 406 additions and 225 deletions

View File

@ -529,7 +529,7 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
match tcx.named_bound_var(hir_id) {
Some(ResolvedArg::EarlyBound(def_id)) => {
expected_captures.insert(def_id);
expected_captures.insert(def_id.to_def_id());
// Make sure we allow capturing these lifetimes through `Self` and
// `T::Assoc` projection syntax, too. These will occur when we only
@ -538,7 +538,7 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
// feature -- see <https://github.com/rust-lang/rust/pull/115659>.
if let DefKind::LifetimeParam = tcx.def_kind(def_id)
&& let Some(def_id) = tcx
.map_opaque_lifetime_to_parent_lifetime(def_id.expect_local())
.map_opaque_lifetime_to_parent_lifetime(def_id)
.opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id()))
{
shadowed_captures.insert(def_id);

View File

@ -7,7 +7,8 @@ use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT
use rustc_middle::span_bug;
use rustc_middle::traits::{ObligationCause, Reveal};
use rustc_middle::ty::{
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor,
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor,
};
use rustc_span::Span;
use rustc_trait_selection::regions::InferCtxtRegionExt;
@ -177,6 +178,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
return;
};
if trait_bounds.references_error() || impl_bounds.references_error() {
return;
}
// For quicker lookup, use an `IndexSet` (we don't use one earlier because
// it's not foldable..).
// Also, We have to anonymize binders in these types because they may contain

View File

@ -13,7 +13,6 @@ use rustc_ast::visit::walk_list;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node};
use rustc_macros::extension;
@ -22,7 +21,7 @@ use rustc_middle::middle::resolve_bound_vars::*;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
@ -32,7 +31,7 @@ use crate::errors;
impl ResolvedArg {
fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
debug!("ResolvedArg::early: def_id={:?}", param.def_id);
(param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id()))
(param.def_id, ResolvedArg::EarlyBound(param.def_id))
}
fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
@ -41,10 +40,10 @@ impl ResolvedArg {
"ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
idx, param, depth, param.def_id,
);
(param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id.to_def_id()))
(param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id))
}
fn id(&self) -> Option<DefId> {
fn id(&self) -> Option<LocalDefId> {
match *self {
ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None,
@ -288,13 +287,14 @@ fn late_arg_as_bound_arg<'tcx>(
) -> ty::BoundVariableKind {
match arg {
ResolvedArg::LateBound(_, _, def_id) => {
let name = tcx.hir().name(tcx.local_def_id_to_hir_id(def_id.expect_local()));
let def_id = def_id.to_def_id();
let name = tcx.item_name(def_id);
match param.kind {
GenericParamKind::Lifetime { .. } => {
ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
ty::BoundVariableKind::Region(ty::BrNamed(def_id, name))
}
GenericParamKind::Type { .. } => {
ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(*def_id, name))
ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, name))
}
GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
}
@ -717,7 +717,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
// In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.hir_id).copied();
let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue };
let Some(lifetime_def_id) = lifetime_def_id.as_local() else { continue };
let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id))
@ -1150,7 +1149,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
.param_def_id_to_index(self.tcx, region_def_id.to_def_id())
.is_some()
{
break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id()));
break Some(ResolvedArg::EarlyBound(region_def_id));
}
break None;
}
@ -1259,7 +1258,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
kind => span_bug!(
use_span,
"did not expect to resolve lifetime to {}",
kind.descr(param_def_id)
kind.descr(param_def_id.to_def_id())
),
};
def = ResolvedArg::Error(guar);
@ -1277,10 +1276,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
kind: hir::ImplItemKind::Fn(..),
..
}) => {
def = ResolvedArg::Free(owner_id.to_def_id(), def.id().unwrap());
def = ResolvedArg::Free(owner_id.def_id, def.id().unwrap());
}
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
def = ResolvedArg::Free(closure.def_id.to_def_id(), def.id().unwrap());
def = ResolvedArg::Free(closure.def_id, def.id().unwrap());
}
_ => {}
}
@ -1351,7 +1350,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
.param_def_id_to_index(self.tcx, param_def_id.to_def_id())
.is_some()
{
break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id()));
break Some(ResolvedArg::EarlyBound(param_def_id));
}
break None;
}

View File

@ -296,25 +296,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static,
Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
let name = lifetime_name(def_id.expect_local());
let name = lifetime_name(def_id);
let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(index),
kind: ty::BrNamed(def_id, name),
kind: ty::BrNamed(def_id.to_def_id(), name),
};
ty::Region::new_bound(tcx, debruijn, br)
}
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
let name = tcx.hir().ty_param_name(def_id.expect_local());
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
let name = tcx.hir().ty_param_name(def_id);
let item_def_id = tcx.hir().ty_param_owner(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
ty::Region::new_early_param(tcx, ty::EarlyParamRegion { index, name })
}
Some(rbv::ResolvedArg::Free(scope, id)) => {
let name = lifetime_name(id.expect_local());
ty::Region::new_late_param(tcx, scope, ty::BrNamed(id, name))
let name = lifetime_name(id);
ty::Region::new_late_param(
tcx,
scope.to_def_id(),
ty::BrNamed(id.to_def_id(), name),
)
// (*) -- not late-bound, won't change
}
@ -1953,15 +1957,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let tcx = self.tcx();
match tcx.named_bound_var(hir_id) {
Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
let name = tcx.item_name(def_id);
let name = tcx.item_name(def_id.to_def_id());
let br = ty::BoundTy {
var: ty::BoundVar::from_u32(index),
kind: ty::BoundTyKind::Param(def_id, name),
kind: ty::BoundTyKind::Param(def_id.to_def_id(), name),
};
Ty::new_bound(tcx, debruijn, br)
}
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
let def_id = def_id.expect_local();
let item_def_id = tcx.hir().ty_param_owner(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
@ -1982,10 +1985,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
// Find the name and index of the const parameter by indexing the generics of
// the parent item and construct a `ParamConst`.
let item_def_id = tcx.parent(def_id);
let item_def_id = tcx.local_parent(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
let name = tcx.item_name(def_id);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
let name = tcx.item_name(def_id.to_def_id());
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
}
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {

View File

@ -1925,8 +1925,8 @@ impl ExplicitOutlivesRequirements {
fn lifetimes_outliving_lifetime<'tcx>(
tcx: TyCtxt<'tcx>,
inferred_outlives: impl Iterator<Item = &'tcx (ty::Clause<'tcx>, Span)>,
item: DefId,
lifetime: DefId,
item: LocalDefId,
lifetime: LocalDefId,
) -> Vec<ty::Region<'tcx>> {
let item_generics = tcx.generics_of(item);
@ -1934,7 +1934,7 @@ impl ExplicitOutlivesRequirements {
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
ty::ReEarlyParam(ebr)
if item_generics.region_param(ebr, tcx).def_id == lifetime =>
if item_generics.region_param(ebr, tcx).def_id == lifetime.to_def_id() =>
{
Some(b)
}
@ -1982,7 +1982,7 @@ impl ExplicitOutlivesRequirements {
let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
.iter()
.any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id })),
.any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id.to_def_id() })),
_ => false,
};
@ -2097,7 +2097,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
inferred_outlives
.iter()
.filter(|(_, span)| !predicate.span.contains(*span)),
item.owner_id.to_def_id(),
item.owner_id.def_id,
region_def_id,
),
&predicate.bounds,

View File

@ -300,16 +300,17 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
Some(
ResolvedArg::EarlyBound(def_id) | ResolvedArg::LateBound(_, _, def_id),
) => {
if self.tcx.def_kind(self.tcx.parent(def_id)) == DefKind::OpaqueTy {
if self.tcx.def_kind(self.tcx.local_parent(def_id)) == DefKind::OpaqueTy
{
let def_id = self
.tcx
.map_opaque_lifetime_to_parent_lifetime(def_id.expect_local())
.map_opaque_lifetime_to_parent_lifetime(def_id)
.opt_param_def_id(self.tcx, self.parent_def_id.to_def_id())
.expect("variable should have been duplicated from parent");
explicitly_captured.insert(def_id);
} else {
explicitly_captured.insert(def_id);
explicitly_captured.insert(def_id.to_def_id());
}
}
_ => {

View File

@ -2,7 +2,7 @@
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{ItemLocalId, OwnerId};
use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable};
@ -11,9 +11,9 @@ use crate::ty;
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum ResolvedArg {
StaticLifetime,
EarlyBound(/* decl */ DefId),
LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId),
Free(DefId, /* lifetime decl */ DefId),
EarlyBound(/* decl */ LocalDefId),
LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ LocalDefId),
Free(LocalDefId, /* lifetime decl */ LocalDefId),
Error(ErrorGuaranteed),
}

View File

@ -3035,13 +3035,13 @@ impl<'tcx> TyCtxt<'tcx> {
match self.named_bound_var(lifetime.hir_id) {
Some(resolve_bound_vars::ResolvedArg::EarlyBound(ebv)) => {
let new_parent = self.parent(ebv);
let new_parent = self.local_parent(ebv);
// If we map to another opaque, then it should be a parent
// of the opaque we mapped from. Continue mapping.
if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) {
debug_assert_eq!(self.parent(parent.to_def_id()), new_parent);
opaque_lifetime_param_def_id = ebv.expect_local();
debug_assert_eq!(self.local_parent(parent), new_parent);
opaque_lifetime_param_def_id = ebv;
continue;
}
@ -3050,20 +3050,20 @@ impl<'tcx> TyCtxt<'tcx> {
self,
ty::EarlyParamRegion {
index: generics
.param_def_id_to_index(self, ebv)
.param_def_id_to_index(self, ebv.to_def_id())
.expect("early-bound var should be present in fn generics"),
name: self.hir().name(self.local_def_id_to_hir_id(ebv.expect_local())),
name: self.item_name(ebv.to_def_id()),
},
);
}
Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => {
let new_parent = self.parent(lbv);
let new_parent = self.local_parent(lbv);
return ty::Region::new_late_param(
self,
new_parent,
new_parent.to_def_id(),
ty::BoundRegionKind::BrNamed(
lbv,
self.hir().name(self.local_def_id_to_hir_id(lbv.expect_local())),
lbv.to_def_id(),
self.item_name(lbv.to_def_id()),
),
);
}

View File

@ -101,7 +101,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
// region at the right depth with the same index
(Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id {
if id.to_def_id() == def_id {
return ControlFlow::Break(arg);
}
}
@ -118,7 +118,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
debruijn_index
);
debug!("LateBound id={:?} def_id={:?}", id, def_id);
if debruijn_index == self.current_index && id == def_id {
if debruijn_index == self.current_index && id.to_def_id() == def_id {
return ControlFlow::Break(arg);
}
}
@ -192,7 +192,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
// the lifetime of the TyPath!
(Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id {
if id.to_def_id() == def_id {
return ControlFlow::Break(());
}
}
@ -201,7 +201,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
debug!("id={:?}", id);
debug!("def_id={:?}", def_id);
if debruijn_index == self.current_index && id == def_id {
if debruijn_index == self.current_index && id.to_def_id() == def_id {
return ControlFlow::Break(());
}
}

View File

@ -58,9 +58,9 @@ dependencies = [
[[package]]
name = "compiler_builtins"
version = "0.1.118"
version = "0.1.120"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92afe7344b64cccf3662ca26d5d1c0828ab826f04206b97d856e3625e390e4b5"
checksum = "38c44e9c76d996d8049dee591a997eab801069ad86ed892ed3039f68b73d301c"
dependencies = [
"cc",
"rustc-std-workspace-core",

View File

@ -10,7 +10,7 @@ edition = "2021"
[dependencies]
core = { path = "../core" }
compiler_builtins = { version = "0.1.118", features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.120", features = ['rustc-dep-of-std'] }
[dev-dependencies]
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }

View File

@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core", public = true }
compiler_builtins = { version = "0.1.118" }
compiler_builtins = { version = "0.1.120" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
hashbrown = { version = "0.14", default-features = false, features = [

View File

@ -2491,6 +2491,8 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
///
/// Consider ignoring the error if validating the removal is not required for your use case.
///
/// [`io::ErrorKind::NotFound`] is only returned if no removal occurs.
///
/// [`fs::remove_file`]: remove_file
/// [`fs::remove_dir`]: remove_dir
///

View File

@ -10,6 +10,7 @@ use crate::sync::Arc;
use crate::sys::time::SystemTime;
use crate::sys::unsupported;
pub use crate::sys_common::fs::exists;
use crate::sys_common::ignore_notfound;
/// A file descriptor.
#[derive(Clone, Copy)]
@ -527,15 +528,23 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
for child in readdir(path)? {
let child = child?;
let child_type = child.file_type()?;
if child_type.is_dir() {
remove_dir_all(&child.path())?;
} else {
unlink(&child.path())?;
let result: io::Result<()> = try {
let child = child?;
let child_type = child.file_type()?;
if child_type.is_dir() {
remove_dir_all(&child.path())?;
} else {
unlink(&child.path())?;
}
};
// ignore internal NotFound errors
if let Err(err) = result
&& err.kind() != io::ErrorKind::NotFound
{
return result;
}
}
rmdir(path)
ignore_notfound(rmdir(path))
}
pub fn readlink(p: &Path) -> io::Result<PathBuf> {

View File

@ -2002,6 +2002,7 @@ mod remove_dir_impl {
use crate::path::{Path, PathBuf};
use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::{cvt, cvt_r};
use crate::sys_common::ignore_notfound;
pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> {
let fd = cvt_r(|| unsafe {
@ -2055,6 +2056,16 @@ mod remove_dir_impl {
}
}
fn is_enoent(result: &io::Result<()>) -> bool {
if let Err(err) = result
&& matches!(err.raw_os_error(), Some(libc::ENOENT))
{
true
} else {
false
}
}
fn remove_dir_all_recursive(parent_fd: Option<RawFd>, path: &CStr) -> io::Result<()> {
// try opening as directory
let fd = match openat_nofollow_dironly(parent_fd, &path) {
@ -2078,27 +2089,35 @@ mod remove_dir_impl {
for child in dir {
let child = child?;
let child_name = child.name_cstr();
match is_dir(&child) {
Some(true) => {
remove_dir_all_recursive(Some(fd), child_name)?;
}
Some(false) => {
cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?;
}
None => {
// POSIX specifies that calling unlink()/unlinkat(..., 0) on a directory can succeed
// if the process has the appropriate privileges. This however can causing orphaned
// directories requiring an fsck e.g. on Solaris and Illumos. So we try recursing
// into it first instead of trying to unlink() it.
remove_dir_all_recursive(Some(fd), child_name)?;
// we need an inner try block, because if one of these
// directories has already been deleted, then we need to
// continue the loop, not return ok.
let result: io::Result<()> = try {
match is_dir(&child) {
Some(true) => {
remove_dir_all_recursive(Some(fd), child_name)?;
}
Some(false) => {
cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?;
}
None => {
// POSIX specifies that calling unlink()/unlinkat(..., 0) on a directory can succeed
// if the process has the appropriate privileges. This however can causing orphaned
// directories requiring an fsck e.g. on Solaris and Illumos. So we try recursing
// into it first instead of trying to unlink() it.
remove_dir_all_recursive(Some(fd), child_name)?;
}
}
};
if result.is_err() && !is_enoent(&result) {
return result;
}
}
// unlink the directory after removing its contents
cvt(unsafe {
ignore_notfound(cvt(unsafe {
unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), path.as_ptr(), libc::AT_REMOVEDIR)
})?;
}))?;
Ok(())
}

View File

@ -13,7 +13,7 @@ use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::time::SystemTime;
use crate::sys::unsupported;
pub use crate::sys_common::fs::exists;
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::sys_common::{ignore_notfound, AsInner, FromInner, IntoInner};
use crate::{fmt, iter, ptr};
pub struct File {
@ -794,14 +794,22 @@ fn remove_dir_all_recursive(parent: &WasiFd, path: &Path) -> io::Result<()> {
io::const_io_error!(io::ErrorKind::Uncategorized, "invalid utf-8 file name found")
})?;
if entry.file_type()?.is_dir() {
remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?;
} else {
entry.inner.dir.fd.unlink_file(path)?;
let result: io::Result<()> = try {
if entry.file_type()?.is_dir() {
remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?;
} else {
entry.inner.dir.fd.unlink_file(path)?;
}
};
// ignore internal NotFound errors
if let Err(err) = &result
&& err.kind() != io::ErrorKind::NotFound
{
return result;
}
}
// Once all this directory's contents are deleted it should be safe to
// delete the directory tiself.
parent.remove_directory(osstr2str(path.as_ref())?)
ignore_notfound(parent.remove_directory(osstr2str(path.as_ref())?))
}

View File

@ -14,7 +14,7 @@ use crate::sys::handle::Handle;
use crate::sys::path::maybe_verbatim;
use crate::sys::time::SystemTime;
use crate::sys::{c, cvt, Align8};
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::sys_common::{ignore_notfound, AsInner, FromInner, IntoInner};
use crate::{fmt, ptr, slice, thread};
pub struct File {
@ -1160,7 +1160,7 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> {
return Err(io::Error::from_raw_os_error(c::ERROR_DIRECTORY as _));
}
match remove_dir_all_iterative(&file, File::posix_delete) {
match ignore_notfound(remove_dir_all_iterative(&file, File::posix_delete)) {
Err(e) => {
if let Some(code) = e.raw_os_error() {
match code as u32 {

View File

@ -3,6 +3,7 @@
use crate::fs;
use crate::io::{self, Error, ErrorKind};
use crate::path::Path;
use crate::sys_common::ignore_notfound;
pub(crate) const NOT_FILE_ERROR: Error = io::const_io_error!(
ErrorKind::InvalidInput,
@ -32,14 +33,22 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> {
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
for child in fs::read_dir(path)? {
let child = child?;
if child.file_type()?.is_dir() {
remove_dir_all_recursive(&child.path())?;
} else {
fs::remove_file(&child.path())?;
let result: io::Result<()> = try {
let child = child?;
if child.file_type()?.is_dir() {
remove_dir_all_recursive(&child.path())?;
} else {
fs::remove_file(&child.path())?;
}
};
// ignore internal NotFound errors to prevent race conditions
if let Err(err) = &result
&& err.kind() != io::ErrorKind::NotFound
{
return result;
}
}
fs::remove_dir(path)
ignore_notfound(fs::remove_dir(path))
}
pub fn exists(path: &Path) -> io::Result<bool> {

View File

@ -80,3 +80,11 @@ pub fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 {
// r < denom, so (denom*numer) is the upper bound of (r*numer)
q * numer + r * numer / denom
}
pub fn ignore_notfound<T>(result: crate::io::Result<T>) -> crate::io::Result<()> {
match result {
Err(err) if err.kind() == crate::io::ErrorKind::NotFound => Ok(()),
Ok(_) => Ok(()),
Err(err) => Err(err),
}
}

View File

@ -269,34 +269,45 @@ fn make_win_dist(
let target_libs = find_files(&target_libs, &lib_path);
// Copy runtime dlls next to rustc.exe
let dist_bin_dir = rust_root.join("bin/");
fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed");
for src in rustc_dlls {
builder.copy_link_to_folder(&src, &dist_bin_dir);
let rust_bin_dir = rust_root.join("bin/");
fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
for src in &rustc_dlls {
builder.copy_link_to_folder(src, &rust_bin_dir);
}
if builder.config.lld_enabled {
// rust-lld.exe also needs runtime dlls
let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
for src in &rustc_dlls {
builder.copy_link_to_folder(src, &rust_target_bin_dir);
}
}
//Copy platform tools to platform-specific bin directory
let target_bin_dir =
plat_root.join("lib").join("rustlib").join(target).join("bin").join("self-contained");
fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
let plat_target_bin_self_contained_dir =
plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
fs::create_dir_all(&plat_target_bin_self_contained_dir)
.expect("creating plat_target_bin_self_contained_dir failed");
for src in target_tools {
builder.copy_link_to_folder(&src, &target_bin_dir);
builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir);
}
// Warn windows-gnu users that the bundled GCC cannot compile C files
builder.create(
&target_bin_dir.join("GCC-WARNING.txt"),
&plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"),
"gcc.exe contained in this folder cannot be used for compiling C files - it is only \
used as a linker. In order to be able to compile projects containing C code use \
the GCC provided by MinGW or Cygwin.",
);
//Copy platform libs to platform-specific lib directory
let target_lib_dir =
plat_root.join("lib").join("rustlib").join(target).join("lib").join("self-contained");
fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
let plat_target_lib_self_contained_dir =
plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
fs::create_dir_all(&plat_target_lib_self_contained_dir)
.expect("creating plat_target_lib_self_contained_dir failed");
for src in target_libs {
builder.copy_link_to_folder(&src, &target_lib_dir);
builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
}
}

View File

@ -272,7 +272,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
| rbv::ResolvedArg::LateBound(_, _, did)
| rbv::ResolvedArg::Free(_, did),
) = cx.tcx.named_bound_var(lifetime.hir_id)
&& let Some(lt) = cx.args.get(&did).and_then(|arg| arg.as_lt())
&& let Some(lt) = cx.args.get(&did.to_def_id()).and_then(|arg| arg.as_lt())
{
return lt.clone();
}

View File

@ -2,7 +2,7 @@
use std::mem;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
@ -145,8 +145,9 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
let old = mem::replace(&mut self.update_retained, false);
let ret = self.set_is_in_hidden_item_and_fold(true, i);
self.update_retained = old;
if ret.is_crate() {
// We don't strip the crate, even if it has `#[doc(hidden)]`.
if ret.item_id == clean::ItemId::DefId(CRATE_DEF_ID.into()) {
// We don't strip the current crate, even if it has `#[doc(hidden)]`.
debug!("strip_hidden: Not strippping local crate");
Some(ret)
} else {
Some(strip_item(ret))

View File

@ -24,3 +24,11 @@ pub fn env_var_os(name: &str) -> OsString {
pub fn no_debug_assertions() -> bool {
std::env::var_os("NO_DEBUG_ASSERTIONS").is_some()
}
/// A wrapper around [`std::env::set_current_dir`] which includes the directory
/// path in the panic message.
#[track_caller]
pub fn set_current_dir<P: AsRef<std::path::Path>>(dir: P) {
std::env::set_current_dir(dir.as_ref())
.expect(&format!("could not set current directory to \"{}\"", dir.as_ref().display()));
}

View File

@ -64,7 +64,7 @@ pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
pub use diff::{diff, Diff};
/// Panic-on-fail [`std::env::var`] and [`std::env::var_os`] wrappers.
pub use env::{env_var, env_var_os};
pub use env::{env_var, env_var_os, set_current_dir};
/// Convenience helpers for running binaries and other commands.
pub use run::{cmd, run, run_fail, run_with_args};

View File

@ -21,6 +21,7 @@ pub fn cwd() -> PathBuf {
/// # Example
///
/// ```rust
/// # use run_make_support::path;
/// let p = path("support_file.txt");
/// ```
pub fn path<P: AsRef<Path>>(p: P) -> PathBuf {

View File

@ -11,4 +11,3 @@ run-make/macos-deployment-target/Makefile
run-make/split-debuginfo/Makefile
run-make/symbol-mangling-hashed/Makefile
run-make/translation/Makefile
run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile

View File

@ -0,0 +1,62 @@
//@ ignore-windows
// This test attempts to make sure that running `remove_dir_all`
// doesn't result in a NotFound error one of the files it
// is deleting is deleted concurrently.
//
// The windows implementation for `remove_dir_all` is significantly
// more complicated, and has not yet been brought up to par with
// the implementation on other platforms, so this test is marked as
// `ignore-windows` until someone more expirenced with windows can
// sort that out.
use std::fs::remove_dir_all;
use std::path::Path;
use std::thread;
use std::time::Duration;
use run_make_support::rfs::{create_dir, write};
use run_make_support::run_in_tmpdir;
fn main() {
let mut race_happened = false;
run_in_tmpdir(|| {
for i in 0..150 {
create_dir("outer");
create_dir("outer/inner");
write("outer/inner.txt", b"sometext");
thread::scope(|scope| {
let t1 = scope.spawn(|| {
thread::sleep(Duration::from_nanos(i));
remove_dir_all("outer").unwrap();
});
let race_happened_ref = &race_happened;
let t2 = scope.spawn(|| {
let r1 = remove_dir_all("outer/inner");
let r2 = remove_dir_all("outer/inner.txt");
if r1.is_ok() && r2.is_err() {
race_happened = true;
}
});
});
assert!(!Path::new("outer").exists());
// trying to remove a nonexistant top-level directory should
// still result in an error.
let Err(err) = remove_dir_all("outer") else {
panic!("removing nonexistant dir did not result in an error");
};
assert_eq!(err.kind(), std::io::ErrorKind::NotFound);
}
});
if !race_happened {
eprintln!(
"WARNING: multithreaded deletion never raced, \
try increasing the number of attempts or \
adjusting the sleep timing"
);
}
}

View File

@ -1,23 +0,0 @@
include ../tools.mk
#only-x86_64-fortanix-unknown-sgx
# For cargo setting
export RUSTC := $(RUSTC_ORIGINAL)
export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
# We need to be outside of 'src' dir in order to run cargo
export WORK_DIR := $(TMPDIR)
export TEST_DIR := $(shell pwd)
## clean up unused env variables which might cause harm.
unexport RUSTC_LINKER
unexport RUSTC_BOOTSTRAP
unexport RUST_BUILD_STAGE
unexport RUST_TEST_THREADS
unexport RUST_TEST_TMPDIR
unexport AR
unexport CC
unexport CXX
all:
bash script.sh

View File

@ -0,0 +1,96 @@
// ignore-tidy-linelength
// Reason: intel.com link
// This security test checks that the disassembled form of certain symbols
// is "hardened" - that means, the assembly instructions match a pattern that
// mitigate potential Load Value Injection vulnerabilities.
// To do so, a test crate is compiled, and certain symbols are found, disassembled
// and checked one by one.
// See https://github.com/rust-lang/rust/pull/77008
// On load value injection:
// https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/load-value-injection.html
//@ only-x86_64-fortanix-unknown-sgx
use run_make_support::{cmd, cwd, llvm_filecheck, llvm_objdump, regex, set_current_dir, target};
fn main() {
let main_dir = cwd();
set_current_dir("enclave");
// HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
// These come from the top-level Rust workspace, that this crate is not a
// member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
cmd("cargo")
.env("RUSTC_BOOTSTRAP", "1")
.arg("-v")
.arg("run")
.arg("--target")
.arg(target())
.run();
set_current_dir(&main_dir);
// Rust has various ways of adding code to a binary:
// - Rust code
// - Inline assembly
// - Global assembly
// - C/C++ code compiled as part of Rust crates
// For those different kinds, we do have very small code examples that should be
// mitigated in some way. Mostly we check that ret instructions should no longer be present.
check("unw_getcontext", "unw_getcontext.checks");
check("__libunwind_Registers_x86_64_jumpto", "jumpto.checks");
check("std::io::stdio::_print::[[:alnum:]]+", "print.with_frame_pointers.checks");
check("rust_plus_one_global_asm", "rust_plus_one_global_asm.checks");
check("cc_plus_one_c", "cc_plus_one_c.checks");
check("cc_plus_one_c_asm", "cc_plus_one_c_asm.checks");
check("cc_plus_one_cxx", "cc_plus_one_cxx.checks");
check("cc_plus_one_cxx_asm", "cc_plus_one_cxx_asm.checks");
check("cc_plus_one_asm", "cc_plus_one_asm.checks");
check("cmake_plus_one_c", "cmake_plus_one_c.checks");
check("cmake_plus_one_c_asm", "cmake_plus_one_c_asm.checks");
check("cmake_plus_one_c_global_asm", "cmake_plus_one_c_global_asm.checks");
check("cmake_plus_one_cxx", "cmake_plus_one_cxx.checks");
check("cmake_plus_one_cxx_asm", "cmake_plus_one_cxx_asm.checks");
check("cmake_plus_one_cxx_global_asm", "cmake_plus_one_cxx_global_asm.checks");
check("cmake_plus_one_asm", "cmake_plus_one_asm.checks");
}
fn check(func_re: &str, mut checks: &str) {
let dump = llvm_objdump()
.input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave")
.args(&["--syms", "--demangle"])
.run()
.stdout_utf8();
let re = regex::Regex::new(&format!("[[:blank:]]+{func_re}")).unwrap();
let func = re.find_iter(&dump).map(|m| m.as_str().trim()).collect::<Vec<&str>>().join(",");
assert!(!func.is_empty());
let dump = llvm_objdump()
.input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave")
.args(&["--demangle", &format!("--disassemble-symbols={func}")])
.run()
.stdout_utf8();
let dump = dump.as_bytes();
// Unique case, must succeed at one of two possible tests.
// This is because frame pointers are optional, and them being enabled requires
// an additional `popq` in the pattern checking file.
if func_re == "std::io::stdio::_print::[[:alnum:]]+" {
let output = llvm_filecheck().stdin(&dump).patterns(checks).run_unchecked();
if !output.status().success() {
checks = "print.without_frame_pointers.checks";
llvm_filecheck().stdin(&dump).patterns(checks).run();
}
} else {
llvm_filecheck().stdin(&dump).patterns(checks).run();
}
if !["rust_plus_one_global_asm", "cmake_plus_one_c_global_asm", "cmake_plus_one_cxx_global_asm"]
.contains(&func_re)
{
// The assembler cannot avoid explicit `ret` instructions. Sequences
// of `shlq $0x0, (%rsp); lfence; retq` are used instead.
llvm_filecheck().args(&["--implicit-check-not", "ret"]).stdin(dump).patterns(checks).run();
}
}

View File

@ -1,69 +0,0 @@
#!/bin/bash
set -exuo pipefail
function build {
CRATE=enclave
mkdir -p "${WORK_DIR}"
pushd "${WORK_DIR}"
rm -rf "${CRATE}"
cp -a "${TEST_DIR}"/enclave .
pushd $CRATE
echo "${WORK_DIR}"
# HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
# These come from the top-level Rust workspace, that this crate is not a
# member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
env RUSTC_BOOTSTRAP=1
cargo -v run --target "${TARGET}"
popd
popd
}
function check {
local func_re="$1"
local checks="${TEST_DIR}/$2"
local asm=""
local objdump="${LLVM_BIN_DIR}/llvm-objdump"
local filecheck="${LLVM_BIN_DIR}/FileCheck"
local enclave=${WORK_DIR}/enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave
asm=$(mktemp)
func="$(${objdump} --syms --demangle "${enclave}" | \
grep --only-matching -E "[[:blank:]]+${func_re}\$" | \
sed -e 's/^[[:space:]]*//' )"
${objdump} --disassemble-symbols="${func}" --demangle \
"${enclave}" > "${asm}"
${filecheck} --input-file "${asm}" "${checks}"
if [ "${func_re}" != "rust_plus_one_global_asm" ] &&
[ "${func_re}" != "cmake_plus_one_c_global_asm" ] &&
[ "${func_re}" != "cmake_plus_one_cxx_global_asm" ]; then
# The assembler cannot avoid explicit `ret` instructions. Sequences
# of `shlq $0x0, (%rsp); lfence; retq` are used instead.
# https://www.intel.com/content/www/us/en/developer/articles/technical/
# software-security-guidance/technical-documentation/load-value-injection.html
${filecheck} --implicit-check-not ret --input-file "${asm}" "${checks}"
fi
}
build
check "unw_getcontext" unw_getcontext.checks
check "__libunwind_Registers_x86_64_jumpto" jumpto.checks
check 'std::io::stdio::_print::[[:alnum:]]+' print.with_frame_pointers.checks ||
check 'std::io::stdio::_print::[[:alnum:]]+' print.without_frame_pointers.checks
check rust_plus_one_global_asm rust_plus_one_global_asm.checks
check cc_plus_one_c cc_plus_one_c.checks
check cc_plus_one_c_asm cc_plus_one_c_asm.checks
check cc_plus_one_cxx cc_plus_one_cxx.checks
check cc_plus_one_cxx_asm cc_plus_one_cxx_asm.checks
check cc_plus_one_asm cc_plus_one_asm.checks
check cmake_plus_one_c cmake_plus_one_c.checks
check cmake_plus_one_c_asm cmake_plus_one_c_asm.checks
check cmake_plus_one_c_global_asm cmake_plus_one_c_global_asm.checks
check cmake_plus_one_cxx cmake_plus_one_cxx.checks
check cmake_plus_one_cxx_asm cmake_plus_one_cxx_asm.checks
check cmake_plus_one_cxx_global_asm cmake_plus_one_cxx_global_asm.checks
check cmake_plus_one_asm cmake_plus_one_asm.checks

View File

@ -0,0 +1,27 @@
// Regression test for <https://github.com/rust-lang/rust/issues/126796>.
// `doc(hidden)` should still be able to hide extern crates, only the local crates
// cannot be hidden because we still need to generate its `index.html` file.
#![crate_name = "foo"]
#![doc(hidden)]
//@ has 'foo/index.html'
// First we check that the page contains the crate name (`foo`).
//@ has - '//*' 'foo'
// But doesn't contain any of the other items.
//@ !has - '//*' 'other'
//@ !has - '//*' 'marker'
//@ !has - '//*' 'PhantomData'
#[doc(inline)]
pub use std as other;
#[doc(inline)]
pub use std::marker;
#[doc(inline)]
pub use std::marker::PhantomData;
//@ !has - '//*' 'myself'
#[doc(inline)]
pub use crate as myself;

View File

@ -0,0 +1,14 @@
#![deny(refining_impl_trait)]
trait FromRow {
fn prepare(self) -> impl Fn() -> T;
//~^ ERROR cannot find type `T` in this scope
}
impl<T> FromRow for T {
fn prepare(self) -> impl Fn() -> T {
|| todo!()
}
}
fn main() {}

View File

@ -0,0 +1,9 @@
error[E0412]: cannot find type `T` in this scope
--> $DIR/refine-err.rs:4:38
|
LL | fn prepare(self) -> impl Fn() -> T;
| ^ not found in this scope
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0412`.

View File

@ -14,7 +14,6 @@ impl<'a, I: 'a + Iterable> Iterable for &'a I {
//~^ ERROR binding for associated type `Item` references lifetime `'missing`
//~| ERROR binding for associated type `Item` references lifetime `'missing`
//~| ERROR `()` is not an iterator
//~| WARNING impl trait in impl method signature does not match trait method signature
}
fn main() {}

View File

@ -32,24 +32,7 @@ LL | fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missin
|
= help: the trait `Iterator` is not implemented for `()`
warning: impl trait in impl method signature does not match trait method signature
--> $DIR/span-bug-issue-121457.rs:13:51
|
LL | fn iter(&self) -> impl Iterator;
| ------------- return type from trait method defined here
...
LL | fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missing>> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this bound is stronger than that defined on the trait
|
= note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate
= note: we are soliciting feedback, see issue #121718 <https://github.com/rust-lang/rust/issues/121718> for more information
= note: `#[warn(refining_impl_trait_reachable)]` on by default
help: replace the return type so that it matches the trait
|
LL | fn iter(&self) -> impl Iterator {}
| ~~~~~~~~~~~~~
error: aborting due to 4 previous errors; 1 warning emitted
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0195, E0277, E0582.
For more information about an error, try `rustc --explain E0195`.