1
Fork 0

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) { match tcx.named_bound_var(hir_id) {
Some(ResolvedArg::EarlyBound(def_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 // Make sure we allow capturing these lifetimes through `Self` and
// `T::Assoc` projection syntax, too. These will occur when we only // `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>. // feature -- see <https://github.com/rust-lang/rust/pull/115659>.
if let DefKind::LifetimeParam = tcx.def_kind(def_id) if let DefKind::LifetimeParam = tcx.def_kind(def_id)
&& let Some(def_id) = tcx && 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())) .opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id()))
{ {
shadowed_captures.insert(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::span_bug;
use rustc_middle::traits::{ObligationCause, Reveal}; use rustc_middle::traits::{ObligationCause, Reveal};
use rustc_middle::ty::{ 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_span::Span;
use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::regions::InferCtxtRegionExt;
@ -177,6 +178,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
return; return;
}; };
if trait_bounds.references_error() || impl_bounds.references_error() {
return;
}
// For quicker lookup, use an `IndexSet` (we don't use one earlier because // For quicker lookup, use an `IndexSet` (we don't use one earlier because
// it's not foldable..). // it's not foldable..).
// Also, We have to anonymize binders in these types because they may contain // 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_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node}; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node};
use rustc_macros::extension; use rustc_macros::extension;
@ -22,7 +21,7 @@ use rustc_middle::middle::resolve_bound_vars::*;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_middle::{bug, span_bug}; 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::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::Span;
@ -32,7 +31,7 @@ use crate::errors;
impl ResolvedArg { impl ResolvedArg {
fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
debug!("ResolvedArg::early: def_id={:?}", param.def_id); 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) { fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
@ -41,10 +40,10 @@ impl ResolvedArg {
"ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}", "ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
idx, param, depth, param.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 { match *self {
ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None, ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None,
@ -288,13 +287,14 @@ fn late_arg_as_bound_arg<'tcx>(
) -> ty::BoundVariableKind { ) -> ty::BoundVariableKind {
match arg { match arg {
ResolvedArg::LateBound(_, _, def_id) => { 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 { match param.kind {
GenericParamKind::Lifetime { .. } => { GenericParamKind::Lifetime { .. } => {
ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name)) ty::BoundVariableKind::Region(ty::BrNamed(def_id, name))
} }
GenericParamKind::Type { .. } => { 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, 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. // In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.hir_id).copied(); let def = self.map.defs.get(&lifetime.hir_id).copied();
let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue }; 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 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)) 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()) .param_def_id_to_index(self.tcx, region_def_id.to_def_id())
.is_some() .is_some()
{ {
break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id())); break Some(ResolvedArg::EarlyBound(region_def_id));
} }
break None; break None;
} }
@ -1259,7 +1258,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
kind => span_bug!( kind => span_bug!(
use_span, use_span,
"did not expect to resolve lifetime to {}", "did not expect to resolve lifetime to {}",
kind.descr(param_def_id) kind.descr(param_def_id.to_def_id())
), ),
}; };
def = ResolvedArg::Error(guar); def = ResolvedArg::Error(guar);
@ -1277,10 +1276,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
kind: hir::ImplItemKind::Fn(..), 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), .. }) => { 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()) .param_def_id_to_index(self.tcx, param_def_id.to_def_id())
.is_some() .is_some()
{ {
break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id())); break Some(ResolvedArg::EarlyBound(param_def_id));
} }
break None; break None;
} }

View file

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

View file

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

View file

