mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-28 11:17:26 +03:00
Auto merge of #147197 - matthiaskrgr:rollup-du5e4pv, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang/rust#142506 (Add `Path::has_trailing_sep` and related methods) - rust-lang/rust#146886 (Add repr(align(2)) to RcInner and ArcInner) - rust-lang/rust#147166 (several small `proc_macro` cleanups) - rust-lang/rust#147172 (bootstrap: build bootstrap docs with in-tree rustdoc) - rust-lang/rust#147181 (cg_llvm: Replace enum `MetadataType` with a list of `MetadataKindId` constants) - rust-lang/rust#147187 (remove unnecessary test directives) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
@@ -34,7 +34,7 @@
|
||||
use crate::back::write::to_llvm_code_model;
|
||||
use crate::callee::get_fn;
|
||||
use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
|
||||
use crate::llvm::Metadata;
|
||||
use crate::llvm::{Metadata, MetadataKindId};
|
||||
use crate::type_::Type;
|
||||
use crate::value::Value;
|
||||
use crate::{attributes, common, coverageinfo, debuginfo, llvm, llvm_util};
|
||||
@@ -1006,11 +1006,11 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
|
||||
pub(crate) fn set_metadata<'a>(
|
||||
&self,
|
||||
val: &'a Value,
|
||||
kind_id: impl Into<llvm::MetadataKindId>,
|
||||
kind_id: MetadataKindId,
|
||||
md: &'ll Metadata,
|
||||
) {
|
||||
let node = self.get_metadata_value(md);
|
||||
llvm::LLVMSetMetadata(val, kind_id.into(), node);
|
||||
llvm::LLVMSetMetadata(val, kind_id, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1611,16 +1611,12 @@ enum VCallVisibility {
|
||||
let v = [llvm::LLVMValueAsMetadata(cx.const_usize(0)), typeid];
|
||||
llvm::LLVMRustGlobalAddMetadata(
|
||||
vtable,
|
||||
llvm::MD_type as c_uint,
|
||||
llvm::MD_type,
|
||||
llvm::LLVMMDNodeInContext2(cx.llcx, v.as_ptr(), v.len()),
|
||||
);
|
||||
let vcall_visibility = llvm::LLVMValueAsMetadata(cx.const_u64(vcall_visibility as u64));
|
||||
let vcall_visibility_metadata = llvm::LLVMMDNodeInContext2(cx.llcx, &vcall_visibility, 1);
|
||||
llvm::LLVMGlobalSetMetadata(
|
||||
vtable,
|
||||
llvm::MetadataType::MD_vcall_visibility as c_uint,
|
||||
vcall_visibility_metadata,
|
||||
);
|
||||
llvm::LLVMGlobalSetMetadata(vtable, llvm::MD_vcall_visibility, vcall_visibility_metadata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
DITemplateTypeParameter, DIType, DebugEmissionKind, DebugNameTableKind,
|
||||
};
|
||||
use crate::llvm;
|
||||
use crate::llvm::MetadataKindId;
|
||||
|
||||
/// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`,
|
||||
/// which has a different ABI from Rust or C++ `bool`.
|
||||
@@ -513,31 +514,6 @@ pub(crate) enum FileType {
|
||||
ObjectFile,
|
||||
}
|
||||
|
||||
/// LLVMMetadataType
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")]
|
||||
pub(crate) enum MetadataType {
|
||||
MD_dbg = 0,
|
||||
MD_tbaa = 1,
|
||||
MD_prof = 2,
|
||||
MD_fpmath = 3,
|
||||
MD_range = 4,
|
||||
MD_tbaa_struct = 5,
|
||||
MD_invariant_load = 6,
|
||||
MD_alias_scope = 7,
|
||||
MD_noalias = 8,
|
||||
MD_nontemporal = 9,
|
||||
MD_mem_parallel_loop_access = 10,
|
||||
MD_nonnull = 11,
|
||||
MD_unpredictable = 15,
|
||||
MD_align = 17,
|
||||
MD_type = 19,
|
||||
MD_vcall_visibility = 28,
|
||||
MD_noundef = 29,
|
||||
MD_kcfi_type = 36,
|
||||
}
|
||||
|
||||
/// Must match the layout of `LLVMInlineAsmDialect`.
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[repr(C)]
|
||||
@@ -1035,16 +1011,6 @@ pub struct GEPNoWrapFlags : c_uint {
|
||||
unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
|
||||
pub(crate) type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct MetadataKindId(c_uint);
|
||||
|
||||
impl From<MetadataType> for MetadataKindId {
|
||||
fn from(value: MetadataType) -> Self {
|
||||
Self(value as c_uint)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
// Create and destroy contexts.
|
||||
pub(crate) fn LLVMContextDispose(C: &'static mut Context);
|
||||
@@ -1139,7 +1105,11 @@ pub(crate) fn LLVMStructTypeInContext<'a>(
|
||||
pub(crate) fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t);
|
||||
pub(crate) fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value);
|
||||
pub(crate) safe fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: MetadataKindId, Node: &'a Value);
|
||||
pub(crate) fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
|
||||
pub(crate) fn LLVMGlobalSetMetadata<'a>(
|
||||
Val: &'a Value,
|
||||
KindID: MetadataKindId,
|
||||
Metadata: &'a Metadata,
|
||||
);
|
||||
pub(crate) safe fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
|
||||
|
||||
// Operations on constants of any type
|
||||
@@ -2059,7 +2029,7 @@ pub(crate) fn LLVMDIBuilderCreateParameterVariable<'ll>(
|
||||
// Operations on all values
|
||||
pub(crate) fn LLVMRustGlobalAddMetadata<'a>(
|
||||
Val: &'a Value,
|
||||
KindID: c_uint,
|
||||
KindID: MetadataKindId,
|
||||
Metadata: &'a Metadata,
|
||||
);
|
||||
pub(crate) fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool;
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
use libc::c_uint;
|
||||
|
||||
pub(crate) use self::fixed_kinds::*;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct MetadataKindId(c_uint);
|
||||
|
||||
macro_rules! declare_fixed_metadata_kinds {
|
||||
(
|
||||
$(
|
||||
FIXED_MD_KIND($variant:ident, $value:literal)
|
||||
)*
|
||||
) => {
|
||||
// Use a submodule to group all declarations into one `#[expect(..)]`.
|
||||
#[expect(dead_code)]
|
||||
mod fixed_kinds {
|
||||
use super::MetadataKindId;
|
||||
$(
|
||||
#[expect(non_upper_case_globals)]
|
||||
pub(crate) const $variant: MetadataKindId = MetadataKindId($value);
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Must be kept in sync with the corresponding static assertions in `RustWrapper.cpp`.
|
||||
declare_fixed_metadata_kinds! {
|
||||
FIXED_MD_KIND(MD_dbg, 0)
|
||||
FIXED_MD_KIND(MD_tbaa, 1)
|
||||
FIXED_MD_KIND(MD_prof, 2)
|
||||
FIXED_MD_KIND(MD_fpmath, 3)
|
||||
FIXED_MD_KIND(MD_range, 4)
|
||||
FIXED_MD_KIND(MD_tbaa_struct, 5)
|
||||
FIXED_MD_KIND(MD_invariant_load, 6)
|
||||
FIXED_MD_KIND(MD_alias_scope, 7)
|
||||
FIXED_MD_KIND(MD_noalias, 8)
|
||||
FIXED_MD_KIND(MD_nontemporal, 9)
|
||||
FIXED_MD_KIND(MD_mem_parallel_loop_access, 10)
|
||||
FIXED_MD_KIND(MD_nonnull, 11)
|
||||
FIXED_MD_KIND(MD_dereferenceable, 12)
|
||||
FIXED_MD_KIND(MD_dereferenceable_or_null, 13)
|
||||
FIXED_MD_KIND(MD_make_implicit, 14)
|
||||
FIXED_MD_KIND(MD_unpredictable, 15)
|
||||
FIXED_MD_KIND(MD_invariant_group, 16)
|
||||
FIXED_MD_KIND(MD_align, 17)
|
||||
FIXED_MD_KIND(MD_loop, 18)
|
||||
FIXED_MD_KIND(MD_type, 19)
|
||||
FIXED_MD_KIND(MD_section_prefix, 20)
|
||||
FIXED_MD_KIND(MD_absolute_symbol, 21)
|
||||
FIXED_MD_KIND(MD_associated, 22)
|
||||
FIXED_MD_KIND(MD_callees, 23)
|
||||
FIXED_MD_KIND(MD_irr_loop, 24)
|
||||
FIXED_MD_KIND(MD_access_group, 25)
|
||||
FIXED_MD_KIND(MD_callback, 26)
|
||||
FIXED_MD_KIND(MD_preserve_access_index, 27)
|
||||
FIXED_MD_KIND(MD_vcall_visibility, 28)
|
||||
FIXED_MD_KIND(MD_noundef, 29)
|
||||
FIXED_MD_KIND(MD_annotation, 30)
|
||||
FIXED_MD_KIND(MD_nosanitize, 31)
|
||||
FIXED_MD_KIND(MD_func_sanitize, 32)
|
||||
FIXED_MD_KIND(MD_exclude, 33)
|
||||
FIXED_MD_KIND(MD_memprof, 34)
|
||||
FIXED_MD_KIND(MD_callsite, 35)
|
||||
FIXED_MD_KIND(MD_kcfi_type, 36)
|
||||
FIXED_MD_KIND(MD_pcsections, 37)
|
||||
FIXED_MD_KIND(MD_DIAssignID, 38)
|
||||
FIXED_MD_KIND(MD_coro_outside_frame, 39)
|
||||
FIXED_MD_KIND(MD_mmra, 40)
|
||||
FIXED_MD_KIND(MD_noalias_addrspace, 41)
|
||||
}
|
||||
@@ -11,13 +11,14 @@
|
||||
|
||||
pub(crate) use self::CallConv::*;
|
||||
pub(crate) use self::CodeGenOptSize::*;
|
||||
pub(crate) use self::MetadataType::*;
|
||||
pub(crate) use self::ffi::*;
|
||||
pub(crate) use self::metadata_kind::*;
|
||||
use crate::common::AsCCharPtr;
|
||||
|
||||
pub(crate) mod diagnostic;
|
||||
pub(crate) mod enzyme_ffi;
|
||||
mod ffi;
|
||||
mod metadata_kind;
|
||||
|
||||
pub(crate) use self::enzyme_ffi::*;
|
||||
|
||||
|
||||
@@ -306,7 +306,7 @@ fn add_type_metadata(&self, function: &'ll Value, typeid: &[u8]) {
|
||||
let v = [llvm::LLVMValueAsMetadata(self.const_usize(0)), typeid_metadata];
|
||||
llvm::LLVMRustGlobalAddMetadata(
|
||||
function,
|
||||
llvm::MD_type as c_uint,
|
||||
llvm::MD_type,
|
||||
llvm::LLVMMDNodeInContext2(self.llcx, v.as_ptr(), v.len()),
|
||||
)
|
||||
}
|
||||
@@ -318,7 +318,7 @@ fn set_type_metadata(&self, function: &'ll Value, typeid: &[u8]) {
|
||||
let v = [llvm::LLVMValueAsMetadata(self.const_usize(0)), typeid_metadata];
|
||||
llvm::LLVMGlobalSetMetadata(
|
||||
function,
|
||||
llvm::MD_type as c_uint,
|
||||
llvm::MD_type,
|
||||
llvm::LLVMMDNodeInContext2(self.llcx, v.as_ptr(), v.len()),
|
||||
)
|
||||
}
|
||||
@@ -333,7 +333,7 @@ fn add_kcfi_type_metadata(&self, function: &'ll Value, kcfi_typeid: u32) {
|
||||
unsafe {
|
||||
llvm::LLVMRustGlobalAddMetadata(
|
||||
function,
|
||||
llvm::MD_kcfi_type as c_uint,
|
||||
llvm::MD_kcfi_type,
|
||||
llvm::LLVMMDNodeInContext2(
|
||||
self.llcx,
|
||||
&llvm::LLVMValueAsMetadata(kcfi_type_metadata),
|
||||
@@ -348,7 +348,7 @@ fn set_kcfi_type_metadata(&self, function: &'ll Value, kcfi_typeid: u32) {
|
||||
unsafe {
|
||||
llvm::LLVMGlobalSetMetadata(
|
||||
function,
|
||||
llvm::MD_kcfi_type as c_uint,
|
||||
llvm::MD_kcfi_type,
|
||||
llvm::LLVMMDNodeInContext2(
|
||||
self.llcx,
|
||||
&llvm::LLVMValueAsMetadata(kcfi_type_metadata),
|
||||
|
||||
@@ -1824,3 +1824,55 @@ extern "C" size_t LLVMRustEnzymeGetMaxTypeDepth() {
|
||||
return 6; // Default fallback depth
|
||||
}
|
||||
#endif
|
||||
|
||||
// Statically assert that the fixed metadata kind IDs declared in
|
||||
// `metadata_kind.rs` match the ones actually used by LLVM.
|
||||
#define FIXED_MD_KIND(VARIANT, VALUE) \
|
||||
static_assert(::llvm::LLVMContext::VARIANT == VALUE);
|
||||
// Must be kept in sync with the corresponding list in `metadata_kind.rs`.
|
||||
FIXED_MD_KIND(MD_dbg, 0)
|
||||
FIXED_MD_KIND(MD_tbaa, 1)
|
||||
FIXED_MD_KIND(MD_prof, 2)
|
||||
FIXED_MD_KIND(MD_fpmath, 3)
|
||||
FIXED_MD_KIND(MD_range, 4)
|
||||
FIXED_MD_KIND(MD_tbaa_struct, 5)
|
||||
FIXED_MD_KIND(MD_invariant_load, 6)
|
||||
FIXED_MD_KIND(MD_alias_scope, 7)
|
||||
FIXED_MD_KIND(MD_noalias, 8)
|
||||
FIXED_MD_KIND(MD_nontemporal, 9)
|
||||
FIXED_MD_KIND(MD_mem_parallel_loop_access, 10)
|
||||
FIXED_MD_KIND(MD_nonnull, 11)
|
||||
FIXED_MD_KIND(MD_dereferenceable, 12)
|
||||
FIXED_MD_KIND(MD_dereferenceable_or_null, 13)
|
||||
FIXED_MD_KIND(MD_make_implicit, 14)
|
||||
FIXED_MD_KIND(MD_unpredictable, 15)
|
||||
FIXED_MD_KIND(MD_invariant_group, 16)
|
||||
FIXED_MD_KIND(MD_align, 17)
|
||||
FIXED_MD_KIND(MD_loop, 18)
|
||||
FIXED_MD_KIND(MD_type, 19)
|
||||
FIXED_MD_KIND(MD_section_prefix, 20)
|
||||
FIXED_MD_KIND(MD_absolute_symbol, 21)
|
||||
FIXED_MD_KIND(MD_associated, 22)
|
||||
FIXED_MD_KIND(MD_callees, 23)
|
||||
FIXED_MD_KIND(MD_irr_loop, 24)
|
||||
FIXED_MD_KIND(MD_access_group, 25)
|
||||
FIXED_MD_KIND(MD_callback, 26)
|
||||
FIXED_MD_KIND(MD_preserve_access_index, 27)
|
||||
FIXED_MD_KIND(MD_vcall_visibility, 28)
|
||||
FIXED_MD_KIND(MD_noundef, 29)
|
||||
FIXED_MD_KIND(MD_annotation, 30)
|
||||
FIXED_MD_KIND(MD_nosanitize, 31)
|
||||
FIXED_MD_KIND(MD_func_sanitize, 32)
|
||||
FIXED_MD_KIND(MD_exclude, 33)
|
||||
FIXED_MD_KIND(MD_memprof, 34)
|
||||
FIXED_MD_KIND(MD_callsite, 35)
|
||||
FIXED_MD_KIND(MD_kcfi_type, 36)
|
||||
FIXED_MD_KIND(MD_pcsections, 37)
|
||||
FIXED_MD_KIND(MD_DIAssignID, 38)
|
||||
FIXED_MD_KIND(MD_coro_outside_frame, 39)
|
||||
FIXED_MD_KIND(MD_mmra, 40)
|
||||
FIXED_MD_KIND(MD_noalias_addrspace, 41)
|
||||
// If some fixed metadata kinds are not present and consistent in all supported
|
||||
// LLVM versions, it's fine to omit them from this list; in that case Rust-side
|
||||
// code cannot declare them as fixed IDs and must look them up by name instead.
|
||||
#undef FIXED_MD_KIND
|
||||
|
||||
@@ -277,7 +277,9 @@
|
||||
// This is repr(C) to future-proof against possible field-reordering, which
|
||||
// would interfere with otherwise safe [into|from]_raw() of transmutable
|
||||
// inner types.
|
||||
#[repr(C)]
|
||||
// repr(align(2)) (forcing alignment to at least 2) is required because usize
|
||||
// has 1-byte alignment on AVR.
|
||||
#[repr(C, align(2))]
|
||||
struct RcInner<T: ?Sized> {
|
||||
strong: Cell<usize>,
|
||||
weak: Cell<usize>,
|
||||
|
||||
@@ -341,7 +341,7 @@ pub struct Weak<
|
||||
// but it is not necessarily a valid pointer.
|
||||
// `Weak::new` sets this to `usize::MAX` so that it doesn’t need
|
||||
// to allocate space on the heap. That's not a value a real pointer
|
||||
// will ever have because RcInner has alignment at least 2.
|
||||
// will ever have because ArcInner has alignment at least 2.
|
||||
ptr: NonNull<ArcInner<T>>,
|
||||
alloc: A,
|
||||
}
|
||||
@@ -366,7 +366,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// This is repr(C) to future-proof against possible field-reordering, which
|
||||
// would interfere with otherwise safe [into|from]_raw() of transmutable
|
||||
// inner types.
|
||||
#[repr(C)]
|
||||
// Unlike RcInner, repr(align(2)) is not strictly required because atomic types
|
||||
// have the alignment same as its size, but we use it for consistency and clarity.
|
||||
#[repr(C, align(2))]
|
||||
struct ArcInner<T: ?Sized> {
|
||||
strong: Atomic<usize>,
|
||||
|
||||
@@ -1613,9 +1615,9 @@ pub fn into_raw_with_allocator(this: Self) -> (*const T, A) {
|
||||
pub fn as_ptr(this: &Self) -> *const T {
|
||||
let ptr: *mut ArcInner<T> = NonNull::as_ptr(this.ptr);
|
||||
|
||||
// SAFETY: This cannot go through Deref::deref or RcInnerPtr::inner because
|
||||
// SAFETY: This cannot go through Deref::deref or ArcInnerPtr::inner because
|
||||
// this is required to retain raw/mut provenance such that e.g. `get_mut` can
|
||||
// write through the pointer after the Rc is recovered through `from_raw`.
|
||||
// write through the pointer after the Arc is recovered through `from_raw`.
|
||||
unsafe { &raw mut (*ptr).data }
|
||||
}
|
||||
|
||||
@@ -2450,7 +2452,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> {
|
||||
/// If any other `Arc` or [`Weak`] pointers to the same allocation exist, then
|
||||
/// they must not be dereferenced or have active borrows for the duration
|
||||
/// of the returned borrow, and their inner type must be exactly the same as the
|
||||
/// inner type of this Rc (including lifetimes). This is trivially the case if no
|
||||
/// inner type of this Arc (including lifetimes). This is trivially the case if no
|
||||
/// such pointers exist, for example immediately after `Arc::new`.
|
||||
///
|
||||
/// # Examples
|
||||
@@ -3022,7 +3024,7 @@ pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self {
|
||||
// Otherwise, we're guaranteed the pointer came from a nondangling Weak.
|
||||
// SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
|
||||
let offset = unsafe { data_offset(ptr) };
|
||||
// Thus, we reverse the offset to get the whole RcInner.
|
||||
// Thus, we reverse the offset to get the whole ArcInner.
|
||||
// SAFETY: the pointer originated from a Weak, so this offset is safe.
|
||||
unsafe { ptr.byte_sub(offset) as *mut ArcInner<T> }
|
||||
};
|
||||
@@ -4015,7 +4017,7 @@ impl<T: ?Sized, A: Allocator> Unpin for Arc<T, A> {}
|
||||
/// valid instance of T, but the T is allowed to be dropped.
|
||||
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> usize {
|
||||
// Align the unsized value to the end of the ArcInner.
|
||||
// Because RcInner is repr(C), it will always be the last field in memory.
|
||||
// Because ArcInner is repr(C), it will always be the last field in memory.
|
||||
// SAFETY: since the only unsized types possible are slices, trait objects,
|
||||
// and extern types, the input safety requirement is currently enough to
|
||||
// satisfy the requirements of align_of_val_raw; this is an implementation
|
||||
|
||||
@@ -26,18 +26,16 @@ pub(super) struct HandleCounters {
|
||||
$(
|
||||
pub(crate) struct $oty {
|
||||
handle: handle::Handle,
|
||||
// Prevent Send and Sync impls. `!Send`/`!Sync` is the usual
|
||||
// way of doing this, but that requires unstable features.
|
||||
// rust-analyzer uses this code and avoids unstable features.
|
||||
_marker: PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
impl !Send for $oty {}
|
||||
impl !Sync for $oty {}
|
||||
|
||||
// Forward `Drop::drop` to the inherent `drop` method.
|
||||
impl Drop for $oty {
|
||||
fn drop(&mut self) {
|
||||
$oty {
|
||||
handle: self.handle,
|
||||
_marker: PhantomData,
|
||||
}.drop();
|
||||
}
|
||||
}
|
||||
@@ -64,7 +62,6 @@ impl<S> DecodeMut<'_, '_, S> for $oty {
|
||||
fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
$oty {
|
||||
handle: handle::Handle::decode(r, s),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,12 +71,11 @@ fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct $ity {
|
||||
handle: handle::Handle,
|
||||
// Prevent Send and Sync impls. `!Send`/`!Sync` is the usual
|
||||
// way of doing this, but that requires unstable features.
|
||||
// rust-analyzer uses this code and avoids unstable features.
|
||||
_marker: PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
impl !Send for $ity {}
|
||||
impl !Sync for $ity {}
|
||||
|
||||
impl<S> Encode<S> for $ity {
|
||||
fn encode(self, w: &mut Writer, s: &mut S) {
|
||||
self.handle.encode(w, s);
|
||||
@@ -90,7 +86,6 @@ impl<S> DecodeMut<'_, '_, S> for $ity {
|
||||
fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
|
||||
$ity {
|
||||
handle: handle::Handle::decode(r, s),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,7 +139,7 @@ macro_rules! define_client_side {
|
||||
|
||||
buf.clear();
|
||||
api_tags::Method::$name(api_tags::$name::$method).encode(&mut buf, &mut ());
|
||||
reverse_encode!(buf; $($arg),*);
|
||||
$($arg.encode(&mut buf, &mut ());)*
|
||||
|
||||
buf = bridge.dispatch.call(buf);
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
pub(super) struct Closure<'a, A, R> {
|
||||
call: unsafe extern "C" fn(*mut Env, A) -> R,
|
||||
env: *mut Env,
|
||||
// Prevent Send and Sync impls. `!Send`/`!Sync` is the usual way of doing
|
||||
// this, but that requires unstable features. rust-analyzer uses this code
|
||||
// and avoids unstable features.
|
||||
// Prevent Send and Sync impls.
|
||||
//
|
||||
// The `'a` lifetime parameter represents the lifetime of `Env`.
|
||||
_marker: PhantomData<*mut &'a mut ()>,
|
||||
|
||||
@@ -119,26 +119,6 @@ macro_rules! with_api_handle_types {
|
||||
};
|
||||
}
|
||||
|
||||
// FIXME(eddyb) this calls `encode` for each argument, but in reverse,
|
||||
// to match the ordering in `reverse_decode`.
|
||||
macro_rules! reverse_encode {
|
||||
($writer:ident;) => {};
|
||||
($writer:ident; $first:ident $(, $rest:ident)*) => {
|
||||
reverse_encode!($writer; $($rest),*);
|
||||
$first.encode(&mut $writer, &mut ());
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) this calls `decode` for each argument, but in reverse,
|
||||
// to avoid borrow conflicts from borrows started by `&mut` arguments.
|
||||
macro_rules! reverse_decode {
|
||||
($reader:ident, $s:ident;) => {};
|
||||
($reader:ident, $s:ident; $first:ident: $first_ty:ty $(, $rest:ident: $rest_ty:ty)*) => {
|
||||
reverse_decode!($reader, $s; $($rest: $rest_ty),*);
|
||||
let $first = <$first_ty>::decode(&mut $reader, $s);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
mod arena;
|
||||
#[allow(unsafe_code)]
|
||||
@@ -180,13 +160,11 @@ pub struct BridgeConfig<'a> {
|
||||
|
||||
/// If 'true', always invoke the default panic hook
|
||||
force_show_panics: bool,
|
||||
|
||||
// Prevent Send and Sync impls. `!Send`/`!Sync` is the usual way of doing
|
||||
// this, but that requires unstable features. rust-analyzer uses this code
|
||||
// and avoids unstable features.
|
||||
_marker: marker::PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
impl !Send for BridgeConfig<'_> {}
|
||||
impl !Sync for BridgeConfig<'_> {}
|
||||
|
||||
#[forbid(unsafe_code)]
|
||||
#[allow(non_camel_case_types)]
|
||||
mod api_tags {
|
||||
|
||||
@@ -178,7 +178,7 @@ fn dispatch(&mut self, mut buf: Buffer) -> Buffer {
|
||||
$(api_tags::Method::$name(m) => match m {
|
||||
$(api_tags::$name::$method => {
|
||||
let mut call_method = || {
|
||||
reverse_decode!(reader, handle_store; $($arg: $arg_ty),*);
|
||||
$(let $arg = <$arg_ty>::decode(&mut reader, handle_store);)*
|
||||
$name::$method(server, $($arg),*)
|
||||
};
|
||||
// HACK(eddyb) don't use `panic::catch_unwind` in a panic.
|
||||
@@ -295,12 +295,7 @@ fn run_bridge_and_client(
|
||||
|
||||
let mut dispatch = |buf| dispatcher.dispatch(buf);
|
||||
|
||||
run_client(BridgeConfig {
|
||||
input,
|
||||
dispatch: (&mut dispatch).into(),
|
||||
force_show_panics,
|
||||
_marker: marker::PhantomData,
|
||||
})
|
||||
run_client(BridgeConfig { input, dispatch: (&mut dispatch).into(), force_show_panics })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,12 +326,7 @@ fn run_bridge_and_client(
|
||||
client.recv().expect("server died while client waiting for reply")
|
||||
};
|
||||
|
||||
run_client(BridgeConfig {
|
||||
input,
|
||||
dispatch: (&mut dispatch).into(),
|
||||
force_show_panics,
|
||||
_marker: marker::PhantomData,
|
||||
})
|
||||
run_client(BridgeConfig { input, dispatch: (&mut dispatch).into(), force_show_panics })
|
||||
});
|
||||
|
||||
while let Some(b) = server.recv() {
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#![feature(panic_can_unwind)]
|
||||
#![feature(restricted_std)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(extend_one)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(internal_features)]
|
||||
|
||||
+184
-3
@@ -1412,6 +1412,99 @@ pub fn pop(&mut self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets whether the path has a trailing [separator](MAIN_SEPARATOR).
|
||||
///
|
||||
/// The value returned by [`has_trailing_sep`](Path::has_trailing_sep) will be equivalent to
|
||||
/// the provided value if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(path_trailing_sep)]
|
||||
/// use std::path::PathBuf;
|
||||
///
|
||||
/// let mut p = PathBuf::from("dir");
|
||||
///
|
||||
/// assert!(!p.has_trailing_sep());
|
||||
/// p.set_trailing_sep(false);
|
||||
/// assert!(!p.has_trailing_sep());
|
||||
/// p.set_trailing_sep(true);
|
||||
/// assert!(p.has_trailing_sep());
|
||||
/// p.set_trailing_sep(false);
|
||||
/// assert!(!p.has_trailing_sep());
|
||||
///
|
||||
/// p = PathBuf::from("/");
|
||||
/// assert!(p.has_trailing_sep());
|
||||
/// p.set_trailing_sep(false);
|
||||
/// assert!(p.has_trailing_sep());
|
||||
/// ```
|
||||
#[unstable(feature = "path_trailing_sep", issue = "142503")]
|
||||
pub fn set_trailing_sep(&mut self, trailing_sep: bool) {
|
||||
if trailing_sep { self.push_trailing_sep() } else { self.pop_trailing_sep() }
|
||||
}
|
||||
|
||||
/// Adds a trailing [separator](MAIN_SEPARATOR) to the path.
|
||||
///
|
||||
/// This acts similarly to [`Path::with_trailing_sep`], but mutates the underlying `PathBuf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(path_trailing_sep)]
|
||||
/// use std::ffi::OsStr;
|
||||
/// use std::path::PathBuf;
|
||||
///
|
||||
/// let mut p = PathBuf::from("dir");
|
||||
///
|
||||
/// assert!(!p.has_trailing_sep());
|
||||
/// p.push_trailing_sep();
|
||||
/// assert!(p.has_trailing_sep());
|
||||
/// p.push_trailing_sep();
|
||||
/// assert!(p.has_trailing_sep());
|
||||
///
|
||||
/// p = PathBuf::from("dir/");
|
||||
/// p.push_trailing_sep();
|
||||
/// assert_eq!(p.as_os_str(), OsStr::new("dir/"));
|
||||
/// ```
|
||||
#[unstable(feature = "path_trailing_sep", issue = "142503")]
|
||||
pub fn push_trailing_sep(&mut self) {
|
||||
if !self.has_trailing_sep() {
|
||||
self.push("");
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes a trailing [separator](MAIN_SEPARATOR) from the path, if possible.
|
||||
///
|
||||
/// This acts similarly to [`Path::trim_trailing_sep`], but mutates the underlying `PathBuf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(path_trailing_sep)]
|
||||
/// use std::ffi::OsStr;
|
||||
/// use std::path::PathBuf;
|
||||
///
|
||||
/// let mut p = PathBuf::from("dir//");
|
||||
///
|
||||
/// assert!(p.has_trailing_sep());
|
||||
/// assert_eq!(p.as_os_str(), OsStr::new("dir//"));
|
||||
/// p.pop_trailing_sep();
|
||||
/// assert!(!p.has_trailing_sep());
|
||||
/// assert_eq!(p.as_os_str(), OsStr::new("dir"));
|
||||
/// p.pop_trailing_sep();
|
||||
/// assert!(!p.has_trailing_sep());
|
||||
/// assert_eq!(p.as_os_str(), OsStr::new("dir"));
|
||||
///
|
||||
/// p = PathBuf::from("/");
|
||||
/// assert!(p.has_trailing_sep());
|
||||
/// p.pop_trailing_sep();
|
||||
/// assert!(p.has_trailing_sep());
|
||||
/// ```
|
||||
#[unstable(feature = "path_trailing_sep", issue = "142503")]
|
||||
pub fn pop_trailing_sep(&mut self) {
|
||||
self.inner.truncate(self.trim_trailing_sep().as_os_str().len());
|
||||
}
|
||||
|
||||
/// Updates [`self.file_name`] to `file_name`.
|
||||
///
|
||||
/// If [`self.file_name`] was [`None`], this is equivalent to pushing
|
||||
@@ -1610,7 +1703,7 @@ fn _add_extension(&mut self, extension: &OsStr) -> bool {
|
||||
let new = extension.as_encoded_bytes();
|
||||
if !new.is_empty() {
|
||||
// truncate until right after the file name
|
||||
// this is necessary for trimming the trailing slash
|
||||
// this is necessary for trimming the trailing separator
|
||||
let end_file_name = file_name[file_name.len()..].as_ptr().addr();
|
||||
let start = self.inner.as_encoded_bytes().as_ptr().addr();
|
||||
self.inner.truncate(end_file_name.wrapping_sub(start));
|
||||
@@ -2755,6 +2848,94 @@ pub fn extension(&self) -> Option<&OsStr> {
|
||||
self.file_name().map(rsplit_file_at_dot).and_then(|(before, after)| before.and(after))
|
||||
}
|
||||
|
||||
/// Checks whether the path ends in a trailing [separator](MAIN_SEPARATOR).
|
||||
///
|
||||
/// This is generally done to ensure that a path is treated as a directory, not a file,
|
||||
/// although it does not actually guarantee that such a path is a directory on the underlying
|
||||
/// file system.
|
||||
///
|
||||
/// Despite this behavior, two paths are still considered the same in Rust whether they have a
|
||||
/// trailing separator or not.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(path_trailing_sep)]
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// assert!(Path::new("dir/").has_trailing_sep());
|
||||
/// assert!(!Path::new("file.rs").has_trailing_sep());
|
||||
/// ```
|
||||
#[unstable(feature = "path_trailing_sep", issue = "142503")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn has_trailing_sep(&self) -> bool {
|
||||
self.as_os_str().as_encoded_bytes().last().copied().is_some_and(is_sep_byte)
|
||||
}
|
||||
|
||||
/// Ensures that a path has a trailing [separator](MAIN_SEPARATOR),
|
||||
/// allocating a [`PathBuf`] if necessary.
|
||||
///
|
||||
/// The resulting path will return true for [`has_trailing_sep`](Self::has_trailing_sep).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(path_trailing_sep)]
|
||||
/// use std::ffi::OsStr;
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// assert_eq!(Path::new("dir//").with_trailing_sep().as_os_str(), OsStr::new("dir//"));
|
||||
/// assert_eq!(Path::new("dir/").with_trailing_sep().as_os_str(), OsStr::new("dir/"));
|
||||
/// assert!(!Path::new("dir").has_trailing_sep());
|
||||
/// assert!(Path::new("dir").with_trailing_sep().has_trailing_sep());
|
||||
/// ```
|
||||
#[unstable(feature = "path_trailing_sep", issue = "142503")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn with_trailing_sep(&self) -> Cow<'_, Path> {
|
||||
if self.has_trailing_sep() { Cow::Borrowed(self) } else { Cow::Owned(self.join("")) }
|
||||
}
|
||||
|
||||
/// Trims a trailing [separator](MAIN_SEPARATOR) from a path, if possible.
|
||||
///
|
||||
/// The resulting path will return false for [`has_trailing_sep`](Self::has_trailing_sep) for
|
||||
/// most paths.
|
||||
///
|
||||
/// Some paths, like `/`, cannot be trimmed in this way.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(path_trailing_sep)]
|
||||
/// use std::ffi::OsStr;
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// assert_eq!(Path::new("dir//").trim_trailing_sep().as_os_str(), OsStr::new("dir"));
|
||||
/// assert_eq!(Path::new("dir/").trim_trailing_sep().as_os_str(), OsStr::new("dir"));
|
||||
/// assert_eq!(Path::new("dir").trim_trailing_sep().as_os_str(), OsStr::new("dir"));
|
||||
/// assert_eq!(Path::new("/").trim_trailing_sep().as_os_str(), OsStr::new("/"));
|
||||
/// assert_eq!(Path::new("//").trim_trailing_sep().as_os_str(), OsStr::new("//"));
|
||||
/// ```
|
||||
#[unstable(feature = "path_trailing_sep", issue = "142503")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn trim_trailing_sep(&self) -> &Path {
|
||||
if self.has_trailing_sep() && (!self.has_root() || self.parent().is_some()) {
|
||||
let mut bytes = self.inner.as_encoded_bytes();
|
||||
while let Some((last, init)) = bytes.split_last()
|
||||
&& is_sep_byte(*last)
|
||||
{
|
||||
bytes = init;
|
||||
}
|
||||
|
||||
// SAFETY: Trimming trailing ASCII bytes will retain the validity of the string.
|
||||
Path::new(unsafe { OsStr::from_encoded_bytes_unchecked(bytes) })
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
|
||||
///
|
||||
/// If `path` is absolute, it replaces the current path.
|
||||
@@ -2907,7 +3088,7 @@ pub fn with_added_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
|
||||
/// `a/b` all have `a` and `b` as components, but `./a/b` starts with
|
||||
/// an additional [`CurDir`] component.
|
||||
///
|
||||
/// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
|
||||
/// * Trailing separators are normalized away, so `/a/b` and `/a/b/` are equivalent.
|
||||
///
|
||||
/// Note that no other normalization takes place; in particular, `a/c`
|
||||
/// and `a/b/../c` are distinct, to account for the possibility that `b`
|
||||
@@ -3718,7 +3899,7 @@ impl Error for NormalizeError {}
|
||||
///
|
||||
/// On POSIX platforms, the path is resolved using [POSIX semantics][posix-semantics],
|
||||
/// except that it stops short of resolving symlinks. This means it will keep `..`
|
||||
/// components and trailing slashes.
|
||||
/// components and trailing separators.
|
||||
///
|
||||
/// On Windows, for verbatim paths, this will simply return the path as given. For other
|
||||
/// paths, this is currently equivalent to calling
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
#![feature(clone_to_uninit, maybe_uninit_slice, normalize_lexically)]
|
||||
// tidy-alphabetical-start
|
||||
#![feature(clone_to_uninit)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(normalize_lexically)]
|
||||
#![feature(path_trailing_sep)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
use std::clone::CloneToUninit;
|
||||
use std::ffi::OsStr;
|
||||
@@ -2542,3 +2547,34 @@ fn compare_path_like_to_str_like() {
|
||||
assert!(path_buf == s);
|
||||
assert!(s == path_buf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trim_trailing_sep() {
|
||||
assert_eq!(Path::new("/").trim_trailing_sep().as_os_str(), OsStr::new("/"));
|
||||
assert_eq!(Path::new("//").trim_trailing_sep().as_os_str(), OsStr::new("//"));
|
||||
assert_eq!(Path::new("").trim_trailing_sep().as_os_str(), OsStr::new(""));
|
||||
assert_eq!(Path::new(".").trim_trailing_sep().as_os_str(), OsStr::new("."));
|
||||
assert_eq!(Path::new("./").trim_trailing_sep().as_os_str(), OsStr::new("."));
|
||||
assert_eq!(Path::new(".//").trim_trailing_sep().as_os_str(), OsStr::new("."));
|
||||
assert_eq!(Path::new("..").trim_trailing_sep().as_os_str(), OsStr::new(".."));
|
||||
assert_eq!(Path::new("../").trim_trailing_sep().as_os_str(), OsStr::new(".."));
|
||||
assert_eq!(Path::new("..//").trim_trailing_sep().as_os_str(), OsStr::new(".."));
|
||||
|
||||
#[cfg(any(windows, target_os = "cygwin"))]
|
||||
{
|
||||
assert_eq!(Path::new("\\").trim_trailing_sep().as_os_str(), OsStr::new("\\"));
|
||||
assert_eq!(Path::new("\\\\").trim_trailing_sep().as_os_str(), OsStr::new("\\\\"));
|
||||
assert_eq!(Path::new("c:/").trim_trailing_sep().as_os_str(), OsStr::new("c:/"));
|
||||
assert_eq!(Path::new("c://").trim_trailing_sep().as_os_str(), OsStr::new("c://"));
|
||||
assert_eq!(Path::new("c:./").trim_trailing_sep().as_os_str(), OsStr::new("c:."));
|
||||
assert_eq!(Path::new("c:.//").trim_trailing_sep().as_os_str(), OsStr::new("c:."));
|
||||
assert_eq!(Path::new("c:../").trim_trailing_sep().as_os_str(), OsStr::new("c:.."));
|
||||
assert_eq!(Path::new("c:..//").trim_trailing_sep().as_os_str(), OsStr::new("c:.."));
|
||||
assert_eq!(Path::new("c:\\").trim_trailing_sep().as_os_str(), OsStr::new("c:\\"));
|
||||
assert_eq!(Path::new("c:\\\\").trim_trailing_sep().as_os_str(), OsStr::new("c:\\\\"));
|
||||
assert_eq!(Path::new("c:.\\").trim_trailing_sep().as_os_str(), OsStr::new("c:."));
|
||||
assert_eq!(Path::new("c:.\\\\").trim_trailing_sep().as_os_str(), OsStr::new("c:."));
|
||||
assert_eq!(Path::new("c:..\\").trim_trailing_sep().as_os_str(), OsStr::new("c:.."));
|
||||
assert_eq!(Path::new("c:..\\\\").trim_trailing_sep().as_os_str(), OsStr::new("c:.."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1024,12 +1024,9 @@ fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(Rustc::from_build_compiler(run.builder, compilers.build_compiler(), target));
|
||||
compilers.build_compiler()
|
||||
}
|
||||
Mode::ToolBootstrap => {
|
||||
// bootstrap/host tools should be documented with the stage 0 compiler
|
||||
prepare_doc_compiler(run.builder, run.builder.host_target, 1)
|
||||
}
|
||||
Mode::ToolTarget => {
|
||||
// target tools should be documented with the in-tree compiler
|
||||
// when shipping multiple docs together in one folder,
|
||||
// they all need to use the same rustdoc version
|
||||
prepare_doc_compiler(run.builder, run.builder.host_target, run.builder.top_stage)
|
||||
}
|
||||
_ => {
|
||||
@@ -1132,7 +1129,11 @@ fn metadata(&self) -> Option<StepMetadata> {
|
||||
tool_doc!(
|
||||
BuildHelper,
|
||||
"src/build_helper",
|
||||
mode = Mode::ToolBootstrap,
|
||||
// ideally, this would use ToolBootstrap,
|
||||
// but we distribute these docs together in the same folder
|
||||
// as a bunch of stage1 tools, and you can't mix rustdoc versions
|
||||
// because that breaks cross-crate data (particularly search)
|
||||
mode = Mode::ToolTarget,
|
||||
is_library = true,
|
||||
crates = ["build_helper"]
|
||||
);
|
||||
@@ -1175,25 +1176,25 @@ fn metadata(&self) -> Option<StepMetadata> {
|
||||
// "specialization" feature in its build script when it detects a nightly toolchain.
|
||||
allow_features: "specialization"
|
||||
);
|
||||
tool_doc!(Tidy, "src/tools/tidy", mode = Mode::ToolBootstrap, crates = ["tidy"]);
|
||||
tool_doc!(Tidy, "src/tools/tidy", mode = Mode::ToolTarget, crates = ["tidy"]);
|
||||
tool_doc!(
|
||||
Bootstrap,
|
||||
"src/bootstrap",
|
||||
mode = Mode::ToolBootstrap,
|
||||
mode = Mode::ToolTarget,
|
||||
is_library = true,
|
||||
crates = ["bootstrap"]
|
||||
);
|
||||
tool_doc!(
|
||||
RunMakeSupport,
|
||||
"src/tools/run-make-support",
|
||||
mode = Mode::ToolBootstrap,
|
||||
mode = Mode::ToolTarget,
|
||||
is_library = true,
|
||||
crates = ["run_make_support"]
|
||||
);
|
||||
tool_doc!(
|
||||
Compiletest,
|
||||
"src/tools/compiletest",
|
||||
mode = Mode::ToolBootstrap,
|
||||
mode = Mode::ToolTarget,
|
||||
is_library = true,
|
||||
crates = ["compiletest"]
|
||||
);
|
||||
|
||||
@@ -1158,13 +1158,12 @@ fn dist_compiler_docs() {
|
||||
[doc] embedded-book (book) <host>
|
||||
[doc] edition-guide (book) <host>
|
||||
[doc] style-guide (book) <host>
|
||||
[build] rustdoc 0 <host>
|
||||
[doc] rustc 0 <host> -> Tidy 1 <host>
|
||||
[doc] rustc 0 <host> -> Bootstrap 1 <host>
|
||||
[doc] rustc 1 <host> -> Tidy 2 <host>
|
||||
[doc] rustc 1 <host> -> Bootstrap 2 <host>
|
||||
[doc] rustc 1 <host> -> releases 2 <host>
|
||||
[doc] rustc 0 <host> -> RunMakeSupport 1 <host>
|
||||
[doc] rustc 0 <host> -> BuildHelper 1 <host>
|
||||
[doc] rustc 0 <host> -> Compiletest 1 <host>
|
||||
[doc] rustc 1 <host> -> RunMakeSupport 2 <host>
|
||||
[doc] rustc 1 <host> -> BuildHelper 2 <host>
|
||||
[doc] rustc 1 <host> -> Compiletest 2 <host>
|
||||
[build] rustc 0 <host> -> RustInstaller 1 <host>
|
||||
"
|
||||
);
|
||||
@@ -2686,8 +2685,11 @@ fn doc_compiletest_stage_2() {
|
||||
.path("src/tools/compiletest")
|
||||
.stage(2)
|
||||
.render_steps(), @r"
|
||||
[build] rustdoc 0 <host>
|
||||
[doc] rustc 0 <host> -> Compiletest 1 <host>
|
||||
[build] llvm <host>
|
||||
[build] rustc 0 <host> -> rustc 1 <host>
|
||||
[build] rustc 1 <host> -> std 1 <host>
|
||||
[build] rustdoc 1 <host>
|
||||
[doc] rustc 1 <host> -> Compiletest 2 <host>
|
||||
");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[next] failure-status: 101
|
||||
//@[next] known-bug: unknown
|
||||
//@[next] normalize-stderr: "note: .*\n\n" -> ""
|
||||
//@[next] normalize-stderr: "thread 'rustc' panicked.*\n.*\n" -> ""
|
||||
//@[next] normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
|
||||
//@[next] normalize-stderr: "delayed at .*" -> ""
|
||||
//@[next] rustc-env:RUST_BACKTRACE=0
|
||||
//@ check-pass
|
||||
|
||||
trait Super {
|
||||
|
||||
Reference in New Issue
Block a user