Auto merge of #142550 - fmease:rollup-fteyzcv, r=fmease

Rollup of 10 pull requests

Successful merges:

 - rust-lang/rust#133952 (Remove wasm legacy abi)
 - rust-lang/rust#134661 (Reduce precedence of expressions that have an outer attr)
 - rust-lang/rust#141769 (Move metadata object generation for dylibs to the linker code )
 - rust-lang/rust#141937 (Report never type lints in dependencies)
 - rust-lang/rust#142347 (Async drop - fix for StorageLive/StorageDead codegen for pinned future)
 - rust-lang/rust#142389 (Apply ABI attributes on return types in `rustc_codegen_cranelift`)
 - rust-lang/rust#142470 (Add some missing mailmap entries)
 - rust-lang/rust#142481 (Add `f16` inline asm support for LoongArch)
 - rust-lang/rust#142499 (Remove check run bootstrap)
 - rust-lang/rust#142543 (Suggest adding semicolon in user code rather than macro impl details)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-06-16 00:39:47 +00:00
commit e314b97ee5
98 changed files with 2791 additions and 1030 deletions

View file

@ -34,10 +34,13 @@ Alona Enraght-Moony <code@alona.page> <nixon@caminus.local>
Alona Enraght-Moony <code@alona.page> <contact@alona.page>
Amanda Stjerna <mail@amandastjerna.se> <albin.stjerna@gmail.com>
Amanda Stjerna <mail@amandastjerna.se> <amanda.stjerna@it.uu.se>
Amanieu d'Antras <amanieu@gmail.com> <amanieu.dantras@huawei.com>
Amos Onn <amosonn@gmail.com>
Ana-Maria Mihalache <mihalacheana.maria@yahoo.com>
Anatoly Ikorsky <aikorsky@gmail.com>
Andre Bogus <bogusandre@gmail.com>
Andre Bogus <bogusandre@gmail.com> <andre.bogus@aleph-alpha.de>
Andre Bogus <bogusandre@gmail.com> <andre.bogus@ankordata.de>
Andrea Ciliberti <meziu210@icloud.com>
Andreas Gal <gal@mozilla.com> <andreas.gal@gmail.com>
Andreas Jonson <andjo403@users.noreply.github.com>
@ -116,6 +119,7 @@ Carol Willing <carolcode@willingconsulting.com>
Chandler Deng <chandde@microsoft.com>
Charles Lew <crlf0710@gmail.com> CrLF0710 <crlf0710@gmail.com>
Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
Chris Denton <chris@chrisdenton.dev> <christophersdenton@gmail.com>
Chris Denton <chris@chrisdenton.dev> Chris Denton <ChrisDenton@users.noreply.github.com>
Chris Gregory <czipperz@gmail.com>
Chris Pardy <chrispardy36@gmail.com>
@ -403,6 +407,8 @@ Urgau <urgau@numericable.fr> <3616612+Urgau@users.noreply.github.com>
Lucy <luxx4x@protonmail.com>
Lukas H. <lukaramu@users.noreply.github.com>
Lukas Lueg <lukas.lueg@gmail.com>
Lukas Wirth <lukastw97@gmail.com> <lukas.wirth@ferrous-systems.com>
Lukas Wirth <lukastw97@gmail.com> <me@lukaswirth.dev>
Luke Metz <luke.metz@students.olin.edu>
Luqman Aden <me@luqman.ca> <laden@csclub.uwaterloo.ca>
Luqman Aden <me@luqman.ca> <laden@mozilla.com>
@ -493,6 +499,7 @@ Nicolas Abram <abramlujan@gmail.com>
Nicole Mazzuca <npmazzuca@gmail.com>
Niko Matsakis <rust@nikomatsakis.com>
Niko Matsakis <rust@nikomatsakis.com> <niko@alum.mit.edu>
Niko Matsakis <rust@nikomatsakis.com> <nikomat@amazon.com>
Noratrieb <48135649+Noratrieb@users.noreply.github.com>
Noratrieb <48135649+Noratrieb@users.noreply.github.com> <48135649+Nilstrieb@users.noreply.github.com>
Noratrieb <48135649+Noratrieb@users.noreply.github.com> <nilstrieb@gmail.com>

View file

@ -1450,11 +1450,20 @@ impl Expr {
}
pub fn precedence(&self) -> ExprPrecedence {
fn prefix_attrs_precedence(attrs: &AttrVec) -> ExprPrecedence {
for attr in attrs {
if let AttrStyle::Outer = attr.style {
return ExprPrecedence::Prefix;
}
}
ExprPrecedence::Unambiguous
}
match &self.kind {
ExprKind::Closure(closure) => {
match closure.fn_decl.output {
FnRetTy::Default(_) => ExprPrecedence::Jump,
FnRetTy::Ty(_) => ExprPrecedence::Unambiguous,
FnRetTy::Ty(_) => prefix_attrs_precedence(&self.attrs),
}
}
@ -1463,7 +1472,7 @@ impl Expr {
| ExprKind::Yield(YieldKind::Prefix(value))
| ExprKind::Yeet(value) => match value {
Some(_) => ExprPrecedence::Jump,
None => ExprPrecedence::Unambiguous,
None => prefix_attrs_precedence(&self.attrs),
},
ExprKind::Become(_) => ExprPrecedence::Jump,
@ -1490,7 +1499,7 @@ impl Expr {
| ExprKind::Let(..)
| ExprKind::Unary(..) => ExprPrecedence::Prefix,
// Never need parens
// Need parens if and only if there are prefix attributes.
ExprKind::Array(_)
| ExprKind::Await(..)
| ExprKind::Use(..)
@ -1525,7 +1534,7 @@ impl Expr {
| ExprKind::While(..)
| ExprKind::Yield(YieldKind::Postfix(..))
| ExprKind::Err(_)
| ExprKind::Dummy => ExprPrecedence::Unambiguous,
| ExprKind::Dummy => prefix_attrs_precedence(&self.attrs),
}
}

View file

@ -342,6 +342,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
}
}
} else if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
let sp = info
.span
.find_ancestor_in_same_ctxt(local_decl.source_info.span)
.unwrap_or(info.span);
if info.tail_result_is_ignored {
// #85581: If the first mutable borrow's scope contains
// the second borrow, this suggestion isn't helpful.
@ -349,7 +353,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
old.to(info.span.shrink_to_hi()).contains(new)
}) {
err.span_suggestion_verbose(
info.span.shrink_to_hi(),
sp.shrink_to_hi(),
"consider adding semicolon after the expression so its \
temporaries are dropped sooner, before the local variables \
declared by the block are dropped",
@ -368,8 +372,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
local variable `x` and then make `x` be the expression at the \
end of the block",
vec![
(info.span.shrink_to_lo(), "let x = ".to_string()),
(info.span.shrink_to_hi(), "; x".to_string()),
(sp.shrink_to_lo(), "let x = ".to_string()),
(sp.shrink_to_hi(), "; x".to_string()),
],
Applicability::MaybeIncorrect,
);

View file

@ -1,6 +1,6 @@
//! Argument passing
use cranelift_codegen::ir::{ArgumentExtension, ArgumentPurpose};
use cranelift_codegen::ir::ArgumentPurpose;
use rustc_abi::{Reg, RegKind};
use rustc_target::callconv::{
ArgAbi, ArgAttributes, ArgExtension as RustcArgExtension, CastTarget, PassMode,
@ -32,13 +32,12 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam {
AbiParam::new(clif_ty)
}
fn apply_arg_attrs_to_abi_param(mut param: AbiParam, arg_attrs: ArgAttributes) -> AbiParam {
fn apply_attrs_to_abi_param(param: AbiParam, arg_attrs: ArgAttributes) -> AbiParam {
match arg_attrs.arg_ext {
RustcArgExtension::None => {}
RustcArgExtension::Zext => param.extension = ArgumentExtension::Uext,
RustcArgExtension::Sext => param.extension = ArgumentExtension::Sext,
RustcArgExtension::None => param,
RustcArgExtension::Zext => param.uext(),
RustcArgExtension::Sext => param.sext(),
}
param
}
fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> {
@ -82,7 +81,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
match self.mode {
PassMode::Ignore => smallvec![],
PassMode::Direct(attrs) => match self.layout.backend_repr {
BackendRepr::Scalar(scalar) => smallvec![apply_arg_attrs_to_abi_param(
BackendRepr::Scalar(scalar) => smallvec![apply_attrs_to_abi_param(
AbiParam::new(scalar_to_clif_type(tcx, scalar)),
attrs
)],
@ -97,8 +96,8 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
let a = scalar_to_clif_type(tcx, a);
let b = scalar_to_clif_type(tcx, b);
smallvec![
apply_arg_attrs_to_abi_param(AbiParam::new(a), attrs_a),
apply_arg_attrs_to_abi_param(AbiParam::new(b), attrs_b),
apply_attrs_to_abi_param(AbiParam::new(a), attrs_a),
apply_attrs_to_abi_param(AbiParam::new(b), attrs_b),
]
}
_ => unreachable!("{:?}", self.layout.backend_repr),
@ -112,19 +111,19 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
// Abi requires aligning struct size to pointer size
let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi);
let size = u32::try_from(size.bytes()).unwrap();
smallvec![apply_arg_attrs_to_abi_param(
smallvec![apply_attrs_to_abi_param(
AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),),
attrs
)]
} else {
smallvec![apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs)]
smallvec![apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs)]
}
}
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
assert!(!on_stack);
smallvec![
apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs),
apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), meta_attrs),
apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs),
apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), meta_attrs),
]
}
}
@ -133,30 +132,46 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option<AbiParam>, Vec<AbiParam>) {
match self.mode {
PassMode::Ignore => (None, vec![]),
PassMode::Direct(_) => match self.layout.backend_repr {
BackendRepr::Scalar(scalar) => {
(None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))])
}
PassMode::Direct(attrs) => match self.layout.backend_repr {
BackendRepr::Scalar(scalar) => (
None,
vec![apply_attrs_to_abi_param(
AbiParam::new(scalar_to_clif_type(tcx, scalar)),
attrs,
)],
),
BackendRepr::SimdVector { .. } => {
let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout);
(None, vec![AbiParam::new(vector_ty)])
(None, vec![apply_attrs_to_abi_param(AbiParam::new(vector_ty), attrs)])
}
_ => unreachable!("{:?}", self.layout.backend_repr),
},
PassMode::Pair(_, _) => match self.layout.backend_repr {
PassMode::Pair(attrs_a, attrs_b) => match self.layout.backend_repr {
BackendRepr::ScalarPair(a, b) => {
let a = scalar_to_clif_type(tcx, a);
let b = scalar_to_clif_type(tcx, b);
(None, vec![AbiParam::new(a), AbiParam::new(b)])
(
None,
vec![
apply_attrs_to_abi_param(AbiParam::new(a), attrs_a),
apply_attrs_to_abi_param(AbiParam::new(b), attrs_b),
],
)
}
_ => unreachable!("{:?}", self.layout.backend_repr),
},
PassMode::Cast { ref cast, .. } => {
(None, cast_target_to_abi_params(cast).into_iter().collect())
}
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack } => {
PassMode::Indirect { attrs, meta_attrs: None, on_stack } => {
assert!(!on_stack);
(Some(AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructReturn)), vec![])
(
Some(apply_attrs_to_abi_param(
AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructReturn),
attrs,
)),
vec![],
)
}
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value")

View file

@ -11,7 +11,6 @@ use std::thread::JoinHandle;
use cranelift_object::{ObjectBuilder, ObjectModule};
use rustc_codegen_ssa::assert_module_sources::CguReuse;
use rustc_codegen_ssa::back::link::ensure_removed;
use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file;
use rustc_codegen_ssa::base::determine_cgu_reuse;
use rustc_codegen_ssa::{
CodegenResults, CompiledModule, CrateInfo, ModuleKind, errors as ssa_errors,
@ -19,7 +18,6 @@ use rustc_codegen_ssa::{
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
use rustc_metadata::EncodedMetadata;
use rustc_metadata::fs::copy_to_stdout;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
@ -61,8 +59,6 @@ impl<HCX> HashStable<HCX> for OngoingModuleCodegen {
pub(crate) struct OngoingCodegen {
modules: Vec<OngoingModuleCodegen>,
allocator_module: Option<CompiledModule>,
metadata_module: Option<CompiledModule>,
metadata: EncodedMetadata,
crate_info: CrateInfo,
concurrency_limiter: ConcurrencyLimiter,
}
@ -134,8 +130,6 @@ impl OngoingCodegen {
let codegen_results = CodegenResults {
modules,
allocator_module: self.allocator_module,
metadata_module: self.metadata_module,
metadata: self.metadata,
crate_info: self.crate_info,
};
@ -646,42 +640,6 @@ fn module_codegen(
}))
}
fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> CompiledModule {
use rustc_middle::mir::mono::CodegenUnitNameBuilder;
let _timer = tcx.sess.timer("write compressed metadata");
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
let metadata_cgu_name = cgu_name_builder
.build_cgu_name(LOCAL_CRATE, ["crate"], Some("metadata"))
.as_str()
.to_string();
let tmp_file = tcx.output_filenames(()).temp_path_for_cgu(
OutputType::Metadata,
&metadata_cgu_name,
tcx.sess.invocation_temp.as_deref(),
);
let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx);
let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name);
if let Err(err) = std::fs::write(&tmp_file, obj) {
tcx.dcx().fatal(format!("error writing metadata object file: {}", err));
}
CompiledModule {
name: metadata_cgu_name,
kind: ModuleKind::Metadata,
object: Some(tmp_file),
dwarf_object: None,
bytecode: None,
assembly: None,
llvm_ir: None,
links_from_incr_cache: Vec::new(),
}
}
fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> {
let mut allocator_module = make_module(tcx.sess, "allocator_shim".to_string());
let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module);
@ -706,11 +664,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> {
}
}
pub(crate) fn run_aot(
tcx: TyCtxt<'_>,
metadata: EncodedMetadata,
need_metadata_module: bool,
) -> Box<OngoingCodegen> {
pub(crate) fn run_aot(tcx: TyCtxt<'_>) -> Box<OngoingCodegen> {
// FIXME handle `-Ctarget-cpu=native`
let target_cpu = match tcx.sess.opts.cg.target_cpu {
Some(ref name) => name,
@ -726,8 +680,6 @@ pub(crate) fn run_aot(
return Box::new(OngoingCodegen {
modules: vec![],
allocator_module: None,
metadata_module: None,
metadata,
crate_info: CrateInfo::new(tcx, target_cpu),
concurrency_limiter: ConcurrencyLimiter::new(0),
});
@ -787,14 +739,9 @@ pub(crate) fn run_aot(
let allocator_module = emit_allocator_module(tcx);
let metadata_module =
if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None };
Box::new(OngoingCodegen {
modules,
allocator_module,
metadata_module,
metadata,
crate_info: CrateInfo::new(tcx, target_cpu),
concurrency_limiter: concurrency_limiter.0,
})

View file

@ -46,7 +46,6 @@ use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::settings::{self, Configurable};
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::{CodegenResults, TargetConfig};
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_session::Session;
use rustc_session::config::OutputFilenames;
@ -238,12 +237,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
println!("Cranelift version: {}", cranelift_codegen::VERSION);
}
fn codegen_crate(
&self,
tcx: TyCtxt<'_>,
metadata: EncodedMetadata,
need_metadata_module: bool,
) -> Box<dyn Any> {
fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
info!("codegen crate {}", tcx.crate_name(LOCAL_CRATE));
let config = self.config.clone().unwrap_or_else(|| {
BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
@ -256,7 +250,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
#[cfg(not(feature = "jit"))]
tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
} else {
driver::aot::run_aot(tcx, metadata, need_metadata_module)
driver::aot::run_aot(tcx)
}
}

View file

@ -30,7 +30,7 @@ use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_target::callconv::FnAbi;
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, WasmCAbi, X86Abi};
use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi};
use crate::common::{SignType, TypeReflection, type_is_pointer};
use crate::context::CodegenCx;
@ -2394,12 +2394,6 @@ impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> {
}
}
impl<'tcx> HasWasmCAbiOpt for Builder<'_, '_, 'tcx> {
fn wasm_c_abi_opt(&self) -> WasmCAbi {
self.cx.wasm_c_abi_opt()
}
}
impl<'tcx> HasX86AbiOpt for Builder<'_, '_, 'tcx> {
fn x86_abi_opt(&self) -> X86Abi {
self.cx.x86_abi_opt()

View file

@ -19,9 +19,7 @@ use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::source_map::respan;
use rustc_span::{DUMMY_SP, Span};
use rustc_target::spec::{
HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi,
};
use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi};
#[cfg(feature = "master")]
use crate::abi::conv_to_fn_attribute;
@ -512,12 +510,6 @@ impl<'gcc, 'tcx> HasTargetSpec for CodegenCx<'gcc, 'tcx> {
}
}
impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> {
fn wasm_c_abi_opt(&self) -> WasmCAbi {
self.tcx.sess.opts.unstable_opts.wasm_c_abi
}
}
impl<'gcc, 'tcx> HasX86AbiOpt for CodegenCx<'gcc, 'tcx> {
fn x86_abi_opt(&self) -> X86Abi {
X86Abi {

View file

@ -48,7 +48,6 @@ extern crate rustc_index;
#[cfg(feature = "master")]
extern crate rustc_interface;
extern crate rustc_macros;
extern crate rustc_metadata;
extern crate rustc_middle;
extern crate rustc_session;
extern crate rustc_span;
@ -106,7 +105,6 @@ use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetCon
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::IntoDynSyncSend;
use rustc_errors::DiagCtxtHandle;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt;
use rustc_middle::util::Providers;
@ -230,20 +228,9 @@ impl CodegenBackend for GccCodegenBackend {
providers.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess, true)
}
fn codegen_crate(
&self,
tcx: TyCtxt<'_>,
metadata: EncodedMetadata,
need_metadata_module: bool,
) -> Box<dyn Any> {
fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
let target_cpu = target_cpu(tcx.sess);
let res = codegen_crate(
self.clone(),
tcx,
target_cpu.to_string(),
metadata,
need_metadata_module,
);
let res = codegen_crate(self.clone(), tcx, target_cpu.to_string());
Box::new(res)
}

View file

@ -1021,6 +1021,15 @@ fn llvm_fixup_input<'ll, 'tcx>(
) if element.primitive() == Primitive::Float(Float::F16) => {
bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
}
(LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
if s.primitive() == Primitive::Float(Float::F16) =>
{
// Smaller floats are always "NaN-boxed" inside larger floats on LoongArch.
let value = bx.bitcast(value, bx.type_i16());
let value = bx.zext(value, bx.type_i32());
let value = bx.or(value, bx.const_u32(0xFFFF_0000));
bx.bitcast(value, bx.type_f32())
}
(Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
match s.primitive() {
// MIPS only supports register-length arithmetics.
@ -1178,6 +1187,13 @@ fn llvm_fixup_output<'ll, 'tcx>(
) if element.primitive() == Primitive::Float(Float::F16) => {
bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
}
(LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
if s.primitive() == Primitive::Float(Float::F16) =>
{
let value = bx.bitcast(value, bx.type_i32());
let value = bx.trunc(value, bx.type_i16());
bx.bitcast(value, bx.type_f16())
}
(Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
match s.primitive() {
// MIPS only supports register-length arithmetics.
@ -1318,6 +1334,11 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
) if element.primitive() == Primitive::Float(Float::F16) => {
cx.type_vector(cx.type_i16(), count)
}
(LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
if s.primitive() == Primitive::Float(Float::F16) =>
{
cx.type_f32()
}
(Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
match s.primitive() {
// MIPS only supports register-length arithmetics.

View file

@ -340,18 +340,11 @@ impl CodegenBackend for LlvmCodegenBackend {
target_config(sess)
}
fn codegen_crate<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
metadata: EncodedMetadata,
need_metadata_module: bool,
) -> Box<dyn Any> {
fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box<dyn Any> {
Box::new(rustc_codegen_ssa::base::codegen_crate(
LlvmCodegenBackend(()),
tcx,
crate::llvm_util::target_cpu(tcx.sess).to_string(),
metadata,
need_metadata_module,
))
}
@ -376,14 +369,20 @@ impl CodegenBackend for LlvmCodegenBackend {
(codegen_results, work_products)
}
fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) {
fn link(
&self,
sess: &Session,
codegen_results: CodegenResults,
metadata: EncodedMetadata,
outputs: &OutputFilenames,
) {
use rustc_codegen_ssa::back::link::link_binary;
use crate::back::archive::LlvmArchiveBuilderBuilder;
// 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, outputs);
link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, metadata, outputs);
}
}

View file

@ -198,8 +198,6 @@ codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status
codegen_ssa_malformed_cgu_name =
found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error}
codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
codegen_ssa_missing_features = add the missing features in a `target_feature` attribute

View file

@ -14,11 +14,12 @@ use object::read::macho::FatArch;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::memmap::Mmap;
use rustc_fs_util::TempDirBuilder;
use rustc_metadata::EncodedMetadata;
use rustc_session::Session;
use rustc_span::Symbol;
use tracing::trace;
use super::metadata::search_for_section;
use super::metadata::{create_compressed_metadata_file, search_for_section};
use crate::common;
// Re-exporting for rustc_codegen_llvm::back::archive
pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
@ -58,6 +59,15 @@ impl From<ImportLibraryItem> for COFFShortExport {
pub trait ArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
fn create_dylib_metadata_wrapper(
&self,
sess: &Session,
metadata: &EncodedMetadata,
symbol_name: &str,
) -> Vec<u8> {
create_compressed_metadata_file(sess, metadata, symbol_name)
}
/// Creates a DLL Import Library <https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation#creating-an-import-library>.
/// and returns the path on disk to that import library.
/// This functions doesn't take `self` so that it can be called from

View file

@ -23,7 +23,8 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_macros::LintDiagnostic;
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
use rustc_metadata::{
NativeLibSearchFallback, find_native_static_library, walk_native_lib_search_dirs,
EncodedMetadata, NativeLibSearchFallback, find_native_static_library,
walk_native_lib_search_dirs,
};
use rustc_middle::bug;
use rustc_middle::lint::lint_level;
@ -91,6 +92,7 @@ pub fn link_binary(
sess: &Session,
archive_builder_builder: &dyn ArchiveBuilderBuilder,
codegen_results: CodegenResults,
metadata: EncodedMetadata,
outputs: &OutputFilenames,
) {
let _timer = sess.timer("link_binary");
@ -142,6 +144,7 @@ pub fn link_binary(
sess,
archive_builder_builder,
&codegen_results,
&metadata,
RlibFlavor::Normal,
&path,
)
@ -152,6 +155,7 @@ pub fn link_binary(
sess,
archive_builder_builder,
&codegen_results,
&metadata,
&out_filename,
&path,
);
@ -163,6 +167,7 @@ pub fn link_binary(
crate_type,
&out_filename,
&codegen_results,
&metadata,
path.as_ref(),
);
}
@ -226,11 +231,7 @@ pub fn link_binary(
let remove_temps_from_module =
|module: &CompiledModule| maybe_remove_temps_from_module(false, false, module);
// Otherwise, always remove the metadata and allocator module temporaries.
if let Some(ref metadata_module) = codegen_results.metadata_module {
remove_temps_from_module(metadata_module);
}
// Otherwise, always remove the allocator module temporaries.
if let Some(ref allocator_module) = codegen_results.allocator_module {
remove_temps_from_module(allocator_module);
}
@ -312,6 +313,7 @@ fn link_rlib<'a>(
sess: &'a Session,
archive_builder_builder: &dyn ArchiveBuilderBuilder,
codegen_results: &CodegenResults,
metadata: &EncodedMetadata,
flavor: RlibFlavor,
tmpdir: &MaybeTempDir,
) -> Box<dyn ArchiveBuilder + 'a> {
@ -319,12 +321,9 @@ fn link_rlib<'a>(
let trailing_metadata = match flavor {
RlibFlavor::Normal => {
let (metadata, metadata_position) = create_wrapper_file(
sess,
".rmeta".to_string(),
codegen_results.metadata.stub_or_full(),
);
let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME);
let (metadata, metadata_position) =
create_wrapper_file(sess, ".rmeta".to_string(), metadata.stub_or_full());
let metadata = emit_wrapper_file(sess, &metadata, tmpdir.as_ref(), METADATA_FILENAME);
match metadata_position {
MetadataPosition::First => {
// Most of the time metadata in rlib files is wrapped in a "dummy" object
@ -392,7 +391,7 @@ fn link_rlib<'a>(
let src = read(path)
.unwrap_or_else(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e }));
let (data, _) = create_wrapper_file(sess, ".bundled_lib".to_string(), &src);
let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str());
let wrapper_file = emit_wrapper_file(sess, &data, tmpdir.as_ref(), filename.as_str());
packed_bundled_libs.push(wrapper_file);
} else {
let path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess);
@ -473,6 +472,7 @@ fn link_staticlib(
sess: &Session,
archive_builder_builder: &dyn ArchiveBuilderBuilder,
codegen_results: &CodegenResults,
metadata: &EncodedMetadata,
out_filename: &Path,
tempdir: &MaybeTempDir,
) {
@ -481,6 +481,7 @@ fn link_staticlib(
sess,
archive_builder_builder,
codegen_results,
metadata,
RlibFlavor::StaticlibBase,
tempdir,
);
@ -694,6 +695,7 @@ fn link_natively(
crate_type: CrateType,
out_filename: &Path,
codegen_results: &CodegenResults,
metadata: &EncodedMetadata,
tmpdir: &Path,
) {
info!("preparing {:?} to {:?}", crate_type, out_filename);
@ -718,6 +720,7 @@ fn link_natively(
tmpdir,
temp_filename,
codegen_results,
metadata,
self_contained_components,
);
@ -2095,17 +2098,25 @@ fn add_local_crate_allocator_objects(cmd: &mut dyn Linker, codegen_results: &Cod
/// Add object files containing metadata for the current crate.
fn add_local_crate_metadata_objects(
cmd: &mut dyn Linker,
sess: &Session,
archive_builder_builder: &dyn ArchiveBuilderBuilder,
crate_type: CrateType,
tmpdir: &Path,
codegen_results: &CodegenResults,
metadata: &EncodedMetadata,
) {
// When linking a dynamic library, we put the metadata into a section of the
// executable. This metadata is in a separate object file from the main
// object file, so we link that in here.
if matches!(crate_type, CrateType::Dylib | CrateType::ProcMacro)
&& let Some(m) = &codegen_results.metadata_module
&& let Some(obj) = &m.object
{
cmd.add_object(obj);
// object file, so we create and link it in here.
if matches!(crate_type, CrateType::Dylib | CrateType::ProcMacro) {
let data = archive_builder_builder.create_dylib_metadata_wrapper(
sess,
&metadata,
&codegen_results.crate_info.metadata_symbol,
);
let obj = emit_wrapper_file(sess, &data, tmpdir, "rmeta.o");
cmd.add_object(&obj);
}
}
@ -2195,6 +2206,7 @@ fn linker_with_args(
tmpdir: &Path,
out_filename: &Path,
codegen_results: &CodegenResults,
metadata: &EncodedMetadata,
self_contained_components: LinkSelfContainedComponents,
) -> Command {
let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled();
@ -2269,7 +2281,15 @@ fn linker_with_args(
// in this DAG so far because they can only depend on other native libraries
// and such dependencies are also required to be specified.
add_local_crate_regular_objects(cmd, codegen_results);
add_local_crate_metadata_objects(cmd, crate_type, codegen_results);
add_local_crate_metadata_objects(
cmd,
sess,
archive_builder_builder,
crate_type,
tmpdir,
codegen_results,
metadata,
);
add_local_crate_allocator_objects(cmd, codegen_results);
// Avoid linking to dynamic libraries unless they satisfy some undefined symbols

View file

@ -24,7 +24,6 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_incremental::{
copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess,
};
use rustc_metadata::EncodedMetadata;
use rustc_metadata::fs::copy_to_stdout;
use rustc_middle::bug;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@ -142,7 +141,6 @@ impl ModuleConfig {
|| match kind {
ModuleKind::Regular => sess.opts.output_types.contains_key(&OutputType::Object),
ModuleKind::Allocator => false,
ModuleKind::Metadata => sess.opts.output_types.contains_key(&OutputType::Metadata),
};
let emit_obj = if !should_emit_obj {
@ -350,7 +348,6 @@ pub struct CodegenContext<B: WriteBackendMethods> {
pub output_filenames: Arc<OutputFilenames>,
pub invocation_temp: Option<String>,
pub regular_module_config: Arc<ModuleConfig>,
pub metadata_module_config: Arc<ModuleConfig>,
pub allocator_module_config: Arc<ModuleConfig>,
pub tm_factory: TargetMachineFactoryFn<B>,
pub msvc_imps_needed: bool,
@ -395,7 +392,6 @@ impl<B: WriteBackendMethods> CodegenContext<B> {
pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {
match kind {
ModuleKind::Regular => &self.regular_module_config,
ModuleKind::Metadata => &self.metadata_module_config,
ModuleKind::Allocator => &self.allocator_module_config,
}
}
@ -474,8 +470,6 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
backend: B,
tcx: TyCtxt<'_>,
target_cpu: String,
metadata: EncodedMetadata,
metadata_module: Option<CompiledModule>,
) -> OngoingCodegen<B> {
let (coordinator_send, coordinator_receive) = channel();
@ -485,7 +479,6 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
let crate_info = CrateInfo::new(tcx, target_cpu);
let regular_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
let metadata_config = ModuleConfig::new(ModuleKind::Metadata, tcx, no_builtins);
let allocator_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);
let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
@ -499,15 +492,12 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
codegen_worker_send,
coordinator_receive,
Arc::new(regular_config),
Arc::new(metadata_config),
Arc::new(allocator_config),
coordinator_send.clone(),
);
OngoingCodegen {
backend,
metadata,
metadata_module,
crate_info,
codegen_worker_receive,
@ -843,12 +833,6 @@ pub(crate) fn compute_per_cgu_lto_type(
sess_crate_types: &[CrateType],
module_kind: ModuleKind,
) -> ComputedLtoType {
// Metadata modules never participate in LTO regardless of the lto
// settings.
if module_kind == ModuleKind::Metadata {
return ComputedLtoType::No;
}
// If the linker does LTO, we don't have to do it. Note that we
// keep doing full LTO, if it is requested, as not to break the
// assumption that the output will be a single module.
@ -1029,10 +1013,7 @@ fn finish_intra_module_work<B: ExtraBackendMethods>(
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
if !cgcx.opts.unstable_opts.combine_cgu
|| module.kind == ModuleKind::Metadata
|| module.kind == ModuleKind::Allocator
{
if !cgcx.opts.unstable_opts.combine_cgu || module.kind == ModuleKind::Allocator {
let module = B::codegen(cgcx, dcx, module, module_config)?;
Ok(WorkItemResult::Finished(module))
} else {
@ -1123,7 +1104,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
codegen_worker_send: Sender<CguMessage>,
coordinator_receive: Receiver<Box<dyn Any + Send>>,
regular_config: Arc<ModuleConfig>,
metadata_config: Arc<ModuleConfig>,
allocator_config: Arc<ModuleConfig>,
tx_to_llvm_workers: Sender<Box<dyn Any + Send>>,
) -> thread::JoinHandle<Result<CompiledModules, ()>> {
@ -1216,7 +1196,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
diag_emitter: shared_emitter.clone(),
output_filenames: Arc::clone(tcx.output_filenames(())),
regular_module_config: regular_config,
metadata_module_config: metadata_config,
allocator_module_config: allocator_config,
tm_factory: backend.target_machine_factory(tcx.sess, ol, backend_features),
msvc_imps_needed: msvc_imps_needed(tcx),
@ -1673,7 +1652,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
assert!(compiled_allocator_module.is_none());
compiled_allocator_module = Some(compiled_module);
}
ModuleKind::Metadata => bug!("Should be handled separately"),
}
}
Ok(WorkItemResult::NeedsLink(module)) => {
@ -2055,8 +2033,6 @@ impl<B: ExtraBackendMethods> Drop for Coordinator<B> {
pub struct OngoingCodegen<B: ExtraBackendMethods> {
pub backend: B,
pub metadata: EncodedMetadata,
pub metadata_module: Option<CompiledModule>,
pub crate_info: CrateInfo,
pub codegen_worker_receive: Receiver<CguMessage>,
pub shared_emitter_main: SharedEmitterMain,
@ -2096,12 +2072,10 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
(
CodegenResults {
metadata: self.metadata,
crate_info: self.crate_info,
modules: compiled_modules.modules,
allocator_module: compiled_modules.allocator_module,
metadata_module: self.metadata_module,
},
work_products,
)

View file

@ -15,11 +15,10 @@ use rustc_data_structures::unord::UnordMap;
use rustc_hir::ItemId;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
use rustc_metadata::EncodedMetadata;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_middle::middle::{exported_symbols, lang_items};
use rustc_middle::middle::exported_symbols::{self, SymbolExportKind};
use rustc_middle::middle::lang_items;
use rustc_middle::mir::BinOp;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions};
@ -28,7 +27,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::Session;
use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
use rustc_session::config::{self, CrateType, EntryFnType};
use rustc_span::{DUMMY_SP, Symbol, sym};
use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
@ -37,7 +36,6 @@ use tracing::{debug, info};
use crate::assert_module_sources::CguReuse;
use crate::back::link::are_upstream_rust_objects_already_included;
use crate::back::metadata::create_compressed_metadata_file;
use crate::back::write::{
ComputedLtoType, OngoingCodegen, compute_per_cgu_lto_type, start_async_codegen,
submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm,
@ -48,8 +46,7 @@ use crate::mir::operand::OperandValue;
use crate::mir::place::PlaceRef;
use crate::traits::*;
use crate::{
CachedModuleCodegen, CodegenLintLevels, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
errors, meth, mir,
CachedModuleCodegen, CodegenLintLevels, CrateInfo, ModuleCodegen, ModuleKind, errors, meth, mir,
};
pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
@ -669,12 +666,10 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
backend: B,
tcx: TyCtxt<'_>,
target_cpu: String,
metadata: EncodedMetadata,
need_metadata_module: bool,
) -> OngoingCodegen<B> {
// Skip crate items and just output metadata in -Z no-codegen mode.
if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None);
let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu);
ongoing_codegen.codegen_finished(tcx);
@ -707,39 +702,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
}
}
let metadata_module = need_metadata_module.then(|| {
// Emit compressed metadata object.
let metadata_cgu_name =
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
tcx.sess.time("write_compressed_metadata", || {
let file_name = tcx.output_filenames(()).temp_path_for_cgu(
OutputType::Metadata,
&metadata_cgu_name,
tcx.sess.invocation_temp.as_deref(),
);
let data = create_compressed_metadata_file(
tcx.sess,
&metadata,
&exported_symbols::metadata_symbol_name(tcx),
);
if let Err(error) = std::fs::write(&file_name, data) {
tcx.dcx().emit_fatal(errors::MetadataObjectFileWrite { error });
}
CompiledModule {
name: metadata_cgu_name,
kind: ModuleKind::Metadata,
object: Some(file_name),
dwarf_object: None,
bytecode: None,
assembly: None,
llvm_ir: None,
links_from_incr_cache: Vec::new(),
}
})
});
let ongoing_codegen =
start_async_codegen(backend.clone(), tcx, target_cpu, metadata, metadata_module);
let ongoing_codegen = start_async_codegen(backend.clone(), tcx, target_cpu);
// Codegen an allocator shim, if necessary.
if let Some(kind) = allocator_kind_for_codegen(tcx) {
@ -1010,6 +973,7 @@ impl CrateInfo {
windows_subsystem,
natvis_debugger_visualizers: Default::default(),
lint_levels: CodegenLintLevels::from_tcx(tcx),
metadata_symbol: exported_symbols::metadata_symbol_name(tcx),
};
info.native_libraries.reserve(n_crates);

View file

@ -777,12 +777,6 @@ pub(crate) struct MultipleMainFunctions {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_metadata_object_file_write)]
pub(crate) struct MetadataObjectFileWrite {
pub error: Error,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_invalid_windows_subsystem)]
pub(crate) struct InvalidWindowsSubsystem {

View file

@ -31,6 +31,7 @@ use rustc_data_structures::unord::UnordMap;
use rustc_hir::CRATE_HIR_ID;
use rustc_hir::def_id::CrateNum;
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::WorkProduct;
use rustc_middle::lint::LevelAndSource;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
@ -169,7 +170,6 @@ pub(crate) struct CachedModuleCodegen {
#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable)]
pub enum ModuleKind {
Regular,
Metadata,
Allocator,
}
@ -233,6 +233,7 @@ pub struct CrateInfo {
pub windows_subsystem: Option<String>,
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
pub lint_levels: CodegenLintLevels,
pub metadata_symbol: String,
}
/// Target-specific options that get set in `cfg(...)`.
@ -257,8 +258,6 @@ pub struct TargetConfig {
pub struct CodegenResults {
pub modules: Vec<CompiledModule>,
pub allocator_module: Option<CompiledModule>,
pub metadata_module: Option<CompiledModule>,
pub metadata: rustc_metadata::EncodedMetadata,
pub crate_info: CrateInfo,
}
@ -303,6 +302,7 @@ impl CodegenResults {
sess: &Session,
rlink_file: &Path,
codegen_results: &CodegenResults,
metadata: &EncodedMetadata,
outputs: &OutputFilenames,
) -> Result<usize, io::Error> {
let mut encoder = FileEncoder::new(rlink_file)?;
@ -312,6 +312,7 @@ impl CodegenResults {
encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
encoder.emit_str(sess.cfg_version);
Encodable::encode(codegen_results, &mut encoder);
Encodable::encode(metadata, &mut encoder);
Encodable::encode(outputs, &mut encoder);
encoder.finish().map_err(|(_path, err)| err)
}
@ -319,7 +320,7 @@ impl CodegenResults {
pub fn deserialize_rlink(
sess: &Session,
data: Vec<u8>,
) -> Result<(Self, OutputFilenames), CodegenErrors> {
) -> Result<(Self, EncodedMetadata, OutputFilenames), CodegenErrors> {
// The Decodable machinery is not used here because it panics if the input data is invalid
// and because its internal representation may change.
if !data.starts_with(RLINK_MAGIC) {
@ -350,8 +351,9 @@ impl CodegenResults {
}
let codegen_results = CodegenResults::decode(&mut decoder);
let metadata = EncodedMetadata::decode(&mut decoder);
let outputs = OutputFilenames::decode(&mut decoder);
Ok((codegen_results, outputs))
Ok((codegen_results, metadata, outputs))
}
}

View file

@ -1,14 +1,13 @@
use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
use rustc_attr_data_structures::InstructionSetAttr;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::mono::{Linkage, MonoItemData, Visibility};
use rustc_middle::mir::{InlineAsmOperand, START_BLOCK};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug, ty};
use rustc_middle::{bug, ty};
use rustc_span::sym;
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
use rustc_target::spec::{BinaryFormat, WasmCAbi};
use rustc_target::spec::BinaryFormat;
use crate::common;
use crate::mir::AsmCodegenMethods;
@ -287,12 +286,7 @@ fn prefix_and_suffix<'tcx>(
writeln!(begin, "{}", arch_prefix).unwrap();
}
writeln!(begin, "{asm_name}:").unwrap();
writeln!(
begin,
".functype {asm_name} {}",
wasm_functype(tcx, fn_abi, instance.def_id())
)
.unwrap();
writeln!(begin, ".functype {asm_name} {}", wasm_functype(tcx, fn_abi)).unwrap();
writeln!(end).unwrap();
// .size is ignored for function symbols, so we can skip it
@ -333,7 +327,7 @@ fn prefix_and_suffix<'tcx>(
/// The webassembly type signature for the given function.
///
/// Used by the `.functype` directive on wasm targets.
fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id: DefId) -> String {
fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String {
let mut signature = String::with_capacity(64);
let ptr_type = match tcx.data_layout.pointer_size.bits() {
@ -342,17 +336,6 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
other => bug!("wasm pointer size cannot be {other} bits"),
};
// FIXME: remove this once the wasm32-unknown-unknown ABI is fixed
// please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs`
// basically the commit introducing this comment should be reverted
if let PassMode::Pair { .. } = fn_abi.ret.mode {
let _ = WasmCAbi::Legacy { with_lint: true };
span_bug!(
tcx.def_span(def_id),
"cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
);
}
let hidden_return = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
signature.push('(');
@ -366,7 +349,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
let mut it = fn_abi.args.iter().peekable();
while let Some(arg_abi) = it.next() {
wasm_type(tcx, &mut signature, arg_abi, ptr_type, def_id);
wasm_type(&mut signature, arg_abi, ptr_type);
if it.peek().is_some() {
signature.push_str(", ");
}
@ -375,7 +358,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
signature.push_str(") -> (");
if !hidden_return {
wasm_type(tcx, &mut signature, &fn_abi.ret, ptr_type, def_id);
wasm_type(&mut signature, &fn_abi.ret, ptr_type);
}
signature.push(')');
@ -383,27 +366,13 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
signature
}
fn wasm_type<'tcx>(
tcx: TyCtxt<'tcx>,
signature: &mut String,
arg_abi: &ArgAbi<'_, Ty<'tcx>>,
ptr_type: &'static str,
def_id: DefId,
) {
fn wasm_type<'tcx>(signature: &mut String, arg_abi: &ArgAbi<'_, Ty<'tcx>>, ptr_type: &'static str) {
match arg_abi.mode {
PassMode::Ignore => { /* do nothing */ }
PassMode::Direct(_) => {
let direct_type = match arg_abi.layout.backend_repr {
BackendRepr::Scalar(scalar) => wasm_primitive(scalar.primitive(), ptr_type),
BackendRepr::SimdVector { .. } => "v128",
BackendRepr::Memory { .. } => {
// FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed
let _ = WasmCAbi::Legacy { with_lint: true };
span_bug!(
tcx.def_span(def_id),
"cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
);
}
other => unreachable!("unexpected BackendRepr: {:?}", other),
};

View file

@ -74,12 +74,7 @@ pub trait CodegenBackend {
fn provide(&self, _providers: &mut Providers) {}
fn codegen_crate<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
metadata: EncodedMetadata,
need_metadata_module: bool,
) -> Box<dyn Any>;
fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box<dyn Any>;
/// This is called on the returned `Box<dyn Any>` from [`codegen_crate`](Self::codegen_crate)
///
@ -94,8 +89,14 @@ pub trait CodegenBackend {
) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>);
/// This is called on the returned [`CodegenResults`] from [`join_codegen`](Self::join_codegen).
fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) {
link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, outputs);
fn link(
&self,
sess: &Session,
codegen_results: CodegenResults,
metadata: EncodedMetadata,
outputs: &OutputFilenames,
) {
link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, metadata, outputs);
}
}

View file

@ -557,27 +557,34 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) {
let rlink_data = fs::read(file).unwrap_or_else(|err| {
dcx.emit_fatal(RlinkUnableToRead { err });
});
let (codegen_results, outputs) = match CodegenResults::deserialize_rlink(sess, rlink_data) {
Ok((codegen, outputs)) => (codegen, outputs),
Err(err) => {
match err {
CodegenErrors::WrongFileType => dcx.emit_fatal(RLinkWrongFileType),
CodegenErrors::EmptyVersionNumber => dcx.emit_fatal(RLinkEmptyVersionNumber),
CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => dcx
.emit_fatal(RLinkEncodingVersionMismatch { version_array, rlink_version }),
CodegenErrors::RustcVersionMismatch { rustc_version } => {
dcx.emit_fatal(RLinkRustcVersionMismatch {
rustc_version,
current_version: sess.cfg_version,
})
}
CodegenErrors::CorruptFile => {
dcx.emit_fatal(RlinkCorruptFile { file });
}
};
}
};
compiler.codegen_backend.link(sess, codegen_results, &outputs);
let (codegen_results, metadata, outputs) =
match CodegenResults::deserialize_rlink(sess, rlink_data) {
Ok((codegen, metadata, outputs)) => (codegen, metadata, outputs),
Err(err) => {
match err {
CodegenErrors::WrongFileType => dcx.emit_fatal(RLinkWrongFileType),
CodegenErrors::EmptyVersionNumber => {
dcx.emit_fatal(RLinkEmptyVersionNumber)
}
CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
dcx.emit_fatal(RLinkEncodingVersionMismatch {
version_array,
rlink_version,
})
}
CodegenErrors::RustcVersionMismatch { rustc_version } => {
dcx.emit_fatal(RLinkRustcVersionMismatch {
rustc_version,
current_version: sess.cfg_version,
})
}
CodegenErrors::CorruptFile => {
dcx.emit_fatal(RlinkCorruptFile { file });
}
};
}
};
compiler.codegen_backend.link(sess, codegen_results, metadata, &outputs);
} else {
dcx.emit_fatal(RlinkNotAFile {});
}

View file

@ -2285,12 +2285,23 @@ pub struct Expr<'hir> {
}
impl Expr<'_> {
pub fn precedence(&self) -> ExprPrecedence {
pub fn precedence(
&self,
for_each_attr: &dyn Fn(HirId, &mut dyn FnMut(&Attribute)),
) -> ExprPrecedence {
let prefix_attrs_precedence = || -> ExprPrecedence {
let mut has_outer_attr = false;
for_each_attr(self.hir_id, &mut |attr: &Attribute| {
has_outer_attr |= matches!(attr.style(), AttrStyle::Outer)
});
if has_outer_attr { ExprPrecedence::Prefix } else { ExprPrecedence::Unambiguous }
};
match &self.kind {
ExprKind::Closure(closure) => {
match closure.fn_decl.output {
FnRetTy::DefaultReturn(_) => ExprPrecedence::Jump,
FnRetTy::Return(_) => ExprPrecedence::Unambiguous,
FnRetTy::Return(_) => prefix_attrs_precedence(),
}
}
@ -2315,7 +2326,7 @@ impl Expr<'_> {
| ExprKind::Let(..)
| ExprKind::Unary(..) => ExprPrecedence::Prefix,
// Never need parens
// Need parens if and only if there are prefix attributes.
ExprKind::Array(_)
| ExprKind::Block(..)
| ExprKind::Call(..)
@ -2337,9 +2348,9 @@ impl Expr<'_> {
| ExprKind::Type(..)
| ExprKind::UnsafeBinderCast(..)
| ExprKind::Use(..)
| ExprKind::Err(_) => ExprPrecedence::Unambiguous,
| ExprKind::Err(_) => prefix_attrs_precedence(),
ExprKind::DropTemps(expr, ..) => expr.precedence(),
ExprKind::DropTemps(expr, ..) => expr.precedence(for_each_attr),
}
}

View file

@ -80,6 +80,13 @@ impl<'a> State<'a> {
(self.attrs)(id)
}
fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
let for_each_attr = |id: HirId, callback: &mut dyn FnMut(&hir::Attribute)| {
self.attrs(id).iter().for_each(callback);
};
expr.precedence(&for_each_attr)
}
fn print_attrs_as_inner(&mut self, attrs: &[hir::Attribute]) {
self.print_either_attributes(attrs, ast::AttrStyle::Inner)
}
@ -1164,7 +1171,7 @@ impl<'a> State<'a> {
}
self.space();
self.word_space("=");
let npals = || parser::needs_par_as_let_scrutinee(init.precedence());
let npals = || parser::needs_par_as_let_scrutinee(self.precedence(init));
self.print_expr_cond_paren(init, Self::cond_needs_par(init) || npals())
}
@ -1265,7 +1272,7 @@ impl<'a> State<'a> {
fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
let needs_paren = match func.kind {
hir::ExprKind::Field(..) => true,
_ => func.precedence() < ExprPrecedence::Unambiguous,
_ => self.precedence(func) < ExprPrecedence::Unambiguous,
};
self.print_expr_cond_paren(func, needs_paren);
@ -1279,7 +1286,10 @@ impl<'a> State<'a> {
args: &[hir::Expr<'_>],
) {
let base_args = args;
self.print_expr_cond_paren(receiver, receiver.precedence() < ExprPrecedence::Unambiguous);
self.print_expr_cond_paren(
receiver,
self.precedence(receiver) < ExprPrecedence::Unambiguous,
);
self.word(".");
self.print_ident(segment.ident);
@ -1293,8 +1303,8 @@ impl<'a> State<'a> {
fn print_expr_binary(&mut self, op: hir::BinOpKind, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
let binop_prec = op.precedence();
let left_prec = lhs.precedence();
let right_prec = rhs.precedence();
let left_prec = self.precedence(lhs);
let right_prec = self.precedence(rhs);
let (mut left_needs_paren, right_needs_paren) = match op.fixity() {
Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
@ -1323,7 +1333,7 @@ impl<'a> State<'a> {
fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) {
self.word(op.as_str());
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Prefix);
}
fn print_expr_addr_of(
@ -1340,7 +1350,7 @@ impl<'a> State<'a> {
self.print_mutability(mutability, true);
}
}
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Prefix);
}
fn print_literal(&mut self, lit: &hir::Lit) {
@ -1483,7 +1493,7 @@ impl<'a> State<'a> {
self.print_literal(lit);
}
hir::ExprKind::Cast(expr, ty) => {
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Cast);
self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Cast);
self.space();
self.word_space("as");
self.print_type(ty);
@ -1580,24 +1590,30 @@ impl<'a> State<'a> {
self.print_block(blk, cb, ib);
}
hir::ExprKind::Assign(lhs, rhs, _) => {
self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
self.print_expr_cond_paren(lhs, self.precedence(lhs) <= ExprPrecedence::Assign);
self.space();
self.word_space("=");
self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
self.print_expr_cond_paren(rhs, self.precedence(rhs) < ExprPrecedence::Assign);
}
hir::ExprKind::AssignOp(op, lhs, rhs) => {
self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
self.print_expr_cond_paren(lhs, self.precedence(lhs) <= ExprPrecedence::Assign);
self.space();
self.word_space(op.node.as_str());
self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
self.print_expr_cond_paren(rhs, self.precedence(rhs) < ExprPrecedence::Assign);
}
hir::ExprKind::Field(expr, ident) => {
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
self.print_expr_cond_paren(
expr,
self.precedence(expr) < ExprPrecedence::Unambiguous,
);
self.word(".");
self.print_ident(ident);
}
hir::ExprKind::Index(expr, index, _) => {
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
self.print_expr_cond_paren(
expr,
self.precedence(expr) < ExprPrecedence::Unambiguous,
);
self.word("[");
self.print_expr(index);
self.word("]");
@ -1611,7 +1627,7 @@ impl<'a> State<'a> {
}
if let Some(expr) = opt_expr {
self.space();
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Jump);
}
}
hir::ExprKind::Continue(destination) => {
@ -1625,13 +1641,13 @@ impl<'a> State<'a> {
self.word("return");
if let Some(expr) = result {
self.word(" ");
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Jump);
}
}
hir::ExprKind::Become(result) => {
self.word("become");
self.word(" ");
self.print_expr_cond_paren(result, result.precedence() < ExprPrecedence::Jump);
self.print_expr_cond_paren(result, self.precedence(result) < ExprPrecedence::Jump);
}
hir::ExprKind::InlineAsm(asm) => {
self.word("asm!");
@ -1669,7 +1685,7 @@ impl<'a> State<'a> {
}
hir::ExprKind::Yield(expr, _) => {
self.word_space("yield");
self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Jump);
}
hir::ExprKind::Err(_) => {
self.popen();

View file

@ -620,7 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
if let Ok(rest_snippet) = rest_snippet {
let sugg = if callee_expr.precedence() >= ExprPrecedence::Unambiguous {
let sugg = if self.precedence(callee_expr) >= ExprPrecedence::Unambiguous {
vec![
(up_to_rcvr_span, "".to_string()),
(rest_span, format!(".{}({rest_snippet}", segment.ident)),

View file

@ -1100,7 +1100,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
}
fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
let expr_prec = self.expr.precedence();
let expr_prec = fcx.precedence(self.expr);
let needs_parens = expr_prec < ExprPrecedence::Unambiguous;
let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize));

View file

@ -6,6 +6,7 @@
//! See [`rustc_hir_analysis::check`] for more context on type checking in general.
use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx};
use rustc_ast::util::parser::ExprPrecedence;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::unord::UnordMap;
@ -17,7 +18,7 @@ use rustc_errors::{
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, HirId, QPath};
use rustc_hir::{Attribute, ExprKind, HirId, QPath};
use rustc_hir_analysis::NoVariantNamed;
use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _};
use rustc_infer::infer;
@ -54,6 +55,30 @@ use crate::{
};
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(crate) fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
let for_each_attr = |id: HirId, callback: &mut dyn FnMut(&Attribute)| {
for attr in self.tcx.hir_attrs(id) {
// For the purpose of rendering suggestions, disregard attributes
// that originate from desugaring of any kind. For example, `x?`
// desugars to `#[allow(unreachable_code)] match ...`. Failing to
// ignore the prefix attribute in the desugaring would cause this
// suggestion:
//
// let y: u32 = x?.try_into().unwrap();
// ++++++++++++++++++++
//
// to be rendered as:
//
// let y: u32 = (x?).try_into().unwrap();
// + +++++++++++++++++++++
if attr.span().desugaring_kind().is_none() {
callback(attr);
}
}
};
expr.precedence(&for_each_attr)
}
/// Check an expr with an expectation type, and also demand that the expr's
/// evaluated type is a subtype of the expectation at the end. This is a
/// *hard* requirement.

View file

@ -399,7 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// so we remove the user's `clone` call.
{
vec![(receiver_method.ident.span, conversion_method_name.to_string())]
} else if expr.precedence() < ExprPrecedence::Unambiguous {
} else if self.precedence(expr) < ExprPrecedence::Unambiguous {
vec![
(expr.span.shrink_to_lo(), "(".to_string()),
(expr.span.shrink_to_hi(), format!(").{}()", conversion_method_name)),
@ -1395,7 +1395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
let mut sugg = if expr.precedence() >= ExprPrecedence::Unambiguous {
let mut sugg = if self.precedence(expr) >= ExprPrecedence::Unambiguous {
vec![(span.shrink_to_hi(), ".into()".to_owned())]
} else {
vec![
@ -3106,7 +3106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`",
);
let close_paren = if expr.precedence() < ExprPrecedence::Unambiguous {
let close_paren = if self.precedence(expr) < ExprPrecedence::Unambiguous {
sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
")"
} else {
@ -3131,7 +3131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let len = src.trim_end_matches(&checked_ty.to_string()).len();
span.with_lo(span.lo() + BytePos(len as u32))
},
if expr.precedence() < ExprPrecedence::Unambiguous {
if self.precedence(expr) < ExprPrecedence::Unambiguous {
// Readd `)`
format!("{expected_ty})")
} else {

View file

@ -18,6 +18,7 @@ use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap};
use rustc_hir::definitions::Definitions;
use rustc_incremental::setup_dep_graph;
use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store};
use rustc_metadata::EncodedMetadata;
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepsType;
@ -1174,7 +1175,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
pub(crate) fn start_codegen<'tcx>(
codegen_backend: &dyn CodegenBackend,
tcx: TyCtxt<'tcx>,
) -> Box<dyn Any> {
) -> (Box<dyn Any>, EncodedMetadata) {
// Hook for tests.
if let Some((def_id, _)) = tcx.entry_fn(())
&& tcx.has_attr(def_id, sym::rustc_delayed_bug_from_inside_query)
@ -1197,11 +1198,9 @@ pub(crate) fn start_codegen<'tcx>(
info!("Pre-codegen\n{:?}", tcx.debug_stats());
let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx);
let metadata = rustc_metadata::fs::encode_and_write_metadata(tcx);
let codegen = tcx.sess.time("codegen_crate", move || {
codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
});
let codegen = tcx.sess.time("codegen_crate", move || codegen_backend.codegen_crate(tcx));
info!("Post-codegen\n{:?}", tcx.debug_stats());
@ -1211,7 +1210,7 @@ pub(crate) fn start_codegen<'tcx>(
tcx.sess.code_stats.print_type_sizes();
}
codegen
(codegen, metadata)
}
/// Compute and validate the crate name.

View file

@ -5,6 +5,7 @@ use rustc_codegen_ssa::CodegenResults;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::svh::Svh;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::DepGraph;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
@ -18,6 +19,7 @@ pub struct Linker {
output_filenames: Arc<OutputFilenames>,
// Only present when incr. comp. is enabled.
crate_hash: Option<Svh>,
metadata: EncodedMetadata,
ongoing_codegen: Box<dyn Any>,
}
@ -26,7 +28,7 @@ impl Linker {
tcx: TyCtxt<'_>,
codegen_backend: &dyn CodegenBackend,
) -> Linker {
let ongoing_codegen = passes::start_codegen(codegen_backend, tcx);
let (ongoing_codegen, metadata) = passes::start_codegen(codegen_backend, tcx);
Linker {
dep_graph: tcx.dep_graph.clone(),
@ -36,6 +38,7 @@ impl Linker {
} else {
None
},
metadata,
ongoing_codegen,
}
}
@ -75,6 +78,7 @@ impl Linker {
sess,
&rlink_file,
&codegen_results,
&self.metadata,
&*self.output_filenames,
)
.unwrap_or_else(|error| {
@ -84,6 +88,6 @@ impl Linker {
}
let _timer = sess.prof.verbose_generic_activity("link_crate");
codegen_backend.link(sess, codegen_results, &self.output_filenames)
codegen_backend.link(sess, codegen_results, self.metadata, &self.output_filenames)
}
}

View file

@ -27,7 +27,7 @@ use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
use rustc_span::{FileName, SourceFileHashAlgorithm, sym};
use rustc_target::spec::{
CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, WasmCAbi,
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel,
};
use crate::interface::{initialize_checked_jobserver, parse_cfg};
@ -882,7 +882,6 @@ fn test_unstable_options_tracking_hash() {
tracked!(verify_llvm_ir, true);
tracked!(virtual_function_elimination, true);
tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
tracked!(wasm_c_abi, WasmCAbi::Spec);
// tidy-alphabetical-end
macro_rules! tracked_no_crate_hash {

View file

@ -7,6 +7,7 @@ use std::cell::Cell;
use std::slice;
use rustc_ast::BindingMode;
use rustc_ast::util::parser::ExprPrecedence;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync;
use rustc_data_structures::unord::UnordMap;
@ -850,6 +851,20 @@ impl<'tcx> LateContext<'tcx> {
})
}
/// Returns the effective precedence of an expression for the purpose of
/// rendering diagnostic. This is not the same as the precedence that would
/// be used for pretty-printing HIR by rustc_hir_pretty.
pub fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
let for_each_attr = |id: hir::HirId, callback: &mut dyn FnMut(&hir::Attribute)| {
for attr in self.tcx.hir_attrs(id) {
if attr.span().desugaring_kind().is_none() {
callback(attr);
}
}
};
expr.precedence(&for_each_attr)
}
/// If the given expression is a local binding, find the initializer expression.
/// If that initializer expression is another local binding, find its initializer again.
///

View file

@ -623,6 +623,7 @@ fn register_builtins(store: &mut LintStore) {
"converted into hard error, \
see <https://github.com/rust-lang/rust/issues/40107> for more information",
);
store.register_removed("wasm_c_abi", "the wasm C ABI has been fixed");
}
fn register_internals(store: &mut LintStore) {

View file

@ -140,7 +140,6 @@ declare_lint_pass! {
UNUSED_VARIABLES,
USELESS_DEPRECATED,
WARNINGS,
WASM_C_ABI,
// tidy-alphabetical-end
]
}
@ -4100,6 +4099,7 @@ declare_lint! {
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(Edition::Edition2024),
reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>",
report_in_deps: true,
};
@edition Edition2024 => Deny;
report_in_external_macro
@ -4154,6 +4154,7 @@ declare_lint! {
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::EditionAndFutureReleaseError(Edition::Edition2024),
reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>",
report_in_deps: true,
};
report_in_external_macro
}
@ -4980,50 +4981,6 @@ declare_lint! {
crate_level_only
}
declare_lint! {
/// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected
/// by a planned ABI change that has the goal of aligning Rust with the standard C ABI
/// of this target.
///
/// ### Example
///
/// ```rust,ignore (needs wasm32-unknown-unknown)
/// #[repr(C)]
/// struct MyType(i32, i32);
///
/// extern "C" my_fun(x: MyType) {}
/// ```
///
/// This will produce:
///
/// ```text
/// error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType`
/// --> $DIR/wasm_c_abi_transition.rs:17:1
/// |
/// | pub extern "C" fn my_fun(_x: MyType) {}
/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/// |
/// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
/// = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
/// = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
/// ```
///
/// ### Explanation
///
/// Rust has historically implemented a non-spec-compliant C ABI on wasm32-unknown-unknown. This
/// has caused incompatibilities with other compilers and Wasm targets. In a future version
/// of Rust, this will be fixed, and therefore code relying on the non-spec-compliant C ABI will
/// stop functioning.
pub WASM_C_ABI,
Warn,
"detects code relying on rustc's non-spec-compliant wasm C ABI",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseError,
reference: "issue #138762 <https://github.com/rust-lang/rust/issues/138762>",
report_in_deps: true,
};
}
declare_lint! {
/// The `aarch64_softfloat_neon` lint detects usage of `#[target_feature(enable = "neon")]` on
/// softfloat aarch64 targets. Enabling this target feature causes LLVM to alter the ABI of

View file

@ -4,9 +4,9 @@ use std::{fs, io};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_fs_util::TempDirBuilder;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::config::{CrateType, OutFileName, OutputType};
use rustc_session::output::filename_for_metadata;
use rustc_session::{MetadataKind, Session};
use crate::errors::{
BinaryOutputToTty, FailedCopyToStdout, FailedCreateEncodedMetadata, FailedCreateFile,
@ -22,13 +22,8 @@ pub const METADATA_FILENAME: &str = "lib.rmeta";
/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
/// directory being searched for `extern crate` (observing an incomplete file).
/// The returned path is the temporary file containing the complete metadata.
pub fn emit_wrapper_file(
sess: &Session,
data: &[u8],
tmpdir: &MaybeTempDir,
name: &str,
) -> PathBuf {
let out_filename = tmpdir.as_ref().join(name);
pub fn emit_wrapper_file(sess: &Session, data: &[u8], tmpdir: &Path, name: &str) -> PathBuf {
let out_filename = tmpdir.join(name);
let result = fs::write(&out_filename, data);
if let Err(err) = result {
@ -38,7 +33,7 @@ pub fn emit_wrapper_file(
out_filename
}
pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
let out_filename = filename_for_metadata(tcx.sess, tcx.output_filenames(()));
// To avoid races with another rustc process scanning the output directory,
// we need to write the file somewhere else and atomically move it to its
@ -59,25 +54,20 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
None
};
// Always create a file at `metadata_filename`, even if we have nothing to write to it.
// This simplifies the creation of the output `out_filename` when requested.
let metadata_kind = tcx.metadata_kind();
match metadata_kind {
MetadataKind::None => {
std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_filename, err });
if tcx.needs_metadata() {
encode_metadata(tcx, &metadata_filename, metadata_stub_filename.as_deref());
} else {
// Always create a file at `metadata_filename`, even if we have nothing to write to it.
// This simplifies the creation of the output `out_filename` when requested.
std::fs::File::create(&metadata_filename).unwrap_or_else(|err| {
tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_filename, err });
});
if let Some(metadata_stub_filename) = &metadata_stub_filename {
std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| {
tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_stub_filename, err });
});
if let Some(metadata_stub_filename) = &metadata_stub_filename {
std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| {
tcx.dcx()
.emit_fatal(FailedCreateFile { filename: &metadata_stub_filename, err });
});
}
}
MetadataKind::Uncompressed | MetadataKind::Compressed => {
encode_metadata(tcx, &metadata_filename, metadata_stub_filename.as_deref())
}
};
}
let _prof_timer = tcx.sess.prof.generic_activity("write_crate_metadata");
@ -118,9 +108,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err });
});
let need_metadata_module = metadata_kind == MetadataKind::Compressed;
(metadata, need_metadata_module)
metadata
}
#[cfg(not(target_os = "linux"))]

View file

@ -47,7 +47,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_session::config::CrateType;
use rustc_session::cstore::{CrateStoreDyn, Untracked};
use rustc_session::lint::Lint;
use rustc_session::{Limit, MetadataKind, Session};
use rustc_session::{Limit, Session};
use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId};
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
use rustc_type_ir::TyKind::*;
@ -1858,23 +1858,14 @@ impl<'tcx> TyCtxt<'tcx> {
&self.crate_types
}
pub fn metadata_kind(self) -> MetadataKind {
self.crate_types()
.iter()
.map(|ty| match *ty {
CrateType::Executable
| CrateType::Staticlib
| CrateType::Cdylib
| CrateType::Sdylib => MetadataKind::None,
CrateType::Rlib => MetadataKind::Uncompressed,
CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed,
})
.max()
.unwrap_or(MetadataKind::None)
}
pub fn needs_metadata(self) -> bool {
self.metadata_kind() != MetadataKind::None
self.crate_types().iter().any(|ty| match *ty {
CrateType::Executable
| CrateType::Staticlib
| CrateType::Cdylib
| CrateType::Sdylib => false,
CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true,
})
}
pub fn needs_crate_hash(self) -> bool {

View file

@ -16,9 +16,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension};
use rustc_session::config::OptLevel;
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
use rustc_target::callconv::FnAbi;
use rustc_target::spec::{
HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, PanicStrategy, Target, WasmCAbi, X86Abi,
};
use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, PanicStrategy, Target, X86Abi};
use tracing::debug;
use {rustc_abi as abi, rustc_hir as hir};
@ -565,12 +563,6 @@ impl<'tcx> HasTargetSpec for TyCtxt<'tcx> {
}
}
impl<'tcx> HasWasmCAbiOpt for TyCtxt<'tcx> {
fn wasm_c_abi_opt(&self) -> WasmCAbi {
self.sess.opts.unstable_opts.wasm_c_abi
}
}
impl<'tcx> HasX86AbiOpt for TyCtxt<'tcx> {
fn x86_abi_opt(&self) -> X86Abi {
X86Abi {
@ -625,12 +617,6 @@ impl<'tcx> HasTargetSpec for LayoutCx<'tcx> {
}
}
impl<'tcx> HasWasmCAbiOpt for LayoutCx<'tcx> {
fn wasm_c_abi_opt(&self) -> WasmCAbi {
self.calc.cx.wasm_c_abi_opt()
}
}
impl<'tcx> HasX86AbiOpt for LayoutCx<'tcx> {
fn x86_abi_opt(&self) -> X86Abi {
self.calc.cx.x86_abi_opt()

View file

@ -132,6 +132,7 @@ fn build_poll_switch<'tcx>(
body: &mut Body<'tcx>,
poll_enum: Ty<'tcx>,
poll_unit_place: &Place<'tcx>,
fut_pin_place: &Place<'tcx>,
ready_block: BasicBlock,
yield_block: BasicBlock,
) -> BasicBlock {
@ -162,9 +163,11 @@ fn build_poll_switch<'tcx>(
Rvalue::Discriminant(*poll_unit_place),
))),
};
let storage_dead =
Statement { source_info, kind: StatementKind::StorageDead(fut_pin_place.local) };
let unreachable_block = insert_term_block(body, TerminatorKind::Unreachable);
body.basic_blocks_mut().push(BasicBlockData {
statements: [discr_assign].to_vec(),
statements: [storage_dead, discr_assign].to_vec(),
terminator: Some(Terminator {
source_info,
kind: TerminatorKind::SwitchInt {
@ -332,10 +335,17 @@ pub(super) fn expand_async_drops<'tcx>(
kind: StatementKind::Assign(Box::new((context_ref_place, arg))),
});
let yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield
let switch_block =
build_poll_switch(tcx, body, poll_enum, &poll_unit_place, target, yield_block);
let (pin_bb, fut_pin_place) =
build_pin_fut(tcx, body, fut_place.clone(), UnwindAction::Continue);
let switch_block = build_poll_switch(
tcx,
body,
poll_enum,
&poll_unit_place,
&fut_pin_place,
target,
yield_block,
);
let call_bb = build_poll_call(
tcx,
body,
@ -357,16 +367,17 @@ pub(super) fn expand_async_drops<'tcx>(
body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span)),
);
let drop_yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield
let (pin_bb2, fut_pin_place2) =
build_pin_fut(tcx, body, fut_place, UnwindAction::Continue);
let drop_switch_block = build_poll_switch(
tcx,
body,
poll_enum,
&poll_unit_place,
&fut_pin_place2,
drop.unwrap(),
drop_yield_block,
);
let (pin_bb2, fut_pin_place2) =
build_pin_fut(tcx, body, fut_place, UnwindAction::Continue);
let drop_call_bb = build_poll_call(
tcx,
body,

View file

@ -390,6 +390,20 @@ where
Location { block: self.succ, statement_index: 0 },
StatementKind::StorageDead(fut.local),
);
// StorageDead(fut) in unwind block (at the begin)
if let Unwind::To(block) = unwind {
self.elaborator.patch().add_statement(
Location { block, statement_index: 0 },
StatementKind::StorageDead(fut.local),
);
}
// StorageDead(fut) in dropline block (at the begin)
if let Some(block) = dropline {
self.elaborator.patch().add_statement(
Location { block, statement_index: 0 },
StatementKind::StorageDead(fut.local),
);
}
// #1:pin_obj_bb >>> call Pin<ObjTy>::new_unchecked(&mut obj)
self.elaborator.patch().patch_terminator(

View file

@ -60,11 +60,4 @@ monomorphize_start_not_found = using `fn main` requires the standard library
monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
monomorphize_wasm_c_abi_transition =
this function {$is_call ->
[true] call
*[false] definition
} involves an argument of type `{$ty}` which is affected by the wasm ABI transition
.help = the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
monomorphize_written_to_path = the full type name has been written to '{$path}'

View file

@ -100,12 +100,3 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
/// Whether this is a problem at a call site or at a declaration.
pub is_call: bool,
}
#[derive(LintDiagnostic)]
#[diag(monomorphize_wasm_c_abi_transition)]
#[help]
pub(crate) struct WasmCAbiTransition<'a> {
pub ty: Ty<'a>,
/// Whether this is a problem at a call site or at a declaration.
pub is_call: bool,
}

View file

@ -3,13 +3,10 @@
use rustc_abi::{BackendRepr, CanonAbi, RegKind, X86Call};
use rustc_hir::{CRATE_HIR_ID, HirId};
use rustc_middle::mir::{self, Location, traversal};
use rustc_middle::ty::layout::LayoutCx;
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv};
use rustc_session::lint::builtin::WASM_C_ABI;
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
use rustc_target::spec::{HasWasmCAbiOpt, WasmCAbi};
use rustc_target::callconv::{FnAbi, PassMode};
use crate::errors;
@ -81,73 +78,6 @@ fn do_check_simd_vector_abi<'tcx>(
}
}
/// Determines whether the given argument is passed the same way on the old and new wasm ABIs.
fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
return true;
}
// Both the old and the new ABIs treat vector types like `v128` the same
// way.
if uses_vector_registers(&arg.mode, &arg.layout.backend_repr) {
return true;
}
// This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
if arg.layout.is_aggregate() {
let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
let size = arg.layout.size;
// Ensure there's just a single `unit` element in `arg`.
if unit.size == size {
return true;
}
}
}
// Zero-sized types are dropped in both ABIs, so they're safe
if arg.layout.is_zst() {
return true;
}
false
}
/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
/// ABI transition.
fn do_check_wasm_abi<'tcx>(
tcx: TyCtxt<'tcx>,
abi: &FnAbi<'tcx, Ty<'tcx>>,
is_call: bool,
loc: impl Fn() -> (Span, HirId),
) {
// Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what
// `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`), and only proceed if
// `wasm_c_abi_opt` indicates we should emit the lint.
if !(tcx.sess.target.arch == "wasm32"
&& tcx.sess.target.os == "unknown"
&& tcx.wasm_c_abi_opt() == WasmCAbi::Legacy { with_lint: true }
&& abi.conv == CanonAbi::C)
{
return;
}
// Warn against all types whose ABI will change. Return values are not affected by this change.
for arg_abi in abi.args.iter() {
if wasm_abi_safe(tcx, arg_abi) {
continue;
}
let (span, hir_id) = loc();
tcx.emit_node_span_lint(
WASM_C_ABI,
hir_id,
span,
errors::WasmCAbiTransition { ty: arg_abi.layout.ty, is_call },
);
// Let's only warn once per function.
break;
}
}
/// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
/// or return values for which the corresponding target feature is not enabled.
fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
@ -173,7 +103,6 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
)
};
do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, loc);
do_check_wasm_abi(tcx, abi, /*is_call*/ false, loc);
}
/// Checks that a call expression does not try to pass a vector-passed argument which requires a
@ -212,7 +141,6 @@ fn check_call_site_abi<'tcx>(
return;
};
do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, loc);
do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, loc);
}
fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) {

View file

@ -3066,7 +3066,7 @@ pub(crate) mod dep_tracking {
use rustc_target::spec::{
CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel,
RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, TargetTuple,
TlsModel, WasmCAbi,
TlsModel,
};
use super::{
@ -3177,7 +3177,6 @@ pub(crate) mod dep_tracking {
Polonius,
InliningThreshold,
FunctionReturn,
WasmCAbi,
Align,
);

View file

@ -16,7 +16,7 @@ use rustc_span::{RealFileName, SourceFileHashAlgorithm};
use rustc_target::spec::{
CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility,
TargetTuple, TlsModel, WasmCAbi,
TargetTuple, TlsModel,
};
use crate::config::*;
@ -802,7 +802,6 @@ mod desc {
"either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
pub(crate) const parse_llvm_module_flag: &str = "<key>:<type>:<value>:<behavior>. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)";
pub(crate) const parse_function_return: &str = "`keep` or `thunk-extern`";
pub(crate) const parse_wasm_c_abi: &str = "`legacy` or `spec`";
pub(crate) const parse_mir_include_spans: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)";
pub(crate) const parse_align: &str = "a number that is a power of 2 between 1 and 2^29";
@ -1898,16 +1897,6 @@ pub mod parse {
true
}
pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool {
match v {
Some("spec") => *slot = WasmCAbi::Spec,
// Explicitly setting the `-Z` flag suppresses the lint.
Some("legacy") => *slot = WasmCAbi::Legacy { with_lint: false },
_ => return false,
}
true
}
pub(crate) fn parse_mir_include_spans(slot: &mut MirIncludeSpans, v: Option<&str>) -> bool {
*slot = match v {
Some("on" | "yes" | "y" | "true") | None => MirIncludeSpans::On,
@ -2642,8 +2631,6 @@ written to standard error output)"),
Requires `-Clto[=[fat,yes]]`"),
wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
"whether to build a wasi command or reactor"),
wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy { with_lint: true }, parse_wasm_c_abi, [TRACKED],
"use spec-compliant C ABI for `wasm32-unknown-unknown` (default: legacy)"),
write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED],
"whether long type names should be written to files instead of being printed in errors"),
// tidy-alphabetical-end