@ -300,16 +300,17 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
Some( Some(
ResolvedArg::EarlyBound(def_id) | ResolvedArg::LateBound(_, _, def_id), 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 let def_id = self
.tcx .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()) .opt_param_def_id(self.tcx, self.parent_def_id.to_def_id())
.expect("variable should have been duplicated from parent"); .expect("variable should have been duplicated from parent");
explicitly_captured.insert(def_id); explicitly_captured.insert(def_id);
} else { } 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_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{ItemLocalId, OwnerId}; use rustc_hir::{ItemLocalId, OwnerId};
use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable}; 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)] #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum ResolvedArg { pub enum ResolvedArg {
StaticLifetime, StaticLifetime,
EarlyBound(/* decl */ DefId), EarlyBound(/* decl */ LocalDefId),
LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId), LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ LocalDefId),
Free(DefId, /* lifetime decl */ DefId), Free(LocalDefId, /* lifetime decl */ LocalDefId),
Error(ErrorGuaranteed), Error(ErrorGuaranteed),
} }

View file

@ -3035,13 +3035,13 @@ impl<'tcx> TyCtxt<'tcx> {
match self.named_bound_var(lifetime.hir_id) { match self.named_bound_var(lifetime.hir_id) {
Some(resolve_bound_vars::ResolvedArg::EarlyBound(ebv)) => { 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 // If we map to another opaque, then it should be a parent
// of the opaque we mapped from. Continue mapping. // of the opaque we mapped from. Continue mapping.
if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) { if matches!(self.def_kind(new_parent), DefKind::OpaqueTy) {
debug_assert_eq!(self.parent(parent.to_def_id()), new_parent); debug_assert_eq!(self.local_parent(parent), new_parent);
opaque_lifetime_param_def_id = ebv.expect_local(); opaque_lifetime_param_def_id = ebv;
continue; continue;
} }
@ -3050,20 +3050,20 @@ impl<'tcx> TyCtxt<'tcx> {
self, self,
ty::EarlyParamRegion { ty::EarlyParamRegion {
index: generics 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"), .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)) => { 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( return ty::Region::new_late_param(
self, self,
new_parent, new_parent.to_def_id(),
ty::BoundRegionKind::BrNamed( ty::BoundRegionKind::BrNamed(
lbv, lbv.to_def_id(),
self.hir().name(self.local_def_id_to_hir_id(lbv.expect_local())), 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 // region at the right depth with the same index
(Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
debug!("EarlyBound id={:?} def_id={:?}", id, 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); return ControlFlow::Break(arg);
} }
} }
@ -118,7 +118,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
debruijn_index debruijn_index
); );
debug!("LateBound id={:?} def_id={:?}", id, def_id); 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); return ControlFlow::Break(arg);
} }
} }
@ -192,7 +192,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
// the lifetime of the TyPath! // the lifetime of the TyPath!
(Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => { (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
debug!("EarlyBound id={:?} def_id={:?}", id, def_id); debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id { if id.to_def_id() == def_id {
return ControlFlow::Break(()); return ControlFlow::Break(());
} }
} }
@ -201,7 +201,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,); debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
debug!("id={:?}", id); debug!("id={:?}", id);
debug!("def_id={:?}", def_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(()); return ControlFlow::Break(());
} }
} }

View file

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

View file

