Merge pull request #4610 from rust-lang/rustup-2025-09-30

Automatic Rustup
This commit is contained in:
Oli Scherer 2025-09-30 05:44:09 +00:00 committed by GitHub
commit fb75fbba95
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
124 changed files with 701 additions and 482 deletions

View file

@ -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,

View file

@ -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.

View file

@ -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)
}
}

View file

@ -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"]

View file

@ -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,
}

View file

@ -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}

View file

@ -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,
);
}
}

View file

@ -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

View file

@ -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> {

View file

@ -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)]

View file

@ -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,
}

View file

@ -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
}
}

View file

@ -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 {

View file

@ -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)]

View file

@ -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,
));

View file

@ -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 {

View file

@ -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(

View file

@ -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));

View file

@ -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,

View file

@ -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() {

View file

@ -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

View file

@ -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,

View file

@ -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).

View file

@ -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")]
{

View file

@ -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,

View file

@ -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,

View file

@ -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);

View file

@ -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(),
);
}
}

View file

@ -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");
}

View file

@ -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);

View file

@ -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),
]);
}

View file

@ -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) => {

View file

@ -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

View file

@ -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(),
);
}
}

View file

@ -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) => {

View file

@ -37,7 +37,7 @@ where
debug!(
"is_disaligned({:?}) - align = {}, packed = {}; not disaligned",
place,
layout.align.abi.bytes(),
layout.align.bytes(),
pack.bytes()
);
false

View file

@ -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);
}

View file

@ -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),

View file

@ -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,
}
}

View file

@ -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,

View file

@ -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 {

View file

@ -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;

View file

@ -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

View file

@ -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(

View file

@ -5,6 +5,7 @@
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(iter_order_by)]
#![feature(never_type)]
// tidy-alphabetical-end

View file

@ -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,

View file

@ -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

View file

@ -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(),
)

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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())

View file

@ -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

View file

@ -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]

View file

@ -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);
}

View file

@ -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())

View file

@ -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),

View file

@ -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

View file

@ -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],

View file

@ -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));
}

View file

@ -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."

View file

@ -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(),

View file

@ -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()),

View file

@ -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."

View file

@ -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

View file

@ -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 {

View file

@ -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,
}
})

View file

@ -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.

View file

@ -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)
}
}

View file

@ -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

View file

@ -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();
}

View file

@ -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;
}
_ => {

View file

@ -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
});

View file

@ -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,

View file

@ -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")

View file

@ -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);

View file

@ -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 => {

View file

@ -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";

View file

@ -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();

View file

@ -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),

View file

@ -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 {

View file

@ -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",

View file

@ -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

View file

@ -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.",
},
];

View file

@ -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.

View file

@ -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),

View file

@ -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)]

View file

@ -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(),
),
);
}

View file

@ -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
})
}

View file

@ -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(),

View file

@ -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()),
}
}
}

View file

@ -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)",

View file

@ -1 +1 @@
f957826bff7a68b267ce75b1ea56352aed0cca0a
29b7717de23f3969ceeb5bef5b01d9223f807655

View file

@ -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(),
)

View file

@ -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");

View file

@ -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]

View file

@ -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 }
};

View file

@ -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;

View file

@ -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> {

View file

@ -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