View file

@ -215,13 +215,6 @@ pub struct Session {
pub invocation_temp: Option<String>,
}
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub enum MetadataKind {
None,
Uncompressed,
Compressed,
}
#[derive(Clone, Copy)]
pub enum CodegenUnits {
/// Specified by the user. In this case we try fairly hard to produce the

View file

@ -37,9 +37,11 @@ impl LoongArchInlineAsmRegClass {
arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<Symbol>)] {
match (self, arch) {
(Self::reg, InlineAsmArch::LoongArch64) => types! { _: I8, I16, I32, I64, F32, F64; },
(Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F32; },
(Self::freg, _) => types! { f: F32; d: F64; },
(Self::reg, InlineAsmArch::LoongArch64) => {
types! { _: I8, I16, I32, I64, F16, F32, F64; }
}
(Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F16, F32; },
(Self::freg, _) => types! { f: F16, F32; d: F64; },
_ => unreachable!("unsupported register class"),
}
}

View file

@ -7,7 +7,7 @@ use rustc_abi::{
use rustc_macros::HashStable_Generic;
pub use crate::spec::AbiMap;
use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi};
use crate::spec::{HasTargetSpec, HasX86AbiOpt};
mod aarch64;
mod amdgpu;
@ -593,7 +593,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
pub fn adjust_for_foreign_abi<C>(&mut self, cx: &C, abi: ExternAbi)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt + HasX86AbiOpt,
C: HasDataLayout + HasTargetSpec + HasX86AbiOpt,
{
if abi == ExternAbi::X86Interrupt {
if let Some(arg) = self.args.first_mut() {
@ -669,14 +669,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
"hexagon" => hexagon::compute_abi_info(self),
"xtensa" => xtensa::compute_abi_info(cx, self),
"riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
"wasm32" => {
if spec.os == "unknown" && matches!(cx.wasm_c_abi_opt(), WasmCAbi::Legacy { .. }) {
wasm::compute_wasm_abi_info(self)
} else {
wasm::compute_c_abi_info(cx, self)
}
}
"wasm64" => wasm::compute_c_abi_info(cx, self),
"wasm32" | "wasm64" => wasm::compute_abi_info(cx, self),
"bpf" => bpf::compute_abi_info(self),
arch => panic!("no lowering implemented for {arch}"),
}

View file

@ -59,7 +59,7 @@ where
}
/// The purpose of this ABI is to match the C ABI (aka clang) exactly.
pub(crate) fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
@ -75,43 +75,3 @@ where
classify_arg(cx, arg);
}
}
/// The purpose of this ABI is for matching the WebAssembly standard. This
/// intentionally diverges from the C ABI and is specifically crafted to take
/// advantage of LLVM's support of multiple returns in WebAssembly.
///
/// This ABI is *bad*! It uses `PassMode::Direct` for `abi::Aggregate` types, which leaks LLVM
/// implementation details into the ABI. It's just hard to fix because ABIs are hard to change.
/// Also see <https://github.com/rust-lang/rust/issues/115666>.
pub(crate) fn compute_wasm_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
if !fn_abi.ret.is_ignore() {
classify_ret_wasm_abi(&mut fn_abi.ret);
}
for arg in fn_abi.args.iter_mut() {
if arg.is_ignore() {
continue;
}
classify_arg_wasm_abi(arg);
}
fn classify_ret_wasm_abi<Ty>(ret: &mut ArgAbi<'_, Ty>) {
if !ret.layout.is_sized() {
// Not touching this...
return;
}
// FIXME: this is bad! https://github.com/rust-lang/rust/issues/115666
ret.make_direct_deprecated();
ret.extend_integer_width_to(32);
}
fn classify_arg_wasm_abi<Ty>(arg: &mut ArgAbi<'_, Ty>) {
if !arg.layout.is_sized() {
// Not touching this...
return;
}
// FIXME: this is bad! https://github.com/rust-lang/rust/issues/115666
arg.make_direct_deprecated();
arg.extend_integer_width_to(32);
}
}