@ -10,7 +10,7 @@ edition = "2021"
[dependencies] [dependencies]
core = { path = "../core" } 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] [dev-dependencies]
rand = { version = "0.8.5", default-features = false, features = ["alloc"] } 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_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" } panic_abort = { path = "../panic_abort" }
core = { path = "../core", public = true } core = { path = "../core", public = true }
compiler_builtins = { version = "0.1.118" } compiler_builtins = { version = "0.1.120" }
profiler_builtins = { path = "../profiler_builtins", optional = true } profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" } unwind = { path = "../unwind" }
hashbrown = { version = "0.14", default-features = false, features = [ 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. /// 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_file`]: remove_file
/// [`fs::remove_dir`]: remove_dir /// [`fs::remove_dir`]: remove_dir
/// ///

View file

@ -10,6 +10,7 @@ use crate::sync::Arc;
use crate::sys::time::SystemTime; use crate::sys::time::SystemTime;
use crate::sys::unsupported; use crate::sys::unsupported;
pub use crate::sys_common::fs::exists; pub use crate::sys_common::fs::exists;
use crate::sys_common::ignore_notfound;
/// A file descriptor. /// A file descriptor.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -527,15 +528,23 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
pub fn remove_dir_all(path: &Path) -> io::Result<()> { pub fn remove_dir_all(path: &Path) -> io::Result<()> {
for child in readdir(path)? { for child in readdir(path)? {
let child = child?; let result: io::Result<()> = try {
let child_type = child.file_type()?; let child = child?;
if child_type.is_dir() { let child_type = child.file_type()?;
remove_dir_all(&child.path())?; if child_type.is_dir() {
} else { remove_dir_all(&child.path())?;
unlink(&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> { 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::path::{Path, PathBuf};
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, cvt_r}; 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> { pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> {
let fd = cvt_r(|| unsafe { 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<()> { fn remove_dir_all_recursive(parent_fd: Option<RawFd>, path: &CStr) -> io::Result<()> {
// try opening as directory // try opening as directory
let fd = match openat_nofollow_dironly(parent_fd, &path) { let fd = match openat_nofollow_dironly(parent_fd, &path) {
@ -2078,27 +2089,35 @@ mod remove_dir_impl {
for child in dir { for child in dir {
let child = child?; let child = child?;
let child_name = child.name_cstr(); let child_name = child.name_cstr();
match is_dir(&child) { // we need an inner try block, because if one of these
Some(true) => { // directories has already been deleted, then we need to
remove_dir_all_recursive(Some(fd), child_name)?; // continue the loop, not return ok.
} let result: io::Result<()> = try {
Some(false) => { match is_dir(&child) {
cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?; Some(true) => {
} remove_dir_all_recursive(Some(fd), child_name)?;
None => { }
// POSIX specifies that calling unlink()/unlinkat(..., 0) on a directory can succeed Some(false) => {
// if the process has the appropriate privileges. This however can causing orphaned cvt(unsafe { unlinkat(fd, child_name.as_ptr(), 0) })?;
// directories requiring an fsck e.g. on Solaris and Illumos. So we try recursing }
// into it first instead of trying to unlink() it. None => {
remove_dir_all_recursive(Some(fd), child_name)?; // 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 // 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) unlinkat(parent_fd.unwrap_or(libc::AT_FDCWD), path.as_ptr(), libc::AT_REMOVEDIR)
})?; }))?;
Ok(()) 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::time::SystemTime;
use crate::sys::unsupported; use crate::sys::unsupported;
pub use crate::sys_common::fs::exists; 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}; use crate::{fmt, iter, ptr};
pub struct File { 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") io::const_io_error!(io::ErrorKind::Uncategorized, "invalid utf-8 file name found")
})?; })?;
if entry.file_type()?.is_dir() { let result: io::Result<()> = try {
remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?; if entry.file_type()?.is_dir() {
} else { remove_dir_all_recursive(&entry.inner.dir.fd, path.as_ref())?;
entry.inner.dir.fd.unlink_file(path)?; } 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 // Once all this directory's contents are deleted it should be safe to
// delete the directory tiself. // 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::path::maybe_verbatim;
use crate::sys::time::SystemTime; use crate::sys::time::SystemTime;
use crate::sys::{c, cvt, Align8}; 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}; use crate::{fmt, ptr, slice, thread};
pub struct File { 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 _)); 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) => { Err(e) => {
if let Some(code) = e.raw_os_error() { if let Some(code) = e.raw_os_error() {
match code as u32 { match code as u32 {

View file

@ -3,6 +3,7 @@
use crate::fs; use crate::fs;
use crate::io::{self, Error, ErrorKind}; use crate::io::{self, Error, ErrorKind};
use crate::path::Path; use crate::path::Path;
use crate::sys_common::ignore_notfound;
pub(crate) const NOT_FILE_ERROR: Error = io::const_io_error!( pub(crate) const NOT_FILE_ERROR: Error = io::const_io_error!(
ErrorKind::InvalidInput, ErrorKind::InvalidInput,
@ -32,14 +33,22 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> {
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
for child in fs::read_dir(path)? { for child in fs::read_dir(path)? {
let child = child?; let result: io::Result<()> = try {
if child.file_type()?.is_dir() { let child = child?;
remove_dir_all_recursive(&child.path())?; if child.file_type()?.is_dir() {
} else { remove_dir_all_recursive(&child.path())?;
fs::remove_file(&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> { 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) // r < denom, so (denom*numer) is the upper bound of (r*numer)
q * numer + r * numer / denom 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); let target_libs = find_files(&target_libs, &lib_path);
// Copy runtime dlls next to rustc.exe // Copy runtime dlls next to rustc.exe
let dist_bin_dir = rust_root.join("bin/"); let rust_bin_dir = rust_root.join("bin/");
fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed"); fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
for src in rustc_dlls { for src in &rustc_dlls {
builder.copy_link_to_folder(&src, &dist_bin_dir); 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 //Copy platform tools to platform-specific bin directory
let target_bin_dir = let plat_target_bin_self_contained_dir =
plat_root.join("lib").join("rustlib").join(target).join("bin").join("self-contained"); plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed"); fs::create_dir_all(&plat_target_bin_self_contained_dir)
.expect("creating plat_target_bin_self_contained_dir failed");
for src in target_tools { 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 // Warn windows-gnu users that the bundled GCC cannot compile C files
builder.create( 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 \ "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 \ used as a linker. In order to be able to compile projects containing C code use \
the GCC provided by MinGW or Cygwin.", the GCC provided by MinGW or Cygwin.",
); );
//Copy platform libs to platform-specific lib directory //Copy platform libs to platform-specific lib directory
let target_lib_dir = let plat_target_lib_self_contained_dir =
plat_root.join("lib").join("rustlib").join(target).join("lib").join("self-contained"); plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed"); fs::create_dir_all(&plat_target_lib_self_contained_dir)
.expect("creating plat_target_lib_self_contained_dir failed");
for src in target_libs { 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::LateBound(_, _, did)
| rbv::ResolvedArg::Free(_, did), | rbv::ResolvedArg::Free(_, did),
) = cx.tcx.named_bound_var(lifetime.hir_id) ) = 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(); return lt.clone();
} }

View file

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

View file

@ -24,3 +24,11 @@ pub fn env_var_os(name: &str) -> OsString {
pub fn no_debug_assertions() -> bool { pub fn no_debug_assertions() -> bool {
std::env::var_os("NO_DEBUG_ASSERTIONS").is_some() 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}; pub use diff::{diff, Diff};
/// Panic-on-fail [`std::env::var`] and [`std::env::var_os`] wrappers. /// 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. /// Convenience helpers for running binaries and other commands.
pub use run::{cmd, run, run_fail, run_with_args}; pub use run::{cmd, run, run_fail, run_with_args};

View file

@ -21,6 +21,7 @@ pub fn cwd() -> PathBuf {
/// # Example /// # Example
/// ///
/// ```rust /// ```rust
/// # use run_make_support::path;
/// let p = path("support_file.txt"); /// let p = path("support_file.txt");
/// ``` /// ```
pub fn path<P: AsRef<Path>>(p: P) -> PathBuf { 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/split-debuginfo/Makefile
run-make/symbol-mangling-hashed/Makefile run-make/symbol-mangling-hashed/Makefile
run-make/translation/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 binding for associated type `Item` references lifetime `'missing` //~| ERROR binding for associated type `Item` references lifetime `'missing`
//~| ERROR `()` is not an iterator //~| ERROR `()` is not an iterator
//~| WARNING impl trait in impl method signature does not match trait method signature
} }
fn main() {} 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 `()` = help: the trait `Iterator` is not implemented for `()`
warning: impl trait in impl method signature does not match trait method signature error: aborting due to 4 previous errors
--> $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
Some errors have detailed explanations: E0195, E0277, E0582. Some errors have detailed explanations: E0195, E0277, E0582.
For more information about an error, try `rustc --explain E0195`. For more information about an error, try `rustc --explain E0195`.