add FCW to warn about wasm ABI transition
This commit is contained in:
parent
be73c1f461
commit
c961d123d2
8 changed files with 259 additions and 13 deletions
|
@ -143,6 +143,7 @@ declare_lint_pass! {
|
||||||
UNUSED_VARIABLES,
|
UNUSED_VARIABLES,
|
||||||
USELESS_DEPRECATED,
|
USELESS_DEPRECATED,
|
||||||
WARNINGS,
|
WARNINGS,
|
||||||
|
WASM_C_ABI,
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -5082,6 +5083,8 @@ declare_lint! {
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// This will produce:
|
||||||
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// warning: ABI error: this function call uses a avx vector type, which is not enabled in the caller
|
/// warning: ABI error: this function call uses a avx vector type, which is not enabled in the caller
|
||||||
/// --> lint_example.rs:18:12
|
/// --> lint_example.rs:18:12
|
||||||
|
@ -5125,3 +5128,46 @@ declare_lint! {
|
||||||
reference: "issue #116558 <https://github.com/rust-lang/rust/issues/116558>",
|
reference: "issue #116558 <https://github.com/rust-lang/rust/issues/116558>",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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::FutureReleaseErrorReportInDeps,
|
||||||
|
reference: "issue #138762 <https://github.com/rust-lang/rust/issues/138762>",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -63,4 +63,11 @@ monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
|
||||||
monomorphize_unknown_cgu_collection_mode =
|
monomorphize_unknown_cgu_collection_mode =
|
||||||
unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
|
unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
|
||||||
|
|
||||||
|
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}'
|
monomorphize_written_to_path = the full type name has been written to '{$path}'
|
||||||
|
|
|
@ -103,3 +103,12 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
|
||||||
/// Whether this is a problem at a call site or at a declaration.
|
/// Whether this is a problem at a call site or at a declaration.
|
||||||
pub is_call: bool,
|
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,11 +3,13 @@
|
||||||
use rustc_abi::{BackendRepr, RegKind};
|
use rustc_abi::{BackendRepr, RegKind};
|
||||||
use rustc_hir::CRATE_HIR_ID;
|
use rustc_hir::CRATE_HIR_ID;
|
||||||
use rustc_middle::mir::{self, traversal};
|
use rustc_middle::mir::{self, traversal};
|
||||||
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
|
use rustc_middle::ty::layout::LayoutCx;
|
||||||
use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES;
|
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv};
|
||||||
|
use rustc_session::lint::builtin::{ABI_UNSUPPORTED_VECTOR_TYPES, WASM_C_ABI};
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||||
use rustc_target::callconv::{Conv, FnAbi, PassMode};
|
use rustc_target::callconv::{ArgAbi, Conv, FnAbi, PassMode};
|
||||||
|
use rustc_target::spec::{HasWasmCAbiOpt, WasmCAbi};
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
|
|
||||||
|
@ -26,13 +28,15 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
|
||||||
/// for a certain function.
|
/// for a certain function.
|
||||||
/// `is_call` indicates whether this is a call-site check or a definition-site check;
|
/// `is_call` indicates whether this is a call-site check or a definition-site check;
|
||||||
/// this is only relevant for the wording in the emitted error.
|
/// this is only relevant for the wording in the emitted error.
|
||||||
fn do_check_abi<'tcx>(
|
fn do_check_simd_vector_abi<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
abi: &FnAbi<'tcx, Ty<'tcx>>,
|
abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
is_call: bool,
|
is_call: bool,
|
||||||
span: impl Fn() -> Span,
|
span: impl Fn() -> Span,
|
||||||
) {
|
) {
|
||||||
|
// We check this on all functions, including those using the "Rust" ABI.
|
||||||
|
// For the "Rust" ABI it would be a bug if the lint ever triggered, but better safe than sorry.
|
||||||
let feature_def = tcx.sess.target.features_for_correct_vector_abi();
|
let feature_def = tcx.sess.target.features_for_correct_vector_abi();
|
||||||
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
|
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
|
||||||
let have_feature = |feat: Symbol| {
|
let have_feature = |feat: Symbol| {
|
||||||
|
@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
|
||||||
|
if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
span: impl Fn() -> Span,
|
||||||
|
) {
|
||||||
|
// 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`).
|
||||||
|
if !(tcx.sess.target.arch == "wasm32"
|
||||||
|
&& tcx.sess.target.os == "unknown"
|
||||||
|
&& tcx.wasm_c_abi_opt() == WasmCAbi::Legacy
|
||||||
|
&& abi.conv == Conv::C)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Warn against all types whose ABI will change. That's all arguments except for things passed as scalars.
|
||||||
|
// 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 = span();
|
||||||
|
tcx.emit_node_span_lint(
|
||||||
|
WASM_C_ABI,
|
||||||
|
CRATE_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
|
/// 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.
|
/// or return values for which the corresponding target feature is not enabled.
|
||||||
fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
|
fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
|
||||||
|
@ -98,13 +156,10 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
|
||||||
// function.
|
// function.
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
do_check_abi(
|
do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, || {
|
||||||
tcx,
|
tcx.def_span(instance.def_id())
|
||||||
abi,
|
});
|
||||||
instance.def_id(),
|
do_check_wasm_abi(tcx, abi, /*is_call*/ false, || tcx.def_span(instance.def_id()));
|
||||||
/*is_call*/ false,
|
|
||||||
|| tcx.def_span(instance.def_id()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that a call expression does not try to pass a vector-passed argument which requires a
|
/// Checks that a call expression does not try to pass a vector-passed argument which requires a
|
||||||
|
@ -141,7 +196,8 @@ fn check_call_site_abi<'tcx>(
|
||||||
// ABI failed to compute; this will not get through codegen.
|
// ABI failed to compute; this will not get through codegen.
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
do_check_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span);
|
do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span);
|
||||||
|
do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, || span);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) {
|
fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) {
|
||||||
|
|
|
@ -10,6 +10,9 @@ where
|
||||||
if val.layout.is_aggregate() {
|
if val.layout.is_aggregate() {
|
||||||
if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) {
|
if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) {
|
||||||
let size = val.layout.size;
|
let size = val.layout.size;
|
||||||
|
// This size check also catches over-aligned scalars as `size` will be rounded up to a
|
||||||
|
// multiple of the alignment, and the default alignment of all scalar types on wasm
|
||||||
|
// equals their size.
|
||||||
if unit.size == size {
|
if unit.size == size {
|
||||||
val.cast_to(unit);
|
val.cast_to(unit);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -62,7 +62,6 @@
|
||||||
//@[nvptx64] needs-llvm-components: nvptx
|
//@[nvptx64] needs-llvm-components: nvptx
|
||||||
#![feature(no_core, rustc_attrs, lang_items)]
|
#![feature(no_core, rustc_attrs, lang_items)]
|
||||||
#![feature(unsized_fn_params, transparent_unions)]
|
#![feature(unsized_fn_params, transparent_unions)]
|
||||||
#![no_std]
|
|
||||||
#![no_core]
|
#![no_core]
|
||||||
#![allow(unused, improper_ctypes_definitions, internal_features)]
|
#![allow(unused, improper_ctypes_definitions, internal_features)]
|
||||||
|
|
||||||
|
|
41
tests/ui/lint/wasm_c_abi_transition.rs
Normal file
41
tests/ui/lint/wasm_c_abi_transition.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
//@ compile-flags: --target wasm32-unknown-unknown
|
||||||
|
//@ needs-llvm-components: webassembly
|
||||||
|
//@ add-core-stubs
|
||||||
|
//@ build-fail
|
||||||
|
|
||||||
|
#![feature(no_core)]
|
||||||
|
#![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
|
||||||
|
}
|
85
tests/ui/lint/wasm_c_abi_transition.stderr
Normal file
85
tests/ui/lint/wasm_c_abi_transition.stderr
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
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)]
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue