mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #99024 - matthiaskrgr:rollup-8ygpcpg, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #97917 (Implement ExitCodeExt for Windows) - #98844 (Reword comments and rename HIR visiting methods.) - #98979 (interpret: use AllocRange in UninitByteAccess) - #98986 (Fix missing word in comment) - #98994 (replace process exit with more detailed exit in src/bootstrap/*.rs) - #98995 (Add a test for #80471) - #99002 (suggest adding a derive for #[default] applied to variants) - #99004 (Add a test for #70408) - #99017 (Replace boolean argument for print_where_clause with an enum to make code more clear) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1517f5de01
@ -427,7 +427,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
err_ub!(DanglingIntPointer(0, _)) =>
|
||||
{ "a null {kind}" },
|
||||
err_ub!(DanglingIntPointer(i, _)) =>
|
||||
{ "a dangling {kind} (address 0x{i:x} is unallocated)" },
|
||||
{ "a dangling {kind} (address {i:#x} is unallocated)" },
|
||||
err_ub!(PointerOutOfBounds { .. }) =>
|
||||
{ "a dangling {kind} (going beyond the bounds of its allocation)" },
|
||||
// This cannot happen during const-eval (because interning already detects
|
||||
@ -941,7 +941,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
// element that byte belongs to so we can
|
||||
// provide an index.
|
||||
let i = usize::try_from(
|
||||
access.uninit_offset.bytes() / layout.size.bytes(),
|
||||
access.uninit.start.bytes() / layout.size.bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
self.path.push(PathElem::ArrayElem(i));
|
||||
|
@ -19,7 +19,7 @@
|
||||
//! - Example: Examine each expression to look for its type and do some check or other.
|
||||
//! - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to
|
||||
//! `nested_filter::OnlyBodies` (and implement `nested_visit_map`), and use
|
||||
//! `tcx.hir().deep_visit_all_item_likes(&mut visitor)`. Within your
|
||||
//! `tcx.hir().visit_all_item_likes_in_crate(&mut visitor)`. Within your
|
||||
//! `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget to invoke
|
||||
//! `intravisit::walk_expr()` to keep walking the subparts).
|
||||
//! - Pro: Visitor methods for any kind of HIR node, not just item-like things.
|
||||
@ -190,7 +190,7 @@ use nested_filter::NestedFilter;
|
||||
/// (this is why the module is called `intravisit`, to distinguish it
|
||||
/// from the AST's `visit` module, which acts differently). If you
|
||||
/// simply want to visit all items in the crate in some order, you
|
||||
/// should call `Crate::visit_all_items`. Otherwise, see the comment
|
||||
/// should call `tcx.hir().visit_all_item_likes_in_crate`. Otherwise, see the comment
|
||||
/// on `visit_nested_item` for details on how to visit nested items.
|
||||
///
|
||||
/// If you want to ensure that your code handles every variant
|
||||
|
@ -75,7 +75,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
|
||||
let mut visitor =
|
||||
IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] };
|
||||
visitor.process_attrs(hir::CRATE_HIR_ID);
|
||||
tcx.hir().deep_visit_all_item_likes(&mut visitor);
|
||||
tcx.hir().visit_all_item_likes_in_crate(&mut visitor);
|
||||
(visitor.if_this_changed, visitor.then_this_would_need)
|
||||
};
|
||||
|
||||
|
@ -419,7 +419,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
self.tcx.hir().deep_visit_all_item_likes(self);
|
||||
self.tcx.hir().visit_all_item_likes_in_crate(self);
|
||||
}
|
||||
|
||||
fn encode_def_path_table(&mut self) {
|
||||
|
@ -561,7 +561,7 @@ impl<'hir> Map<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Walks the contents of a crate. See also `Crate::visit_all_items`.
|
||||
/// Walks the contents of the local crate. See also `visit_all_item_likes_in_crate`.
|
||||
pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) {
|
||||
let (top_mod, span, hir_id) = self.get_module(CRATE_DEF_ID);
|
||||
visitor.visit_mod(top_mod, span, hir_id);
|
||||
@ -581,53 +581,61 @@ impl<'hir> Map<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Visits all items in the crate in some deterministic (but
|
||||
/// unspecified) order. If you need to process every item,
|
||||
/// and care about nesting -- usually because your algorithm
|
||||
/// follows lexical scoping rules -- then this method is the best choice.
|
||||
/// If you don't care about nesting, you should use the `tcx.hir_crate_items()` query
|
||||
/// or `items()` instead.
|
||||
/// Visits all item-likes in the crate in some deterministic (but unspecified) order. If you
|
||||
/// need to process every item-like, and don't care about visiting nested items in a particular
|
||||
/// order then this method is the best choice. If you do care about this nesting, you should
|
||||
/// use the `tcx.hir().walk_toplevel_module`.
|
||||
///
|
||||
/// Note that this function will access HIR for all the item-likes in the crate. If you only
|
||||
/// need to access some of them, it is usually better to manually loop on the iterators
|
||||
/// provided by `tcx.hir_crate_items(())`.
|
||||
///
|
||||
/// Please see the notes in `intravisit.rs` for more information.
|
||||
pub fn deep_visit_all_item_likes<V>(self, visitor: &mut V)
|
||||
pub fn visit_all_item_likes_in_crate<V>(self, visitor: &mut V)
|
||||
where
|
||||
V: Visitor<'hir>,
|
||||
{
|
||||
let krate = self.krate();
|
||||
for owner in krate.owners.iter().filter_map(|i| i.as_owner()) {
|
||||
match owner.node() {
|
||||
OwnerNode::Item(item) => visitor.visit_item(item),
|
||||
OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
|
||||
OwnerNode::ImplItem(item) => visitor.visit_impl_item(item),
|
||||
OwnerNode::TraitItem(item) => visitor.visit_trait_item(item),
|
||||
OwnerNode::Crate(_) => {}
|
||||
}
|
||||
let krate = self.tcx.hir_crate_items(());
|
||||
|
||||
for id in krate.items() {
|
||||
visitor.visit_item(self.item(id));
|
||||
}
|
||||
|
||||
for id in krate.trait_items() {
|
||||
visitor.visit_trait_item(self.trait_item(id));
|
||||
}
|
||||
|
||||
for id in krate.impl_items() {
|
||||
visitor.visit_impl_item(self.impl_item(id));
|
||||
}
|
||||
|
||||
for id in krate.foreign_items() {
|
||||
visitor.visit_foreign_item(self.foreign_item(id));
|
||||
}
|
||||
}
|
||||
|
||||
/// If you don't care about nesting, you should use the
|
||||
/// `tcx.hir_module_items()` query or `module_items()` instead.
|
||||
/// Please see notes in `deep_visit_all_item_likes`.
|
||||
pub fn deep_visit_item_likes_in_module<V>(self, module: LocalDefId, visitor: &mut V)
|
||||
/// This method is the equivalent of `visit_all_item_likes_in_crate` but restricted to
|
||||
/// item-likes in a single module.
|
||||
pub fn visit_item_likes_in_module<V>(self, module: LocalDefId, visitor: &mut V)
|
||||
where
|
||||
V: Visitor<'hir>,
|
||||
{
|
||||
let module = self.tcx.hir_module_items(module);
|
||||
|
||||
for id in module.items.iter() {
|
||||
visitor.visit_item(self.item(*id));
|
||||
for id in module.items() {
|
||||
visitor.visit_item(self.item(id));
|
||||
}
|
||||
|
||||
for id in module.trait_items.iter() {
|
||||
visitor.visit_trait_item(self.trait_item(*id));
|
||||
for id in module.trait_items() {
|
||||
visitor.visit_trait_item(self.trait_item(id));
|
||||
}
|
||||
|
||||
for id in module.impl_items.iter() {
|
||||
visitor.visit_impl_item(self.impl_item(*id));
|
||||
for id in module.impl_items() {
|
||||
visitor.visit_impl_item(self.impl_item(id));
|
||||
}
|
||||
|
||||
for id in module.foreign_items.iter() {
|
||||
visitor.visit_foreign_item(self.foreign_item(*id));
|
||||
for id in module.foreign_items() {
|
||||
visitor.visit_foreign_item(self.foreign_item(id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ use rustc_hir::intravisit::nested_filter::NestedFilter;
|
||||
/// constant arguments of types, e.g. in `let _: [(); /* HERE */];`.
|
||||
///
|
||||
/// **This is the most common choice.** A very common pattern is
|
||||
/// to use `deep_visit_all_item_likes()` as an outer loop,
|
||||
/// to use `visit_all_item_likes_in_crate()` as an outer loop,
|
||||
/// and to have the visitor that visits the contents of each item
|
||||
/// using this setting.
|
||||
pub struct OnlyBodies(());
|
||||
|
@ -179,6 +179,11 @@ pub fn alloc_range(start: Size, size: Size) -> AllocRange {
|
||||
}
|
||||
|
||||
impl AllocRange {
|
||||
#[inline]
|
||||
pub fn from(r: Range<Size>) -> Self {
|
||||
alloc_range(r.start, r.end - r.start) // `Size` subtraction (overflow-checked)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn end(self) -> Size {
|
||||
self.start + self.size // This does overflow checking.
|
||||
@ -1095,9 +1100,9 @@ impl InitMask {
|
||||
/// Returns `Ok(())` if it's initialized. Otherwise returns a range of byte
|
||||
/// indexes for the first contiguous span of the uninitialized access.
|
||||
#[inline]
|
||||
pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), Range<Size>> {
|
||||
pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), AllocRange> {
|
||||
if end > self.len {
|
||||
return Err(self.len..end);
|
||||
return Err(AllocRange::from(self.len..end));
|
||||
}
|
||||
|
||||
let uninit_start = self.find_bit(start, end, false);
|
||||
@ -1105,7 +1110,7 @@ impl InitMask {
|
||||
match uninit_start {
|
||||
Some(uninit_start) => {
|
||||
let uninit_end = self.find_bit(uninit_start, end, true).unwrap_or(end);
|
||||
Err(uninit_start..uninit_end)
|
||||
Err(AllocRange::from(uninit_start..uninit_end))
|
||||
}
|
||||
None => Ok(()),
|
||||
}
|
||||
@ -1176,19 +1181,17 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
|
||||
///
|
||||
/// Returns `Ok(())` if it's initialized. Otherwise returns the range of byte
|
||||
/// indexes of the first contiguous uninitialized access.
|
||||
fn is_init(&self, range: AllocRange) -> Result<(), Range<Size>> {
|
||||
fn is_init(&self, range: AllocRange) -> Result<(), AllocRange> {
|
||||
self.init_mask.is_range_initialized(range.start, range.end()) // `Size` addition
|
||||
}
|
||||
|
||||
/// Checks that a range of bytes is initialized. If not, returns the `InvalidUninitBytes`
|
||||
/// error which will report the first range of bytes which is uninitialized.
|
||||
fn check_init(&self, range: AllocRange) -> AllocResult {
|
||||
self.is_init(range).map_err(|idx_range| {
|
||||
self.is_init(range).map_err(|uninit_range| {
|
||||
AllocError::InvalidUninitBytes(Some(UninitBytesAccess {
|
||||
access_offset: range.start,
|
||||
access_size: range.size,
|
||||
uninit_offset: idx_range.start,
|
||||
uninit_size: idx_range.end - idx_range.start, // `Size` subtraction
|
||||
access: range,
|
||||
uninit: uninit_range,
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{AllocId, ConstAlloc, Pointer, Scalar};
|
||||
use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};
|
||||
|
||||
use crate::mir::interpret::ConstValue;
|
||||
use crate::ty::{layout, query::TyCtxtAt, tls, FnSig, Ty, ValTree};
|
||||
@ -162,9 +162,9 @@ impl fmt::Display for InvalidProgramInfo<'_> {
|
||||
AlreadyReported(ErrorGuaranteed { .. }) => {
|
||||
write!(f, "encountered constants with type errors, stopping evaluation")
|
||||
}
|
||||
Layout(ref err) => write!(f, "{}", err),
|
||||
FnAbiAdjustForForeignAbi(ref err) => write!(f, "{}", err),
|
||||
SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{}`", ty),
|
||||
Layout(ref err) => write!(f, "{err}"),
|
||||
FnAbiAdjustForForeignAbi(ref err) => write!(f, "{err}"),
|
||||
SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{ty}`"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -205,14 +205,10 @@ impl fmt::Display for CheckInAllocMsg {
|
||||
/// Details of an access to uninitialized bytes where it is not allowed.
|
||||
#[derive(Debug)]
|
||||
pub struct UninitBytesAccess {
|
||||
/// Location of the original memory access.
|
||||
pub access_offset: Size,
|
||||
/// Size of the original memory access.
|
||||
pub access_size: Size,
|
||||
/// Location of the first uninitialized byte that was accessed.
|
||||
pub uninit_offset: Size,
|
||||
/// Number of consecutive uninitialized bytes that were accessed.
|
||||
pub uninit_size: Size,
|
||||
/// Range of the original memory access.
|
||||
pub access: AllocRange,
|
||||
/// Range of the uninit memory that was encountered. (Might not be maximal.)
|
||||
pub uninit: AllocRange,
|
||||
}
|
||||
|
||||
/// Information about a size mismatch.
|
||||
@ -308,30 +304,28 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use UndefinedBehaviorInfo::*;
|
||||
match self {
|
||||
Ub(msg) => write!(f, "{}", msg),
|
||||
Ub(msg) => write!(f, "{msg}"),
|
||||
Unreachable => write!(f, "entering unreachable code"),
|
||||
BoundsCheckFailed { ref len, ref index } => {
|
||||
write!(f, "indexing out of bounds: the len is {} but the index is {}", len, index)
|
||||
write!(f, "indexing out of bounds: the len is {len} but the index is {index}")
|
||||
}
|
||||
DivisionByZero => write!(f, "dividing by zero"),
|
||||
RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
|
||||
DivisionOverflow => write!(f, "overflow in signed division (dividing MIN by -1)"),
|
||||
RemainderOverflow => write!(f, "overflow in signed remainder (dividing MIN by -1)"),
|
||||
PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
|
||||
InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
|
||||
InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {msg}"),
|
||||
InvalidVtableDropFn(sig) => write!(
|
||||
f,
|
||||
"invalid drop function signature: got {}, expected exactly one argument which must be a pointer type",
|
||||
sig
|
||||
"invalid drop function signature: got {sig}, expected exactly one argument which must be a pointer type",
|
||||
),
|
||||
InvalidVtableSize => {
|
||||
write!(f, "invalid vtable: size is bigger than largest supported object")
|
||||
}
|
||||
InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {}", msg),
|
||||
InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {msg}"),
|
||||
UnterminatedCString(p) => write!(
|
||||
f,
|
||||
"reading a null-terminated string starting at {:?} with no null found before end of allocation",
|
||||
p,
|
||||
"reading a null-terminated string starting at {p:?} with no null found before end of allocation",
|
||||
),
|
||||
PointerUseAfterFree(a) => {
|
||||
write!(f, "pointer to {a:?} was dereferenced after this allocation got freed")
|
||||
@ -359,41 +353,36 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
|
||||
}
|
||||
AlignmentCheckFailed { required, has } => write!(
|
||||
f,
|
||||
"accessing memory with alignment {}, but alignment {} is required",
|
||||
has.bytes(),
|
||||
required.bytes()
|
||||
"accessing memory with alignment {has}, but alignment {required} is required",
|
||||
has = has.bytes(),
|
||||
required = required.bytes()
|
||||
),
|
||||
WriteToReadOnly(a) => write!(f, "writing to {a:?} which is read-only"),
|
||||
DerefFunctionPointer(a) => write!(f, "accessing {a:?} which contains a function"),
|
||||
ValidationFailure { path: None, msg } => {
|
||||
write!(f, "constructing invalid value: {}", msg)
|
||||
write!(f, "constructing invalid value: {msg}")
|
||||
}
|
||||
ValidationFailure { path: Some(path), msg } => {
|
||||
write!(f, "constructing invalid value at {}: {}", path, msg)
|
||||
write!(f, "constructing invalid value at {path}: {msg}")
|
||||
}
|
||||
InvalidBool(b) => {
|
||||
write!(f, "interpreting an invalid 8-bit value as a bool: 0x{:02x}", b)
|
||||
write!(f, "interpreting an invalid 8-bit value as a bool: 0x{b:02x}")
|
||||
}
|
||||
InvalidChar(c) => {
|
||||
write!(f, "interpreting an invalid 32-bit value as a char: 0x{:08x}", c)
|
||||
write!(f, "interpreting an invalid 32-bit value as a char: 0x{c:08x}")
|
||||
}
|
||||
InvalidTag(val) => write!(f, "enum value has invalid tag: {:x}", val),
|
||||
InvalidTag(val) => write!(f, "enum value has invalid tag: {val:x}"),
|
||||
InvalidFunctionPointer(p) => {
|
||||
write!(f, "using {:?} as function pointer but it does not point to a function", p)
|
||||
write!(f, "using {p:?} as function pointer but it does not point to a function")
|
||||
}
|
||||
InvalidStr(err) => write!(f, "this string is not valid UTF-8: {}", err),
|
||||
InvalidUninitBytes(Some((alloc, access))) => write!(
|
||||
InvalidStr(err) => write!(f, "this string is not valid UTF-8: {err}"),
|
||||
InvalidUninitBytes(Some((alloc, info))) => write!(
|
||||
f,
|
||||
"reading {} byte{} of memory starting at {:?}, \
|
||||
but {} byte{} {} uninitialized starting at {:?}, \
|
||||
"reading memory at {alloc:?}{access:?}, \
|
||||
but memory is uninitialized at {uninit:?}, \
|
||||
and this operation requires initialized memory",
|
||||
access.access_size.bytes(),
|
||||
pluralize!(access.access_size.bytes()),
|
||||
Pointer::new(*alloc, access.access_offset),
|
||||
access.uninit_size.bytes(),
|
||||
pluralize!(access.uninit_size.bytes()),
|
||||
pluralize!("is", access.uninit_size.bytes()),
|
||||
Pointer::new(*alloc, access.uninit_offset),
|
||||
access = info.access,
|
||||
uninit = info.uninit,
|
||||
),
|
||||
InvalidUninitBytes(None) => write!(
|
||||
f,
|
||||
@ -402,8 +391,7 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
|
||||
DeadLocal => write!(f, "accessing a dead local variable"),
|
||||
ScalarSizeMismatch(self::ScalarSizeMismatch { target_size, data_size }) => write!(
|
||||
f,
|
||||
"scalar size mismatch: expected {} bytes but got {} bytes instead",
|
||||
target_size, data_size
|
||||
"scalar size mismatch: expected {target_size} bytes but got {data_size} bytes instead",
|
||||
),
|
||||
UninhabitedEnumVariantWritten => {
|
||||
write!(f, "writing discriminant of an uninhabited enum")
|
||||
@ -437,13 +425,13 @@ impl fmt::Display for UnsupportedOpInfo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use UnsupportedOpInfo::*;
|
||||
match self {
|
||||
Unsupported(ref msg) => write!(f, "{}", msg),
|
||||
Unsupported(ref msg) => write!(f, "{msg}"),
|
||||
ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes"),
|
||||
PartialPointerOverwrite(ptr) => {
|
||||
write!(f, "unable to overwrite parts of a pointer in memory at {:?}", ptr)
|
||||
write!(f, "unable to overwrite parts of a pointer in memory at {ptr:?}")
|
||||
}
|
||||
ThreadLocalStatic(did) => write!(f, "cannot access thread local static ({:?})", did),
|
||||
ReadExternStatic(did) => write!(f, "cannot read from extern static ({:?})", did),
|
||||
ThreadLocalStatic(did) => write!(f, "cannot access thread local static ({did:?})"),
|
||||
ReadExternStatic(did) => write!(f, "cannot read from extern static ({did:?})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -526,11 +514,11 @@ impl fmt::Display for InterpError<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use InterpError::*;
|
||||
match *self {
|
||||
Unsupported(ref msg) => write!(f, "{}", msg),
|
||||
InvalidProgram(ref msg) => write!(f, "{}", msg),
|
||||
UndefinedBehavior(ref msg) => write!(f, "{}", msg),
|
||||
ResourceExhaustion(ref msg) => write!(f, "{}", msg),
|
||||
MachineStop(ref msg) => write!(f, "{}", msg),
|
||||
Unsupported(ref msg) => write!(f, "{msg}"),
|
||||
InvalidProgram(ref msg) => write!(f, "{msg}"),
|
||||
UndefinedBehavior(ref msg) => write!(f, "{msg}"),
|
||||
ResourceExhaustion(ref msg) => write!(f, "{msg}"),
|
||||
MachineStop(ref msg) => write!(f, "{msg}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
|
||||
_: &mir::Statement<'tcx>,
|
||||
loc: Location,
|
||||
) {
|
||||
// If we move from a place then only stops needing storage *after*
|
||||
// If we move from a place then it only stops needing storage *after*
|
||||
// that statement.
|
||||
self.check_for_move(trans, loc);
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
|
||||
intravisit::walk_struct_def(self, v)
|
||||
}
|
||||
}
|
||||
tcx.hir().deep_visit_all_item_likes(&mut GatherCtors { tcx, set: &mut set });
|
||||
tcx.hir().visit_all_item_likes_in_crate(&mut GatherCtors { tcx, set: &mut set });
|
||||
|
||||
set
|
||||
}
|
||||
|
@ -2428,7 +2428,7 @@ fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>)
|
||||
|
||||
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
let check_attr_visitor = &mut CheckAttrVisitor { tcx };
|
||||
tcx.hir().deep_visit_item_likes_in_module(module_def_id, check_attr_visitor);
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, check_attr_visitor);
|
||||
if module_def_id.is_top_level_module() {
|
||||
check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None);
|
||||
check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
|
||||
|
@ -56,7 +56,7 @@ impl NonConstExpr {
|
||||
|
||||
fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
let mut vis = CheckConstVisitor::new(tcx);
|
||||
tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut vis);
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis);
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
|
@ -28,7 +28,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||
errors: &errors,
|
||||
};
|
||||
|
||||
tcx.hir().deep_visit_item_likes_in_module(module_id, &mut v);
|
||||
tcx.hir().visit_item_likes_in_module(module_id, &mut v);
|
||||
});
|
||||
|
||||
let errors = errors.into_inner();
|
||||
|
@ -140,7 +140,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String {
|
||||
}
|
||||
|
||||
fn check_mod_liveness(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx));
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx));
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
|
@ -31,7 +31,7 @@ struct CheckLoopVisitor<'a, 'hir> {
|
||||
}
|
||||
|
||||
fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
tcx.hir().deep_visit_item_likes_in_module(
|
||||
tcx.hir().visit_item_likes_in_module(
|
||||
module_def_id,
|
||||
&mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal },
|
||||
);
|
||||
|
@ -14,7 +14,7 @@ use rustc_span::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut CheckNakedFunctions { tcx });
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckNakedFunctions { tcx });
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
|
@ -660,7 +660,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
|
||||
/// Cross-references the feature names of unstable APIs with enabled
|
||||
/// features and possibly prints errors.
|
||||
fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut Checker { tcx });
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx });
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
@ -890,7 +890,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
||||
let mut missing = MissingStabilityAnnotations { tcx, access_levels };
|
||||
missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
|
||||
tcx.hir().walk_toplevel_module(&mut missing);
|
||||
tcx.hir().deep_visit_all_item_likes(&mut missing);
|
||||
tcx.hir().visit_all_item_likes_in_crate(&mut missing);
|
||||
}
|
||||
|
||||
let declared_lang_features = &tcx.features().declared_lang_features;
|
||||
|
@ -1499,10 +1499,16 @@ impl<'a> Resolver<'a> {
|
||||
&& let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind
|
||||
&& let Some(span) = self.opt_span(def_id)
|
||||
{
|
||||
err.span_help(
|
||||
self.session.source_map().guess_head_span(span),
|
||||
"consider adding `#[derive(Default)]` to this enum",
|
||||
);
|
||||
let source_map = self.session.source_map();
|
||||
let head_span = source_map.guess_head_span(span);
|
||||
if let Ok(head) = source_map.span_to_snippet(head_span) {
|
||||
err.span_suggestion(head_span, "consider adding a derive", format!("#[derive(Default)]\n{head}"), Applicability::MaybeIncorrect);
|
||||
} else {
|
||||
err.span_help(
|
||||
head_span,
|
||||
"consider adding `#[derive(Default)]` to this enum",
|
||||
);
|
||||
}
|
||||
}
|
||||
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
|
||||
if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
|
||||
|
@ -59,7 +59,7 @@ struct OnlySelfBounds(bool);
|
||||
// Main entry point
|
||||
|
||||
fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx });
|
||||
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx });
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
|
@ -234,3 +234,26 @@ impl ChildExt for process::Child {
|
||||
self.handle.main_thread_handle()
|
||||
}
|
||||
}
|
||||
|
||||
/// Windows-specific extensions to [`process::ExitCode`].
|
||||
///
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[unstable(feature = "windows_process_exit_code_from", issue = "none")]
|
||||
pub trait ExitCodeExt: Sealed {
|
||||
/// Creates a new `ExitCode` from the raw underlying `u32` return value of
|
||||
/// a process.
|
||||
///
|
||||
/// The exit code should not be 259, as this conflicts with the `STILL_ACTIVE`
|
||||
/// macro returned from the `GetExitCodeProcess` function to signal that the
|
||||
/// process has yet to run to completion.
|
||||
#[unstable(feature = "windows_process_exit_code_from", issue = "none")]
|
||||
fn from_raw(raw: u32) -> Self;
|
||||
}
|
||||
|
||||
#[unstable(feature = "windows_process_exit_code_from", issue = "none")]
|
||||
impl ExitCodeExt for process::ExitCode {
|
||||
fn from_raw(raw: u32) -> Self {
|
||||
process::ExitCode::from_inner(From::from(raw))
|
||||
}
|
||||
}
|
||||
|
@ -1724,6 +1724,10 @@ impl crate::error::Error for ExitStatusError {}
|
||||
#[stable(feature = "process_exitcode", since = "1.61.0")]
|
||||
pub struct ExitCode(imp::ExitCode);
|
||||
|
||||
/// Allows extension traits within `std`.
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
impl crate::sealed::Sealed for ExitCode {}
|
||||
|
||||
#[stable(feature = "process_exitcode", since = "1.61.0")]
|
||||
impl ExitCode {
|
||||
/// The canonical `ExitCode` for successful termination on this platform.
|
||||
@ -1814,6 +1818,18 @@ impl From<u8> for ExitCode {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<imp::ExitCode> for ExitCode {
|
||||
fn as_inner(&self) -> &imp::ExitCode {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<imp::ExitCode> for ExitCode {
|
||||
fn from_inner(s: imp::ExitCode) -> ExitCode {
|
||||
ExitCode(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Child {
|
||||
/// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
|
||||
/// error is returned.
|
||||
|
@ -707,6 +707,12 @@ impl From<u8> for ExitCode {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for ExitCode {
|
||||
fn from(code: u32) -> Self {
|
||||
ExitCode(c::DWORD::from(code))
|
||||
}
|
||||
}
|
||||
|
||||
fn zeroed_startupinfo() -> c::STARTUPINFO {
|
||||
c::STARTUPINFO {
|
||||
cb: 0,
|
||||
|
@ -346,11 +346,7 @@ impl StepDescription {
|
||||
eprintln!(
|
||||
"note: if you are adding a new Step to bootstrap itself, make sure you register it with `describe!`"
|
||||
);
|
||||
#[cfg(not(test))]
|
||||
std::process::exit(1);
|
||||
#[cfg(test)]
|
||||
// so we can use #[should_panic]
|
||||
panic!()
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1008,7 +1004,7 @@ impl<'a> Builder<'a> {
|
||||
if !help_on_error.is_empty() {
|
||||
eprintln!("{}", help_on_error);
|
||||
}
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1437,7 +1433,7 @@ impl<'a> Builder<'a> {
|
||||
"error: `x.py clippy` requires a host `rustc` toolchain with the `clippy` component"
|
||||
);
|
||||
eprintln!("help: try `rustup component add clippy`");
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
});
|
||||
if !t!(std::str::from_utf8(&output.stdout)).contains("nightly") {
|
||||
rustflags.arg("--cfg=bootstrap");
|
||||
|
@ -13,7 +13,7 @@ use std::fs;
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{exit, Command, Stdio};
|
||||
use std::process::{Command, Stdio};
|
||||
use std::str;
|
||||
|
||||
use serde::Deserialize;
|
||||
@ -1377,7 +1377,7 @@ pub fn run_cargo(
|
||||
});
|
||||
|
||||
if !ok {
|
||||
exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
|
||||
// Ok now we need to actually find all the files listed in `toplevel`. We've
|
||||
|
@ -11,7 +11,7 @@ use std::ffi::OsStr;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{exit, Command};
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::builder::{Builder, TaskPath};
|
||||
@ -805,8 +805,6 @@ impl Config {
|
||||
let get_toml = |_| TomlConfig::default();
|
||||
#[cfg(not(test))]
|
||||
let get_toml = |file: &Path| {
|
||||
use std::process;
|
||||
|
||||
let contents =
|
||||
t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
|
||||
// Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
|
||||
@ -817,7 +815,7 @@ impl Config {
|
||||
Ok(table) => table,
|
||||
Err(err) => {
|
||||
eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
|
||||
process::exit(2);
|
||||
crate::detail_exit(2);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1487,7 +1485,7 @@ fn download_ci_rustc_commit(
|
||||
println!("help: maybe your repository history is too shallow?");
|
||||
println!("help: consider disabling `download-rustc`");
|
||||
println!("help: or fetch enough history to include one upstream commit");
|
||||
exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
|
||||
// Warn if there were changes to the compiler or standard library since the ancestor commit.
|
||||
|
@ -4,7 +4,6 @@
|
||||
//! has various flags to configure how it's run.
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
|
||||
use getopts::Options;
|
||||
|
||||
@ -261,7 +260,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
|
||||
// subcommand.
|
||||
println!("{}\n", subcommand_help);
|
||||
let exit_code = if args.is_empty() { 0 } else { 1 };
|
||||
process::exit(exit_code);
|
||||
crate::detail_exit(exit_code);
|
||||
}
|
||||
};
|
||||
|
||||
@ -347,7 +346,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
|
||||
} else if verbose {
|
||||
panic!("No paths available for subcommand `{}`", subcommand.as_str());
|
||||
}
|
||||
process::exit(exit_code);
|
||||
crate::detail_exit(exit_code);
|
||||
};
|
||||
|
||||
// Done specifying what options are possible, so do the getopts parsing
|
||||
@ -379,7 +378,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
|
||||
"Sorry, I couldn't figure out which subcommand you were trying to specify.\n\
|
||||
You may need to move some options to after the subcommand.\n"
|
||||
);
|
||||
process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
// Extra help text for some commands
|
||||
match subcommand {
|
||||
@ -600,7 +599,7 @@ Arguments:
|
||||
eprintln!("error: {}", err);
|
||||
eprintln!("help: the available profiles are:");
|
||||
eprint!("{}", Profile::all_for_help("- "));
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
})
|
||||
} else {
|
||||
t!(crate::setup::interactive_path())
|
||||
@ -614,7 +613,7 @@ Arguments:
|
||||
|| matches.opt_str("keep-stage-std").is_some()
|
||||
{
|
||||
eprintln!("--keep-stage not yet supported for x.py check");
|
||||
process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -805,7 +804,7 @@ fn parse_deny_warnings(matches: &getopts::Matches) -> Option<bool> {
|
||||
Some("warn") => Some(false),
|
||||
Some(value) => {
|
||||
eprintln!(r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#, value,);
|
||||
process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F
|
||||
code, run `./x.py fmt` instead.",
|
||||
cmd_debug,
|
||||
);
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,7 +114,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
|
||||
|
||||
let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| {
|
||||
eprintln!("./x.py fmt is not supported on this channel");
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
});
|
||||
assert!(rustfmt_path.exists(), "{}", rustfmt_path.display());
|
||||
let src = build.src.clone();
|
||||
|
@ -109,7 +109,7 @@ use std::env;
|
||||
use std::fs::{self, File};
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{self, Command};
|
||||
use std::process::Command;
|
||||
use std::str;
|
||||
|
||||
use filetime::FileTime;
|
||||
@ -711,7 +711,7 @@ impl Build {
|
||||
for failure in failures.iter() {
|
||||
eprintln!(" - {}\n", failure);
|
||||
}
|
||||
process::exit(1);
|
||||
detail_exit(1);
|
||||
}
|
||||
|
||||
#[cfg(feature = "build-metrics")]
|
||||
@ -1617,7 +1617,7 @@ Alternatively, set `download-ci-llvm = true` in that `[llvm]` section
|
||||
to download LLVM rather than building it.
|
||||
"
|
||||
);
|
||||
std::process::exit(1);
|
||||
detail_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1646,6 +1646,20 @@ fn chmod(path: &Path, perms: u32) {
|
||||
#[cfg(windows)]
|
||||
fn chmod(_path: &Path, _perms: u32) {}
|
||||
|
||||
/// If code is not 0 (successful exit status), exit status is 101 (rust's default error code.)
|
||||
/// If the test is running and code is an error code, it will cause a panic.
|
||||
fn detail_exit(code: i32) -> ! {
|
||||
// Successful exit
|
||||
if code == 0 {
|
||||
std::process::exit(0);
|
||||
}
|
||||
if cfg!(test) {
|
||||
panic!("status code: {}", code);
|
||||
} else {
|
||||
std::panic::resume_unwind(Box::new(code));
|
||||
}
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
pub fn with_stage(mut self, stage: u32) -> Compiler {
|
||||
self.stage = stage;
|
||||
|
@ -104,7 +104,7 @@ You should install cmake, or set `download-ci-llvm = true` in the
|
||||
than building it.
|
||||
"
|
||||
);
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ pub fn setup(config: &Config, profile: Profile) {
|
||||
"note: this will use the configuration in {}",
|
||||
profile.include_path(&config.src).display()
|
||||
);
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
|
||||
let settings = format!(
|
||||
@ -287,7 +287,7 @@ pub fn interactive_path() -> io::Result<Profile> {
|
||||
io::stdin().read_line(&mut input)?;
|
||||
if input.is_empty() {
|
||||
eprintln!("EOF on stdin, when expecting answer to question. Giving up.");
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
break match parse_with_abbrev(&input) {
|
||||
Ok(profile) => profile,
|
||||
|
@ -673,7 +673,7 @@ impl Step for Clippy {
|
||||
}
|
||||
|
||||
if !builder.config.cmd.bless() {
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::ToolRustc, SourceType::InTree, host, "run");
|
||||
@ -1021,7 +1021,7 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
|
||||
PATH = inferred_rustfmt_dir.display(),
|
||||
CHAN = builder.config.channel,
|
||||
);
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
crate::format::format(&builder, !builder.config.cmd.bless(), &[]);
|
||||
}
|
||||
@ -1251,7 +1251,7 @@ help: to test the compiler, use `--stage 1` instead
|
||||
help: to test the standard library, use `--stage 0 library/std` instead
|
||||
note: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`."
|
||||
);
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
|
||||
let compiler = self.compiler;
|
||||
|
@ -2,7 +2,7 @@ use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{exit, Command};
|
||||
use std::process::Command;
|
||||
|
||||
use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
|
||||
use crate::channel::GitInfo;
|
||||
@ -204,7 +204,7 @@ impl Step for ToolBuild {
|
||||
|
||||
if !is_expected {
|
||||
if !is_optional_tool {
|
||||
exit(1);
|
||||
crate::detail_exit(1);
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ fn print_error(tool: &str, submodule: &str) {
|
||||
eprintln!("If you do NOT intend to update '{}', please ensure you did not accidentally", tool);
|
||||
eprintln!("change the submodule at '{}'. You may ask your reviewer for the", submodule);
|
||||
eprintln!("proper steps.");
|
||||
std::process::exit(3);
|
||||
crate::detail_exit(3);
|
||||
}
|
||||
|
||||
fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) {
|
||||
@ -108,7 +108,7 @@ fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) {
|
||||
Ok(o) => o,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to get changed files: {:?}", e);
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
@ -179,7 +179,7 @@ impl Step for ToolStateCheck {
|
||||
}
|
||||
|
||||
if did_error {
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
|
||||
check_changed_files(&toolstates);
|
||||
@ -225,7 +225,7 @@ impl Step for ToolStateCheck {
|
||||
}
|
||||
|
||||
if did_error {
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
|
||||
if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() {
|
||||
|
@ -336,7 +336,7 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>(
|
||||
|
||||
pub fn run(cmd: &mut Command, print_cmd_on_fail: bool) {
|
||||
if !try_run(cmd, print_cmd_on_fail) {
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,7 +375,7 @@ pub fn check_run(cmd: &mut Command, print_cmd_on_fail: bool) -> bool {
|
||||
|
||||
pub fn run_suppressed(cmd: &mut Command) {
|
||||
if !try_run_suppressed(cmd) {
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,7 +465,7 @@ fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
|
||||
|
||||
fn fail(s: &str) -> ! {
|
||||
eprintln!("\n\n{}\n\n", s);
|
||||
std::process::exit(1);
|
||||
crate::detail_exit(1);
|
||||
}
|
||||
|
||||
/// Copied from `std::path::absolute` until it stabilizes.
|
||||
|
@ -268,6 +268,12 @@ impl clean::Generics {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum Ending {
|
||||
Newline,
|
||||
NoNewline,
|
||||
}
|
||||
|
||||
/// * The Generics from which to emit a where-clause.
|
||||
/// * The number of spaces to indent each line with.
|
||||
/// * Whether the where-clause needs to add a comma and newline after the last bound.
|
||||
@ -275,7 +281,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
|
||||
gens: &'a clean::Generics,
|
||||
cx: &'a Context<'tcx>,
|
||||
indent: usize,
|
||||
end_newline: bool,
|
||||
ending: Ending,
|
||||
) -> impl fmt::Display + 'a + Captures<'tcx> {
|
||||
use fmt::Write;
|
||||
|
||||
@ -342,7 +348,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
|
||||
|
||||
let where_preds = comma_sep(where_predicates, false);
|
||||
let clause = if f.alternate() {
|
||||
if end_newline {
|
||||
if ending == Ending::Newline {
|
||||
// add a space so stripping <br> tags and breaking spaces still renders properly
|
||||
format!(" where{where_preds}, ")
|
||||
} else {
|
||||
@ -356,7 +362,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
|
||||
}
|
||||
let where_preds = where_preds.to_string().replace("<br>", &br_with_padding);
|
||||
|
||||
if end_newline {
|
||||
if ending == Ending::Newline {
|
||||
let mut clause = " ".repeat(indent.saturating_sub(1));
|
||||
// add a space so stripping <br> tags and breaking spaces still renders properly
|
||||
write!(
|
||||
@ -1167,7 +1173,7 @@ impl clean::Impl {
|
||||
fmt_type(&self.for_, f, use_absolute, cx)?;
|
||||
}
|
||||
|
||||
fmt::Display::fmt(&print_where_clause(&self.generics, cx, 0, true), f)?;
|
||||
fmt::Display::fmt(&print_where_clause(&self.generics, cx, 0, Ending::Newline), f)?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ use crate::formats::{AssocItemRender, Impl, RenderMode};
|
||||
use crate::html::escape::Escape;
|
||||
use crate::html::format::{
|
||||
href, join_with_double_colon, print_abi_with_space, print_constness_with_space,
|
||||
print_default_space, print_generic_bounds, print_where_clause, Buffer, HrefError,
|
||||
print_default_space, print_generic_bounds, print_where_clause, Buffer, Ending, HrefError,
|
||||
PrintWithSpace,
|
||||
};
|
||||
use crate::html::highlight;
|
||||
@ -747,7 +747,7 @@ fn assoc_type(
|
||||
if !bounds.is_empty() {
|
||||
write!(w, ": {}", print_generic_bounds(bounds, cx))
|
||||
}
|
||||
write!(w, "{}", print_where_clause(generics, cx, indent, false));
|
||||
write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline));
|
||||
if let Some(default) = default {
|
||||
write!(w, " = {}", default.print(cx))
|
||||
}
|
||||
@ -796,10 +796,10 @@ fn assoc_method(
|
||||
header_len += 4;
|
||||
let indent_str = " ";
|
||||
render_attributes_in_pre(w, meth, indent_str);
|
||||
(4, indent_str, false)
|
||||
(4, indent_str, Ending::NoNewline)
|
||||
} else {
|
||||
render_attributes_in_code(w, meth);
|
||||
(0, "", true)
|
||||
(0, "", Ending::Newline)
|
||||
};
|
||||
w.reserve(header_len + "<a href=\"\" class=\"fnname\">{".len() + "</a>".len());
|
||||
write!(
|
||||
|
@ -29,7 +29,7 @@ use crate::formats::{AssocItemRender, Impl, RenderMode};
|
||||
use crate::html::escape::Escape;
|
||||
use crate::html::format::{
|
||||
join_with_double_colon, print_abi_with_space, print_constness_with_space, print_where_clause,
|
||||
Buffer, PrintWithSpace,
|
||||
Buffer, Ending, PrintWithSpace,
|
||||
};
|
||||
use crate::html::highlight;
|
||||
use crate::html::layout::Page;
|
||||
@ -69,7 +69,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>(
|
||||
cx: &'a Context<'tcx>,
|
||||
) -> bool {
|
||||
let len_before = buffer.len();
|
||||
write!(buffer, "{}", print_where_clause(gens, cx, 0, true));
|
||||
write!(buffer, "{}", print_where_clause(gens, cx, 0, Ending::Newline));
|
||||
len_before != buffer.len()
|
||||
}
|
||||
|
||||
@ -519,7 +519,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
|
||||
abi = abi,
|
||||
name = name,
|
||||
generics = f.generics.print(cx),
|
||||
where_clause = print_where_clause(&f.generics, cx, 0, true),
|
||||
where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
|
||||
decl = f.decl.full_print(header_len, 0, header.asyncness, cx),
|
||||
notable_traits = notable_traits_decl(&f.decl, cx),
|
||||
);
|
||||
@ -556,7 +556,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
||||
);
|
||||
|
||||
if !t.generics.where_predicates.is_empty() {
|
||||
write!(w, "{}", print_where_clause(&t.generics, cx, 0, true));
|
||||
write!(w, "{}", print_where_clause(&t.generics, cx, 0, Ending::Newline));
|
||||
} else {
|
||||
w.write_str(" ");
|
||||
}
|
||||
@ -1025,7 +1025,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &
|
||||
"trait {}{}{} = {};",
|
||||
it.name.unwrap(),
|
||||
t.generics.print(cx),
|
||||
print_where_clause(&t.generics, cx, 0, true),
|
||||
print_where_clause(&t.generics, cx, 0, Ending::Newline),
|
||||
bounds(&t.bounds, true, cx)
|
||||
);
|
||||
});
|
||||
@ -1049,7 +1049,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &cl
|
||||
"type {}{}{where_clause} = impl {bounds};",
|
||||
it.name.unwrap(),
|
||||
t.generics.print(cx),
|
||||
where_clause = print_where_clause(&t.generics, cx, 0, true),
|
||||
where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
|
||||
bounds = bounds(&t.bounds, false, cx),
|
||||
);
|
||||
});
|
||||
@ -1074,7 +1074,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
|
||||
"type {}{}{where_clause} = {type_};",
|
||||
it.name.unwrap(),
|
||||
t.generics.print(cx),
|
||||
where_clause = print_where_clause(&t.generics, cx, 0, true),
|
||||
where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
|
||||
type_ = t.type_.print(cx),
|
||||
);
|
||||
});
|
||||
@ -1784,7 +1784,7 @@ fn render_struct(
|
||||
}
|
||||
w.write_str(")");
|
||||
if let Some(g) = g {
|
||||
write!(w, "{}", print_where_clause(g, cx, 0, false));
|
||||
write!(w, "{}", print_where_clause(g, cx, 0, Ending::NoNewline));
|
||||
}
|
||||
// We only want a ";" when we are displaying a tuple struct, not a variant tuple struct.
|
||||
if structhead {
|
||||
@ -1794,7 +1794,7 @@ fn render_struct(
|
||||
CtorKind::Const => {
|
||||
// Needed for PhantomData.
|
||||
if let Some(g) = g {
|
||||
write!(w, "{}", print_where_clause(g, cx, 0, false));
|
||||
write!(w, "{}", print_where_clause(g, cx, 0, Ending::NoNewline));
|
||||
}
|
||||
w.write_str(";");
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ pub(crate) fn run(
|
||||
// Run call-finder on all items
|
||||
let mut calls = FxHashMap::default();
|
||||
let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates };
|
||||
tcx.hir().deep_visit_all_item_likes(&mut finder);
|
||||
tcx.hir().visit_all_item_likes_in_crate(&mut finder);
|
||||
|
||||
// Sort call locations within a given file in document order
|
||||
for fn_calls in calls.values_mut() {
|
||||
|
13
src/test/ui/const-generics/issue-70408.rs
Normal file
13
src/test/ui/const-generics/issue-70408.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// build-pass
|
||||
|
||||
#![feature(adt_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub fn function_with_bytes<const BYTES: &'static [u8; 4]>() -> &'static [u8] {
|
||||
BYTES
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
assert_eq!(function_with_bytes::<b"AAAA">(), &[0x41, 0x41, 0x41, 0x41]);
|
||||
assert_eq!(function_with_bytes::<{ &[0x41, 0x41, 0x41, 0x41] }>(), b"AAAA");
|
||||
}
|
13
src/test/ui/const-generics/issue-80471.rs
Normal file
13
src/test/ui/const-generics/issue-80471.rs
Normal file
@ -0,0 +1,13 @@
|
||||
#![feature(adt_const_params)]
|
||||
//~^ WARN the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum Nat {
|
||||
Z,
|
||||
S(Box<Nat>),
|
||||
}
|
||||
|
||||
fn foo<const N: Nat>() {}
|
||||
//~^ ERROR `Box<Nat>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
|
||||
|
||||
fn main() {}
|
18
src/test/ui/const-generics/issue-80471.stderr
Normal file
18
src/test/ui/const-generics/issue-80471.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/issue-80471.rs:1:12
|
||||
|
|
||||
LL | #![feature(adt_const_params)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
|
||||
|
||||
error[E0741]: `Box<Nat>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
|
||||
--> $DIR/issue-80471.rs:10:17
|
||||
|
|
||||
LL | fn foo<const N: Nat>() {}
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0741`.
|
@ -16,12 +16,6 @@ error: no path from `WillChange` to `trait_def`
|
||||
LL | #[rustc_then_this_would_need(trait_def)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:32:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:36:5
|
||||
|
|
||||
@ -52,36 +46,12 @@ error: OK
|
||||
LL | #[rustc_then_this_would_need(type_of)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:48:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:49:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(typeck)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:53:5
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(type_of)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:55:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:56:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(typeck)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:61:9
|
||||
|
|
||||
@ -106,12 +76,6 @@ error: no path from `WillChange` to `type_of`
|
||||
LL | #[rustc_then_this_would_need(type_of)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: no path from `WillChange` to `fn_sig`
|
||||
--> $DIR/dep-graph-struct-signature.rs:77:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: no path from `WillChange` to `fn_sig`
|
||||
--> $DIR/dep-graph-struct-signature.rs:81:5
|
||||
|
|
||||
@ -130,5 +94,41 @@ error: no path from `WillChange` to `typeck`
|
||||
LL | #[rustc_then_this_would_need(typeck)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:32:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: no path from `WillChange` to `fn_sig`
|
||||
--> $DIR/dep-graph-struct-signature.rs:77:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:48:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:49:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(typeck)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:55:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-struct-signature.rs:56:9
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(typeck)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 22 previous errors
|
||||
|
||||
|
@ -28,30 +28,12 @@ error: no path from `TypeAlias` to `type_of`
|
||||
LL | #[rustc_then_this_would_need(type_of)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-type-alias.rs:36:5
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: no path from `TypeAlias` to `type_of`
|
||||
--> $DIR/dep-graph-type-alias.rs:42:1
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(type_of)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-type-alias.rs:44:5
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-type-alias.rs:45:5
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(typeck)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-type-alias.rs:49:1
|
||||
|
|
||||
@ -70,5 +52,23 @@ error: OK
|
||||
LL | #[rustc_then_this_would_need(typeck)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-type-alias.rs:36:5
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-type-alias.rs:44:5
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(fn_sig)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: OK
|
||||
--> $DIR/dep-graph-type-alias.rs:45:5
|
||||
|
|
||||
LL | #[rustc_then_this_would_need(typeck)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
pub enum Test { //~ HELP consider adding `#[derive(Default)]` to this enum
|
||||
pub enum Test { //~ HELP consider adding a derive
|
||||
#[default]
|
||||
//~^ ERROR cannot find attribute `default` in this scope
|
||||
First,
|
||||
|
@ -4,11 +4,11 @@ error: cannot find attribute `default` in this scope
|
||||
LL | #[default]
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: consider adding `#[derive(Default)]` to this enum
|
||||
--> $DIR/suggest-default-attribute.rs:1:1
|
||||
help: consider adding a derive
|
||||
|
|
||||
LL + #[derive(Default)]
|
||||
LL ~ pub enum Test {
|
||||
|
|
||||
LL | pub enum Test {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/intrinsic-raw_eq-const-padding.rs:6:5
|
||||
|
|
||||
LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading 4 bytes of memory starting at alloc3, but 1 byte is uninitialized starting at alloc3+0x1, and this operation requires initialized memory
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc3[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,12 +4,6 @@ error: function has missing const stability attribute
|
||||
LL | pub const fn foo() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: associated function has missing const stability attribute
|
||||
--> $DIR/missing-const-stability.rs:15:5
|
||||
|
|
||||
LL | pub const fn foo() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: implementation has missing const stability attribute
|
||||
--> $DIR/missing-const-stability.rs:27:1
|
||||
|
|
||||
@ -19,5 +13,11 @@ LL | | fn fun() {}
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: associated function has missing const stability attribute
|
||||
--> $DIR/missing-const-stability.rs:15:5
|
||||
|
|
||||
LL | pub const fn foo() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user