Merge pull request #4610 from rust-lang/rustup-2025-09-30
Automatic Rustup
This commit is contained in:
commit
fb75fbba95
124 changed files with 701 additions and 482 deletions
|
|
@ -1167,7 +1167,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
// To allow unsizing `&Foo<Type>` -> `&Foo<dyn Trait>`, the layout of the struct must
|
||||
// not depend on the layout of the tail.
|
||||
let max_field_align =
|
||||
fields_excluding_tail.iter().map(|f| f.align.abi.bytes()).max().unwrap_or(1);
|
||||
fields_excluding_tail.iter().map(|f| f.align.bytes()).max().unwrap_or(1);
|
||||
let largest_niche_size = fields_excluding_tail
|
||||
.iter()
|
||||
.filter_map(|f| f.largest_niche)
|
||||
|
|
@ -1187,7 +1187,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
} else {
|
||||
// Returns `log2(effective-align)`. The calculation assumes that size is an
|
||||
// integer multiple of align, except for ZSTs.
|
||||
let align = layout.align.abi.bytes();
|
||||
let align = layout.align.bytes();
|
||||
let size = layout.size.bytes();
|
||||
let niche_size = layout.largest_niche.map(|n| n.available(dl)).unwrap_or(0);
|
||||
// Group [u8; 4] with align-4 or [u8; 6] with align-2 fields.
|
||||
|
|
@ -1485,7 +1485,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
for i in layout.fields.index_by_increasing_offset() {
|
||||
let offset = layout.fields.offset(i);
|
||||
let f = &fields[FieldIdx::new(i)];
|
||||
write!(s, "[o{}a{}s{}", offset.bytes(), f.align.abi.bytes(), f.size.bytes()).unwrap();
|
||||
write!(s, "[o{}a{}s{}", offset.bytes(), f.align.bytes(), f.size.bytes()).unwrap();
|
||||
if let Some(n) = f.largest_niche {
|
||||
write!(
|
||||
s,
|
||||
|
|
|
|||
|
|
@ -2156,7 +2156,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
|
|||
|
||||
/// Returns `true` if the type is sized and a 1-ZST (meaning it has size 0 and alignment 1).
|
||||
pub fn is_1zst(&self) -> bool {
|
||||
self.is_sized() && self.size.bytes() == 0 && self.align.abi.bytes() == 1
|
||||
self.is_sized() && self.size.bytes() == 0 && self.align.bytes() == 1
|
||||
}
|
||||
|
||||
/// Returns `true` if the type is a ZST and not unsized.
|
||||
|
|
|
|||
|
|
@ -114,8 +114,7 @@ impl PartialEq<Symbol> for Path {
|
|||
impl PartialEq<&[Symbol]> for Path {
|
||||
#[inline]
|
||||
fn eq(&self, names: &&[Symbol]) -> bool {
|
||||
self.segments.len() == names.len()
|
||||
&& self.segments.iter().zip(names.iter()).all(|(s1, s2)| s1 == s2)
|
||||
self.segments.iter().eq(*names)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_order_by)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![recursion_limit = "256"]
|
||||
|
|
|
|||
|
|
@ -48,9 +48,7 @@ impl TokenTree {
|
|||
match (self, other) {
|
||||
(TokenTree::Token(token, _), TokenTree::Token(token2, _)) => token.kind == token2.kind,
|
||||
(TokenTree::Delimited(.., delim, tts), TokenTree::Delimited(.., delim2, tts2)) => {
|
||||
delim == delim2
|
||||
&& tts.len() == tts2.len()
|
||||
&& tts.iter().zip(tts2.iter()).all(|(a, b)| a.eq_unspanned(b))
|
||||
delim == delim2 && tts.iter().eq_by(tts2.iter(), |a, b| a.eq_unspanned(b))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,15 @@ attr_parsing_deprecated_item_suggestion =
|
|||
|
||||
attr_parsing_empty_attribute =
|
||||
unused attribute
|
||||
.suggestion = remove this attribute
|
||||
.suggestion = {$valid_without_list ->
|
||||
[true] remove these parentheses
|
||||
*[other] remove this attribute
|
||||
}
|
||||
.note = {$valid_without_list ->
|
||||
[true] using `{$attr_path}` with an empty list is equivalent to not using a list at all
|
||||
*[other] using `{$attr_path}` with an empty list has no effect
|
||||
}
|
||||
|
||||
|
||||
attr_parsing_invalid_target = `#[{$name}]` attribute cannot be used on {$target}
|
||||
.help = `#[{$name}]` can {$only}be applied to {$applied}
|
||||
|
|
|
|||
|
|
@ -597,7 +597,12 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
}
|
||||
|
||||
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
|
||||
self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
|
||||
let attr_path = self.attr_path.clone();
|
||||
let valid_without_list = self.template.word;
|
||||
self.emit_lint(
|
||||
AttributeLintKind::EmptyAttribute { first_span: span, attr_path, valid_without_list },
|
||||
span,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,12 +43,18 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emi
|
|||
),
|
||||
},
|
||||
),
|
||||
AttributeLintKind::EmptyAttribute { first_span } => lint_emitter.emit_node_span_lint(
|
||||
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
|
||||
*id,
|
||||
*first_span,
|
||||
session_diagnostics::EmptyAttributeList { attr_span: *first_span },
|
||||
),
|
||||
AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => {
|
||||
lint_emitter.emit_node_span_lint(
|
||||
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
|
||||
*id,
|
||||
*first_span,
|
||||
session_diagnostics::EmptyAttributeList {
|
||||
attr_span: *first_span,
|
||||
attr_path: attr_path.clone(),
|
||||
valid_without_list: *valid_without_list,
|
||||
},
|
||||
)
|
||||
}
|
||||
AttributeLintKind::InvalidTarget { name, target, applied, only } => lint_emitter
|
||||
.emit_node_span_lint(
|
||||
// This check is here because `deprecated` had its own lint group and removing this would be a breaking change
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ impl<'a> PathParser<'a> {
|
|||
}
|
||||
|
||||
pub fn segments_is(&self, segments: &[Symbol]) -> bool {
|
||||
self.len() == segments.len() && self.segments().zip(segments).all(|(a, b)| a.name == *b)
|
||||
self.segments().map(|segment| &segment.name).eq(segments)
|
||||
}
|
||||
|
||||
pub fn word(&self) -> Option<Ident> {
|
||||
|
|
|
|||
|
|
@ -503,9 +503,12 @@ pub(crate) struct EmptyConfusables {
|
|||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(attr_parsing_empty_attribute)]
|
||||
#[note]
|
||||
pub(crate) struct EmptyAttributeList {
|
||||
#[suggestion(code = "", applicability = "machine-applicable")]
|
||||
pub attr_span: Span,
|
||||
pub attr_path: AttrPath,
|
||||
pub valid_without_list: bool,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
|
|||
|
|
@ -377,8 +377,7 @@ mod llvm_enzyme {
|
|||
(ast::AttrKind::Normal(a), ast::AttrKind::Normal(b)) => {
|
||||
let a = &a.item.path;
|
||||
let b = &b.item.path;
|
||||
a.segments.len() == b.segments.len()
|
||||
&& a.segments.iter().zip(b.segments.iter()).all(|(a, b)| a.ident == b.ident)
|
||||
a.segments.iter().eq_by(&b.segments, |a, b| a.ident == b.ident)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,21 +356,14 @@ fn contains_maybe_sized_bound(bounds: &[GenericBound]) -> bool {
|
|||
bounds.iter().any(is_maybe_sized_bound)
|
||||
}
|
||||
|
||||
fn path_segment_is_exact_match(path_segments: &[ast::PathSegment], syms: &[Symbol]) -> bool {
|
||||
path_segments.iter().zip(syms).all(|(segment, &symbol)| segment.ident.name == symbol)
|
||||
}
|
||||
|
||||
fn is_sized_marker(path: &ast::Path) -> bool {
|
||||
const CORE_UNSIZE: [Symbol; 3] = [sym::core, sym::marker, sym::Sized];
|
||||
const STD_UNSIZE: [Symbol; 3] = [sym::std, sym::marker, sym::Sized];
|
||||
if path.segments.len() == 4 && path.is_global() {
|
||||
path_segment_is_exact_match(&path.segments[1..], &CORE_UNSIZE)
|
||||
|| path_segment_is_exact_match(&path.segments[1..], &STD_UNSIZE)
|
||||
} else if path.segments.len() == 3 {
|
||||
path_segment_is_exact_match(&path.segments, &CORE_UNSIZE)
|
||||
|| path_segment_is_exact_match(&path.segments, &STD_UNSIZE)
|
||||
let segments = || path.segments.iter().map(|segment| segment.ident.name);
|
||||
if path.is_global() {
|
||||
segments().skip(1).eq(CORE_UNSIZE) || segments().skip(1).eq(STD_UNSIZE)
|
||||
} else {
|
||||
*path == sym::Sized
|
||||
segments().eq(CORE_UNSIZE) || segments().eq(STD_UNSIZE) || *path == sym::Sized
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -768,7 +768,7 @@ fn report_missing_placeholders(
|
|||
|
||||
if !found_foreign && invalid_refs.is_empty() {
|
||||
// Show example if user didn't use any format specifiers
|
||||
let show_example = used.iter().all(|used| !used);
|
||||
let show_example = !used.contains(&true);
|
||||
|
||||
if !show_example {
|
||||
if unused.len() > 1 {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#![feature(box_patterns)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_order_by)]
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(proc_macro_quote)]
|
||||
#![feature(rustdoc_internals)]
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ pub(super) fn add_local_place_comments<'tcx>(
|
|||
format!("{:?}", local),
|
||||
format!("{:?}", ty),
|
||||
size.bytes(),
|
||||
align.abi.bytes(),
|
||||
align.bytes(),
|
||||
if extra.is_empty() { "" } else { " " },
|
||||
extra,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ pub(super) fn from_casted_value<'tcx>(
|
|||
// It may also be smaller for example when the type is a wrapper around an integer with a
|
||||
// larger alignment than the integer.
|
||||
std::cmp::max(abi_param_size, layout_size),
|
||||
u32::try_from(layout.align.abi.bytes()).unwrap(),
|
||||
u32::try_from(layout.align.bytes()).unwrap(),
|
||||
);
|
||||
let mut block_params_iter = block_params.iter().copied();
|
||||
for (offset, _) in abi_params {
|
||||
|
|
|
|||
|
|
@ -846,7 +846,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
|
|||
let layout = fx.layout_of(fx.monomorphize(ty));
|
||||
let val = match null_op {
|
||||
NullOp::SizeOf => layout.size.bytes(),
|
||||
NullOp::AlignOf => layout.align.abi.bytes(),
|
||||
NullOp::AlignOf => layout.align.bytes(),
|
||||
NullOp::OffsetOf(fields) => fx
|
||||
.tcx
|
||||
.offset_of_subfield(
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ impl DebugContext {
|
|||
entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
|
||||
entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));
|
||||
|
||||
entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.abi.bytes()));
|
||||
entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.bytes()));
|
||||
|
||||
let mut expr = Expression::new();
|
||||
expr.op_addr(address_for_data(data_id));
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ impl DebugContext {
|
|||
let tuple_entry = self.dwarf.unit.get_mut(tuple_type_id);
|
||||
tuple_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(self.dwarf.strings.add(name)));
|
||||
tuple_entry.set(gimli::DW_AT_byte_size, AttributeValue::Udata(layout.size.bytes()));
|
||||
tuple_entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(layout.align.abi.bytes()));
|
||||
tuple_entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(layout.align.bytes()));
|
||||
|
||||
for (i, (ty, dw_ty)) in components.into_iter().enumerate() {
|
||||
let member_id = self.dwarf.unit.add(tuple_type_id, gimli::DW_TAG_member);
|
||||
|
|
@ -178,9 +178,7 @@ impl DebugContext {
|
|||
member_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(dw_ty));
|
||||
member_entry.set(
|
||||
gimli::DW_AT_alignment,
|
||||
AttributeValue::Udata(
|
||||
FullyMonomorphizedLayoutCx(tcx).layout_of(ty).align.abi.bytes(),
|
||||
),
|
||||
AttributeValue::Udata(FullyMonomorphizedLayoutCx(tcx).layout_of(ty).align.bytes()),
|
||||
);
|
||||
member_entry.set(
|
||||
gimli::DW_AT_data_member_location,
|
||||
|
|
|
|||
|
|
@ -165,6 +165,10 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
|||
""
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"cranelift"
|
||||
}
|
||||
|
||||
fn init(&self, sess: &Session) {
|
||||
use rustc_session::config::{InstrumentCoverage, Lto};
|
||||
match sess.lto() {
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ pub(crate) fn size_and_align_of<'tcx>(
|
|||
if layout.is_sized() {
|
||||
return (
|
||||
fx.bcx.ins().iconst(fx.pointer_type, layout.size.bytes() as i64),
|
||||
fx.bcx.ins().iconst(fx.pointer_type, layout.align.abi.bytes() as i64),
|
||||
fx.bcx.ins().iconst(fx.pointer_type, layout.align.bytes() as i64),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +186,7 @@ pub(crate) fn size_and_align_of<'tcx>(
|
|||
// times the unit size.
|
||||
(
|
||||
fx.bcx.ins().imul_imm(info.unwrap(), unit.size.bytes() as i64),
|
||||
fx.bcx.ins().iconst(fx.pointer_type, unit.align.abi.bytes() as i64),
|
||||
fx.bcx.ins().iconst(fx.pointer_type, unit.align.bytes() as i64),
|
||||
)
|
||||
}
|
||||
ty::Foreign(_) => {
|
||||
|
|
@ -224,7 +224,7 @@ pub(crate) fn size_and_align_of<'tcx>(
|
|||
let unsized_offset_unadjusted = layout.fields.offset(i).bytes();
|
||||
let unsized_offset_unadjusted =
|
||||
fx.bcx.ins().iconst(fx.pointer_type, unsized_offset_unadjusted as i64);
|
||||
let sized_align = layout.align.abi.bytes();
|
||||
let sized_align = layout.align.bytes();
|
||||
let sized_align = fx.bcx.ins().iconst(fx.pointer_type, sized_align as i64);
|
||||
|
||||
// Recurse to get the size of the dynamically sized field (must be
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ impl<'tcx> CPlace<'tcx> {
|
|||
|
||||
let stack_slot = fx.create_stack_slot(
|
||||
u32::try_from(layout.size.bytes()).unwrap(),
|
||||
u32::try_from(layout.align.abi.bytes()).unwrap(),
|
||||
u32::try_from(layout.align.bytes()).unwrap(),
|
||||
);
|
||||
CPlace { inner: CPlaceInner::Addr(stack_slot, None), layout }
|
||||
}
|
||||
|
|
@ -641,8 +641,8 @@ impl<'tcx> CPlace<'tcx> {
|
|||
let size = dst_layout.size.bytes();
|
||||
// `emit_small_memory_copy` uses `u8` for alignments, just use the maximum
|
||||
// alignment that fits in a `u8` if the actual alignment is larger.
|
||||
let src_align = src_layout.align.abi.bytes().try_into().unwrap_or(128);
|
||||
let dst_align = dst_layout.align.abi.bytes().try_into().unwrap_or(128);
|
||||
let src_align = src_layout.align.bytes().try_into().unwrap_or(128);
|
||||
let dst_align = dst_layout.align.bytes().try_into().unwrap_or(128);
|
||||
fx.bcx.emit_small_memory_copy(
|
||||
fx.target_config,
|
||||
to_addr,
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
let layout = tcx
|
||||
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type))
|
||||
.unwrap();
|
||||
let align = layout.align.abi.bytes();
|
||||
let align = layout.align.bytes();
|
||||
// For types with size 1, the alignment can be 1 and only 1
|
||||
// So, we can skip the call to ``get_aligned`.
|
||||
// In the future, we can add a GCC API to query the type align,
|
||||
|
|
@ -186,9 +186,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
(i128_type, u128_type)
|
||||
} else {
|
||||
/*let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.i128)).unwrap();
|
||||
let i128_align = layout.align.abi.bytes();
|
||||
let i128_align = layout.align.bytes();
|
||||
let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.u128)).unwrap();
|
||||
let u128_align = layout.align.abi.bytes();*/
|
||||
let u128_align = layout.align.bytes();*/
|
||||
|
||||
// TODO(antoyo): re-enable the alignment when libgccjit fixed the issue in
|
||||
// gcc_jit_context_new_array_constructor (it should not use reinterpret_cast).
|
||||
|
|
|
|||
|
|
@ -184,6 +184,10 @@ impl CodegenBackend for GccCodegenBackend {
|
|||
crate::DEFAULT_LOCALE_RESOURCE
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"gcc"
|
||||
}
|
||||
|
||||
fn init(&self, _sess: &Session) {
|
||||
#[cfg(feature = "master")]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1043,7 +1043,7 @@ fn create_member_type<'ll, 'tcx>(
|
|||
file_metadata,
|
||||
line_number,
|
||||
layout.size.bits(),
|
||||
layout.align.abi.bits() as u32,
|
||||
layout.align.bits() as u32,
|
||||
offset.bits(),
|
||||
flags,
|
||||
type_di_node,
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>(
|
|||
file_metadata,
|
||||
line_number,
|
||||
enum_type_and_layout.size.bits(),
|
||||
enum_type_and_layout.align.abi.bits() as u32,
|
||||
enum_type_and_layout.align.bits() as u32,
|
||||
DIFlags::FlagZero,
|
||||
tag_member_di_node,
|
||||
create_DIArray(DIB(cx), &[]),
|
||||
|
|
@ -449,7 +449,7 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>(
|
|||
file_di_node,
|
||||
line_number,
|
||||
enum_type_and_layout.size.bits(),
|
||||
enum_type_and_layout.align.abi.bits() as u32,
|
||||
enum_type_and_layout.align.bits() as u32,
|
||||
Size::ZERO.bits(),
|
||||
discr,
|
||||
DIFlags::FlagZero,
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
let align = if name == sym::unaligned_volatile_load {
|
||||
1
|
||||
} else {
|
||||
result.layout.align.abi.bytes() as u32
|
||||
result.layout.align.bytes() as u32
|
||||
};
|
||||
unsafe {
|
||||
llvm::LLVMSetAlignment(load, align);
|
||||
|
|
|
|||
|
|
@ -232,6 +232,10 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
crate::DEFAULT_LOCALE_RESOURCE
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"llvm"
|
||||
}
|
||||
|
||||
fn init(&self, sess: &Session) {
|
||||
llvm_util::init(sess); // Make sure llvm is inited
|
||||
}
|
||||
|
|
@ -350,7 +354,14 @@ impl CodegenBackend for LlvmCodegenBackend {
|
|||
|
||||
// Run the linker on any artifacts that resulted from the LLVM run.
|
||||
// This should produce either a finished executable or library.
|
||||
link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, metadata, outputs);
|
||||
link_binary(
|
||||
sess,
|
||||
&LlvmArchiveBuilderBuilder,
|
||||
codegen_results,
|
||||
metadata,
|
||||
outputs,
|
||||
self.name(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
|
|||
// the offset again.
|
||||
|
||||
bx.switch_to_block(maybe_reg);
|
||||
if gr_type && layout.align.abi.bytes() > 8 {
|
||||
if gr_type && layout.align.bytes() > 8 {
|
||||
reg_off_v = bx.add(reg_off_v, bx.const_i32(15));
|
||||
reg_off_v = bx.and(reg_off_v, bx.const_i32(-16));
|
||||
}
|
||||
|
|
@ -761,7 +761,7 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>(
|
|||
// byte boundary if alignment needed by type exceeds 8 byte boundary.
|
||||
// It isn't stated explicitly in the standard, but in practice we use
|
||||
// alignment greater than 16 where necessary.
|
||||
if layout.layout.align.abi.bytes() > 8 {
|
||||
if layout.layout.align.bytes() > 8 {
|
||||
unreachable!("all instances of VaArgSafe have an alignment <= 8");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ pub fn link_binary(
|
|||
codegen_results: CodegenResults,
|
||||
metadata: EncodedMetadata,
|
||||
outputs: &OutputFilenames,
|
||||
codegen_backend: &'static str,
|
||||
) {
|
||||
let _timer = sess.timer("link_binary");
|
||||
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
|
||||
|
|
@ -154,6 +155,7 @@ pub fn link_binary(
|
|||
&codegen_results,
|
||||
&metadata,
|
||||
path.as_ref(),
|
||||
codegen_backend,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -680,6 +682,7 @@ fn link_natively(
|
|||
codegen_results: &CodegenResults,
|
||||
metadata: &EncodedMetadata,
|
||||
tmpdir: &Path,
|
||||
codegen_backend: &'static str,
|
||||
) {
|
||||
info!("preparing {:?} to {:?}", crate_type, out_filename);
|
||||
let (linker_path, flavor) = linker_and_flavor(sess);
|
||||
|
|
@ -705,6 +708,7 @@ fn link_natively(
|
|||
codegen_results,
|
||||
metadata,
|
||||
self_contained_components,
|
||||
codegen_backend,
|
||||
);
|
||||
|
||||
linker::disable_localization(&mut cmd);
|
||||
|
|
@ -2208,6 +2212,7 @@ fn linker_with_args(
|
|||
codegen_results: &CodegenResults,
|
||||
metadata: &EncodedMetadata,
|
||||
self_contained_components: LinkSelfContainedComponents,
|
||||
codegen_backend: &'static str,
|
||||
) -> Command {
|
||||
let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled();
|
||||
let cmd = &mut *super::linker::get_linker(
|
||||
|
|
@ -2216,6 +2221,7 @@ fn linker_with_args(
|
|||
flavor,
|
||||
self_contained_components.are_any_components_enabled(),
|
||||
&codegen_results.crate_info.target_cpu,
|
||||
codegen_backend,
|
||||
);
|
||||
let link_output_kind = link_output_kind(sess, crate_type);
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ pub(crate) fn get_linker<'a>(
|
|||
flavor: LinkerFlavor,
|
||||
self_contained: bool,
|
||||
target_cpu: &'a str,
|
||||
codegen_backend: &'static str,
|
||||
) -> Box<dyn Linker + 'a> {
|
||||
let msvc_tool = find_msvc_tools::find_tool(&sess.target.arch, "link.exe");
|
||||
|
||||
|
|
@ -154,6 +155,7 @@ pub(crate) fn get_linker<'a>(
|
|||
is_ld: cc == Cc::No,
|
||||
is_gnu: flavor.is_gnu(),
|
||||
uses_lld: flavor.uses_lld(),
|
||||
codegen_backend,
|
||||
}) as Box<dyn Linker>,
|
||||
LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
|
|
@ -367,6 +369,7 @@ struct GccLinker<'a> {
|
|||
is_ld: bool,
|
||||
is_gnu: bool,
|
||||
uses_lld: bool,
|
||||
codegen_backend: &'static str,
|
||||
}
|
||||
|
||||
impl<'a> GccLinker<'a> {
|
||||
|
|
@ -423,9 +426,15 @@ impl<'a> GccLinker<'a> {
|
|||
if let Some(path) = &self.sess.opts.unstable_opts.profile_sample_use {
|
||||
self.link_arg(&format!("-plugin-opt=sample-profile={}", path.display()));
|
||||
};
|
||||
let prefix = if self.codegen_backend == "gcc" {
|
||||
// The GCC linker plugin requires a leading dash.
|
||||
"-"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
self.link_args(&[
|
||||
&format!("-plugin-opt={opt_level}"),
|
||||
&format!("-plugin-opt=mcpu={}", self.target_cpu),
|
||||
&format!("-plugin-opt={prefix}{opt_level}"),
|
||||
&format!("-plugin-opt={prefix}mcpu={}", self.target_cpu),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -617,7 +617,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
mir::NullOp::AlignOf => {
|
||||
assert!(bx.cx().type_is_sized(ty));
|
||||
let val = layout.align.abi.bytes();
|
||||
let val = layout.align.bytes();
|
||||
bx.cx().const_usize(val)
|
||||
}
|
||||
mir::NullOp::OffsetOf(fields) => {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
trace!("size_and_align_of_dst(ty={}, info={:?}): layout: {:?}", t, info, layout);
|
||||
if layout.is_sized() {
|
||||
let size = bx.const_usize(layout.size.bytes());
|
||||
let align = bx.const_usize(layout.align.abi.bytes());
|
||||
let align = bx.const_usize(layout.align.bytes());
|
||||
return (size, align);
|
||||
}
|
||||
match t.kind() {
|
||||
|
|
@ -49,7 +49,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
// All slice sizes must fit into `isize`, so this multiplication cannot
|
||||
// wrap -- neither signed nor unsigned.
|
||||
bx.unchecked_sumul(info.unwrap(), bx.const_usize(unit.size.bytes())),
|
||||
bx.const_usize(unit.align.abi.bytes()),
|
||||
bx.const_usize(unit.align.bytes()),
|
||||
)
|
||||
}
|
||||
ty::Foreign(_) => {
|
||||
|
|
@ -82,7 +82,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
// This function does not return so we can now return whatever we want.
|
||||
let size = bx.const_usize(layout.size.bytes());
|
||||
let align = bx.const_usize(layout.align.abi.bytes());
|
||||
let align = bx.const_usize(layout.align.bytes());
|
||||
(size, align)
|
||||
}
|
||||
ty::Adt(..) | ty::Tuple(..) => {
|
||||
|
|
@ -94,7 +94,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
let i = layout.fields.count() - 1;
|
||||
let unsized_offset_unadjusted = layout.fields.offset(i).bytes();
|
||||
let sized_align = layout.align.abi.bytes();
|
||||
let sized_align = layout.align.bytes();
|
||||
debug!(
|
||||
"DST {} offset of dyn field: {}, statically sized align: {}",
|
||||
t, unsized_offset_unadjusted, sized_align
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ pub trait CodegenBackend {
|
|||
/// Called before `init` so that all other functions are able to emit translatable diagnostics.
|
||||
fn locale_resource(&self) -> &'static str;
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
fn init(&self, _sess: &Session) {}
|
||||
|
||||
fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {}
|
||||
|
|
@ -96,7 +98,14 @@ pub trait CodegenBackend {
|
|||
metadata: EncodedMetadata,
|
||||
outputs: &OutputFilenames,
|
||||
) {
|
||||
link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, metadata, outputs);
|
||||
link_binary(
|
||||
sess,
|
||||
&ArArchiveBuilderBuilder,
|
||||
codegen_results,
|
||||
metadata,
|
||||
outputs,
|
||||
self.name(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
if !layout.is_sized() {
|
||||
span_bug!(self.cur_span(), "unsized type for `NullaryOp::AlignOf`");
|
||||
}
|
||||
let val = layout.align.abi.bytes();
|
||||
let val = layout.align.bytes();
|
||||
ImmTy::from_uint(val, usize_layout())
|
||||
}
|
||||
OffsetOf(fields) => {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ where
|
|||
debug!(
|
||||
"is_disaligned({:?}) - align = {}, packed = {}; not disaligned",
|
||||
place,
|
||||
layout.align.abi.bytes(),
|
||||
layout.align.bytes(),
|
||||
pack.bytes()
|
||||
);
|
||||
false
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ fn check_validity_requirement_lax<'tcx>(
|
|||
if let Some(pointee) = this.ty.builtin_deref(false) {
|
||||
let pointee = cx.layout_of(pointee)?;
|
||||
// We need to ensure that the LLVM attributes `aligned` and `dereferenceable(size)` are satisfied.
|
||||
if pointee.align.abi.bytes() > 1 {
|
||||
if pointee.align.bytes() > 1 {
|
||||
// 0x01-filling is not aligned.
|
||||
return Ok(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,9 +102,9 @@ declare_features! (
|
|||
/// Allows deriving traits as per `SmartPointer` specification
|
||||
(removed, derive_smart_pointer, "1.84.0", Some(123430), Some("replaced by `CoercePointee`"), 131284),
|
||||
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
|
||||
(removed, doc_auto_cfg, "1.58.0", Some(43781), Some("merged into `doc_cfg`"), 138907),
|
||||
(removed, doc_auto_cfg, "CURRENT_RUSTC_VERSION", Some(43781), Some("merged into `doc_cfg`"), 138907),
|
||||
/// Allows `#[doc(cfg_hide(...))]`.
|
||||
(removed, doc_cfg_hide, "1.57.0", Some(43781), Some("merged into `doc_cfg`"), 138907),
|
||||
(removed, doc_cfg_hide, "CURRENT_RUSTC_VERSION", Some(43781), Some("merged into `doc_cfg`"), 138907),
|
||||
/// Allows using `#[doc(keyword = "...")]`.
|
||||
(removed, doc_keyword, "1.58.0", Some(51315),
|
||||
Some("merged into `#![feature(rustdoc_internals)]`"), 90420),
|
||||
|
|
|
|||
|
|
@ -1298,10 +1298,7 @@ impl AttributeExt for Attribute {
|
|||
#[inline]
|
||||
fn path_matches(&self, name: &[Symbol]) -> bool {
|
||||
match &self {
|
||||
Attribute::Unparsed(n) => {
|
||||
n.path.segments.len() == name.len()
|
||||
&& n.path.segments.iter().zip(name).all(|(s, n)| s.name == *n)
|
||||
}
|
||||
Attribute::Unparsed(n) => n.path.segments.iter().map(|ident| &ident.name).eq(name),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,12 @@ pub struct AttributeLint<Id> {
|
|||
|
||||
#[derive(Clone, Debug, HashStable_Generic)]
|
||||
pub enum AttributeLintKind {
|
||||
/// Copy of `IllFormedAttributeInput`
|
||||
/// specifically for the `invalid_macro_export_arguments` lint until that is removed,
|
||||
/// see <https://github.com/rust-lang/rust/pull/143857#issuecomment-3079175663>
|
||||
InvalidMacroExportArguments {
|
||||
suggestions: Vec<String>,
|
||||
},
|
||||
UnusedDuplicate {
|
||||
this: Span,
|
||||
other: Span,
|
||||
|
|
@ -41,13 +47,8 @@ pub enum AttributeLintKind {
|
|||
},
|
||||
EmptyAttribute {
|
||||
first_span: Span,
|
||||
},
|
||||
|
||||
/// Copy of `IllFormedAttributeInput`
|
||||
/// specifically for the `invalid_macro_export_arguments` lint until that is removed,
|
||||
/// see <https://github.com/rust-lang/rust/pull/143857#issuecomment-3079175663>
|
||||
InvalidMacroExportArguments {
|
||||
suggestions: Vec<String>,
|
||||
attr_path: AttrPath,
|
||||
valid_without_list: bool,
|
||||
},
|
||||
InvalidTarget {
|
||||
name: AttrPath,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeV
|
|||
use rustc_span::Span;
|
||||
use tracing::debug;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub(crate) struct Parameter(pub u32);
|
||||
|
||||
impl From<ty::ParamTy> for Parameter {
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ fn is_valid_cmse_inputs<'tcx>(
|
|||
for (index, ty) in fn_sig.inputs().iter().enumerate() {
|
||||
let layout = tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(*ty))?;
|
||||
|
||||
let align = layout.layout.align().abi.bytes();
|
||||
let align = layout.layout.align().bytes();
|
||||
let size = layout.layout.size().bytes();
|
||||
|
||||
accum += size;
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ fn check_duplicate_params<'tcx>(
|
|||
span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let mut base_params = cgp::parameters_for(tcx, parent_args, true);
|
||||
base_params.sort_by_key(|param| param.0);
|
||||
base_params.sort_unstable();
|
||||
if let (_, [duplicate, ..]) = base_params.partition_dedup() {
|
||||
let param = impl1_args[duplicate.0 as usize];
|
||||
return Err(tcx
|
||||
|
|
|
|||
|
|
@ -2803,9 +2803,7 @@ impl<'a, 'b, 'tcx> ArgMatchingCtxt<'a, 'b, 'tcx> {
|
|||
if let Some((assoc, fn_sig)) = self.similar_assoc(call_name)
|
||||
&& fn_sig.inputs()[1..]
|
||||
.iter()
|
||||
.zip(input_types.iter())
|
||||
.all(|(expected, found)| self.may_coerce(*expected, *found))
|
||||
&& fn_sig.inputs()[1..].len() == input_types.len()
|
||||
.eq_by(input_types, |expected, found| self.may_coerce(*expected, found))
|
||||
{
|
||||
let assoc_name = assoc.name();
|
||||
err.span_suggestion_verbose(
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(iter_order_by)]
|
||||
#![feature(never_type)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -1914,9 +1914,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Some(ref args) = call_args
|
||||
&& fn_sig.inputs()[1..]
|
||||
.iter()
|
||||
.zip(args.into_iter())
|
||||
.all(|(expected, found)| self.may_coerce(*expected, *found))
|
||||
&& fn_sig.inputs()[1..].len() == args.len()
|
||||
.eq_by(args, |expected, found| self.may_coerce(*expected, *found))
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
item_name.span,
|
||||
|
|
|
|||
|
|
@ -1122,18 +1122,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
|
||||
sess.time("layout_testing", || layout_test::test_layout(tcx));
|
||||
sess.time("abi_testing", || abi_test::test_abi(tcx));
|
||||
|
||||
// If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item
|
||||
// (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs
|
||||
// in MIR optimizations that may only be reachable through codegen, or other codepaths
|
||||
// that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts.
|
||||
if tcx.sess.opts.unstable_opts.validate_mir {
|
||||
sess.time("ensuring_final_MIR_is_computable", || {
|
||||
tcx.par_hir_body_owners(|def_id| {
|
||||
tcx.instance_mir(ty::InstanceKind::Item(def_id.into()));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs the type-checking, region checking and other miscellaneous analysis
|
||||
|
|
@ -1199,6 +1187,20 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
|
|||
// we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally.
|
||||
let _ = tcx.all_diagnostic_items(());
|
||||
});
|
||||
|
||||
// If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item
|
||||
// (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs
|
||||
// in MIR optimizations that may only be reachable through codegen, or other codepaths
|
||||
// that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts.
|
||||
// Nevertheless, wait after type checking is finished, as optimizing code that does not
|
||||
// type-check is very prone to ICEs.
|
||||
if tcx.sess.opts.unstable_opts.validate_mir {
|
||||
sess.time("ensuring_final_MIR_is_computable", || {
|
||||
tcx.par_hir_body_owners(|def_id| {
|
||||
tcx.instance_mir(ty::InstanceKind::Item(def_id.into()));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs the codegen backend, after which the AST and analysis can
|
||||
|
|
|
|||
|
|
@ -542,6 +542,7 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu
|
|||
stem,
|
||||
None,
|
||||
sess.io.temps_dir.clone(),
|
||||
sess.opts.unstable_opts.split_dwarf_out_dir.clone(),
|
||||
sess.opts.cg.extra_filename.clone(),
|
||||
sess.opts.output_types.clone(),
|
||||
)
|
||||
|
|
@ -571,6 +572,7 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu
|
|||
out_filestem,
|
||||
ofile,
|
||||
sess.io.temps_dir.clone(),
|
||||
sess.opts.unstable_opts.split_dwarf_out_dir.clone(),
|
||||
sess.opts.cg.extra_filename.clone(),
|
||||
sess.opts.output_types.clone(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
|
|||
.expect("failed to build vtable representation");
|
||||
assert!(layout.is_sized(), "can't create a vtable for an unsized type");
|
||||
let size = layout.size.bytes();
|
||||
let align = layout.align.abi.bytes();
|
||||
let align = layout.align.bytes();
|
||||
|
||||
let ptr_size = tcx.data_layout.pointer_size();
|
||||
let ptr_align = tcx.data_layout.pointer_align().abi;
|
||||
|
|
|
|||
|
|
@ -476,7 +476,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
|
|||
};
|
||||
let val = match null_op {
|
||||
NullOp::SizeOf if layout.is_sized() => layout.size.bytes(),
|
||||
NullOp::AlignOf if layout.is_sized() => layout.align.abi.bytes(),
|
||||
NullOp::AlignOf if layout.is_sized() => layout.align.bytes(),
|
||||
NullOp::OffsetOf(fields) => self
|
||||
.ecx
|
||||
.tcx
|
||||
|
|
|
|||
|
|
@ -618,7 +618,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
}
|
||||
let val = match null_op {
|
||||
NullOp::SizeOf => arg_layout.size.bytes(),
|
||||
NullOp::AlignOf => arg_layout.align.abi.bytes(),
|
||||
NullOp::AlignOf => arg_layout.align.bytes(),
|
||||
NullOp::OffsetOf(fields) => self
|
||||
.ecx
|
||||
.tcx
|
||||
|
|
|
|||
|
|
@ -609,7 +609,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
let op_layout = self.ecx.layout_of(ty).ok()?;
|
||||
let val = match null_op {
|
||||
NullOp::SizeOf => op_layout.size.bytes(),
|
||||
NullOp::AlignOf => op_layout.align.abi.bytes(),
|
||||
NullOp::AlignOf => op_layout.align.bytes(),
|
||||
NullOp::OffsetOf(fields) => self
|
||||
.tcx
|
||||
.offset_of_subfield(self.typing_env, op_layout, fields.iter())
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#![feature(default_field_values)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(iter_order_by)]
|
||||
#![recursion_limit = "256"]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ fn sp(a: u32, b: u32) -> Span {
|
|||
}
|
||||
|
||||
fn cmp_token_stream(a: &TokenStream, b: &TokenStream) -> bool {
|
||||
a.len() == b.len() && a.iter().zip(b.iter()).all(|(x, y)| x.eq_unspanned(y))
|
||||
a.iter().eq_by(b.iter(), |x, y| x.eq_unspanned(y))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -901,6 +901,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
binding,
|
||||
if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None },
|
||||
parent_scope,
|
||||
module,
|
||||
finalize,
|
||||
shadowing,
|
||||
);
|
||||
|
|
@ -1025,6 +1026,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
binding: Option<NameBinding<'ra>>,
|
||||
shadowed_glob: Option<NameBinding<'ra>>,
|
||||
parent_scope: &ParentScope<'ra>,
|
||||
module: Module<'ra>,
|
||||
finalize: Finalize,
|
||||
shadowing: Shadowing,
|
||||
) -> Result<NameBinding<'ra>, (Determinacy, Weak)> {
|
||||
|
|
@ -1076,6 +1078,37 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
|
||||
}
|
||||
|
||||
// If we encounter a re-export for a type with private fields, it will not be able to
|
||||
// be constructed through this re-export. We track that case here to expand later
|
||||
// privacy errors with appropriate information.
|
||||
if let Res::Def(_, def_id) = binding.res() {
|
||||
let struct_ctor = match def_id.as_local() {
|
||||
Some(def_id) => self.struct_constructors.get(&def_id).cloned(),
|
||||
None => {
|
||||
let ctor = self.cstore().ctor_untracked(def_id);
|
||||
ctor.map(|(ctor_kind, ctor_def_id)| {
|
||||
let ctor_res = Res::Def(
|
||||
DefKind::Ctor(rustc_hir::def::CtorOf::Struct, ctor_kind),
|
||||
ctor_def_id,
|
||||
);
|
||||
let ctor_vis = self.tcx.visibility(ctor_def_id);
|
||||
let field_visibilities = self
|
||||
.tcx
|
||||
.associated_item_def_ids(def_id)
|
||||
.iter()
|
||||
.map(|field_id| self.tcx.visibility(field_id))
|
||||
.collect();
|
||||
(ctor_res, ctor_vis, field_visibilities)
|
||||
})
|
||||
}
|
||||
};
|
||||
if let Some((_, _, fields)) = struct_ctor
|
||||
&& fields.iter().any(|vis| !self.is_accessible_from(*vis, module))
|
||||
{
|
||||
self.inaccessible_ctor_reexport.insert(path_span, binding.span);
|
||||
}
|
||||
}
|
||||
|
||||
self.record_use(ident, binding, used);
|
||||
return Ok(binding);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1942,44 +1942,77 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
return true;
|
||||
};
|
||||
|
||||
let update_message =
|
||||
|this: &mut Self, err: &mut Diag<'_>, source: &PathSource<'_, '_, '_>| {
|
||||
match source {
|
||||
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
|
||||
PathSource::TupleStruct(_, pattern_spans) => {
|
||||
err.primary_message(
|
||||
"cannot match against a tuple struct which contains private fields",
|
||||
);
|
||||
|
||||
// Use spans of the tuple struct pattern.
|
||||
Some(Vec::from(*pattern_spans))
|
||||
}
|
||||
// e.g. `let _ = Enum::TupleVariant(field1, field2);`
|
||||
PathSource::Expr(Some(Expr {
|
||||
kind: ExprKind::Call(path, args),
|
||||
span: call_span,
|
||||
..
|
||||
})) => {
|
||||
err.primary_message(
|
||||
"cannot initialize a tuple struct which contains private fields",
|
||||
);
|
||||
this.suggest_alternative_construction_methods(
|
||||
def_id,
|
||||
err,
|
||||
path.span,
|
||||
*call_span,
|
||||
&args[..],
|
||||
);
|
||||
// Use spans of the tuple struct definition.
|
||||
this.r
|
||||
.field_idents(def_id)
|
||||
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
|
||||
if let Some(use_span) = self.r.inaccessible_ctor_reexport.get(&span)
|
||||
&& is_accessible
|
||||
{
|
||||
err.span_note(
|
||||
*use_span,
|
||||
"the type is accessed through this re-export, but the type's constructor \
|
||||
is not visible in this import's scope due to private fields",
|
||||
);
|
||||
if is_accessible
|
||||
&& fields
|
||||
.iter()
|
||||
.all(|vis| self.r.is_accessible_from(*vis, self.parent_scope.module))
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"the type can be constructed directly, because its fields are \
|
||||
available from the current scope",
|
||||
// Using `tcx.def_path_str` causes the compiler to hang.
|
||||
// We don't need to handle foreign crate types because in that case you
|
||||
// can't access the ctor either way.
|
||||
format!(
|
||||
"crate{}", // The method already has leading `::`.
|
||||
self.r.tcx.def_path(def_id).to_string_no_crate_verbose(),
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
update_message(self, err, &source);
|
||||
}
|
||||
if !is_expected(ctor_def) || is_accessible {
|
||||
return true;
|
||||
}
|
||||
|
||||
let field_spans = match source {
|
||||
// e.g. `if let Enum::TupleVariant(field1, field2) = _`
|
||||
PathSource::TupleStruct(_, pattern_spans) => {
|
||||
err.primary_message(
|
||||
"cannot match against a tuple struct which contains private fields",
|
||||
);
|
||||
|
||||
// Use spans of the tuple struct pattern.
|
||||
Some(Vec::from(pattern_spans))
|
||||
}
|
||||
// e.g. `let _ = Enum::TupleVariant(field1, field2);`
|
||||
PathSource::Expr(Some(Expr {
|
||||
kind: ExprKind::Call(path, args),
|
||||
span: call_span,
|
||||
..
|
||||
})) => {
|
||||
err.primary_message(
|
||||
"cannot initialize a tuple struct which contains private fields",
|
||||
);
|
||||
self.suggest_alternative_construction_methods(
|
||||
def_id,
|
||||
err,
|
||||
path.span,
|
||||
*call_span,
|
||||
&args[..],
|
||||
);
|
||||
// Use spans of the tuple struct definition.
|
||||
self.r
|
||||
.field_idents(def_id)
|
||||
.map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let field_spans = update_message(self, err, &source);
|
||||
|
||||
if let Some(spans) =
|
||||
field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len())
|
||||
|
|
|
|||
|
|
@ -1167,6 +1167,11 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
/// Crate-local macro expanded `macro_export` referred to by a module-relative path.
|
||||
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)> = BTreeSet::new(),
|
||||
|
||||
/// When a type is re-exported that has an inaccessible constructor because it has fields that
|
||||
/// are inaccessible from the import's scope, we mark that as the type won't be able to be built
|
||||
/// through the re-export. We use this information to extend the existing diagnostic.
|
||||
inaccessible_ctor_reexport: FxHashMap<Span, Span>,
|
||||
|
||||
arenas: &'ra ResolverArenas<'ra>,
|
||||
dummy_binding: NameBinding<'ra>,
|
||||
builtin_types_bindings: FxHashMap<Symbol, NameBinding<'ra>>,
|
||||
|
|
@ -1595,6 +1600,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
glob_map: Default::default(),
|
||||
used_imports: FxHashSet::default(),
|
||||
maybe_unused_trait_imports: Default::default(),
|
||||
inaccessible_ctor_reexport: Default::default(),
|
||||
|
||||
arenas,
|
||||
dummy_binding: arenas.new_pub_res_binding(Res::Err, DUMMY_SP, LocalExpnId::ROOT),
|
||||
|
|
|
|||
|
|
@ -1195,6 +1195,7 @@ pub struct OutputFilenames {
|
|||
filestem: String,
|
||||
pub single_output_file: Option<OutFileName>,
|
||||
temps_directory: Option<PathBuf>,
|
||||
explicit_dwo_out_directory: Option<PathBuf>,
|
||||
pub outputs: OutputTypes,
|
||||
}
|
||||
|
||||
|
|
@ -1227,6 +1228,7 @@ impl OutputFilenames {
|
|||
out_filestem: String,
|
||||
single_output_file: Option<OutFileName>,
|
||||
temps_directory: Option<PathBuf>,
|
||||
explicit_dwo_out_directory: Option<PathBuf>,
|
||||
extra: String,
|
||||
outputs: OutputTypes,
|
||||
) -> Self {
|
||||
|
|
@ -1234,6 +1236,7 @@ impl OutputFilenames {
|
|||
out_directory,
|
||||
single_output_file,
|
||||
temps_directory,
|
||||
explicit_dwo_out_directory,
|
||||
outputs,
|
||||
crate_stem: format!("{out_crate_name}{extra}"),
|
||||
filestem: format!("{out_filestem}{extra}"),
|
||||
|
|
@ -1283,7 +1286,14 @@ impl OutputFilenames {
|
|||
codegen_unit_name: &str,
|
||||
invocation_temp: Option<&str>,
|
||||
) -> PathBuf {
|
||||
self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp)
|
||||
let p = self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp);
|
||||
if let Some(dwo_out) = &self.explicit_dwo_out_directory {
|
||||
let mut o = dwo_out.clone();
|
||||
o.push(p.file_name().unwrap());
|
||||
o
|
||||
} else {
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
/// Like `temp_path`, but also supports things where there is no corresponding
|
||||
|
|
|
|||
|
|
@ -2634,6 +2634,8 @@ written to standard error output)"),
|
|||
file which is ignored by the linker
|
||||
`single`: sections which do not require relocation are written into object file but ignored
|
||||
by the linker"),
|
||||
split_dwarf_out_dir : Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
|
||||
"location for writing split DWARF objects (`.dwo`) if enabled"),
|
||||
split_lto_unit: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"enable LTO unit splitting (default: no)"),
|
||||
src_hash_algorithm: Option<SourceFileHashAlgorithm> = (None, parse_src_file_hash, [TRACKED],
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
let align = arg.layout.align.abi.bytes();
|
||||
let align = arg.layout.align.bytes();
|
||||
let total = arg.layout.size;
|
||||
arg.cast_to(Uniform::consecutive(if align <= 4 { Reg::i32() } else { Reg::i64() }, total));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ fn classify_arg<'a, Ty, C>(
|
|||
}
|
||||
|
||||
let total = arg.layout.size;
|
||||
let align = arg.layout.align.abi.bits();
|
||||
let align = arg.layout.align.bits();
|
||||
|
||||
// "Scalars wider than 2✕XLEN are passed by reference and are replaced in
|
||||
// the argument list with the address."
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
|
|||
|
||||
/// the pass mode used for aggregates in arg and ret position
|
||||
fn classify_aggregate<Ty>(arg: &mut ArgAbi<'_, Ty>) {
|
||||
let align_bytes = arg.layout.align.abi.bytes();
|
||||
let align_bytes = arg.layout.align.bytes();
|
||||
let size = arg.layout.size;
|
||||
|
||||
let reg = match align_bytes {
|
||||
|
|
@ -60,7 +60,7 @@ where
|
|||
// "`extern \"ptx-kernel\"` doesn't allow passing types other than primitives and structs"
|
||||
// );
|
||||
|
||||
let align_bytes = arg.layout.align.abi.bytes();
|
||||
let align_bytes = arg.layout.align.bytes();
|
||||
|
||||
let unit = match align_bytes {
|
||||
1 => Reg::i8(),
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ where
|
|||
// Aggregates larger than i64 should be padded at the tail to fill out a whole number
|
||||
// of i64s or i128s, depending on the aggregate alignment. Always use an array for
|
||||
// this, even if there is only a single element.
|
||||
let reg = if arg.layout.align.abi.bytes() > 8 { Reg::i128() } else { Reg::i64() };
|
||||
let reg = if arg.layout.align.bytes() > 8 { Reg::i128() } else { Reg::i64() };
|
||||
arg.cast_to(Uniform::consecutive(
|
||||
reg,
|
||||
size.align_to(Align::from_bytes(reg.size.bytes()).unwrap()),
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ fn classify_arg<'a, Ty, C>(
|
|||
}
|
||||
|
||||
let total = arg.layout.size;
|
||||
let align = arg.layout.align.abi.bits();
|
||||
let align = arg.layout.align.bits();
|
||||
|
||||
// "Scalars wider than 2✕XLEN are passed by reference and are replaced in
|
||||
// the argument list with the address."
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ where
|
|||
}
|
||||
|
||||
let size = arg.layout.size.bits();
|
||||
let needed_align = arg.layout.align.abi.bits();
|
||||
let needed_align = arg.layout.align.bits();
|
||||
let mut must_use_stack = false;
|
||||
|
||||
// Determine the number of GPRs needed to pass the current argument
|
||||
|
|
|
|||
|
|
@ -361,7 +361,7 @@ pub(crate) mod rustc {
|
|||
|
||||
ty::Ref(region, ty, mutability) => {
|
||||
let layout = layout_of(cx, *ty)?;
|
||||
let referent_align = layout.align.abi.bytes_usize();
|
||||
let referent_align = layout.align.bytes_usize();
|
||||
let referent_size = layout.size.bytes_usize();
|
||||
|
||||
Ok(Tree::Ref(Reference {
|
||||
|
|
|
|||
|
|
@ -795,7 +795,7 @@ fn variant_info_for_adt<'tcx>(
|
|||
name,
|
||||
offset: offset.bytes(),
|
||||
size: field_layout.size.bytes(),
|
||||
align: field_layout.align.abi.bytes(),
|
||||
align: field_layout.align.bytes(),
|
||||
type_name: None,
|
||||
}
|
||||
})
|
||||
|
|
@ -804,7 +804,7 @@ fn variant_info_for_adt<'tcx>(
|
|||
VariantInfo {
|
||||
name: n,
|
||||
kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
|
||||
align: layout.align.abi.bytes(),
|
||||
align: layout.align.bytes(),
|
||||
size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() },
|
||||
fields: field_info,
|
||||
}
|
||||
|
|
@ -877,7 +877,7 @@ fn variant_info_for_coroutine<'tcx>(
|
|||
name: *name,
|
||||
offset: offset.bytes(),
|
||||
size: field_layout.size.bytes(),
|
||||
align: field_layout.align.abi.bytes(),
|
||||
align: field_layout.align.bytes(),
|
||||
type_name: None,
|
||||
}
|
||||
})
|
||||
|
|
@ -905,7 +905,7 @@ fn variant_info_for_coroutine<'tcx>(
|
|||
}),
|
||||
offset: offset.bytes(),
|
||||
size: field_layout.size.bytes(),
|
||||
align: field_layout.align.abi.bytes(),
|
||||
align: field_layout.align.bytes(),
|
||||
// Include the type name if there is no field name, or if the name is the
|
||||
// __awaitee placeholder symbol which means a child future being `.await`ed.
|
||||
type_name: (field_name.is_none() || field_name == Some(sym::__awaitee))
|
||||
|
|
@ -946,7 +946,7 @@ fn variant_info_for_coroutine<'tcx>(
|
|||
name: Some(Symbol::intern(&ty::CoroutineArgs::variant_name(variant_idx))),
|
||||
kind: SizeKind::Exact,
|
||||
size: variant_size.bytes(),
|
||||
align: variant_layout.align.abi.bytes(),
|
||||
align: variant_layout.align.bytes(),
|
||||
fields,
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout};
|
|||
pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
|
||||
let tcx = cx.tcx();
|
||||
|
||||
if !layout.size.bytes().is_multiple_of(layout.align.abi.bytes()) {
|
||||
if !layout.size.bytes().is_multiple_of(layout.align.bytes()) {
|
||||
bug!("size is not a multiple of align, in the following layout:\n{layout:#?}");
|
||||
}
|
||||
if layout.size.bytes() >= tcx.data_layout.obj_size_bound() {
|
||||
|
|
@ -300,8 +300,8 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
|
|||
if variant.align.abi > layout.align.abi {
|
||||
bug!(
|
||||
"Type with alignment {} bytes has variant with alignment {} bytes: {layout:#?}",
|
||||
layout.align.abi.bytes(),
|
||||
variant.align.abi.bytes(),
|
||||
layout.align.bytes(),
|
||||
variant.align.bytes(),
|
||||
)
|
||||
}
|
||||
// Skip empty variants.
|
||||
|
|
|
|||
|
|
@ -2413,7 +2413,7 @@ impl<K, V> Default for BTreeMap<K, V> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<K: PartialEq, V: PartialEq, A: Allocator + Clone> PartialEq for BTreeMap<K, V, A> {
|
||||
fn eq(&self, other: &BTreeMap<K, V, A>) -> bool {
|
||||
self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a == b)
|
||||
self.iter().eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ impl Nanoseconds {
|
|||
pub const ZERO: Self = unsafe { Nanoseconds::new_unchecked(0) };
|
||||
}
|
||||
|
||||
impl Default for Nanoseconds {
|
||||
#[rustc_const_unstable(feature = "const_default", issue = "143894")]
|
||||
impl const Default for Nanoseconds {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::ZERO
|
||||
|
|
|
|||
|
|
@ -148,6 +148,13 @@ mod imp {
|
|||
|
||||
let mut guard_page_range = unsafe { install_main_guard() };
|
||||
|
||||
// Even for panic=immediate-abort, installing the guard pages is important for soundness.
|
||||
// That said, we do not care about giving nice stackoverflow messages via our custom
|
||||
// signal handler, just exit early and let the user enjoy the segfault.
|
||||
if cfg!(panic = "immediate-abort") {
|
||||
return;
|
||||
}
|
||||
|
||||
// SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
|
||||
let mut action: sigaction = unsafe { mem::zeroed() };
|
||||
for &signal in &[SIGSEGV, SIGBUS] {
|
||||
|
|
@ -179,6 +186,9 @@ mod imp {
|
|||
/// Must be called only once
|
||||
#[forbid(unsafe_op_in_unsafe_fn)]
|
||||
pub unsafe fn cleanup() {
|
||||
if cfg!(panic = "immediate-abort") {
|
||||
return;
|
||||
}
|
||||
// FIXME: I probably cause more bugs than I'm worth!
|
||||
// see https://github.com/rust-lang/rust/issues/111272
|
||||
unsafe { drop_handler(MAIN_ALTSTACK.load(Ordering::Relaxed)) };
|
||||
|
|
@ -230,7 +240,7 @@ mod imp {
|
|||
/// Mutates the alternate signal stack
|
||||
#[forbid(unsafe_op_in_unsafe_fn)]
|
||||
pub unsafe fn make_handler(main_thread: bool, thread_name: Option<Box<str>>) -> Handler {
|
||||
if !NEED_ALTSTACK.load(Ordering::Acquire) {
|
||||
if cfg!(panic = "immediate-abort") || !NEED_ALTSTACK.load(Ordering::Acquire) {
|
||||
return Handler::null();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ pub mod os;
|
|||
pub mod pipe;
|
||||
pub mod time;
|
||||
cfg_select! {
|
||||
not(target_vendor = "uwp") => {
|
||||
// We don't care about printing nice error messages for panic=immediate-abort
|
||||
all(not(target_vendor = "uwp"), not(panic = "immediate-abort")) => {
|
||||
pub mod stack_overflow;
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use crate::core::build_steps::compile::{
|
|||
};
|
||||
use crate::core::build_steps::tool;
|
||||
use crate::core::build_steps::tool::{
|
||||
COMPILETEST_ALLOW_FEATURES, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, ToolTargetBuildMode,
|
||||
get_tool_target_compiler, prepare_tool_cargo,
|
||||
SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, ToolTargetBuildMode, get_tool_target_compiler,
|
||||
prepare_tool_cargo,
|
||||
};
|
||||
use crate::core::builder::{
|
||||
self, Alias, Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
|
||||
|
|
@ -61,6 +61,9 @@ impl Step for Std {
|
|||
return;
|
||||
}
|
||||
|
||||
// Explicitly pass -p for all dependencies crates -- this will force cargo
|
||||
// to also check the tests/benches/examples for these crates, rather
|
||||
// than just the leaf crate.
|
||||
let crates = std_crates_for_run_make(&run);
|
||||
run.builder.ensure(Std {
|
||||
build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std)
|
||||
|
|
@ -83,16 +86,12 @@ impl Step for Std {
|
|||
Kind::Check,
|
||||
);
|
||||
|
||||
std_cargo(builder, target, &mut cargo);
|
||||
std_cargo(builder, target, &mut cargo, &self.crates);
|
||||
if matches!(builder.config.cmd, Subcommand::Fix) {
|
||||
// By default, cargo tries to fix all targets. Tell it not to fix tests until we've added `test` to the sysroot.
|
||||
cargo.arg("--lib");
|
||||
}
|
||||
|
||||
for krate in &*self.crates {
|
||||
cargo.arg("-p").arg(krate);
|
||||
}
|
||||
|
||||
let _guard = builder.msg(
|
||||
Kind::Check,
|
||||
format_args!("library artifacts{}", crate_description(&self.crates)),
|
||||
|
|
@ -135,14 +134,7 @@ impl Step for Std {
|
|||
Kind::Check,
|
||||
);
|
||||
|
||||
std_cargo(builder, target, &mut cargo);
|
||||
|
||||
// Explicitly pass -p for all dependencies krates -- this will force cargo
|
||||
// to also check the tests/benches/examples for these crates, rather
|
||||
// than just the leaf crate.
|
||||
for krate in &*self.crates {
|
||||
cargo.arg("-p").arg(krate);
|
||||
}
|
||||
std_cargo(builder, target, &mut cargo, &self.crates);
|
||||
|
||||
let stamp =
|
||||
build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
|
||||
|
|
@ -654,7 +646,7 @@ macro_rules! tool_check_step {
|
|||
// The part of this path after the final '/' is also used as a display name.
|
||||
path: $path:literal
|
||||
$(, alt_path: $alt_path:literal )*
|
||||
// Closure that returns `Mode` based on the passed `&Builder<'_>`
|
||||
// `Mode` to use when checking this tool
|
||||
, mode: $mode:expr
|
||||
// Subset of nightly features that are allowed to be used when checking
|
||||
$(, allow_features: $allow_features:expr )?
|
||||
|
|
@ -682,8 +674,7 @@ macro_rules! tool_check_step {
|
|||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let target = run.target;
|
||||
let builder = run.builder;
|
||||
let mode = $mode(builder);
|
||||
let mode: Mode = $mode;
|
||||
|
||||
let compiler = prepare_compiler_for_check(run.builder, target, mode);
|
||||
|
||||
|
|
@ -704,7 +695,7 @@ macro_rules! tool_check_step {
|
|||
_value
|
||||
};
|
||||
let extra_features: &[&str] = &[$($($enable_features),*)?];
|
||||
let mode = $mode(builder);
|
||||
let mode: Mode = $mode;
|
||||
run_tool_check_step(builder, compiler, target, $path, mode, allow_features, extra_features);
|
||||
}
|
||||
|
||||
|
|
@ -767,57 +758,50 @@ fn run_tool_check_step(
|
|||
tool_check_step!(Rustdoc {
|
||||
path: "src/tools/rustdoc",
|
||||
alt_path: "src/librustdoc",
|
||||
mode: |_builder| Mode::ToolRustcPrivate
|
||||
mode: Mode::ToolRustcPrivate
|
||||
});
|
||||
// Clippy, miri and Rustfmt are hybrids. They are external tools, but use a git subtree instead
|
||||
// of a submodule. Since the SourceType only drives the deny-warnings
|
||||
// behavior, treat it as in-tree so that any new warnings in clippy will be
|
||||
// rejected.
|
||||
tool_check_step!(Clippy { path: "src/tools/clippy", mode: |_builder| Mode::ToolRustcPrivate });
|
||||
tool_check_step!(Miri { path: "src/tools/miri", mode: |_builder| Mode::ToolRustcPrivate });
|
||||
tool_check_step!(CargoMiri {
|
||||
path: "src/tools/miri/cargo-miri",
|
||||
mode: |_builder| Mode::ToolRustcPrivate
|
||||
});
|
||||
tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: |_builder| Mode::ToolRustcPrivate });
|
||||
tool_check_step!(Clippy { path: "src/tools/clippy", mode: Mode::ToolRustcPrivate });
|
||||
tool_check_step!(Miri { path: "src/tools/miri", mode: Mode::ToolRustcPrivate });
|
||||
tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustcPrivate });
|
||||
tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustcPrivate });
|
||||
tool_check_step!(RustAnalyzer {
|
||||
path: "src/tools/rust-analyzer",
|
||||
mode: |_builder| Mode::ToolRustcPrivate,
|
||||
mode: Mode::ToolRustcPrivate,
|
||||
allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
|
||||
enable_features: ["in-rust-tree"],
|
||||
});
|
||||
tool_check_step!(MiroptTestTools {
|
||||
path: "src/tools/miropt-test-tools",
|
||||
mode: |_builder| Mode::ToolBootstrap
|
||||
mode: Mode::ToolBootstrap
|
||||
});
|
||||
// We want to test the local std
|
||||
tool_check_step!(TestFloatParse {
|
||||
path: "src/tools/test-float-parse",
|
||||
mode: |_builder| Mode::ToolStd,
|
||||
mode: Mode::ToolStd,
|
||||
allow_features: TEST_FLOAT_PARSE_ALLOW_FEATURES
|
||||
});
|
||||
tool_check_step!(FeaturesStatusDump {
|
||||
path: "src/tools/features-status-dump",
|
||||
mode: |_builder| Mode::ToolBootstrap
|
||||
mode: Mode::ToolBootstrap
|
||||
});
|
||||
|
||||
tool_check_step!(Bootstrap {
|
||||
path: "src/bootstrap",
|
||||
mode: |_builder| Mode::ToolBootstrap,
|
||||
default: false
|
||||
});
|
||||
tool_check_step!(Bootstrap { path: "src/bootstrap", mode: Mode::ToolBootstrap, default: false });
|
||||
|
||||
// `run-make-support` will be built as part of suitable run-make compiletest test steps, but support
|
||||
// check to make it easier to work on.
|
||||
tool_check_step!(RunMakeSupport {
|
||||
path: "src/tools/run-make-support",
|
||||
mode: |_builder| Mode::ToolBootstrap,
|
||||
mode: Mode::ToolBootstrap,
|
||||
default: false
|
||||
});
|
||||
|
||||
tool_check_step!(CoverageDump {
|
||||
path: "src/tools/coverage-dump",
|
||||
mode: |_builder| Mode::ToolBootstrap,
|
||||
mode: Mode::ToolBootstrap,
|
||||
default: false
|
||||
});
|
||||
|
||||
|
|
@ -825,23 +809,18 @@ tool_check_step!(CoverageDump {
|
|||
// so this is mainly for people working on compiletest to run locally.
|
||||
tool_check_step!(Compiletest {
|
||||
path: "src/tools/compiletest",
|
||||
mode: |builder: &Builder<'_>| if builder.config.compiletest_use_stage0_libtest {
|
||||
Mode::ToolBootstrap
|
||||
} else {
|
||||
Mode::ToolStd
|
||||
},
|
||||
allow_features: COMPILETEST_ALLOW_FEATURES,
|
||||
mode: Mode::ToolBootstrap,
|
||||
default: false,
|
||||
});
|
||||
|
||||
tool_check_step!(Linkchecker {
|
||||
path: "src/tools/linkchecker",
|
||||
mode: |_builder| Mode::ToolBootstrap,
|
||||
mode: Mode::ToolBootstrap,
|
||||
default: false
|
||||
});
|
||||
|
||||
tool_check_step!(BumpStage0 {
|
||||
path: "src/tools/bump-stage0",
|
||||
mode: |_builder| Mode::ToolBootstrap,
|
||||
mode: Mode::ToolBootstrap,
|
||||
default: false
|
||||
});
|
||||
|
|
|
|||
|
|
@ -195,11 +195,7 @@ impl Step for Std {
|
|||
Kind::Clippy,
|
||||
);
|
||||
|
||||
std_cargo(builder, target, &mut cargo);
|
||||
|
||||
for krate in &*self.crates {
|
||||
cargo.arg("-p").arg(krate);
|
||||
}
|
||||
std_cargo(builder, target, &mut cargo, &self.crates);
|
||||
|
||||
let _guard = builder.msg(
|
||||
Kind::Clippy,
|
||||
|
|
|
|||
|
|
@ -266,10 +266,7 @@ impl Step for Std {
|
|||
target,
|
||||
Kind::Build,
|
||||
);
|
||||
std_cargo(builder, target, &mut cargo);
|
||||
for krate in &*self.crates {
|
||||
cargo.arg("-p").arg(krate);
|
||||
}
|
||||
std_cargo(builder, target, &mut cargo, &self.crates);
|
||||
cargo
|
||||
};
|
||||
|
||||
|
|
@ -497,7 +494,12 @@ fn compiler_rt_for_profiler(builder: &Builder<'_>) -> PathBuf {
|
|||
|
||||
/// Configure cargo to compile the standard library, adding appropriate env vars
|
||||
/// and such.
|
||||
pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Cargo) {
|
||||
pub fn std_cargo(
|
||||
builder: &Builder<'_>,
|
||||
target: TargetSelection,
|
||||
cargo: &mut Cargo,
|
||||
crates: &[String],
|
||||
) {
|
||||
// rustc already ensures that it builds with the minimum deployment
|
||||
// target, so ideally we shouldn't need to do anything here.
|
||||
//
|
||||
|
|
@ -605,6 +607,10 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Car
|
|||
cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
|
||||
}
|
||||
|
||||
for krate in crates {
|
||||
cargo.args(["-p", krate]);
|
||||
}
|
||||
|
||||
let mut features = String::new();
|
||||
|
||||
if builder.no_std(target) == Some(true) {
|
||||
|
|
@ -614,8 +620,10 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Car
|
|||
}
|
||||
|
||||
// for no-std targets we only compile a few no_std crates
|
||||
if crates.is_empty() {
|
||||
cargo.args(["-p", "alloc"]);
|
||||
}
|
||||
cargo
|
||||
.args(["-p", "alloc"])
|
||||
.arg("--manifest-path")
|
||||
.arg(builder.src.join("library/alloc/Cargo.toml"))
|
||||
.arg("--features")
|
||||
|
|
|
|||
|
|
@ -783,7 +783,7 @@ fn doc_std(
|
|||
Kind::Doc,
|
||||
);
|
||||
|
||||
compile::std_cargo(builder, target, &mut cargo);
|
||||
compile::std_cargo(builder, target, &mut cargo, requested_crates);
|
||||
cargo
|
||||
.arg("--no-deps")
|
||||
.arg("--target-dir")
|
||||
|
|
@ -803,10 +803,6 @@ fn doc_std(
|
|||
cargo.rustdocflag("--document-private-items").rustdocflag("--document-hidden-items");
|
||||
}
|
||||
|
||||
for krate in requested_crates {
|
||||
cargo.arg("-p").arg(krate);
|
||||
}
|
||||
|
||||
let description =
|
||||
format!("library{} in {} format", crate_description(requested_crates), format.as_str());
|
||||
let _guard = builder.msg(Kind::Doc, description, Mode::Std, build_compiler, target);
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ use crate::core::build_steps::llvm::get_llvm_version;
|
|||
use crate::core::build_steps::run::get_completion_paths;
|
||||
use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
|
||||
use crate::core::build_steps::tool::{
|
||||
self, COMPILETEST_ALLOW_FEATURES, RustcPrivateCompilers, SourceType,
|
||||
TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool, ToolTargetBuildMode, get_tool_target_compiler,
|
||||
self, RustcPrivateCompilers, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool,
|
||||
ToolTargetBuildMode, get_tool_target_compiler,
|
||||
};
|
||||
use crate::core::build_steps::toolstate::ToolState;
|
||||
use crate::core::build_steps::{compile, dist, llvm};
|
||||
|
|
@ -36,7 +36,7 @@ use crate::utils::helpers::{
|
|||
linker_args, linker_flags, t, target_supports_cranelift_backend, up_to_date,
|
||||
};
|
||||
use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
|
||||
use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, debug, envify};
|
||||
use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, envify};
|
||||
|
||||
const ADB_TEST_DIR: &str = "/data/local/tmp/work";
|
||||
|
||||
|
|
@ -786,26 +786,26 @@ impl Step for CompiletestTest {
|
|||
fn run(self, builder: &Builder<'_>) {
|
||||
let host = self.host;
|
||||
|
||||
// Now that compiletest uses only stable Rust, building it always uses
|
||||
// the stage 0 compiler. However, some of its unit tests need to be able
|
||||
// to query information from an in-tree compiler, so we treat `--stage`
|
||||
// as selecting the stage of that secondary compiler.
|
||||
|
||||
if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
|
||||
eprintln!("\
|
||||
ERROR: `--stage 0` runs compiletest self-tests against the stage0 (precompiled) compiler, not the in-tree compiler, and will almost always cause tests to fail
|
||||
ERROR: `--stage 0` causes compiletest to query information from the stage0 (precompiled) compiler, instead of the in-tree compiler, which can cause some tests to fail inappropriately
|
||||
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 `--set build.compiletest-allow-stage0=true`."
|
||||
);
|
||||
crate::exit!(1);
|
||||
}
|
||||
|
||||
let compiler = builder.compiler(builder.top_stage, host);
|
||||
debug!(?compiler);
|
||||
let bootstrap_compiler = builder.compiler(0, host);
|
||||
let staged_compiler = builder.compiler(builder.top_stage, host);
|
||||
|
||||
// We need `ToolStd` for the locally-built sysroot because
|
||||
// compiletest uses unstable features of the `test` crate.
|
||||
builder.std(compiler, host);
|
||||
let mut cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
compiler,
|
||||
// compiletest uses libtest internals; make it use the in-tree std to make sure it never
|
||||
// breaks when std sources change.
|
||||
Mode::ToolStd,
|
||||
bootstrap_compiler,
|
||||
Mode::ToolBootstrap,
|
||||
host,
|
||||
Kind::Test,
|
||||
"src/tools/compiletest",
|
||||
|
|
@ -816,9 +816,8 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||
// Used for `compiletest` self-tests to have the path to the *staged* compiler. Getting this
|
||||
// right is important, as `compiletest` is intended to only support one target spec JSON
|
||||
// format, namely that of the staged compiler.
|
||||
cargo.env("TEST_RUSTC", builder.rustc(compiler));
|
||||
cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
|
||||
|
||||
cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
|
||||
run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
|
||||
}
|
||||
}
|
||||
|
|
@ -2964,7 +2963,7 @@ impl Step for Crate {
|
|||
.arg("--manifest-path")
|
||||
.arg(builder.src.join("library/sysroot/Cargo.toml"));
|
||||
} else {
|
||||
compile::std_cargo(builder, target, &mut cargo);
|
||||
compile::std_cargo(builder, target, &mut cargo, &[]);
|
||||
}
|
||||
}
|
||||
Mode::Rustc => {
|
||||
|
|
|
|||
|
|
@ -380,7 +380,6 @@ macro_rules! bootstrap_tool {
|
|||
($(
|
||||
$name:ident, $path:expr, $tool_name:expr
|
||||
$(,is_external_tool = $external:expr)*
|
||||
$(,is_unstable_tool = $unstable:expr)*
|
||||
$(,allow_features = $allow_features:expr)?
|
||||
$(,submodules = $submodules:expr)?
|
||||
$(,artifact_kind = $artifact_kind:expr)?
|
||||
|
|
@ -438,19 +437,11 @@ macro_rules! bootstrap_tool {
|
|||
}
|
||||
)*
|
||||
|
||||
let is_unstable = false $(|| $unstable)*;
|
||||
let compiletest_wants_stage0 = $tool_name == "compiletest" && builder.config.compiletest_use_stage0_libtest;
|
||||
|
||||
builder.ensure(ToolBuild {
|
||||
build_compiler: self.compiler,
|
||||
target: self.target,
|
||||
tool: $tool_name,
|
||||
mode: if is_unstable && !compiletest_wants_stage0 {
|
||||
// use in-tree libraries for unstable features
|
||||
Mode::ToolStd
|
||||
} else {
|
||||
Mode::ToolBootstrap
|
||||
},
|
||||
mode: Mode::ToolBootstrap,
|
||||
path: $path,
|
||||
source_type: if false $(|| $external)* {
|
||||
SourceType::Submodule
|
||||
|
|
@ -483,8 +474,6 @@ macro_rules! bootstrap_tool {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) const COMPILETEST_ALLOW_FEATURES: &str = "internal_output_capture";
|
||||
|
||||
bootstrap_tool!(
|
||||
// This is marked as an external tool because it includes dependencies
|
||||
// from submodules. Trying to keep the lints in sync between all the repos
|
||||
|
|
@ -495,7 +484,7 @@ bootstrap_tool!(
|
|||
Tidy, "src/tools/tidy", "tidy";
|
||||
Linkchecker, "src/tools/linkchecker", "linkchecker";
|
||||
CargoTest, "src/tools/cargotest", "cargotest";
|
||||
Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
|
||||
Compiletest, "src/tools/compiletest", "compiletest";
|
||||
BuildManifest, "src/tools/build-manifest", "build-manifest";
|
||||
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
|
||||
RustInstaller, "src/tools/rust-installer", "rust-installer";
|
||||
|
|
@ -509,8 +498,7 @@ bootstrap_tool!(
|
|||
CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
|
||||
GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
|
||||
GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
|
||||
// rustdoc-gui-test has a crate dependency on compiletest, so it needs the same unstable features.
|
||||
RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
|
||||
RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test";
|
||||
CoverageDump, "src/tools/coverage-dump", "coverage-dump";
|
||||
UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
|
||||
FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
|
||||
|
|
|
|||
|
|
@ -2004,21 +2004,6 @@ mod snapshot {
|
|||
.render_steps(), @"[check] rustc 0 <host> -> Compiletest 1 <host>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_compiletest_stage1_libtest() {
|
||||
let ctx = TestCtx::new();
|
||||
insta::assert_snapshot!(
|
||||
ctx.config("check")
|
||||
.path("compiletest")
|
||||
.args(&["--set", "build.compiletest-use-stage0-libtest=false"])
|
||||
.render_steps(), @r"
|
||||
[build] llvm <host>
|
||||
[build] rustc 0 <host> -> rustc 1 <host>
|
||||
[build] rustc 1 <host> -> std 1 <host>
|
||||
[check] rustc 1 <host> -> Compiletest 2 <host>
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_codegen() {
|
||||
let ctx = TestCtx::new();
|
||||
|
|
@ -2145,6 +2130,17 @@ mod snapshot {
|
|||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compiletest_self_test() {
|
||||
let ctx = TestCtx::new();
|
||||
let steps = ctx.config("test").arg("compiletest").render_steps();
|
||||
insta::assert_snapshot!(steps, @r"
|
||||
[build] llvm <host>
|
||||
[build] rustc 0 <host> -> rustc 1 <host>
|
||||
[build] rustdoc 0 <host>
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compiletest_suites_stage1() {
|
||||
let ctx = TestCtx::new();
|
||||
|
|
|
|||
|
|
@ -310,9 +310,6 @@ pub struct Config {
|
|||
/// sources.
|
||||
pub compiletest_allow_stage0: bool,
|
||||
|
||||
/// Whether to use the precompiled stage0 libtest with compiletest.
|
||||
pub compiletest_use_stage0_libtest: bool,
|
||||
|
||||
/// Default value for `--extra-checks`
|
||||
pub tidy_extra_checks: Option<String>,
|
||||
pub is_running_on_ci: bool,
|
||||
|
|
@ -497,7 +494,8 @@ impl Config {
|
|||
optimized_compiler_builtins: build_optimized_compiler_builtins,
|
||||
jobs: build_jobs,
|
||||
compiletest_diff_tool: build_compiletest_diff_tool,
|
||||
compiletest_use_stage0_libtest: build_compiletest_use_stage0_libtest,
|
||||
// No longer has any effect; kept (for now) to avoid breaking people's configs.
|
||||
compiletest_use_stage0_libtest: _,
|
||||
tidy_extra_checks: build_tidy_extra_checks,
|
||||
ccache: build_ccache,
|
||||
exclude: build_exclude,
|
||||
|
|
@ -1197,7 +1195,6 @@ impl Config {
|
|||
compiler_docs: build_compiler_docs.unwrap_or(false),
|
||||
compiletest_allow_stage0: build_compiletest_allow_stage0.unwrap_or(false),
|
||||
compiletest_diff_tool: build_compiletest_diff_tool,
|
||||
compiletest_use_stage0_libtest: build_compiletest_use_stage0_libtest.unwrap_or(true),
|
||||
config: toml_path,
|
||||
configure_args: build_configure_args.unwrap_or_default(),
|
||||
control_flow_guard: rust_control_flow_guard.unwrap_or(false),
|
||||
|
|
|
|||
|
|
@ -47,11 +47,17 @@ use crate::str::FromStr;
|
|||
#[macro_export]
|
||||
macro_rules! define_config {
|
||||
($(#[$attr:meta])* struct $name:ident {
|
||||
$($field:ident: Option<$field_ty:ty> = $field_key:literal,)*
|
||||
$(
|
||||
$(#[$field_attr:meta])*
|
||||
$field:ident: Option<$field_ty:ty> = $field_key:literal,
|
||||
)*
|
||||
}) => {
|
||||
$(#[$attr])*
|
||||
pub struct $name {
|
||||
$(pub $field: Option<$field_ty>,)*
|
||||
$(
|
||||
$(#[$field_attr])*
|
||||
pub $field: Option<$field_ty>,
|
||||
)*
|
||||
}
|
||||
|
||||
impl Merge for $name {
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ define_config! {
|
|||
jobs: Option<u32> = "jobs",
|
||||
compiletest_diff_tool: Option<String> = "compiletest-diff-tool",
|
||||
compiletest_allow_stage0: Option<bool> = "compiletest-allow-stage0",
|
||||
/// No longer has any effect; kept (for now) to avoid breaking people's configs.
|
||||
/// FIXME(#146929): Remove this in 2026.
|
||||
compiletest_use_stage0_libtest: Option<bool> = "compiletest-use-stage0-libtest",
|
||||
tidy_extra_checks: Option<String> = "tidy-extra-checks",
|
||||
ccache: Option<StringOrBool> = "ccache",
|
||||
|
|
|
|||
|
|
@ -327,8 +327,8 @@ pub enum Mode {
|
|||
ToolTarget,
|
||||
|
||||
/// Build a tool which uses the locally built std, placing output in the
|
||||
/// "stageN-tools" directory. Its usage is quite rare, mainly used by
|
||||
/// compiletest which needs libtest.
|
||||
/// "stageN-tools" directory. Its usage is quite rare; historically it was
|
||||
/// needed by compiletest, but now it is mainly used by `test-float-parse`.
|
||||
ToolStd,
|
||||
|
||||
/// Build a tool which uses the `rustc_private` mechanism, and thus
|
||||
|
|
|
|||
|
|
@ -557,8 +557,13 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
|
|||
summary: "New option `build.windows-rc` that will override which resource compiler on Windows will be used to compile Rust.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 99999,
|
||||
change_id: 147046,
|
||||
severity: ChangeSeverity::Warning,
|
||||
summary: "The `rust.use-lld` option has been renamed to `rust.bootstrap-override-lld`. Note that it only serves for overriding the linker used when building Rust code in bootstrap to be LLD.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 146929,
|
||||
severity: ChangeSeverity::Info,
|
||||
summary: "`compiletest` is now always built with the stage 0 compiler, so `build.compiletest-use-stage0-libtest` has no effect.",
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
# `split-dwarf-out-dir`
|
||||
|
||||
On systems which use DWARF debug info this flag causes `.dwo` files produced
|
||||
by `-C split-debuginfo` to be written to the specified directory rather than
|
||||
placed next to the object files. This is mostly useful if you have a build
|
||||
system which needs to control where to find compile outputs without running the
|
||||
compiler and have to put your `.dwo` files in a separate directory.
|
||||
|
|
@ -1685,7 +1685,7 @@ impl Type {
|
|||
match (self_cleared, other_cleared) {
|
||||
// Recursive cases.
|
||||
(Type::Tuple(a), Type::Tuple(b)) => {
|
||||
a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.is_doc_subtype_of(b, cache))
|
||||
a.iter().eq_by(b, |a, b| a.is_doc_subtype_of(b, cache))
|
||||
}
|
||||
(Type::Slice(a), Type::Slice(b)) => a.is_doc_subtype_of(b, cache),
|
||||
(Type::Array(a, al), Type::Array(b, bl)) => al == bl && a.is_doc_subtype_of(b, cache),
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#![feature(if_let_guard)]
|
||||
#![feature(iter_advance_by)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(iter_order_by)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(test)]
|
||||
#![warn(rustc::internal)]
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_f
|
|||
expr.span,
|
||||
format!(
|
||||
"casting from `{cast_from}` to a more-strictly-aligned pointer (`{cast_to}`) ({} < {} bytes)",
|
||||
from_layout.align.abi.bytes(),
|
||||
to_layout.align.abi.bytes(),
|
||||
from_layout.align.bytes(),
|
||||
to_layout.align.bytes(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ fn is_literal_aligned(cx: &LateContext<'_>, lit: &Spanned<LitKind>, to: &Ty<'_>)
|
|||
cx.tcx
|
||||
.layout_of(cx.typing_env().as_query_input(to_mid_ty))
|
||||
.is_ok_and(|layout| {
|
||||
let align = u128::from(layout.align.abi.bytes());
|
||||
let align = u128::from(layout.align.bytes());
|
||||
u128::from(val) <= align
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -661,18 +661,10 @@ pub struct Config {
|
|||
pub builtin_cfg_names: OnceLock<HashSet<String>>,
|
||||
pub supported_crate_types: OnceLock<HashSet<String>>,
|
||||
|
||||
/// FIXME: this is why we still need to depend on *staged* `std`, it's because we currently rely
|
||||
/// on `#![feature(internal_output_capture)]` for [`std::io::set_output_capture`] to implement
|
||||
/// `libtest`-esque `--no-capture`.
|
||||
///
|
||||
/// FIXME: rename this to the more canonical `no_capture`, or better, invert this to `capture`
|
||||
/// to avoid `!nocapture` double-negatives.
|
||||
pub nocapture: bool,
|
||||
|
||||
/// True if the experimental new output-capture implementation should be
|
||||
/// used, avoiding the need for `#![feature(internal_output_capture)]`.
|
||||
pub new_output_capture: bool,
|
||||
|
||||
/// Needed both to construct [`build_helper::git::GitConfig`].
|
||||
pub nightly_branch: String,
|
||||
pub git_merge_commit_email: String,
|
||||
|
|
@ -790,7 +782,6 @@ impl Config {
|
|||
builtin_cfg_names: Default::default(),
|
||||
supported_crate_types: Default::default(),
|
||||
nocapture: Default::default(),
|
||||
new_output_capture: Default::default(),
|
||||
nightly_branch: Default::default(),
|
||||
git_merge_commit_email: Default::default(),
|
||||
profiler_runtime: Default::default(),
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ use std::borrow::Cow;
|
|||
use std::collections::HashMap;
|
||||
use std::hash::{BuildHasherDefault, DefaultHasher};
|
||||
use std::num::NonZero;
|
||||
use std::sync::{Arc, Mutex, mpsc};
|
||||
use std::{env, hint, io, mem, panic, thread};
|
||||
use std::sync::{Arc, mpsc};
|
||||
use std::{env, hint, mem, panic, thread};
|
||||
|
||||
use camino::Utf8PathBuf;
|
||||
|
||||
|
|
@ -130,10 +130,6 @@ fn run_test_inner(
|
|||
panic_hook::set_capture_buf(Default::default());
|
||||
}
|
||||
|
||||
if let CaptureKind::Old { ref buf } = capture {
|
||||
io::set_output_capture(Some(Arc::clone(buf)));
|
||||
}
|
||||
|
||||
let stdout = capture.stdout();
|
||||
let stderr = capture.stderr();
|
||||
|
||||
|
|
@ -144,9 +140,6 @@ fn run_test_inner(
|
|||
// Forward any captured panic message to (captured) stderr.
|
||||
write!(stderr, "{panic_buf}");
|
||||
}
|
||||
if matches!(capture, CaptureKind::Old { .. }) {
|
||||
io::set_output_capture(None);
|
||||
}
|
||||
|
||||
let outcome = match (should_panic, panic_payload) {
|
||||
(ShouldPanic::No, None) | (ShouldPanic::Yes, Some(_)) => TestOutcome::Succeeded,
|
||||
|
|
@ -167,31 +160,24 @@ enum CaptureKind {
|
|||
/// runners, whose output is always captured.)
|
||||
None,
|
||||
|
||||
/// Use the old output-capture implementation, which relies on the unstable
|
||||
/// library feature `#![feature(internal_output_capture)]`.
|
||||
Old { buf: Arc<Mutex<Vec<u8>>> },
|
||||
|
||||
/// Use the new output-capture implementation, which only uses stable Rust.
|
||||
New { buf: output_capture::CaptureBuf },
|
||||
/// Capture all console output that would be printed by test runners via
|
||||
/// their `stdout` and `stderr` trait objects, or via the custom panic hook.
|
||||
Capture { buf: output_capture::CaptureBuf },
|
||||
}
|
||||
|
||||
impl CaptureKind {
|
||||
fn for_config(config: &Config) -> Self {
|
||||
if config.nocapture {
|
||||
Self::None
|
||||
} else if config.new_output_capture {
|
||||
Self::New { buf: output_capture::CaptureBuf::new() }
|
||||
} else {
|
||||
// Create a capure buffer for `io::set_output_capture`.
|
||||
Self::Old { buf: Default::default() }
|
||||
Self::Capture { buf: output_capture::CaptureBuf::new() }
|
||||
}
|
||||
}
|
||||
|
||||
fn should_set_panic_hook(&self) -> bool {
|
||||
match self {
|
||||
Self::None => false,
|
||||
Self::Old { .. } => true,
|
||||
Self::New { .. } => true,
|
||||
Self::Capture { .. } => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -205,16 +191,15 @@ impl CaptureKind {
|
|||
|
||||
fn capture_buf_or<'a>(&'a self, fallback: &'a dyn ConsoleOut) -> &'a dyn ConsoleOut {
|
||||
match self {
|
||||
Self::None | Self::Old { .. } => fallback,
|
||||
Self::New { buf } => buf,
|
||||
Self::None => fallback,
|
||||
Self::Capture { buf } => buf,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_inner(self) -> Option<Vec<u8>> {
|
||||
match self {
|
||||
Self::None => None,
|
||||
Self::Old { buf } => Some(buf.lock().unwrap_or_else(|e| e.into_inner()).to_vec()),
|
||||
Self::New { buf } => Some(buf.into_inner().into()),
|
||||
Self::Capture { buf } => Some(buf.into_inner().into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,4 @@
|
|||
#![crate_name = "compiletest"]
|
||||
// Needed by the "new" test executor that does not depend on libtest.
|
||||
// FIXME(Zalathar): We should be able to get rid of `internal_output_capture`,
|
||||
// by having `runtest` manually capture all of its println-like output instead.
|
||||
// That would result in compiletest being written entirely in stable Rust!
|
||||
#![feature(internal_output_capture)]
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
@ -178,12 +173,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
// FIXME: Temporarily retained so we can point users to `--no-capture`
|
||||
.optflag("", "nocapture", "")
|
||||
.optflag("", "no-capture", "don't capture stdout/stderr of tests")
|
||||
.optopt(
|
||||
"N",
|
||||
"new-output-capture",
|
||||
"enables or disables the new output-capture implementation",
|
||||
"off|on",
|
||||
)
|
||||
.optflag("", "profiler-runtime", "is the profiler runtime enabled for this target")
|
||||
.optflag("h", "help", "show this message")
|
||||
.reqopt("", "channel", "current Rust channel", "CHANNEL")
|
||||
|
|
@ -480,14 +469,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
supported_crate_types: OnceLock::new(),
|
||||
|
||||
nocapture: matches.opt_present("no-capture"),
|
||||
new_output_capture: {
|
||||
let value = matches
|
||||
.opt_str("new-output-capture")
|
||||
.or_else(|| env::var("COMPILETEST_NEW_OUTPUT_CAPTURE").ok())
|
||||
.unwrap_or_else(|| "on".to_owned());
|
||||
parse_bool_option(&value)
|
||||
.unwrap_or_else(|| panic!("unknown `--new-output-capture` value `{value}` given"))
|
||||
},
|
||||
|
||||
nightly_branch: matches.opt_str("nightly-branch").unwrap(),
|
||||
git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(),
|
||||
|
|
@ -503,19 +484,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parses the same set of boolean values accepted by rustc command-line arguments.
|
||||
///
|
||||
/// Accepting all of these values is more complicated than just picking one
|
||||
/// pair, but has the advantage that contributors who are used to rustc
|
||||
/// shouldn't have to think about which values are legal.
|
||||
fn parse_bool_option(value: &str) -> Option<bool> {
|
||||
match value {
|
||||
"off" | "no" | "n" | "false" => Some(false),
|
||||
"on" | "yes" | "y" | "true" => Some(true),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn opt_str(maybestr: &Option<String>) -> &str {
|
||||
match *maybestr {
|
||||
None => "(none)",
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
f957826bff7a68b267ce75b1ea56352aed0cca0a
|
||||
29b7717de23f3969ceeb5bef5b01d9223f807655
|
||||
|
|
|
|||
|
|
@ -1340,7 +1340,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
|
|||
name = ecx.tcx.def_path_str(def_id),
|
||||
krate = ecx.tcx.crate_name(def_id.krate),
|
||||
decl_size = extern_decl_layout.size.bytes(),
|
||||
decl_align = extern_decl_layout.align.abi.bytes(),
|
||||
decl_align = extern_decl_layout.align.bytes(),
|
||||
shim_size = info.size.bytes(),
|
||||
shim_align = info.align.bytes(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -366,6 +366,13 @@ impl Rustc {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn split_dwarf_out_dir(&mut self, out_dir: Option<&str>) -> &mut Self {
|
||||
if let Some(out_dir) = out_dir {
|
||||
self.cmd.arg(format!("-Zsplit-dwarf-out-dir={out_dir}"));
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Pass the `--verbose` flag.
|
||||
pub fn verbose(&mut self) -> &mut Self {
|
||||
self.cmd.arg("--verbose");
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ fn check_size_and_align(
|
|||
) {
|
||||
let l = eval_goal(ra_fixture, minicore).unwrap();
|
||||
assert_eq!(l.size.bytes(), size, "size mismatch");
|
||||
assert_eq!(l.align.abi.bytes(), align, "align mismatch");
|
||||
assert_eq!(l.align.bytes(), align, "align mismatch");
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
|
@ -162,7 +162,7 @@ fn check_size_and_align_expr(
|
|||
) {
|
||||
let l = eval_expr(ra_fixture, minicore).unwrap();
|
||||
assert_eq!(l.size.bytes(), size, "size mismatch");
|
||||
assert_eq!(l.align.abi.bytes(), align, "align mismatch");
|
||||
assert_eq!(l.align.bytes(), align, "align mismatch");
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
|
|
|
|||
|
|
@ -2085,7 +2085,7 @@ impl<'db> Evaluator<'db> {
|
|||
if let Some(layout) = self.layout_cache.borrow().get(&ty.to_nextsolver(interner)) {
|
||||
return Ok(layout
|
||||
.is_sized()
|
||||
.then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize)));
|
||||
.then(|| (layout.size.bytes_usize(), layout.align.bytes() as usize)));
|
||||
}
|
||||
if let DefWithBodyId::VariantId(f) = locals.body.owner
|
||||
&& let Some((AdtId::EnumId(e), _)) = ty.as_adt()
|
||||
|
|
@ -2104,7 +2104,7 @@ impl<'db> Evaluator<'db> {
|
|||
let layout = layout?;
|
||||
Ok(layout
|
||||
.is_sized()
|
||||
.then(|| (layout.size.bytes_usize(), layout.align.abi.bytes() as usize)))
|
||||
.then(|| (layout.size.bytes_usize(), layout.align.bytes() as usize)))
|
||||
}
|
||||
|
||||
/// A version of `self.size_of` which returns error if the type is unsized. `what` argument should
|
||||
|
|
@ -2797,7 +2797,7 @@ impl<'db> Evaluator<'db> {
|
|||
)?;
|
||||
// FIXME: there is some leak here
|
||||
let size = layout.size.bytes_usize();
|
||||
let addr = self.heap_allocate(size, layout.align.abi.bytes() as usize)?;
|
||||
let addr = self.heap_allocate(size, layout.align.bytes() as usize)?;
|
||||
self.write_memory(addr, &result)?;
|
||||
IntervalAndTy { interval: Interval { addr, size }, ty }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -767,7 +767,7 @@ impl Evaluator<'_> {
|
|||
"align_of generic arg is not provided".into(),
|
||||
));
|
||||
};
|
||||
let align = self.layout(ty.to_nextsolver(interner))?.align.abi.bytes();
|
||||
let align = self.layout(ty.to_nextsolver(interner))?.align.bytes();
|
||||
destination.write_from_bytes(self, &align.to_le_bytes()[0..destination.size])
|
||||
}
|
||||
"size_of_val" => {
|
||||
|
|
@ -1431,7 +1431,7 @@ impl Evaluator<'_> {
|
|||
field_types.iter().next_back().unwrap().1.clone().substitute(Interner, subst);
|
||||
let sized_part_size =
|
||||
layout.fields.offset(field_types.iter().count() - 1).bytes_usize();
|
||||
let sized_part_align = layout.align.abi.bytes() as usize;
|
||||
let sized_part_align = layout.align.bytes() as usize;
|
||||
let (unsized_part_size, unsized_part_align) =
|
||||
self.size_align_of_unsized(&last_field_ty, metadata, locals)?;
|
||||
let align = sized_part_align.max(unsized_part_align) as isize;
|
||||
|
|
|
|||
|
|
@ -6094,7 +6094,7 @@ impl Layout {
|
|||
}
|
||||
|
||||
pub fn align(&self) -> u64 {
|
||||
self.0.align.abi.bytes()
|
||||
self.0.align.bytes()
|
||||
}
|
||||
|
||||
pub fn niches(&self) -> Option<u128> {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//@ known-bug: rust-lang/rust#125772
|
||||
//@ only-x86_64
|
||||
//@ only-64bit
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
struct Outer<const A: i64, const B: i64>();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue