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:
commit
c8b14ba7b6
@ -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);
|
||||
|
@ -7,7 +7,8 @@
|
||||
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
|
||||
|
@ -13,7 +13,6 @@
|
||||
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::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 @@
|
||||
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 @@ fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, 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 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'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 @@ fn resolve_lifetime_ref(
|
||||
.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 @@ fn resolve_lifetime_ref(
|
||||
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 @@ fn resolve_lifetime_ref(
|
||||
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 @@ fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: HirId) {
|
||||
.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;
|
||||
}
|
||||
|
@ -296,25 +296,29 @@ pub fn lower_lifetime(
|
||||
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 @@ pub(crate) fn lower_ty_param(&self, hir_id: HirId) -> Ty<'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 @@ pub(crate) fn lower_const_param(&self, hir_id: HirId) -> Const<'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, _)) => {
|
||||
|
@ -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 @@ fn lifetimes_outliving_lifetime<'tcx>(
|
||||
.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 @@ fn collect_outlives_bound_spans<'tcx>(
|
||||
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 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
|
||||
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,
|
||||
|
@ -300,16 +300,17 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
|
||||
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());
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -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 @@
|
||||
#[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),
|
||||
}
|
||||
|
||||
|
@ -3035,13 +3035,13 @@ pub fn map_opaque_lifetime_to_parent_lifetime(
|
||||
|
||||
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 @@ pub fn map_opaque_lifetime_to_parent_lifetime(
|
||||
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()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
||||
// 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 @@ fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
||||
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 @@ fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) -> Self::Result {
|
||||
// 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 @@ fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) -> Self::Result {
|
||||
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(());
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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"] }
|
||||
|
@ -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 = [
|
||||
|
@ -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
|
||||
///
|
||||
|
@ -10,6 +10,7 @@
|
||||
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> {
|
||||
|
@ -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 @@ fn is_dir(ent: &DirEntry) -> Option<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ fn remove_dir_all_recursive(parent_fd: Option<RawFd>, path: &CStr) -> io::Result
|
||||
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(())
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
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())?))
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
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 {
|
||||
|
@ -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> {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||
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))
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ pub mod rfs {
|
||||
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};
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
62
tests/run-make/remove-dir-all-race/rmake.rs
Normal file
62
tests/run-make/remove-dir-all-race/rmake.rs
Normal 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"
|
||||
);
|
||||
}
|
||||
}
|
@ -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
|
96
tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
Normal file
96
tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
Normal 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();
|
||||
}
|
||||
}
|
@ -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
|
27
tests/rustdoc/doc-hidden-crate.rs
Normal file
27
tests/rustdoc/doc-hidden-crate.rs
Normal 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;
|
14
tests/ui/impl-trait/in-trait/refine-err.rs
Normal file
14
tests/ui/impl-trait/in-trait/refine-err.rs
Normal 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() {}
|
9
tests/ui/impl-trait/in-trait/refine-err.stderr
Normal file
9
tests/ui/impl-trait/in-trait/refine-err.stderr
Normal 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`.
|
@ -14,7 +14,6 @@ fn iter(&self) -> impl for<'missing> Iterator<Item = Self::Item<'missing>> {}
|
||||
//~^ 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() {}
|
||||
|
@ -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`.
|
||||
|
Loading…
Reference in New Issue
Block a user