View file

@ -7,6 +7,7 @@ use rustc_abi::{
};
use crate::callconv::{ArgAbi, CastTarget, FnAbi};
use crate::spec::HasTargetSpec;
/// Classification of "eightbyte" components.
// N.B., the order of the variants is from general to specific,
@ -175,7 +176,7 @@ const MAX_SSE_REGS: usize = 8; // XMM0-7
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
C: HasDataLayout + HasTargetSpec,
{
let mut int_regs = MAX_INT_REGS;
let mut sse_regs = MAX_SSE_REGS;
@ -236,7 +237,7 @@ where
if arg.layout.is_aggregate() {
let size = arg.layout.size;
arg.cast_to(cast_target(cls, size));
} else {
} else if is_arg || cx.target_spec().is_like_darwin {
arg.extend_integer_width_to(32);
}
}

View file

@ -2233,22 +2233,6 @@ impl HasTargetSpec for Target {
}
}
/// Which C ABI to use for `wasm32-unknown-unknown`.
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum WasmCAbi {
/// Spec-compliant C ABI.
Spec,
/// Legacy ABI. Which is non-spec-compliant.
Legacy {
/// Indicates whether the `wasm_c_abi` lint should be emitted.
with_lint: bool,
},
}
pub trait HasWasmCAbiOpt {
fn wasm_c_abi_opt(&self) -> WasmCAbi;
}
/// x86 (32-bit) abi options.
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct X86Abi {

View file

@ -403,28 +403,18 @@ fn fn_abi_sanity_check<'tcx>(
// For an unsized type we'd only pass the sized prefix, so there is no universe
// in which we ever want to allow this.
assert!(sized, "`PassMode::Direct` for unsized type in ABI: {:#?}", fn_abi);
// This really shouldn't happen even for sized aggregates, since
// `immediate_llvm_type` will use `layout.fields` to turn this Rust type into an
// LLVM type. This means all sorts of Rust type details leak into the ABI.
// However wasm sadly *does* currently use this mode for it's "C" ABI so we
// have to allow it -- but we absolutely shouldn't let any more targets do
// that. (Also see <https://github.com/rust-lang/rust/issues/115666>.)
//
// The unadjusted ABI also uses Direct for all args and is ill-specified,
// The unadjusted ABI however uses Direct for all args. It is ill-specified,
// but unfortunately we need it for calling certain LLVM intrinsics.
match spec_abi {
ExternAbi::Unadjusted => {}
ExternAbi::C { unwind: _ }
if matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64") => {}
_ => {
panic!(
"`PassMode::Direct` for aggregates only allowed for \"unadjusted\" functions and on wasm\n\
Problematic type: {:#?}",
arg.layout,
);
}
}
assert!(
matches!(spec_abi, ExternAbi::Unadjusted),
"`PassMode::Direct` for aggregates only allowed for \"unadjusted\"\n\
Problematic type: {:#?}",
arg.layout,
);
}
}
}

View file

@ -7,9 +7,6 @@
//! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
#![deny(unsafe_code)]
// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
// be built with different versions of rustc, the wasm ABI changes don't really matter.
#![allow(wasm_c_abi)]
use std::hash::Hash;
use std::ops::{Bound, Range};

View file

@ -1373,12 +1373,13 @@ impl Config {
}
println!("Updating submodule {relative_path}");
self.check_run(
helpers::git(Some(&self.src))
.run_always()
.args(["submodule", "-q", "sync"])
.arg(relative_path),
);
helpers::git(Some(&self.src))
.allow_failure()
.run_always()
.args(["submodule", "-q", "sync"])
.arg(relative_path)
.run(self);
// Try passing `--progress` to start, then run git again without if that fails.
let update = |progress: bool| {
@ -1407,26 +1408,23 @@ impl Config {
git.arg(relative_path);
git
};
if !self.check_run(&mut update(true)) {
self.check_run(&mut update(false));
if !update(true).allow_failure().run(self) {
update(false).allow_failure().run(self);
}
// Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error).
// diff-index reports the modifications through the exit status
let has_local_modifications = !self.check_run(submodule_git().allow_failure().args([
"diff-index",
"--quiet",
"HEAD",
]));
let has_local_modifications =
!submodule_git().allow_failure().args(["diff-index", "--quiet", "HEAD"]).run(self);
if has_local_modifications {
self.check_run(submodule_git().args(["stash", "push"]));
submodule_git().allow_failure().args(["stash", "push"]).run(self);
}
self.check_run(submodule_git().args(["reset", "-q", "--hard"]));
self.check_run(submodule_git().args(["clean", "-qdfx"]));
submodule_git().allow_failure().args(["reset", "-q", "--hard"]).run(self);
submodule_git().allow_failure().args(["clean", "-qdfx"]).run(self);
if has_local_modifications {
self.check_run(submodule_git().args(["stash", "pop"]));
submodule_git().allow_failure().args(["stash", "pop"]).run(self);
}
}

View file

@ -9,8 +9,8 @@ use xz2::bufread::XzDecoder;
use crate::core::config::BUILDER_CONFIG_FILENAME;
use crate::utils::build_stamp::BuildStamp;
use crate::utils::exec::{BootstrapCommand, command};
use crate::utils::helpers::{check_run, exe, hex_encode, move_file};
use crate::utils::exec::command;
use crate::utils::helpers::{exe, hex_encode, move_file};
use crate::{Config, t};
static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock<bool> = OnceLock::new();
@ -65,17 +65,6 @@ impl Config {
tmp
}
/// Runs a command, printing out nice contextual information if it fails.
/// Returns false if do not execute at all, otherwise returns its
/// `status.success()`.
pub(crate) fn check_run(&self, cmd: &mut BootstrapCommand) -> bool {
if self.dry_run() && !cmd.run_always {
return true;
}
self.verbose(|| println!("running: {cmd:?}"));
check_run(cmd, self.is_verbose())
}
/// Whether or not `fix_bin_or_dylib` needs to be run; can only be true
/// on NixOS
fn should_fix_bins_and_dylibs(&self) -> bool {
@ -214,7 +203,7 @@ impl Config {
// options should be kept in sync with
// src/bootstrap/src/core/download.rs
// for consistency
let mut curl = command("curl");
let mut curl = command("curl").allow_failure();
curl.args([
// follow redirect
"--location",
@ -255,7 +244,7 @@ impl Config {
curl.arg("--retry-all-errors");
}
curl.arg(url);
if !self.check_run(&mut curl) {
if !curl.run(self) {
if self.host_target.contains("windows-msvc") {
eprintln!("Fallback to PowerShell");
for _ in 0..3 {

View file

@ -270,24 +270,6 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef<Path>>(
}
}
// FIXME: get rid of this function
pub fn check_run(cmd: &mut BootstrapCommand, print_cmd_on_fail: bool) -> bool {
let status = match cmd.as_command_mut().status() {
Ok(status) => status,
Err(e) => {
println!("failed to execute command: {cmd:?}\nERROR: {e}");
return false;
}
};
if !status.success() && print_cmd_on_fail {
println!(
"\n\ncommand did not execute successfully: {cmd:?}\n\
expected success, got: {status}\n\n"
);
}
status.success()
}
pub fn make(host: &str) -> PathBuf {
if host.contains("dragonfly")
|| host.contains("freebsd")

View file

@ -207,120 +207,3 @@ conditionally compile code instead. This is notably different to the way native
platforms such as x86\_64 work, and this is due to the fact that WebAssembly
binaries must only contain code the engine understands. Native binaries work so
long as the CPU doesn't execute unknown code dynamically at runtime.
## Broken `extern "C"` ABI
This target has what is considered a broken `extern "C"` ABI implementation at
this time. Notably the same signature in Rust and C will compile to different
WebAssembly functions and be incompatible. This is considered a bug and it will
be fixed in a future version of Rust.
For example this Rust code:
```rust,ignore (does-not-link)
#[repr(C)]
struct MyPair {
a: u32,
b: u32,
}
extern "C" {
fn take_my_pair(pair: MyPair) -> u32;
}
#[no_mangle]
pub unsafe extern "C" fn call_c() -> u32 {
take_my_pair(MyPair { a: 1, b: 2 })
}
```
compiles to a WebAssembly module that looks like:
```wasm
(module
(import "env" "take_my_pair" (func $take_my_pair (param i32 i32) (result i32)))
(func $call_c
i32.const 1
i32.const 2
call $take_my_pair
)
)
```
The function when defined in C, however, looks like
```c
struct my_pair {
unsigned a;
unsigned b;
};
unsigned take_my_pair(struct my_pair pair) {
return pair.a + pair.b;
}
```
```wasm
(module
(import "env" "__linear_memory" (memory 0))
(func $take_my_pair (param i32) (result i32)
local.get 0
i32.load offset=4
local.get 0
i32.load
i32.add
)
)
```
Notice how Rust thinks `take_my_pair` takes two `i32` parameters but C thinks it
only takes one.
The correct definition of the `extern "C"` ABI for WebAssembly is located in the
[WebAssembly/tool-conventions](https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md)
repository. The `wasm32-unknown-unknown` target (and only this target, not other
WebAssembly targets Rust support) does not correctly follow this document.
Example issues in the Rust repository about this bug are:
* [#115666](https://github.com/rust-lang/rust/issues/115666)
* [#129486](https://github.com/rust-lang/rust/issues/129486)
This current state of the `wasm32-unknown-unknown` backend is due to an
unfortunate accident which got relied on. The `wasm-bindgen` project prior to
0.2.89 was incompatible with the "correct" definition of `extern "C"` and it was
seen as not worth the tradeoff of breaking `wasm-bindgen` historically to fix
this issue in the compiler.
Thanks to the heroic efforts of many involved in this, however, `wasm-bindgen`
0.2.89 and later are compatible with the correct definition of `extern "C"` and
the nightly compiler currently supports a `-Zwasm-c-abi` implemented in
[#117919](https://github.com/rust-lang/rust/pull/117919). This nightly-only flag
can be used to indicate whether the spec-defined version of `extern "C"` should
be used instead of the "legacy" version of
whatever-the-Rust-target-originally-implemented. For example using the above
code you can see (lightly edited for clarity):
```shell
$ rustc +nightly -Zwasm-c-abi=spec foo.rs --target wasm32-unknown-unknown --crate-type lib --emit obj -O
$ wasm-tools print foo.o
(module
(import "env" "take_my_pair" (func $take_my_pair (param i32) (result i32)))
(func $call_c (result i32)
;; ...
)
;; ...
)
```
which shows that the C and Rust definitions of the same function now agree like
they should.
The `-Zwasm-c-abi` compiler flag is tracked in
[#122532](https://github.com/rust-lang/rust/issues/122532) and a lint was
implemented in [#117918](https://github.com/rust-lang/rust/issues/117918) to
help warn users about the transition if they're using `wasm-bindgen` 0.2.88 or
prior. The current plan is to, in the future, switch `-Zwasm-c-api=spec` to
being the default. Some time after that the `-Zwasm-c-abi` flag and the
"legacy" implementation will all be removed. During this process users on a
sufficiently updated version of `wasm-bindgen` should not experience breakage.

View file

@ -185,7 +185,7 @@ pub(super) fn check<'tcx>(
Node::Expr(parent) if is_borrow_expr(cx, parent) && !is_in_allowed_macro(cx, parent) => {
MaybeParenOrBlock::Block
},
Node::Expr(parent) if cast_expr.precedence() < parent.precedence() => MaybeParenOrBlock::Paren,
Node::Expr(parent) if cx.precedence(cast_expr) < cx.precedence(parent) => MaybeParenOrBlock::Paren,
_ => MaybeParenOrBlock::Nothing,
};

View file

@ -972,7 +972,7 @@ fn report<'tcx>(
"&"
};
let expr_str = if !expr_is_macro_call && is_ufcs && expr.precedence() < ExprPrecedence::Prefix {
let expr_str = if !expr_is_macro_call && is_ufcs && cx.precedence(expr) < ExprPrecedence::Prefix {
Cow::Owned(format!("({expr_str})"))
} else {
expr_str
@ -1015,10 +1015,10 @@ fn report<'tcx>(
Node::Expr(e) => match e.kind {
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false,
ExprKind::Call(..) => {
expr.precedence() < ExprPrecedence::Unambiguous
cx.precedence(expr) < ExprPrecedence::Unambiguous
|| matches!(expr.kind, ExprKind::Field(..))
},
_ => expr.precedence() < e.precedence(),
_ => cx.precedence(expr) < cx.precedence(e),
},
_ => false,
};
@ -1066,7 +1066,7 @@ fn report<'tcx>(
Mutability::Not => "&",
Mutability::Mut => "&mut ",
};
(prefix, expr.precedence() < ExprPrecedence::Prefix)
(prefix, cx.precedence(expr) < ExprPrecedence::Prefix)
},
None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false),
_ => ("", false),
@ -1172,7 +1172,7 @@ impl<'tcx> Dereferencing<'tcx> {
},
Some(parent) if !parent.span.from_expansion() => {
// Double reference might be needed at this point.
if parent.precedence() == ExprPrecedence::Unambiguous {
if cx.precedence(parent) == ExprPrecedence::Unambiguous {
// Parentheses would be needed here, don't lint.
*outer_pat = None;
} else {

View file

@ -84,7 +84,7 @@ pub(super) fn check<'tcx>(
if !prefix.is_empty()
&& (
// Precedence of internal expression is less than or equal to precedence of `&expr`.
arg_expression.precedence() <= ExprPrecedence::Prefix || is_range_literal(arg_expression)
cx.precedence(arg_expression) <= ExprPrecedence::Prefix || is_range_literal(arg_expression)
)
{
arg_snip = format!("({arg_snip})").into();

View file

@ -117,7 +117,7 @@ where
// it's being passed by value.
let scrutinee = peel_hir_expr_refs(scrutinee).0;
let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < ExprPrecedence::Unambiguous {
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && cx.precedence(scrutinee) < ExprPrecedence::Unambiguous {
format!("({scrutinee_str})")
} else {
scrutinee_str.into()

View file

@ -64,7 +64,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
{
let mut applicability = Applicability::MachineApplicable;
let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability);
let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) {
let suggestion = if !from_macro && cx.precedence(exp) < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) {
format!("-({snip})")
} else {
format!("-{snip}")

View file

@ -86,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed));
let parent_expr = get_parent_expr(cx, expr);
let needs_parens_for_prefix =
parent_expr.is_some_and(|parent| parent.precedence() > ExprPrecedence::Prefix);
parent_expr.is_some_and(|parent| cx.precedence(parent) > ExprPrecedence::Prefix);
if expr_ty == indexed_ty {
if expr_ref_count > indexed_ref_count {

View file

@ -44,7 +44,7 @@ pub(super) fn check<'tcx>(
};
if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id)
&& parent.precedence() > ExprPrecedence::Cast
&& cx.precedence(parent) > ExprPrecedence::Cast
{
sugg = format!("({sugg})");
}

View file

@ -4,7 +4,7 @@
//@ compile-flags: -Zmerge-functions=disabled
//@ needs-llvm-components: loongarch
#![feature(no_core)]
#![feature(no_core, f16)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
@ -69,6 +69,12 @@ check!(reg_i8, i8, reg, "move");
// CHECK: #NO_APP
check!(reg_i16, i16, reg, "move");
// CHECK-LABEL: reg_f16:
// CHECK: #APP
// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
// CHECK: #NO_APP
check!(reg_f16, f16, reg, "move");
// CHECK-LABEL: reg_i32:
// CHECK: #APP
// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
@ -99,6 +105,12 @@ check!(reg_f64, f64, reg, "move");
// CHECK: #NO_APP
check!(reg_ptr, ptr, reg, "move");
// CHECK-LABEL: freg_f16:
// CHECK: #APP
// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
// CHECK: #NO_APP
check!(freg_f16, f16, freg, "fmov.s");
// CHECK-LABEL: freg_f32:
// CHECK: #APP
// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
@ -123,6 +135,12 @@ check_reg!(r4_i8, i8, "$r4", "move");
// CHECK: #NO_APP
check_reg!(r4_i16, i16, "$r4", "move");
// CHECK-LABEL: r4_f16:
// CHECK: #APP
// CHECK: move $a0, $a0
// CHECK: #NO_APP
check_reg!(r4_f16, f16, "$r4", "move");
// CHECK-LABEL: r4_i32:
// CHECK: #APP
// CHECK: move $a0, $a0
@ -153,6 +171,12 @@ check_reg!(r4_f64, f64, "$r4", "move");
// CHECK: #NO_APP
check_reg!(r4_ptr, ptr, "$r4", "move");
// CHECK-LABEL: f0_f16:
// CHECK: #APP
// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
// CHECK: #NO_APP
check_reg!(f0_f16, f16, "$f0", "fmov.s");
// CHECK-LABEL: f0_f32:
// CHECK: #APP
// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}

View file

@ -19,7 +19,7 @@ pub fn call_other_fn() -> u8 {
}
// CHECK-LABEL: other_fn:
// CHECK: callq *foreign_fn@GOTPCREL(%rip)
// CHECK: {{(jmpq|callq)}} *foreign_fn@GOTPCREL(%rip)
#[no_mangle]
#[inline(never)]
pub fn other_fn() -> u8 {

View file

@ -22,7 +22,7 @@ pub fn call_other_fn() -> u8 {
// CHECK-LABEL: other_fn:
// External functions are still called through GOT, since we don't know if the symbol
// is defined in the binary or in the shared library.
// CHECK: callq *foreign_fn@GOTPCREL(%rip)
// CHECK: {{(jmpq|callq)}} *foreign_fn@GOTPCREL(%rip)
#[no_mangle]
#[inline(never)]
pub fn other_fn() -> u8 {

View file

@ -13,7 +13,7 @@ pub fn call_foreign_fn() -> u8 {
// External functions are still marked as non-dso_local, since we don't know if the symbol
// is defined in the binary or in the shared library.
// CHECK: declare zeroext i8 @foreign_fn()
// CHECK: declare i8 @foreign_fn()
extern "C" {
fn foreign_fn() -> u8;
}

View file

@ -0,0 +1,100 @@
// MIR for `a::{closure#0}` 0 coroutine_drop_async
fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
debug _task_context => _19;
debug x => ((*(_1.0: &mut {async fn body of a<T>()})).0: T);
let mut _0: std::task::Poll<()>;
let _3: T;
let mut _4: impl std::future::Future<Output = ()>;
let mut _5: &mut T;
let mut _6: std::pin::Pin<&mut T>;
let mut _7: &mut T;
let mut _8: *mut T;
let mut _9: ();
let mut _10: std::task::Poll<()>;
let mut _11: &mut std::task::Context<'_>;
let mut _12: &mut impl std::future::Future<Output = ()>;
let mut _13: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
let mut _14: isize;
let mut _15: &mut std::task::Context<'_>;
let mut _16: &mut impl std::future::Future<Output = ()>;
let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
let mut _18: isize;
let mut _19: &mut std::task::Context<'_>;
let mut _20: u32;
scope 1 {
debug x => (((*(_1.0: &mut {async fn body of a<T>()})) as variant#4).0: T);
}
bb0: {
_20 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
switchInt(move _20) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14];
}
bb1: {
nop;
nop;
goto -> bb2;
}
bb2: {
_0 = Poll::<()>::Ready(const ());
return;
}
bb3: {
_0 = Poll::<()>::Pending;
discriminant((*(_1.0: &mut {async fn body of a<T>()}))) = 4;
return;
}
bb4: {
StorageLive(_17);
_16 = &mut (((*(_1.0: &mut {async fn body of a<T>()})) as variant#4).1: impl std::future::Future<Output = ()>);
_17 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _16) -> [return: bb7, unwind unreachable];
}
bb5: {
unreachable;
}
bb6: {
StorageDead(_17);
_18 = discriminant(_10);
switchInt(move _18) -> [0: bb1, 1: bb3, otherwise: bb5];
}
bb7: {
_10 = <impl Future<Output = ()> as Future>::poll(move _17, move _15) -> [return: bb6, unwind unreachable];
}
bb8: {
_0 = Poll::<()>::Ready(const ());
return;
}
bb9: {
goto -> bb11;
}
bb10: {
goto -> bb8;
}
bb11: {
drop(((*(_1.0: &mut {async fn body of a<T>()})).0: T)) -> [return: bb10, unwind unreachable];
}
bb12: {
goto -> bb4;
}
bb13: {
goto -> bb4;
}
bb14: {
_0 = Poll::<()>::Ready(const ());
return;
}
}

View file

@ -0,0 +1,123 @@
// MIR for `a::{closure#0}` 0 coroutine_drop_async
fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
debug _task_context => _19;
debug x => ((*(_1.0: &mut {async fn body of a<T>()})).0: T);
let mut _0: std::task::Poll<()>;
let _3: T;
let mut _4: impl std::future::Future<Output = ()>;
let mut _5: &mut T;
let mut _6: std::pin::Pin<&mut T>;
let mut _7: &mut T;
let mut _8: *mut T;
let mut _9: ();
let mut _10: std::task::Poll<()>;
let mut _11: &mut std::task::Context<'_>;
let mut _12: &mut impl std::future::Future<Output = ()>;
let mut _13: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
let mut _14: isize;
let mut _15: &mut std::task::Context<'_>;
let mut _16: &mut impl std::future::Future<Output = ()>;
let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
let mut _18: isize;
let mut _19: &mut std::task::Context<'_>;
let mut _20: u32;
scope 1 {
debug x => (((*(_1.0: &mut {async fn body of a<T>()})) as variant#4).0: T);
}
bb0: {
_20 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
switchInt(move _20) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19];
}
bb1: {
nop;
nop;
goto -> bb2;
}
bb2: {
_0 = Poll::<()>::Ready(const ());
return;
}
bb3 (cleanup): {
nop;
nop;
goto -> bb5;
}
bb4 (cleanup): {
goto -> bb15;
}
bb5 (cleanup): {
goto -> bb4;
}
bb6: {
_0 = Poll::<()>::Pending;
discriminant((*(_1.0: &mut {async fn body of a<T>()}))) = 4;
return;
}
bb7: {
StorageLive(_17);
_16 = &mut (((*(_1.0: &mut {async fn body of a<T>()})) as variant#4).1: impl std::future::Future<Output = ()>);
_17 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _16) -> [return: bb10, unwind: bb15];
}
bb8: {
unreachable;
}
bb9: {
StorageDead(_17);
_18 = discriminant(_10);
switchInt(move _18) -> [0: bb1, 1: bb6, otherwise: bb8];
}
bb10: {
_10 = <impl Future<Output = ()> as Future>::poll(move _17, move _15) -> [return: bb9, unwind: bb3];
}
bb11: {
_0 = Poll::<()>::Ready(const ());
return;
}
bb12: {
goto -> bb14;
}
bb13: {
goto -> bb11;
}
bb14: {
drop(((*(_1.0: &mut {async fn body of a<T>()})).0: T)) -> [return: bb13, unwind: bb4];
}
bb15 (cleanup): {
discriminant((*(_1.0: &mut {async fn body of a<T>()}))) = 2;
resume;
}
bb16: {
goto -> bb7;
}
bb17: {
goto -> bb7;
}
bb18: {
assert(const false, "`async fn` resumed after panicking") -> [success: bb18, unwind continue];
}
bb19: {
_0 = Poll::<()>::Ready(const ());
return;
}
}

View file

@ -0,0 +1,11 @@
//@ edition:2024
// skip-filecheck
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
#![feature(async_drop)]
#![allow(incomplete_features)]
// EMIT_MIR async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.mir
async fn a<T>(x: T) {}
fn main() {}

View file

@ -7,15 +7,17 @@ extern crate rustc_parse;
extern crate rustc_session;
extern crate rustc_span;
use rustc_ast::ast::{DUMMY_NODE_ID, Expr};
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::ast::{AttrKind, Attribute, DUMMY_NODE_ID, Expr};
use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_ast::node_id::NodeId;
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::token::{self, Token};
use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, LazyAttrTokenStream};
use rustc_errors::Diag;
use rustc_parse::parser::Recovery;
use rustc_session::parse::ParseSess;
use rustc_span::{DUMMY_SP, FileName, Span};
use rustc_span::{AttrId, DUMMY_SP, FileName, Span};
use std::sync::Arc;
pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<P<Expr>> {
let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str(
@ -46,4 +48,36 @@ impl MutVisitor for Normalize {
fn visit_span(&mut self, span: &mut Span) {
*span = DUMMY_SP;
}
fn visit_attribute(&mut self, attr: &mut Attribute) {
attr.id = AttrId::from_u32(0);
if let AttrKind::Normal(normal_attr) = &mut attr.kind {
if let Some(tokens) = &mut normal_attr.tokens {
let mut stream = tokens.to_attr_token_stream();
normalize_attr_token_stream(&mut stream);
*tokens = LazyAttrTokenStream::new_direct(stream);
}
}
mut_visit::walk_attribute(self, attr);
}
}
fn normalize_attr_token_stream(stream: &mut AttrTokenStream) {
Arc::make_mut(&mut stream.0)
.iter_mut()
.for_each(normalize_attr_token_tree);
}
fn normalize_attr_token_tree(token: &mut AttrTokenTree) {
match token {
AttrTokenTree::Token(token, _spacing) => {
Normalize.visit_span(&mut token.span);
}
AttrTokenTree::Delimited(dspan, _spacing, _delim, stream) => {
normalize_attr_token_stream(stream);
Normalize.visit_span(&mut dspan.open);
Normalize.visit_span(&mut dspan.close);
}
AttrTokenTree::AttrsTarget(_) => unimplemented!("AttrTokenTree::AttrsTarget"),
}
}

View file

@ -33,17 +33,10 @@ impl CodegenBackend for TheBackend {
""
}
fn codegen_crate<'a, 'tcx>(
&self,
tcx: TyCtxt<'tcx>,
metadata: EncodedMetadata,
_need_metadata_module: bool,
) -> Box<dyn Any> {
fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
Box::new(CodegenResults {
modules: vec![],
allocator_module: None,
metadata_module: None,
metadata,
crate_info: CrateInfo::new(tcx, "fake_target_cpu".to_string()),
})
}
@ -60,7 +53,13 @@ impl CodegenBackend for TheBackend {
(*codegen_results, FxIndexMap::default())
}
fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) {
fn link(
&self,
sess: &Session,
codegen_results: CodegenResults,
_metadata: EncodedMetadata,
outputs: &OutputFilenames,
) {
use std::io::Write;
use rustc_session::config::{CrateType, OutFileName};

View file

@ -88,6 +88,11 @@ static EXPRS: &[&str] = &[
// expressions.
"match 2 { _ => 1 - 1 }",
"match 2 { _ => ({ 1 }) - 1 }",
// Expressions with an outer attr have lower precedence than expressions
// with an inner attr.
"#[attr] loop {}.field",
"(#[attr] loop {}).field",
"loop { #![attr] }.field",
// Grammar restriction: break value starting with a labeled loop is not
// allowed, except if the break is also labeled.
"break 'outer 'inner: loop {} + 2",

View file

@ -0,0 +1,536 @@
error: fn_abi_of(i8) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: i8,
layout: Layout {
size: Size(1 bytes),
align: AbiAlign {
abi: Align(1 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I8,
true,
),
valid_range: 0..=255,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
randomization_seed: 71776123356184577,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Sext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: i8,
layout: Layout {
size: Size(1 bytes),
align: AbiAlign {
abi: Align(1 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I8,
true,
),
valid_range: 0..=255,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
randomization_seed: 71776123356184577,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Sext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:13:1
|
LL | pub extern "sysv64" fn i8(x: i8) -> i8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: fn_abi_of(u8) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: u8,
layout: Layout {
size: Size(1 bytes),
align: AbiAlign {
abi: Align(1 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I8,
false,
),
valid_range: 0..=255,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
randomization_seed: 71776127651151873,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Zext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: u8,
layout: Layout {
size: Size(1 bytes),
align: AbiAlign {
abi: Align(1 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I8,
false,
),
valid_range: 0..=255,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
randomization_seed: 71776127651151873,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Zext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:19:1
|
LL | pub extern "sysv64" fn u8(x: u8) -> u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: fn_abi_of(i16) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: i16,
layout: Layout {
size: Size(2 bytes),
align: AbiAlign {
abi: Align(2 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I16,
true,
),
valid_range: 0..=65535,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
randomization_seed: 18446462603027808258,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Sext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: i16,
layout: Layout {
size: Size(2 bytes),
align: AbiAlign {
abi: Align(2 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I16,
true,
),
valid_range: 0..=65535,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
randomization_seed: 18446462603027808258,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Sext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:25:1
|
LL | pub extern "sysv64" fn i16(x: i16) -> i16 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: fn_abi_of(u16) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: u16,
layout: Layout {
size: Size(2 bytes),
align: AbiAlign {
abi: Align(2 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I16,
false,
),
valid_range: 0..=65535,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
randomization_seed: 18446462607322775554,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Zext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: u16,
layout: Layout {
size: Size(2 bytes),
align: AbiAlign {
abi: Align(2 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I16,
false,
),
valid_range: 0..=65535,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
randomization_seed: 18446462607322775554,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Zext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:31:1
|
LL | pub extern "sysv64" fn u16(x: u16) -> u16 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: fn_abi_of(i32) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: i32,
layout: Layout {
size: Size(4 bytes),
align: AbiAlign {
abi: Align(4 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I32,
true,
),
valid_range: 0..=4294967295,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(4 bytes),
randomization_seed: 18446462603027873795,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: i32,
layout: Layout {
size: Size(4 bytes),
align: AbiAlign {
abi: Align(4 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I32,
true,
),
valid_range: 0..=4294967295,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(4 bytes),
randomization_seed: 18446462603027873795,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:37:1
|
LL | pub extern "sysv64" fn i32(x: i32) -> i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: fn_abi_of(u32) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: u32,
layout: Layout {
size: Size(4 bytes),
align: AbiAlign {
abi: Align(4 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I32,
false,
),
valid_range: 0..=4294967295,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(4 bytes),
randomization_seed: 18446462607322841091,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: u32,
layout: Layout {
size: Size(4 bytes),
align: AbiAlign {
abi: Align(4 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I32,
false,
),
valid_range: 0..=4294967295,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(4 bytes),
randomization_seed: 18446462607322841091,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:43:1
|
LL | pub extern "sysv64" fn u32(x: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors

View file

@ -0,0 +1,536 @@
error: fn_abi_of(i8) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: i8,
layout: Layout {
size: Size(1 bytes),
align: AbiAlign {
abi: Align(1 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I8,
true,
),
valid_range: 0..=255,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
randomization_seed: 71776123356184577,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Sext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: i8,
layout: Layout {
size: Size(1 bytes),
align: AbiAlign {
abi: Align(1 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I8,
true,
),
valid_range: 0..=255,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
randomization_seed: 71776123356184577,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:13:1
|
LL | pub extern "sysv64" fn i8(x: i8) -> i8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: fn_abi_of(u8) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: u8,
layout: Layout {
size: Size(1 bytes),
align: AbiAlign {
abi: Align(1 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I8,
false,
),
valid_range: 0..=255,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
randomization_seed: 71776127651151873,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Zext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: u8,
layout: Layout {
size: Size(1 bytes),
align: AbiAlign {
abi: Align(1 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I8,
false,
),
valid_range: 0..=255,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
randomization_seed: 71776127651151873,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:19:1
|
LL | pub extern "sysv64" fn u8(x: u8) -> u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: fn_abi_of(i16) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: i16,
layout: Layout {
size: Size(2 bytes),
align: AbiAlign {
abi: Align(2 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I16,
true,
),
valid_range: 0..=65535,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
randomization_seed: 18446462603027808258,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Sext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: i16,
layout: Layout {
size: Size(2 bytes),
align: AbiAlign {
abi: Align(2 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I16,
true,
),
valid_range: 0..=65535,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
randomization_seed: 18446462603027808258,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:25:1
|
LL | pub extern "sysv64" fn i16(x: i16) -> i16 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: fn_abi_of(u16) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: u16,
layout: Layout {
size: Size(2 bytes),
align: AbiAlign {
abi: Align(2 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I16,
false,
),
valid_range: 0..=65535,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
randomization_seed: 18446462607322775554,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: Zext,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: u16,
layout: Layout {
size: Size(2 bytes),
align: AbiAlign {
abi: Align(2 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I16,
false,
),
valid_range: 0..=65535,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
randomization_seed: 18446462607322775554,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:31:1
|
LL | pub extern "sysv64" fn u16(x: u16) -> u16 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: fn_abi_of(i32) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: i32,
layout: Layout {
size: Size(4 bytes),
align: AbiAlign {
abi: Align(4 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I32,
true,
),
valid_range: 0..=4294967295,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(4 bytes),
randomization_seed: 18446462603027873795,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: i32,
layout: Layout {
size: Size(4 bytes),
align: AbiAlign {
abi: Align(4 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I32,
true,
),
valid_range: 0..=4294967295,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(4 bytes),
randomization_seed: 18446462603027873795,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:37:1
|
LL | pub extern "sysv64" fn i32(x: i32) -> i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: fn_abi_of(u32) = FnAbi {
args: [
ArgAbi {
layout: TyAndLayout {
ty: u32,
layout: Layout {
size: Size(4 bytes),
align: AbiAlign {
abi: Align(4 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I32,
false,
),
valid_range: 0..=4294967295,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(4 bytes),
randomization_seed: 18446462607322841091,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
],
ret: ArgAbi {
layout: TyAndLayout {
ty: u32,
layout: Layout {
size: Size(4 bytes),
align: AbiAlign {
abi: Align(4 bytes),
},
backend_repr: Scalar(
Initialized {
value: Int(
I32,
false,
),
valid_range: 0..=4294967295,
},
),
fields: Primitive,
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(4 bytes),
randomization_seed: 18446462607322841091,
},
},
mode: Direct(
ArgAttributes {
regular: NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
),
},
c_variadic: false,
fixed_count: 1,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/x86-64-sysv64-arg-ext.rs:43:1
|
LL | pub extern "sysv64" fn u32(x: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors

View file

@ -0,0 +1,46 @@
//@ only-x86_64
//@ revisions: apple other
//@[apple] only-apple
//@[other] ignore-apple
// Apple targets extend up to 32 bits for both arguments and returns, other targets only extend
// arguments.
#![crate_type = "lib"]
#![feature(rustc_attrs)]
#[rustc_abi(debug)]
pub extern "sysv64" fn i8(x: i8) -> i8 {
//~^ ERROR fn_abi_of(i8)
x
}
#[rustc_abi(debug)]
pub extern "sysv64" fn u8(x: u8) -> u8 {
//~^ ERROR fn_abi_of(u8)
x
}
#[rustc_abi(debug)]
pub extern "sysv64" fn i16(x: i16) -> i16 {
//~^ ERROR fn_abi_of(i16)
x
}
#[rustc_abi(debug)]
pub extern "sysv64" fn u16(x: u16) -> u16 {
//~^ ERROR fn_abi_of(u16)
x
}
#[rustc_abi(debug)]
pub extern "sysv64" fn i32(x: i32) -> i32 {
//~^ ERROR fn_abi_of(i32)
x
}
#[rustc_abi(debug)]
pub extern "sysv64" fn u32(x: u32) -> u32 {
//~^ ERROR fn_abi_of(u32)
x
}

View file

@ -62,7 +62,7 @@ fn main() {
test_async_drop(&j, 16).await;
test_async_drop(
AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 },
if cfg!(panic = "unwind") { 168 } else { 136 },
136,
).await;
test_async_drop(ManuallyDrop::new(AsyncInt(9)), 16).await;

View file

@ -1,6 +1,9 @@
//@ known-bug: #140429
// ex-ice: #140429
//@ compile-flags: -Zlint-mir --crate-type lib
//@ edition:2024
//@ check-pass
#![feature(async_drop)]
#![allow(incomplete_features)]
async fn a<T>(x: T) {}

View file

@ -1,7 +1,11 @@
//@ known-bug: #140531
//@compile-flags: -Zlint-mir --crate-type lib
// ex-ice: #140531
//@ compile-flags: -Zlint-mir --crate-type lib
//@ edition:2024
//@ check-pass
#![feature(async_drop)]
#![allow(incomplete_features)]
async fn call_once(f: impl AsyncFnOnce()) {
let fut = Box::pin(f());
}

View file

@ -0,0 +1,56 @@
// ex-ice: #141761
//@ compile-flags: -Zlint-mir --crate-type lib
//@ edition:2024
//@ check-pass
#![feature(async_drop)]
#![allow(incomplete_features)]
type BoxFuture<T> = std::pin::Pin<Box<dyn Future<Output = T>>>;
fn main() {}
async fn f() {
run("").await
}
struct InMemoryStorage;
struct User<'dep> {
dep: &'dep str,
}
impl<'a> StorageRequest<InMemoryStorage> for SaveUser<'a> {
fn execute(&self) -> BoxFuture<Result<(), String>> {
todo!()
}
}
trait Storage {
type Error;
}
impl Storage for InMemoryStorage {
type Error = String;
}
trait StorageRequestReturnType {
type Output;
}
trait StorageRequest<S: Storage>: StorageRequestReturnType {
fn execute(&self) -> BoxFuture<Result<<Self>::Output, S::Error>>;
}
struct SaveUser<'a> {
name: &'a str,
}
impl<'a> StorageRequestReturnType for SaveUser<'a> {
type Output = ();
}
impl<'dep> User<'dep> {
async fn save<S>(self)
where
S: Storage,
for<'a> SaveUser<'a>: StorageRequest<S>,
{
SaveUser { name: "" }.execute().await;
}
}
async fn run<S>(dep: &str)
where
S: Storage,
for<'a> SaveUser<'a>: StorageRequest<S>,
{
User { dep }.save().await
}

View file

@ -0,0 +1,56 @@
// ex-ice: #141409
//@ compile-flags: -Zmir-enable-passes=+Inline -Zvalidate-mir -Zlint-mir --crate-type lib
//@ edition:2024
//@ check-pass
#![feature(async_drop)]
#![allow(incomplete_features)]
#![allow(non_snake_case)]
use std::mem::ManuallyDrop;
use std::{
future::{async_drop_in_place, Future},
pin::{pin, Pin},
sync::{mpsc, Arc},
task::{Context, Poll, Wake, Waker},
};
fn main() {
block_on(bar(0))
}
async fn baz(ident_base: usize) {}
async fn bar(ident_base: usize) {
baz(1).await
}
fn block_on<F>(fut_unpin: F) -> F::Output
where
F: Future,
{
let fut_pin = pin!(ManuallyDrop::new(fut_unpin));
let mut fut = unsafe { Pin::map_unchecked_mut(fut_pin, |x| &mut **x) };
let (waker, rx) = simple_waker();
let mut context = Context::from_waker(&waker);
let rv = loop {
match fut.as_mut().poll(&mut context) {
Poll::Ready(out) => break out,
PollPending => (),
}
};
let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) };
let drop_fut = pin!(drop_fut_unpin);
loop {
match drop_fut.poll(&mut context) {
Poll => break,
}
}
rv
}
fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
struct SimpleWaker {
tx: mpsc::Sender<()>,
}
impl Wake for SimpleWaker {
fn wake(self: Arc<Self>) {}
}
let (tx, rx) = mpsc::channel();
(Waker::from(Arc::new(SimpleWaker { tx })), rx)
}

View file

@ -0,0 +1,52 @@
// Make sure the generated suggestion suggest editing the user
// code instead of the std macro implementation
//@ run-rustfix
#![allow(dead_code)]
use std::fmt::{self, Display};
struct Mutex;
impl Mutex {
fn lock(&self) -> MutexGuard<'_> {
MutexGuard(self)
}
}
struct MutexGuard<'a>(&'a Mutex);
impl<'a> Drop for MutexGuard<'a> {
fn drop(&mut self) {}
}
struct Out;
impl Out {
fn write_fmt(&self, _args: fmt::Arguments) {}
}
impl<'a> Display for MutexGuard<'a> {
fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
Ok(())
}
}
fn main() {
let _write = {
let mutex = Mutex;
write!(Out, "{}", mutex.lock());
//~^ ERROR `mutex` does not live long enough
//~| SUGGESTION ;
};
let _write = {
use std::io::Write as _;
let mutex = Mutex;
let x = write!(std::io::stdout(), "{}", mutex.lock()); x
//~^ ERROR `mutex` does not live long enough
//~| SUGGESTION let x
};
}

View file

@ -0,0 +1,52 @@
// Make sure the generated suggestion suggest editing the user
// code instead of the std macro implementation
//@ run-rustfix
#![allow(dead_code)]
use std::fmt::{self, Display};
struct Mutex;
impl Mutex {
fn lock(&self) -> MutexGuard<'_> {
MutexGuard(self)
}
}
struct MutexGuard<'a>(&'a Mutex);
impl<'a> Drop for MutexGuard<'a> {
fn drop(&mut self) {}
}
struct Out;
impl Out {
fn write_fmt(&self, _args: fmt::Arguments) {}
}
impl<'a> Display for MutexGuard<'a> {
fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
Ok(())
}
}
fn main() {
let _write = {
let mutex = Mutex;
write!(Out, "{}", mutex.lock())
//~^ ERROR `mutex` does not live long enough
//~| SUGGESTION ;
};
let _write = {
use std::io::Write as _;
let mutex = Mutex;
write!(std::io::stdout(), "{}", mutex.lock())
//~^ ERROR `mutex` does not live long enough
//~| SUGGESTION let x
};
}

View file

@ -0,0 +1,47 @@
error[E0597]: `mutex` does not live long enough
--> $DIR/span-semicolon-issue-139049.rs:39:27
|
LL | let mutex = Mutex;
| ----- binding `mutex` declared here
LL | write!(Out, "{}", mutex.lock())
| ^^^^^-------
| |
| borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
...
LL | };
| -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard`
| |
| `mutex` dropped here while still borrowed
|
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
LL | write!(Out, "{}", mutex.lock());
| +
error[E0597]: `mutex` does not live long enough
--> $DIR/span-semicolon-issue-139049.rs:48:41
|
LL | let mutex = Mutex;
| ----- binding `mutex` declared here
LL | write!(std::io::stdout(), "{}", mutex.lock())
| ^^^^^-------
| |
| borrowed value does not live long enough
| a temporary with access to the borrow is created here ...
...
LL | };
| -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard`
| |
| `mutex` dropped here while still borrowed
|
= note: the temporary is part of an expression at the end of a block;
consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block
|
LL | let x = write!(std::io::stdout(), "{}", mutex.lock()); x
| +++++++ +++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0597`.

View file

@ -96,3 +96,108 @@ LL | takes_apit2(mk::<()>()?);
warning: 5 warnings emitted
Future incompatibility report: Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/never-type-fallback-breaking.rs:18:1
|
LL | fn m() {
| ^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: Default` will fail
--> $DIR/never-type-fallback-breaking.rs:22:17
|
LL | true => Default::default(),
| ^^^^^^^^^^^^^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let x: () = match true {
| ++++
Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/never-type-fallback-breaking.rs:30:1
|
LL | fn q() -> Option<()> {
| ^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: Default` will fail
--> $DIR/never-type-fallback-breaking.rs:37:5
|
LL | deserialize()?;
| ^^^^^^^^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | deserialize::<()>()?;
| ++++++
Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/never-type-fallback-breaking.rs:47:1
|
LL | fn meow() -> Result<(), ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `(): From<!>` will fail
--> $DIR/never-type-fallback-breaking.rs:50:5
|
LL | help(1)?;
| ^^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | help::<(), _>(1)?;
| +++++++++
Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/never-type-fallback-breaking.rs:59:1
|
LL | pub fn fallback_return() -> Result<(), ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: Default` will fail
--> $DIR/never-type-fallback-breaking.rs:62:19
|
LL | takes_apit(|| Default::default())?;
| ^^^^^^^^^^^^^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | takes_apit::<()>(|| Default::default())?;
| ++++++
Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/never-type-fallback-breaking.rs:73:1
|
LL | fn fully_apit() -> Result<(), ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: Default` will fail
--> $DIR/never-type-fallback-breaking.rs:76:17
|
LL | takes_apit2(mk()?);
| ^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | takes_apit2(mk::<()>()?);
| ++++++

View file

@ -1,57 +0,0 @@
//@ compile-flags: --target wasm32-unknown-unknown
//@ needs-llvm-components: webassembly
//@ add-core-stubs
//@ build-fail
#![feature(no_core, repr_simd)]
#![no_core]
#![crate_type = "lib"]
#![deny(wasm_c_abi)]
extern crate minicore;
use minicore::*;
pub extern "C" fn my_fun_trivial(_x: i32, _y: f32) {}
#[repr(C)]
pub struct MyType(i32, i32);
pub extern "C" fn my_fun(_x: MyType) {} //~ERROR: wasm ABI transition
//~^WARN: previously accepted
// This one is ABI-safe as it only wraps a single field,
// and the return type can be anything.
#[repr(C)]
pub struct MySafeType(i32);
pub extern "C" fn my_fun_safe(_x: MySafeType) -> MyType { loop {} }
// This one not ABI-safe due to the alignment.
#[repr(C, align(16))]
pub struct MyAlignedType(i32);
pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {} //~ERROR: wasm ABI transition
//~^WARN: previously accepted
// Check call-site warning
extern "C" {
fn other_fun(x: MyType);
}
pub fn call_other_fun(x: MyType) {
unsafe { other_fun(x) } //~ERROR: wasm ABI transition
//~^WARN: previously accepted
}
// Zero-sized types are safe in both ABIs
#[repr(C)]
pub struct MyZstType;
#[allow(improper_ctypes_definitions)]
pub extern "C" fn zst_safe(_x: (), _y: MyZstType) {}
// The old and new wasm ABI treats simd types like `v128` the same way, so no
// wasm_c_abi warning should be emitted.
#[repr(simd)]
#[allow(non_camel_case_types)]
pub struct v128([i32; 4]);
#[target_feature(enable = "simd128")]
pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
//~^ WARN `extern` fn uses type `v128`, which is not FFI-safe
//~| WARN `extern` fn uses type `v128`, which is not FFI-safe

View file

@ -1,114 +0,0 @@
warning: `extern` fn uses type `v128`, which is not FFI-safe
--> $DIR/wasm_c_abi_transition.rs:55:35
|
LL | pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
| ^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
--> $DIR/wasm_c_abi_transition.rs:53:1
|
LL | pub struct v128([i32; 4]);
| ^^^^^^^^^^^^^^^
= note: `#[warn(improper_ctypes_definitions)]` on by default
warning: `extern` fn uses type `v128`, which is not FFI-safe
--> $DIR/wasm_c_abi_transition.rs:55:44
|
LL | pub extern "C" fn my_safe_simd(x: v128) -> v128 { x }
| ^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
--> $DIR/wasm_c_abi_transition.rs:53:1
|
LL | pub struct v128([i32; 4]);
| ^^^^^^^^^^^^^^^
error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
--> $DIR/wasm_c_abi_transition.rs:18:1
|
LL | pub extern "C" fn my_fun(_x: MyType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
note: the lint level is defined here
--> $DIR/wasm_c_abi_transition.rs:9:9
|
LL | #![deny(wasm_c_abi)]
| ^^^^^^^^^^
error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition
--> $DIR/wasm_c_abi_transition.rs:30:1
|
LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition
--> $DIR/wasm_c_abi_transition.rs:39:14
|
LL | unsafe { other_fun(x) }
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
error: aborting due to 3 previous errors; 2 warnings emitted
Future incompatibility report: Future breakage diagnostic:
error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
--> $DIR/wasm_c_abi_transition.rs:18:1
|
LL | pub extern "C" fn my_fun(_x: MyType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
note: the lint level is defined here
--> $DIR/wasm_c_abi_transition.rs:9:9
|
LL | #![deny(wasm_c_abi)]
| ^^^^^^^^^^
Future breakage diagnostic:
error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition
--> $DIR/wasm_c_abi_transition.rs:30:1
|
LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
note: the lint level is defined here
--> $DIR/wasm_c_abi_transition.rs:9:9
|
LL | #![deny(wasm_c_abi)]
| ^^^^^^^^^^
Future breakage diagnostic:
error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition
--> $DIR/wasm_c_abi_transition.rs:39:14
|
LL | unsafe { other_fun(x) }
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
= help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
note: the lint level is defined here
--> $DIR/wasm_c_abi_transition.rs:9:9
|
LL | #![deny(wasm_c_abi)]
| ^^^^^^^^^^

View file

@ -14,6 +14,10 @@ LL | };
| |
| `mutex` dropped here while still borrowed
|
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
LL | write!(Out, "{}", mutex.lock()); /* no semicolon */
| +
error[E0597]: `mutex` does not live long enough
--> $DIR/format-args-temporaries-in-write.rs:47:29
@ -31,6 +35,10 @@ LL | };
| |
| `mutex` dropped here while still borrowed
|
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
LL | writeln!(Out, "{}", mutex.lock()); /* no semicolon */
| +
error: aborting due to 2 previous errors

View file

@ -20,3 +20,24 @@ LL | let _x: () = return;
warning: 1 warning emitted
Future incompatibility report: Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/defaulted-never-note.rs:28:1
|
LL | fn smeg() {
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: ImplementedForUnitButNotNever` will fail
--> $DIR/defaulted-never-note.rs:32:9
|
LL | foo(_x);
| ^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let _x: () = return;
| ++++

View file

@ -40,3 +40,46 @@ LL | deserialize::<()>()?;
warning: 2 warnings emitted
Future incompatibility report: Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/dependency-on-fallback-to-unit.rs:8:1
|
LL | fn def() {
| ^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: Default` will fail
--> $DIR/dependency-on-fallback-to-unit.rs:12:19
|
LL | false => <_>::default(),
| ^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL - false => <_>::default(),
LL + false => <()>::default(),
|
Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/dependency-on-fallback-to-unit.rs:19:1
|
LL | fn question_mark() -> Result<(), ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: Default` will fail
--> $DIR/dependency-on-fallback-to-unit.rs:22:5
|
LL | deserialize()?;
| ^^^^^^^^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | deserialize::<()>()?;
| ++++++

View file

@ -39,3 +39,45 @@ LL | let x: ();
warning: 2 warnings emitted
Future incompatibility report: Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/diverging-fallback-control-flow.rs:30:1
|
LL | fn assignment() {
| ^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: UnitDefault` will fail
--> $DIR/diverging-fallback-control-flow.rs:36:13
|
LL | x = UnitDefault::default();
| ^^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let x: ();
| ++++
Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/diverging-fallback-control-flow.rs:42:1
|
LL | fn assignment_rev() {
| ^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: UnitDefault` will fail
--> $DIR/diverging-fallback-control-flow.rs:50:13
|
LL | x = UnitDefault::default();
| ^^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let x: ();
| ++++

View file

@ -20,3 +20,24 @@ LL | unconstrained_arg::<()>(return);
warning: 1 warning emitted
Future incompatibility report: Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/diverging-fallback-no-leak.rs:14:1
|
LL | fn main() {
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: Test` will fail
--> $DIR/diverging-fallback-no-leak.rs:20:23
|
LL | unconstrained_arg(return);
| ^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | unconstrained_arg::<()>(return);
| ++++++

View file

@ -20,3 +20,24 @@ LL | let _: () = if true { unconstrained_return() } else { panic!() };
warning: 1 warning emitted
Future incompatibility report: Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/diverging-fallback-unconstrained-return.rs:28:1
|
LL | fn main() {
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: UnitReturn` will fail
--> $DIR/diverging-fallback-unconstrained-return.rs:39:23
|
LL | let _ = if true { unconstrained_return() } else { panic!() };
| ^^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let _: () = if true { unconstrained_return() } else { panic!() };
| ++++

View file

@ -24,3 +24,28 @@ LL | let created: () = create_ok_default()?;
error: aborting due to 1 previous error
Future incompatibility report: Future breakage diagnostic:
error: this function depends on never type fallback being `()`
--> $DIR/dont-suggest-turbofish-from-expansion.rs:10:1
|
LL | fn main() -> Result<(), ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: Default` will fail
--> $DIR/dont-suggest-turbofish-from-expansion.rs:14:23
|
LL | let created = create_ok_default()?;
| ^^^^^^^^^^^^^^^^^^^
note: the lint level is defined here
--> $DIR/dont-suggest-turbofish-from-expansion.rs:1:9
|
LL | #![deny(dependency_on_unit_never_type_fallback)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: use `()` annotations to avoid fallback changes
|
LL | let created: () = create_ok_default()?;
| ++++

View file

@ -20,3 +20,24 @@ LL | foo::<()>(|| panic!());
warning: 1 warning emitted
Future incompatibility report: Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/fallback-closure-ret.rs:21:1
|
LL | fn main() {
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: Bar` will fail
--> $DIR/fallback-closure-ret.rs:24:5
|
LL | foo(|| panic!());
| ^^^^^^^^^^^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | foo::<()>(|| panic!());
| ++++++

View file

@ -16,3 +16,20 @@ LL | fn should_ret_unit() -> impl T {
warning: 1 warning emitted
Future incompatibility report: Future breakage diagnostic:
warning: this function depends on never type fallback being `()`
--> $DIR/impl_trait_fallback.rs:8:1
|
LL | fn should_ret_unit() -> impl T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: T` will fail
--> $DIR/impl_trait_fallback.rs:8:25
|
LL | fn should_ret_unit() -> impl T {
| ^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default

View file

@ -24,3 +24,28 @@ LL | _ = foo::<()>()?;
error: aborting due to 1 previous error
Future incompatibility report: Future breakage diagnostic:
error: this function depends on never type fallback being `()`
--> $DIR/lint-breaking-2024-assign-underscore.rs:10:1
|
LL | fn test() -> Result<(), ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: Default` will fail
--> $DIR/lint-breaking-2024-assign-underscore.rs:13:9
|
LL | _ = foo()?;
| ^^^^^
note: the lint level is defined here
--> $DIR/lint-breaking-2024-assign-underscore.rs:4:9
|
LL | #![deny(dependency_on_unit_never_type_fallback)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: use `()` annotations to avoid fallback changes
|
LL | _ = foo::<()>()?;
| ++++++

View file

@ -133,3 +133,155 @@ LL | msg_send!();
warning: 10 warnings emitted
Future incompatibility report: Future breakage diagnostic:
warning: never type fallback affects this call to an `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18
|
LL | unsafe { mem::zeroed() }
| ^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | unsafe { mem::zeroed::<()>() }
| ++++++
Future breakage diagnostic:
warning: never type fallback affects this call to an `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13
|
LL | core::mem::transmute(Zst)
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | core::mem::transmute::<_, ()>(Zst)
| +++++++++
Future breakage diagnostic:
warning: never type fallback affects this union access
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18
|
LL | unsafe { Union { a: () }.b }
| ^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
Future breakage diagnostic:
warning: never type fallback affects this raw pointer dereference
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18
|
LL | unsafe { *ptr::from_ref(&()).cast() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | unsafe { *ptr::from_ref(&()).cast::<()>() }
| ++++++
Future breakage diagnostic:
warning: never type fallback affects this call to an `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18
|
LL | unsafe { internally_create(x) }
| ^^^^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | unsafe { internally_create::<()>(x) }
| ++++++
Future breakage diagnostic:
warning: never type fallback affects this call to an `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18
|
LL | unsafe { zeroed() }
| ^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let zeroed = mem::zeroed::<()>;
| ++++++
Future breakage diagnostic:
warning: never type fallback affects this `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22
|
LL | let zeroed = mem::zeroed;
| ^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let zeroed = mem::zeroed::<()>;
| ++++++
Future breakage diagnostic:
warning: never type fallback affects this `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17
|
LL | let f = internally_create;
| ^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let f = internally_create::<()>;
| ++++++
Future breakage diagnostic:
warning: never type fallback affects this call to an `unsafe` method
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13
|
LL | S(marker::PhantomData).create_out_of_thin_air()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
Future breakage diagnostic:
warning: never type fallback affects this call to an `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19
|
LL | match send_message::<_ /* ?0 */>() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | msg_send!();
| ----------- in this macro invocation
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
= note: this warning originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)

View file

@ -142,3 +142,155 @@ LL | unsafe { mem::zeroed() }
error: aborting due to 10 previous errors; 1 warning emitted
Future incompatibility report: Future breakage diagnostic:
error: never type fallback affects this call to an `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18
|
LL | unsafe { mem::zeroed() }
| ^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | unsafe { mem::zeroed::<()>() }
| ++++++
Future breakage diagnostic:
error: never type fallback affects this call to an `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13
|
LL | core::mem::transmute(Zst)
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | core::mem::transmute::<_, ()>(Zst)
| +++++++++
Future breakage diagnostic:
error: never type fallback affects this union access
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18
|
LL | unsafe { Union { a: () }.b }
| ^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
Future breakage diagnostic:
error: never type fallback affects this raw pointer dereference
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18
|
LL | unsafe { *ptr::from_ref(&()).cast() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | unsafe { *ptr::from_ref(&()).cast::<()>() }
| ++++++
Future breakage diagnostic:
error: never type fallback affects this call to an `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18
|
LL | unsafe { internally_create(x) }
| ^^^^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | unsafe { internally_create::<()>(x) }
| ++++++
Future breakage diagnostic:
error: never type fallback affects this call to an `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18
|
LL | unsafe { zeroed() }
| ^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let zeroed = mem::zeroed::<()>;
| ++++++
Future breakage diagnostic:
error: never type fallback affects this `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22
|
LL | let zeroed = mem::zeroed;
| ^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let zeroed = mem::zeroed::<()>;
| ++++++
Future breakage diagnostic:
error: never type fallback affects this `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17
|
LL | let f = internally_create;
| ^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
help: use `()` annotations to avoid fallback changes
|
LL | let f = internally_create::<()>;
| ++++++
Future breakage diagnostic:
error: never type fallback affects this call to an `unsafe` method
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13
|
LL | S(marker::PhantomData).create_out_of_thin_air()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
Future breakage diagnostic:
error: never type fallback affects this call to an `unsafe` function
--> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19
|
LL | match send_message::<_ /* ?0 */>() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | msg_send!();
| ----------- in this macro invocation
|
= warning: this changes meaning in Rust 2024 and in a future release in all editions!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
= help: specify the type explicitly
= note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
= note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)