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:
commit
e314b97ee5
98 changed files with 2791 additions and 1030 deletions
7
.mailmap
7
.mailmap
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"))]
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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}'
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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})");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]+}}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
11
tests/mir-opt/async_drop_live_dead.rs
Normal file
11
tests/mir-opt/async_drop_live_dead.rs
Normal 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() {}
|
||||
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
46
tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.rs
Normal file
46
tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.rs
Normal 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
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
|
@ -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());
|
||||
}
|
||||
56
tests/ui/async-await/async-drop/live-dead-storage3.rs
Normal file
56
tests/ui/async-await/async-drop/live-dead-storage3.rs
Normal 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
|
||||
}
|
||||
56
tests/ui/async-await/async-drop/live-dead-storage4.rs
Normal file
56
tests/ui/async-await/async-drop/live-dead-storage4.rs
Normal 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)
|
||||
}
|
||||
52
tests/ui/borrowck/span-semicolon-issue-139049.fixed
Normal file
52
tests/ui/borrowck/span-semicolon-issue-139049.fixed
Normal 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
|
||||
};
|
||||
}
|
||||
52
tests/ui/borrowck/span-semicolon-issue-139049.rs
Normal file
52
tests/ui/borrowck/span-semicolon-issue-139049.rs
Normal 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
|
||||
};
|
||||
}
|
||||
47
tests/ui/borrowck/span-semicolon-issue-139049.stderr
Normal file
47
tests/ui/borrowck/span-semicolon-issue-139049.stderr
Normal 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`.
|
||||
|
|
@ -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::<()>()?);
|
||||
| ++++++
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
| ++++
|
||||
|
||||
|
|
|
|||
|
|
@ -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::<()>()?;
|
||||
| ++++++
|
||||
|
||||
|
|
|
|||
|
|
@ -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: ();
|
||||
| ++++
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
| ++++++
|
||||
|
||||
|
|
|
|||
|
|
@ -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!() };
|
||||
| ++++
|
||||
|
||||
|
|
|
|||
|
|
@ -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()?;
|
||||
| ++++
|
||||
|
||||
|
|
|
|||
|
|
@ -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!());
|
||||
| ++++++
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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::<()>()?;
|
||||
| ++++++
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue