diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 3724438cc6ed2..87c4bfae1af23 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -196,6 +196,14 @@ impl<'a> PostExpansionVisitor<'a> { "thiscall-unwind ABI is experimental and subject to change" ); } + "wasm" => { + gate_feature_post!( + &self, + wasm_abi, + span, + "wasm ABI is experimental and subject to change" + ); + } abi => self .sess .parse_sess diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 64ebe585dd837..0bc5b0d69099e 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -13,6 +13,7 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::{OptLevel, SanitizerSet}; use rustc_session::Session; +use rustc_target::spec::abi::Abi; use rustc_target::spec::StackProbeType; use crate::attributes; @@ -289,7 +290,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: // The target doesn't care; the subtarget reads our attribute. apply_tune_cpu_attr(cx, llfn); - let function_features = codegen_fn_attrs + let mut function_features = codegen_fn_attrs .target_features .iter() .map(|f| { @@ -301,6 +302,18 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(), })) .collect::>(); + + // The `"wasm"` abi on wasm targets automatically enables the `+multivalue` + // feature because the purpose of the wasm abi is to match the WebAssembly + // specification, which has this feature. This won't be needed when LLVM + // enables this `multivalue` feature by default. + if cx.tcx.sess.target.arch == "wasm32" && !cx.tcx.is_closure(instance.def_id()) { + let abi = cx.tcx.fn_sig(instance.def_id()).abi(); + if abi == Abi::Wasm { + function_features.push("+multivalue".to_string()); + } + } + if !function_features.is_empty() { let mut global_features = llvm_util::llvm_global_features(cx.tcx.sess); global_features.extend(function_features.into_iter()); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 32f4fc76b3d1f..afc2bdbfd52ec 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -250,13 +250,9 @@ fn add_unused_function_coverage( // Insert at least one real counter so the LLVM CoverageMappingReader will find expected // definitions. function_coverage.add_counter(UNUSED_FUNCTION_COUNTER_ID, code_region.clone()); + } else { + function_coverage.add_unreachable_region(code_region.clone()); } - // Add a Zero Counter for every code region. - // - // Even though the first coverage region already has an actual Counter, `llvm-cov` will not - // always report it. Re-adding an unreachable region (zero counter) for the same region - // seems to help produce the expected coverage. - function_coverage.add_unreachable_region(code_region.clone()); } if let Some(coverage_context) = cx.coverage_context() { diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs index af6c476292bd1..962c01c2ee7a6 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs @@ -24,21 +24,39 @@ pub enum CounterKind { pub struct Counter { // Important: The layout (order and types of fields) must match its C++ counterpart. pub kind: CounterKind, - pub id: u32, + id: u32, } impl Counter { + /// Constructs a new `Counter` of kind `Zero`. For this `CounterKind`, the + /// `id` is not used. pub fn zero() -> Self { Self { kind: CounterKind::Zero, id: 0 } } + /// Constructs a new `Counter` of kind `CounterValueReference`, and converts + /// the given 1-based counter_id to the required 0-based equivalent for + /// the `Counter` encoding. pub fn counter_value_reference(counter_id: CounterValueReference) -> Self { - Self { kind: CounterKind::CounterValueReference, id: counter_id.into() } + Self { kind: CounterKind::CounterValueReference, id: counter_id.zero_based_index() } } + /// Constructs a new `Counter` of kind `Expression`. pub fn expression(mapped_expression_index: MappedExpressionIndex) -> Self { Self { kind: CounterKind::Expression, id: mapped_expression_index.into() } } + + /// Returns true if the `Counter` kind is `Zero`. + pub fn is_zero(&self) -> bool { + matches!(self.kind, CounterKind::Zero) + } + + /// An explicitly-named function to get the ID value, making it more obvious + /// that the stored value is now 0-based. + pub fn zero_based_id(&self) -> u32 { + debug_assert!(!self.is_zero(), "`id` is undefined for CounterKind::Zero"); + self.id + } } /// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147) diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs index 7a17bced1c0b0..4458fd686788f 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs @@ -163,9 +163,7 @@ impl<'tcx> FunctionCoverage<'tcx> { self.counters.iter_enumerated().filter_map(|(index, entry)| { // Option::map() will return None to filter out missing counters. This may happen // if, for example, a MIR-instrumented counter is removed during an optimization. - entry.as_ref().map(|region| { - (Counter::counter_value_reference(index as CounterValueReference), region) - }) + entry.as_ref().map(|region| (Counter::counter_value_reference(index), region)) }) } @@ -206,9 +204,15 @@ impl<'tcx> FunctionCoverage<'tcx> { if id == ExpressionOperandId::ZERO { Some(Counter::zero()) } else if id.index() < self.counters.len() { + debug_assert!( + id.index() > 0, + "ExpressionOperandId indexes for counters are 1-based, but this id={}", + id.index() + ); // Note: Some codegen-injected Counters may be only referenced by `Expression`s, // and may not have their own `CodeRegion`s, let index = CounterValueReference::from(id.index()); + // Note, the conversion to LLVM `Counter` adjusts the index to be zero-based. Some(Counter::counter_value_reference(index)) } else { let index = self.expression_index(u32::from(id)); @@ -233,19 +237,60 @@ impl<'tcx> FunctionCoverage<'tcx> { let optional_region = &expression.region; let Expression { lhs, op, rhs, .. } = *expression; - if let Some(Some((lhs_counter, rhs_counter))) = - id_to_counter(&new_indexes, lhs).map(|lhs_counter| { + if let Some(Some((lhs_counter, mut rhs_counter))) = id_to_counter(&new_indexes, lhs) + .map(|lhs_counter| { id_to_counter(&new_indexes, rhs).map(|rhs_counter| (lhs_counter, rhs_counter)) }) { + if lhs_counter.is_zero() && op.is_subtract() { + // The left side of a subtraction was probably optimized out. As an example, + // a branch condition might be evaluated as a constant expression, and the + // branch could be removed, dropping unused counters in the process. + // + // Since counters are unsigned, we must assume the result of the expression + // can be no more and no less than zero. An expression known to evaluate to zero + // does not need to be added to the coverage map. + // + // Coverage test `loops_branches.rs` includes multiple variations of branches + // based on constant conditional (literal `true` or `false`), and demonstrates + // that the expected counts are still correct. + debug!( + "Expression subtracts from zero (assume unreachable): \ + original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", + original_index, lhs, op, rhs, optional_region, + ); + rhs_counter = Counter::zero(); + } debug_assert!( - (lhs_counter.id as usize) - < usize::max(self.counters.len(), self.expressions.len()) + lhs_counter.is_zero() + // Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16` + || ((lhs_counter.zero_based_id() as usize) + <= usize::max(self.counters.len(), self.expressions.len())), + "lhs id={} > both counters.len()={} and expressions.len()={} + ({:?} {:?} {:?})", + lhs_counter.zero_based_id(), + self.counters.len(), + self.expressions.len(), + lhs_counter, + op, + rhs_counter, ); + debug_assert!( - (rhs_counter.id as usize) - < usize::max(self.counters.len(), self.expressions.len()) + rhs_counter.is_zero() + // Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16` + || ((rhs_counter.zero_based_id() as usize) + <= usize::max(self.counters.len(), self.expressions.len())), + "rhs id={} > both counters.len()={} and expressions.len()={} + ({:?} {:?} {:?})", + rhs_counter.zero_based_id(), + self.counters.len(), + self.expressions.len(), + lhs_counter, + op, + rhs_counter, ); + // Both operands exist. `Expression` operands exist in `self.expressions` and have // been assigned a `new_index`. let mapped_expression_index = @@ -268,11 +313,15 @@ impl<'tcx> FunctionCoverage<'tcx> { expression_regions.push((Counter::expression(mapped_expression_index), region)); } } else { - debug!( - "Ignoring expression with one or more missing operands: \ - original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", - original_index, lhs, op, rhs, optional_region, - ) + bug!( + "expression has one or more missing operands \ + original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}", + original_index, + lhs, + op, + rhs, + optional_region, + ); } } (counter_expressions, expression_regions.into_iter()) diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index e2f75b2e337cc..621ec0519c956 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(function_source_hash); let num_counters = bx.const_u32(coverageinfo.num_counters); - let index = bx.const_u32(u32::from(id)); + let index = bx.const_u32(id.zero_based_index()); debug!( "codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})", fn_name, hash, num_counters, index, diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 040260f5cf5a4..92358ffb37f1c 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -645,6 +645,9 @@ declare_features! ( /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries. (active, c_unwind, "1.52.0", Some(74990), None), + /// Allows `extern "wasm" fn` + (active, wasm_abi, "1.53.0", Some(83788), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs index 28529affd5d5a..b1f78a83e7407 100644 --- a/compiler/rustc_hir/src/pat_util.rs +++ b/compiler/rustc_hir/src/pat_util.rs @@ -1,6 +1,7 @@ use crate::def::{CtorOf, DefKind, Res}; use crate::def_id::DefId; use crate::hir::{self, HirId, PatKind}; +use rustc_data_structures::stable_set::FxHashSet; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -118,8 +119,10 @@ impl hir::Pat<'_> { } _ => true, }); - variants.sort(); - variants.dedup(); + // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering + // the bounds + let mut duplicates = FxHashSet::default(); + variants.retain(|def_id| duplicates.insert(*def_id)); variants } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index ad48b236a9a1d..ddb1a84fe7bdf 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -41,8 +41,16 @@ rustc_index::newtype_index! { } impl CounterValueReference { - // Counters start at 1 to reserve 0 for ExpressionOperandId::ZERO. + /// Counters start at 1 to reserve 0 for ExpressionOperandId::ZERO. pub const START: Self = Self::from_u32(1); + + /// Returns explicitly-requested zero-based version of the counter id, used + /// during codegen. LLVM expects zero-based indexes. + pub fn zero_based_index(&self) -> u32 { + let one_based_index = self.as_u32(); + debug_assert!(one_based_index > 0); + one_based_index - 1 + } } rustc_index::newtype_index! { @@ -175,3 +183,13 @@ pub enum Op { Subtract, Add, } + +impl Op { + pub fn is_add(&self) -> bool { + matches!(self, Self::Add) + } + + pub fn is_subtract(&self) -> bool { + matches!(self, Self::Subtract) + } +} diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index e7bbdc3ccebdf..c2e9dba6c8e8a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2630,6 +2630,7 @@ fn fn_can_unwind( | AvrInterrupt | AvrNonBlockingInterrupt | CCmseNonSecureCall + | Wasm | RustIntrinsic | PlatformIntrinsic | Unadjusted => false, @@ -2712,6 +2713,7 @@ where AmdGpuKernel => Conv::AmdGpuKernel, AvrInterrupt => Conv::AvrInterrupt, AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt, + Wasm => Conv::C, // These API constants ought to be more specific... Cdecl => Conv::C, diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index fd5dbfb186efd..1fda71d74bbf5 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -59,11 +59,15 @@ //! //! ### Discovering roots //! -//! The roots of the mono item graph correspond to the non-generic +//! The roots of the mono item graph correspond to the public non-generic //! syntactic items in the source code. We find them by walking the HIR of the -//! crate, and whenever we hit upon a function, method, or static item, we -//! create a mono item consisting of the items DefId and, since we only -//! consider non-generic items, an empty type-substitution set. +//! crate, and whenever we hit upon a public function, method, or static item, +//! we create a mono item consisting of the items DefId and, since we only +//! consider non-generic items, an empty type-substitution set. (In eager +//! collection mode, during incremental compilation, all non-generic functions +//! are considered as roots, as well as when the `-Clink-dead-code` option is +//! specified. Functions marked `#[no_mangle]` and functions called by inlinable +//! functions also always act as roots.) //! //! ### Finding neighbor nodes //! Given a mono item node, we can discover neighbors by inspecting its diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index c90f94c6d63fb..3a189e6b33dda 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -609,6 +609,7 @@ fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: LocalDefId, abi: Abi) -> bo | AvrInterrupt | AvrNonBlockingInterrupt | CCmseNonSecureCall + | Wasm | RustIntrinsic | PlatformIntrinsic | Unadjusted => true, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c5f929ab183a5..890e058fbf9f2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1294,6 +1294,7 @@ symbols! { vreg, vreg_low16, warn, + wasm_abi, wasm_import_module, wasm_target_feature, while_let, diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 2c3f7762759bf..56a176c8a9a8e 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -19,7 +19,6 @@ mod s390x; mod sparc; mod sparc64; mod wasm32; -mod wasm32_bindgen_compat; mod x86; mod x86_64; mod x86_win64; @@ -647,11 +646,14 @@ impl<'a, Ty> FnAbi<'a, Ty> { "nvptx64" => nvptx64::compute_abi_info(self), "hexagon" => hexagon::compute_abi_info(self), "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), - "wasm32" => match cx.target_spec().os.as_str() { - "emscripten" | "wasi" => wasm32::compute_abi_info(cx, self), - _ => wasm32_bindgen_compat::compute_abi_info(self), - }, - "asmjs" => wasm32::compute_abi_info(cx, self), + "wasm32" => { + if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::Wasm { + wasm32::compute_wasm_abi_info(self) + } else { + wasm32::compute_c_abi_info(cx, self) + } + } + "asmjs" => wasm32::compute_c_abi_info(cx, self), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), } diff --git a/compiler/rustc_target/src/abi/call/wasm32.rs b/compiler/rustc_target/src/abi/call/wasm32.rs index ff2c0e9bb6fcc..bf2c08bb1662d 100644 --- a/compiler/rustc_target/src/abi/call/wasm32.rs +++ b/compiler/rustc_target/src/abi/call/wasm32.rs @@ -40,7 +40,8 @@ where } } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +/// The purpose of this ABI is to match the C ABI (aka clang) exactly. +pub fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAndLayoutMethods<'a, C> + Copy, C: LayoutOf> + HasDataLayout, @@ -56,3 +57,27 @@ 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. +pub fn compute_wasm_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { + if !fn_abi.ret.is_ignore() { + classify_ret(&mut fn_abi.ret); + } + + for arg in &mut fn_abi.args { + if arg.is_ignore() { + continue; + } + classify_arg(arg); + } + + fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { + ret.extend_integer_width_to(32); + } + + fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { + arg.extend_integer_width_to(32); + } +} diff --git a/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs b/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs deleted file mode 100644 index 59571fd9d4821..0000000000000 --- a/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs +++ /dev/null @@ -1,29 +0,0 @@ -// This is not and has never been a correct C ABI for WebAssembly, but -// for a long time this was the C ABI that Rust used. wasm-bindgen -// depends on ABI details for this ABI and is incompatible with the -// correct C ABI, so this ABI is being kept around until wasm-bindgen -// can be fixed to work with the correct ABI. See #63649 for further -// discussion. - -use crate::abi::call::{ArgAbi, FnAbi}; - -fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { - ret.extend_integer_width_to(32); -} - -fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { - arg.extend_integer_width_to(32); -} - -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { - if !fn_abi.ret.is_ignore() { - classify_ret(&mut fn_abi.ret); - } - - for arg in &mut fn_abi.args { - if arg.is_ignore() { - continue; - } - classify_arg(arg); - } -} diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index 17eb33b8f2eaa..a026a623f7866 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -34,6 +34,7 @@ pub enum Abi { AvrInterrupt, AvrNonBlockingInterrupt, CCmseNonSecureCall, + Wasm, // Multiplatform / generic ABIs System { unwind: bool }, @@ -83,6 +84,7 @@ const AbiDatas: &[AbiData] = &[ generic: false, }, AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call", generic: false }, + AbiData { abi: Abi::Wasm, name: "wasm", generic: false }, // Cross-platform ABIs AbiData { abi: Abi::System { unwind: false }, name: "system", generic: true }, AbiData { abi: Abi::System { unwind: true }, name: "system-unwind", generic: true }, @@ -131,13 +133,14 @@ impl Abi { AvrInterrupt => 18, AvrNonBlockingInterrupt => 19, CCmseNonSecureCall => 20, + Wasm => 21, // Cross-platform ABIs - System { unwind: false } => 21, - System { unwind: true } => 22, - RustIntrinsic => 23, - RustCall => 24, - PlatformIntrinsic => 25, - Unadjusted => 26, + System { unwind: false } => 22, + System { unwind: true } => 23, + RustIntrinsic => 24, + RustCall => 25, + PlatformIntrinsic => 26, + Unadjusted => 27, }; debug_assert!( AbiDatas diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ddfd82625221f..7f2f744e91f70 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1164,6 +1164,9 @@ pub struct TargetOptions { /// How to handle split debug information, if at all. Specifying `None` has /// target-specific meaning. pub split_debuginfo: SplitDebuginfo, + + /// If present it's a default value to use for adjusting the C ABI. + pub default_adjusted_cabi: Option, } impl Default for TargetOptions { @@ -1265,6 +1268,7 @@ impl Default for TargetOptions { eh_frame_header: true, has_thumb_interworking: false, split_debuginfo: SplitDebuginfo::Off, + default_adjusted_cabi: None, } } } @@ -1316,6 +1320,9 @@ impl Target { Abi::C { unwind: false } } } + + Abi::C { unwind } => self.default_adjusted_cabi.unwrap_or(Abi::C { unwind }), + abi => abi, } } @@ -1632,6 +1639,16 @@ impl Target { } } } ); + ($key_name:ident, Option) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + match lookup_abi(s) { + Some(abi) => base.$key_name = Some(abi), + _ => return Some(Err(format!("'{}' is not a valid value for abi", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); } if let Some(s) = obj.find("target-endian").and_then(Json::as_string) { @@ -1729,6 +1746,7 @@ impl Target { key!(eh_frame_header, bool); key!(has_thumb_interworking, bool); key!(split_debuginfo, SplitDebuginfo)?; + key!(default_adjusted_cabi, Option)?; // NB: The old name is deprecated, but support for it is retained for // compatibility. @@ -1967,6 +1985,10 @@ impl ToJson for Target { target_option_val!(has_thumb_interworking); target_option_val!(split_debuginfo); + if let Some(abi) = self.default_adjusted_cabi { + d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json()); + } + if default.unsupported_abis != self.unsupported_abis { d.insert( "unsupported-abis".to_string(), diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 73a5e16c82b75..0c7ee8041b1cc 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -12,11 +12,23 @@ use super::wasm32_base; use super::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::abi::Abi; pub fn target() -> Target { let mut options = wasm32_base::options(); options.os = "unknown".to_string(); options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); + + // This is a default for backwards-compatibility with the original + // definition of this target oh-so-long-ago. Once the "wasm" ABI is + // stable and the wasm-bindgen project has switched to using it then there's + // no need for this and it can be removed. + // + // Currently this is the reason that this target's ABI is mismatched with + // clang's ABI. This means that, in the limit, you can't merge C and Rust + // code on this target due to this ABI mismatch. + options.default_adjusted_cabi = Some(Abi::Wasm); + let clang_args = options.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); // Make sure clang uses LLD as its linker and is configured appropriately diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 80c35307d52ac..14c2f961d3261 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -33,15 +33,22 @@ use crate::string; use crate::sync::Arc; /// `Error` is a trait representing the basic expectations for error values, -/// i.e., values of type `E` in [`Result`]. Errors must describe -/// themselves through the [`Display`] and [`Debug`] traits, and may provide -/// cause chain information: +/// i.e., values of type `E` in [`Result`]. /// -/// [`Error::source()`] is generally used when errors cross -/// "abstraction boundaries". If one module must report an error that is caused -/// by an error from a lower-level module, it can allow accessing that error -/// via [`Error::source()`]. This makes it possible for the high-level -/// module to provide its own errors while also revealing some of the +/// Errors must describe themselves through the [`Display`] and [`Debug`] +/// traits. Error messages are typically concise lowercase sentences without +/// trailing punctuation: +/// +/// ``` +/// let err = "NaN".parse::().unwrap_err(); +/// assert_eq!(err.to_string(), "invalid digit found in string"); +/// ``` +/// +/// Errors may provide cause chain information. [`Error::source()`] is generally +/// used when errors cross "abstraction boundaries". If one module must report +/// an error that is caused by an error from a lower-level module, it can allow +/// accessing that error via [`Error::source()`]. This makes it possible for the +/// high-level module to provide its own errors while also revealing some of the /// implementation for debugging via `source` chains. #[stable(feature = "rust1", since = "1.0.0")] pub trait Error: Debug + Display { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d5ba2d36346b5..6ab68100b1d66 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -249,6 +249,7 @@ #![feature(const_ip)] #![feature(const_ipv6)] #![feature(const_raw_ptr_deref)] +#![feature(const_socketaddr)] #![feature(const_ipv4)] #![feature(container_error_extra)] #![feature(core_intrinsics)] diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index 55546a5b03771..70376d5e06575 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -149,7 +149,8 @@ impl SocketAddr { /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] - pub fn ip(&self) -> IpAddr { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn ip(&self) -> IpAddr { match *self { SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), @@ -188,7 +189,8 @@ impl SocketAddr { /// assert_eq!(socket.port(), 8080); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn port(&self) -> u16 { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn port(&self) -> u16 { match *self { SocketAddr::V4(ref a) => a.port(), SocketAddr::V6(ref a) => a.port(), @@ -230,7 +232,8 @@ impl SocketAddr { /// assert_eq!(socket.is_ipv6(), false); /// ``` #[stable(feature = "sockaddr_checker", since = "1.16.0")] - pub fn is_ipv4(&self) -> bool { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn is_ipv4(&self) -> bool { matches!(*self, SocketAddr::V4(_)) } @@ -250,7 +253,8 @@ impl SocketAddr { /// assert_eq!(socket.is_ipv6(), true); /// ``` #[stable(feature = "sockaddr_checker", since = "1.16.0")] - pub fn is_ipv6(&self) -> bool { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn is_ipv6(&self) -> bool { matches!(*self, SocketAddr::V6(_)) } } @@ -290,7 +294,8 @@ impl SocketAddrV4 { /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn ip(&self) -> &Ipv4Addr { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn ip(&self) -> &Ipv4Addr { // SAFETY: `Ipv4Addr` is `#[repr(C)] struct { _: in_addr; }`. // It is safe to cast from `&in_addr` to `&Ipv4Addr`. unsafe { &*(&self.inner.sin_addr as *const c::in_addr as *const Ipv4Addr) } @@ -323,7 +328,8 @@ impl SocketAddrV4 { /// assert_eq!(socket.port(), 8080); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn port(&self) -> u16 { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn port(&self) -> u16 { ntohs(self.inner.sin_port) } @@ -386,7 +392,8 @@ impl SocketAddrV6 { /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn ip(&self) -> &Ipv6Addr { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn ip(&self) -> &Ipv6Addr { unsafe { &*(&self.inner.sin6_addr as *const c::in6_addr as *const Ipv6Addr) } } @@ -417,7 +424,8 @@ impl SocketAddrV6 { /// assert_eq!(socket.port(), 8080); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn port(&self) -> u16 { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn port(&self) -> u16 { ntohs(self.inner.sin6_port) } @@ -458,7 +466,8 @@ impl SocketAddrV6 { /// assert_eq!(socket.flowinfo(), 10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn flowinfo(&self) -> u32 { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn flowinfo(&self) -> u32 { self.inner.sin6_flowinfo } @@ -496,7 +505,8 @@ impl SocketAddrV6 { /// assert_eq!(socket.scope_id(), 78); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn scope_id(&self) -> u32 { + #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] + pub const fn scope_id(&self) -> u32 { self.inner.sin6_scope_id } diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt index d9097bb50e5a0..e0a5937c24686 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async.txt @@ -10,7 +10,7 @@ 10| | } 11| 1|} 12| | - 13| |async fn d() -> u8 { 1 } // should have a coverage count `0` (see below) + 13| 0|async fn d() -> u8 { 1 } 14| | 15| 0|async fn e() -> u8 { 1 } // unused function; executor does not block on `g()` 16| | @@ -66,7 +66,8 @@ 63| 1| 0 64| 1| } 65| 1| } - 66| 1| fn d() -> u8 { 1 } + 66| 1| fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed + ^0 67| 1| fn f() -> u8 { 1 } 68| 1| match x { 69| 1| y if c(x) == y + 1 => { d(); } @@ -115,11 +116,14 @@ 109| | 110| 1| pub fn block_on(mut future: F) -> F::Output { 111| 1| let mut future = unsafe { Pin::new_unchecked(&mut future) }; - 112| 1| + 112| 1| use std::hint::unreachable_unchecked; 113| 1| static VTABLE: RawWakerVTable = RawWakerVTable::new( - 114| 1| |_| unimplemented!("clone"), - 115| 1| |_| unimplemented!("wake"), - 116| 1| |_| unimplemented!("wake_by_ref"), + 114| 1| |_| unsafe { unreachable_unchecked() }, // clone + ^0 + 115| 1| |_| unsafe { unreachable_unchecked() }, // wake + ^0 + 116| 1| |_| unsafe { unreachable_unchecked() }, // wake_by_ref + ^0 117| 1| |_| (), 118| 1| ); 119| 1| let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; @@ -132,15 +136,4 @@ 126| | } 127| 1| } 128| |} - 129| | - 130| |// `llvm-cov show` shows no coverage results for the `d()`, even though the - 131| |// crate's LLVM IR shows the function exists and has an InstrProf PGO counter, - 132| |// and appears to be registered like all other counted functions. - 133| |// - 134| |// `llvm-cov show --debug` output shows there is at least one `Counter` for this - 135| |// line, but counters do not appear in the `Combined regions` section (unlike - 136| |// `f()`, which is similar, but does appear in `Combined regions`, and does show - 137| |// coverage). The only difference is, `f()` is awaited, but the call to await - 138| |// `d()` is not reached. (Note: `d()` will appear in coverage if the test is - 139| |// modified to cause it to be awaited.) diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt index 7d2abe05973e1..1b6bb9ff8891d 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt @@ -56,7 +56,7 @@ 46| 1|//! println!("called some_func()"); 47| 1|//! } 48| |//! - 49| |//! #[derive(Debug)] + 49| 0|//! #[derive(Debug)] 50| |//! struct SomeError; 51| |//! 52| |//! extern crate doctest_crate; diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt index 6148d89ed75e1..31d3ddea8d95a 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.inline.txt @@ -47,7 +47,7 @@ 46| 6|} 47| | 48| |#[inline(always)] - 49| |fn error() { - 50| | panic!("error"); - 51| |} + 49| 0|fn error() { + 50| 0| panic!("error"); + 51| 0|} diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt index 474f02b700734..81d5c7d90346d 100644 --- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt +++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt @@ -1,7 +1,7 @@ 1| |#![allow(unused_assignments, unused_variables, while_true)] 2| | - 3| |// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the - 4| |// structure of this `fmt` function. + 3| |// This test confirms that (1) unexecuted infinite loops are handled correctly by the + 4| |// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped. 5| | 6| |struct DebugTest; 7| | @@ -16,23 +16,51 @@ ^0 16| | } else { 17| | } - 18| 1| Ok(()) - 19| 1| } - 20| |} - 21| | - 22| 1|fn main() { - 23| 1| let debug_test = DebugTest; - 24| 1| println!("{:?}", debug_test); - 25| 1|} - 26| | - 27| |/* - 28| | - 29| |This is the error message generated, before the issue was fixed: - 30| | - 31| |error: internal compiler error: compiler/rustc_mir/src/transform/coverage/mod.rs:374:42: - 32| |Error processing: DefId(0:6 ~ bug_incomplete_cov_graph_traversal_simplified[317d]::{impl#0}::fmt): - 33| |Error { message: "`TraverseCoverageGraphWithLoops` missed some `BasicCoverageBlock`s: - 34| |[bcb6, bcb7, bcb9]" } - 35| | - 36| |*/ + 18| | + 19| 10| for i in 0..10 { + 20| 10| if true { + 21| 10| if false { + 22| | while true {} + 23| 10| } + 24| 10| write!(f, "error")?; + ^0 + 25| | } else { + 26| | } + 27| | } + 28| 1| Ok(()) + 29| 1| } + 30| |} + 31| | + 32| |struct DisplayTest; + 33| | + 34| |impl std::fmt::Display for DisplayTest { + 35| 1| fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + 36| 1| if false { + 37| | } else { + 38| 1| if false { + 39| | while true {} + 40| 1| } + 41| 1| write!(f, "error")?; + ^0 + 42| | } + 43| 10| for i in 0..10 { + 44| 10| if false { + 45| | } else { + 46| 10| if false { + 47| | while true {} + 48| 10| } + 49| 10| write!(f, "error")?; + ^0 + 50| | } + 51| | } + 52| 1| Ok(()) + 53| 1| } + 54| |} + 55| | + 56| 1|fn main() { + 57| 1| let debug_test = DebugTest; + 58| 1| println!("{:?}", debug_test); + 59| 1| let display_test = DisplayTest; + 60| 1| println!("{}", display_test); + 61| 1|} diff --git a/src/test/run-make-fulldeps/coverage/async.rs b/src/test/run-make-fulldeps/coverage/async.rs index f08a7b44fbd1a..67bf696d0729f 100644 --- a/src/test/run-make-fulldeps/coverage/async.rs +++ b/src/test/run-make-fulldeps/coverage/async.rs @@ -10,7 +10,7 @@ async fn c(x: u8) -> u8 { } } -async fn d() -> u8 { 1 } // should have a coverage count `0` (see below) +async fn d() -> u8 { 1 } async fn e() -> u8 { 1 } // unused function; executor does not block on `g()` @@ -63,7 +63,7 @@ fn j(x: u8) { 0 } } - fn d() -> u8 { 1 } + fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed fn f() -> u8 { 1 } match x { y if c(x) == y + 1 => { d(); } @@ -109,11 +109,11 @@ mod executor { pub fn block_on(mut future: F) -> F::Output { let mut future = unsafe { Pin::new_unchecked(&mut future) }; - + use std::hint::unreachable_unchecked; static VTABLE: RawWakerVTable = RawWakerVTable::new( - |_| unimplemented!("clone"), - |_| unimplemented!("wake"), - |_| unimplemented!("wake_by_ref"), + |_| unsafe { unreachable_unchecked() }, // clone + |_| unsafe { unreachable_unchecked() }, // wake + |_| unsafe { unreachable_unchecked() }, // wake_by_ref |_| (), ); let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) }; @@ -126,14 +126,3 @@ mod executor { } } } - -// `llvm-cov show` shows no coverage results for the `d()`, even though the -// crate's LLVM IR shows the function exists and has an InstrProf PGO counter, -// and appears to be registered like all other counted functions. -// -// `llvm-cov show --debug` output shows there is at least one `Counter` for this -// line, but counters do not appear in the `Combined regions` section (unlike -// `f()`, which is similar, but does appear in `Combined regions`, and does show -// coverage). The only difference is, `f()` is awaited, but the call to await -// `d()` is not reached. (Note: `d()` will appear in coverage if the test is -// modified to cause it to be awaited.) diff --git a/src/test/run-make-fulldeps/coverage/loops_branches.rs b/src/test/run-make-fulldeps/coverage/loops_branches.rs index 938421d32e7a5..4d9bbad3367f6 100644 --- a/src/test/run-make-fulldeps/coverage/loops_branches.rs +++ b/src/test/run-make-fulldeps/coverage/loops_branches.rs @@ -1,7 +1,7 @@ #![allow(unused_assignments, unused_variables, while_true)] -// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the -// structure of this `fmt` function. +// This test confirms that (1) unexecuted infinite loops are handled correctly by the +// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped. struct DebugTest; @@ -15,6 +15,40 @@ impl std::fmt::Debug for DebugTest { write!(f, "error")?; } else { } + + for i in 0..10 { + if true { + if false { + while true {} + } + write!(f, "error")?; + } else { + } + } + Ok(()) + } +} + +struct DisplayTest; + +impl std::fmt::Display for DisplayTest { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if false { + } else { + if false { + while true {} + } + write!(f, "error")?; + } + for i in 0..10 { + if false { + } else { + if false { + while true {} + } + write!(f, "error")?; + } + } Ok(()) } } @@ -22,15 +56,6 @@ impl std::fmt::Debug for DebugTest { fn main() { let debug_test = DebugTest; println!("{:?}", debug_test); + let display_test = DisplayTest; + println!("{}", display_test); } - -/* - -This is the error message generated, before the issue was fixed: - -error: internal compiler error: compiler/rustc_mir/src/transform/coverage/mod.rs:374:42: -Error processing: DefId(0:6 ~ bug_incomplete_cov_graph_traversal_simplified[317d]::{impl#0}::fmt): -Error { message: "`TraverseCoverageGraphWithLoops` missed some `BasicCoverageBlock`s: -[bcb6, bcb7, bcb9]" } - -*/ diff --git a/src/test/run-make/wasm-abi/Makefile b/src/test/run-make/wasm-abi/Makefile new file mode 100644 index 0000000000000..61fc4e8f57fb8 --- /dev/null +++ b/src/test/run-make/wasm-abi/Makefile @@ -0,0 +1,7 @@ +-include ../../run-make-fulldeps/tools.mk + +# only-wasm32-bare + +all: + $(RUSTC) foo.rs --target wasm32-unknown-unknown + $(NODE) foo.js $(TMPDIR)/foo.wasm diff --git a/src/test/run-make/wasm-abi/foo.js b/src/test/run-make/wasm-abi/foo.js new file mode 100644 index 0000000000000..9e9a65401af81 --- /dev/null +++ b/src/test/run-make/wasm-abi/foo.js @@ -0,0 +1,22 @@ +const fs = require('fs'); +const process = require('process'); +const assert = require('assert'); +const buffer = fs.readFileSync(process.argv[2]); + +const m = new WebAssembly.Module(buffer); +const i = new WebAssembly.Instance(m, { + host: { + two_i32: () => [100, 101], + two_i64: () => [102n, 103n], + two_f32: () => [104, 105], + two_f64: () => [106, 107], + mishmash: () => [108, 109, 110, 111n, 112, 113], + } +}); + +assert.deepEqual(i.exports.return_two_i32(), [1, 2]) +assert.deepEqual(i.exports.return_two_i64(), [3, 4]) +assert.deepEqual(i.exports.return_two_f32(), [5, 6]) +assert.deepEqual(i.exports.return_two_f64(), [7, 8]) +assert.deepEqual(i.exports.return_mishmash(), [9, 10, 11, 12, 13, 14]) +i.exports.call_imports(); diff --git a/src/test/run-make/wasm-abi/foo.rs b/src/test/run-make/wasm-abi/foo.rs new file mode 100644 index 0000000000000..0678eb3ff51ae --- /dev/null +++ b/src/test/run-make/wasm-abi/foo.rs @@ -0,0 +1,87 @@ +#![crate_type = "cdylib"] +#![deny(warnings)] +#![feature(wasm_abi)] + +#[repr(C)] +#[derive(PartialEq, Debug)] +pub struct TwoI32 { + pub a: i32, + pub b: i32, +} + +#[no_mangle] +pub extern "wasm" fn return_two_i32() -> TwoI32 { + TwoI32 { a: 1, b: 2 } +} + +#[repr(C)] +#[derive(PartialEq, Debug)] +pub struct TwoI64 { + pub a: i64, + pub b: i64, +} + +#[no_mangle] +pub extern "wasm" fn return_two_i64() -> TwoI64 { + TwoI64 { a: 3, b: 4 } +} + +#[repr(C)] +#[derive(PartialEq, Debug)] +pub struct TwoF32 { + pub a: f32, + pub b: f32, +} + +#[no_mangle] +pub extern "wasm" fn return_two_f32() -> TwoF32 { + TwoF32 { a: 5., b: 6. } +} + +#[repr(C)] +#[derive(PartialEq, Debug)] +pub struct TwoF64 { + pub a: f64, + pub b: f64, +} + +#[no_mangle] +pub extern "wasm" fn return_two_f64() -> TwoF64 { + TwoF64 { a: 7., b: 8. } +} + +#[repr(C)] +#[derive(PartialEq, Debug)] +pub struct Mishmash { + pub a: f64, + pub b: f32, + pub c: i32, + pub d: i64, + pub e: TwoI32, +} + +#[no_mangle] +pub extern "wasm" fn return_mishmash() -> Mishmash { + Mishmash { a: 9., b: 10., c: 11, d: 12, e: TwoI32 { a: 13, b: 14 } } +} + +#[link(wasm_import_module = "host")] +extern "wasm" { + fn two_i32() -> TwoI32; + fn two_i64() -> TwoI64; + fn two_f32() -> TwoF32; + fn two_f64() -> TwoF64; + fn mishmash() -> Mishmash; +} + +#[no_mangle] +pub unsafe extern "C" fn call_imports() { + assert_eq!(two_i32(), TwoI32 { a: 100, b: 101 }); + assert_eq!(two_i64(), TwoI64 { a: 102, b: 103 }); + assert_eq!(two_f32(), TwoF32 { a: 104., b: 105. }); + assert_eq!(two_f64(), TwoF64 { a: 106., b: 107. }); + assert_eq!( + mishmash(), + Mishmash { a: 108., b: 109., c: 110, d: 111, e: TwoI32 { a: 112, b: 113 } } + ); +} diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr index b7ba4fa46d92b..357dd25389ecb 100644 --- a/src/test/ui/codemap_tests/unicode.stderr +++ b/src/test/ui/codemap_tests/unicode.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́` LL | extern "路濫狼á́́" fn foo() {} | ^^^^^^^^^ invalid ABI | - = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted + = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-abi.rs b/src/test/ui/feature-gates/feature-gate-abi.rs index 31f09cc61f9ac..cde76031f42c2 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.rs +++ b/src/test/ui/feature-gates/feature-gate-abi.rs @@ -11,9 +11,9 @@ // Functions extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change -//~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental -//~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental @@ -22,13 +22,14 @@ extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change extern "amdgpu-kernel" fn f9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" fn f10() {} //~ ERROR efiapi ABI is experimental and subject to change +extern "wasm" fn f11() {} //~ ERROR wasm ABI is experimental and subject to change // Methods in trait definition trait Tr { extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change - //~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental - //~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental @@ -37,6 +38,7 @@ trait Tr { extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change extern "amdgpu-kernel" fn m9(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" fn m10(); //~ ERROR efiapi ABI is experimental and subject to change + extern "wasm" fn m11() {} //~ ERROR wasm ABI is experimental and subject to change extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change @@ -46,6 +48,7 @@ trait Tr { extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change extern "amdgpu-kernel" fn dm9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" fn dm10() {} //~ ERROR efiapi ABI is experimental and subject to change + extern "wasm" fn dm11() {} //~ ERROR wasm ABI is experimental and subject to change } struct S; @@ -53,9 +56,9 @@ struct S; // Methods in trait impl impl Tr for S { extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change - //~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental - //~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental @@ -64,14 +67,15 @@ impl Tr for S { extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change extern "amdgpu-kernel" fn m9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" fn m10() {} //~ ERROR efiapi ABI is experimental and subject to change + extern "wasm" fn m11() {} //~ ERROR wasm ABI is experimental and subject to change } // Methods in inherent impl impl S { extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change - //~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental - //~^ ERROR intrinsic must be in + //~^ ERROR intrinsic must be in extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental @@ -80,6 +84,7 @@ impl S { extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change extern "amdgpu-kernel" fn im9() {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" fn im10() {} //~ ERROR efiapi ABI is experimental and subject to change + extern "wasm" fn im11() {} //~ ERROR wasm ABI is experimental and subject to change } // Function pointer types @@ -88,11 +93,12 @@ type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are ex type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental -type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change +type A6 = extern "ptx-kernel" fn(); //~ ERROR PTX ABIs are experimental and subject to change type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change type A9 = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental and subject to change type A10 = extern "efiapi" fn(); //~ ERROR efiapi ABI is experimental and subject to change +type A11 = extern "wasm" fn(); //~ ERROR wasm ABI is experimental and subject to change // Foreign modules extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change @@ -105,5 +111,6 @@ extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental and subject to change extern "efiapi" {} //~ ERROR efiapi ABI is experimental and subject to change +extern "wasm" {} //~ ERROR wasm ABI is experimental and subject to change fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr index 25f0c259d111c..ff7965fd3d90e 100644 --- a/src/test/ui/feature-gates/feature-gate-abi.stderr +++ b/src/test/ui/feature-gates/feature-gate-abi.stderr @@ -85,8 +85,17 @@ LL | extern "efiapi" fn f10() {} = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-abi.rs:25:8 + | +LL | extern "wasm" fn f11() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:28:12 + --> $DIR/feature-gate-abi.rs:29:12 | LL | extern "rust-intrinsic" fn m1(); | ^^^^^^^^^^^^^^^^ @@ -94,7 +103,7 @@ LL | extern "rust-intrinsic" fn m1(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:30:12 + --> $DIR/feature-gate-abi.rs:31:12 | LL | extern "platform-intrinsic" fn m2(); | ^^^^^^^^^^^^^^^^^^^^ @@ -103,7 +112,7 @@ LL | extern "platform-intrinsic" fn m2(); = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:32:12 + --> $DIR/feature-gate-abi.rs:33:12 | LL | extern "vectorcall" fn m3(); | ^^^^^^^^^^^^ @@ -111,7 +120,7 @@ LL | extern "vectorcall" fn m3(); = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:33:12 + --> $DIR/feature-gate-abi.rs:34:12 | LL | extern "rust-call" fn m4(_: ()); | ^^^^^^^^^^^ @@ -120,7 +129,7 @@ LL | extern "rust-call" fn m4(_: ()); = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:34:12 + --> $DIR/feature-gate-abi.rs:35:12 | LL | extern "msp430-interrupt" fn m5(); | ^^^^^^^^^^^^^^^^^^ @@ -129,7 +138,7 @@ LL | extern "msp430-interrupt" fn m5(); = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:35:12 + --> $DIR/feature-gate-abi.rs:36:12 | LL | extern "ptx-kernel" fn m6(); | ^^^^^^^^^^^^ @@ -138,7 +147,7 @@ LL | extern "ptx-kernel" fn m6(); = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:36:12 + --> $DIR/feature-gate-abi.rs:37:12 | LL | extern "x86-interrupt" fn m7(); | ^^^^^^^^^^^^^^^ @@ -147,7 +156,7 @@ LL | extern "x86-interrupt" fn m7(); = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:37:12 + --> $DIR/feature-gate-abi.rs:38:12 | LL | extern "thiscall" fn m8(); | ^^^^^^^^^^ @@ -155,7 +164,7 @@ LL | extern "thiscall" fn m8(); = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:38:12 + --> $DIR/feature-gate-abi.rs:39:12 | LL | extern "amdgpu-kernel" fn m9(); | ^^^^^^^^^^^^^^^ @@ -164,7 +173,7 @@ LL | extern "amdgpu-kernel" fn m9(); = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:39:12 + --> $DIR/feature-gate-abi.rs:40:12 | LL | extern "efiapi" fn m10(); | ^^^^^^^^ @@ -172,16 +181,25 @@ LL | extern "efiapi" fn m10(); = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable -error[E0658]: vectorcall is experimental and subject to change +error[E0658]: wasm ABI is experimental and subject to change --> $DIR/feature-gate-abi.rs:41:12 | +LL | extern "wasm" fn m11() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error[E0658]: vectorcall is experimental and subject to change + --> $DIR/feature-gate-abi.rs:43:12 + | LL | extern "vectorcall" fn dm3() {} | ^^^^^^^^^^^^ | = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:42:12 + --> $DIR/feature-gate-abi.rs:44:12 | LL | extern "rust-call" fn dm4(_: ()) {} | ^^^^^^^^^^^ @@ -190,7 +208,7 @@ LL | extern "rust-call" fn dm4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:43:12 + --> $DIR/feature-gate-abi.rs:45:12 | LL | extern "msp430-interrupt" fn dm5() {} | ^^^^^^^^^^^^^^^^^^ @@ -199,7 +217,7 @@ LL | extern "msp430-interrupt" fn dm5() {} = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:44:12 + --> $DIR/feature-gate-abi.rs:46:12 | LL | extern "ptx-kernel" fn dm6() {} | ^^^^^^^^^^^^ @@ -208,7 +226,7 @@ LL | extern "ptx-kernel" fn dm6() {} = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:45:12 + --> $DIR/feature-gate-abi.rs:47:12 | LL | extern "x86-interrupt" fn dm7() {} | ^^^^^^^^^^^^^^^ @@ -217,7 +235,7 @@ LL | extern "x86-interrupt" fn dm7() {} = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:46:12 + --> $DIR/feature-gate-abi.rs:48:12 | LL | extern "thiscall" fn dm8() {} | ^^^^^^^^^^ @@ -225,7 +243,7 @@ LL | extern "thiscall" fn dm8() {} = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:47:12 + --> $DIR/feature-gate-abi.rs:49:12 | LL | extern "amdgpu-kernel" fn dm9() {} | ^^^^^^^^^^^^^^^ @@ -234,7 +252,7 @@ LL | extern "amdgpu-kernel" fn dm9() {} = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:48:12 + --> $DIR/feature-gate-abi.rs:50:12 | LL | extern "efiapi" fn dm10() {} | ^^^^^^^^ @@ -242,8 +260,17 @@ LL | extern "efiapi" fn dm10() {} = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-abi.rs:51:12 + | +LL | extern "wasm" fn dm11() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:55:12 + --> $DIR/feature-gate-abi.rs:58:12 | LL | extern "rust-intrinsic" fn m1() {} | ^^^^^^^^^^^^^^^^ @@ -251,7 +278,7 @@ LL | extern "rust-intrinsic" fn m1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:57:12 + --> $DIR/feature-gate-abi.rs:60:12 | LL | extern "platform-intrinsic" fn m2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -260,7 +287,7 @@ LL | extern "platform-intrinsic" fn m2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:59:12 + --> $DIR/feature-gate-abi.rs:62:12 | LL | extern "vectorcall" fn m3() {} | ^^^^^^^^^^^^ @@ -268,7 +295,7 @@ LL | extern "vectorcall" fn m3() {} = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:60:12 + --> $DIR/feature-gate-abi.rs:63:12 | LL | extern "rust-call" fn m4(_: ()) {} | ^^^^^^^^^^^ @@ -277,7 +304,7 @@ LL | extern "rust-call" fn m4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:61:12 + --> $DIR/feature-gate-abi.rs:64:12 | LL | extern "msp430-interrupt" fn m5() {} | ^^^^^^^^^^^^^^^^^^ @@ -286,7 +313,7 @@ LL | extern "msp430-interrupt" fn m5() {} = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:62:12 + --> $DIR/feature-gate-abi.rs:65:12 | LL | extern "ptx-kernel" fn m6() {} | ^^^^^^^^^^^^ @@ -295,7 +322,7 @@ LL | extern "ptx-kernel" fn m6() {} = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:63:12 + --> $DIR/feature-gate-abi.rs:66:12 | LL | extern "x86-interrupt" fn m7() {} | ^^^^^^^^^^^^^^^ @@ -304,7 +331,7 @@ LL | extern "x86-interrupt" fn m7() {} = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:64:12 + --> $DIR/feature-gate-abi.rs:67:12 | LL | extern "thiscall" fn m8() {} | ^^^^^^^^^^ @@ -312,7 +339,7 @@ LL | extern "thiscall" fn m8() {} = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:65:12 + --> $DIR/feature-gate-abi.rs:68:12 | LL | extern "amdgpu-kernel" fn m9() {} | ^^^^^^^^^^^^^^^ @@ -321,7 +348,7 @@ LL | extern "amdgpu-kernel" fn m9() {} = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:66:12 + --> $DIR/feature-gate-abi.rs:69:12 | LL | extern "efiapi" fn m10() {} | ^^^^^^^^ @@ -329,8 +356,17 @@ LL | extern "efiapi" fn m10() {} = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-abi.rs:70:12 + | +LL | extern "wasm" fn m11() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:71:12 + --> $DIR/feature-gate-abi.rs:75:12 | LL | extern "rust-intrinsic" fn im1() {} | ^^^^^^^^^^^^^^^^ @@ -338,7 +374,7 @@ LL | extern "rust-intrinsic" fn im1() {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:73:12 + --> $DIR/feature-gate-abi.rs:77:12 | LL | extern "platform-intrinsic" fn im2() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -347,7 +383,7 @@ LL | extern "platform-intrinsic" fn im2() {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:75:12 + --> $DIR/feature-gate-abi.rs:79:12 | LL | extern "vectorcall" fn im3() {} | ^^^^^^^^^^^^ @@ -355,7 +391,7 @@ LL | extern "vectorcall" fn im3() {} = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:76:12 + --> $DIR/feature-gate-abi.rs:80:12 | LL | extern "rust-call" fn im4(_: ()) {} | ^^^^^^^^^^^ @@ -364,7 +400,7 @@ LL | extern "rust-call" fn im4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:77:12 + --> $DIR/feature-gate-abi.rs:81:12 | LL | extern "msp430-interrupt" fn im5() {} | ^^^^^^^^^^^^^^^^^^ @@ -373,7 +409,7 @@ LL | extern "msp430-interrupt" fn im5() {} = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:78:12 + --> $DIR/feature-gate-abi.rs:82:12 | LL | extern "ptx-kernel" fn im6() {} | ^^^^^^^^^^^^ @@ -382,7 +418,7 @@ LL | extern "ptx-kernel" fn im6() {} = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:79:12 + --> $DIR/feature-gate-abi.rs:83:12 | LL | extern "x86-interrupt" fn im7() {} | ^^^^^^^^^^^^^^^ @@ -391,7 +427,7 @@ LL | extern "x86-interrupt" fn im7() {} = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:80:12 + --> $DIR/feature-gate-abi.rs:84:12 | LL | extern "thiscall" fn im8() {} | ^^^^^^^^^^ @@ -399,7 +435,7 @@ LL | extern "thiscall" fn im8() {} = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:81:12 + --> $DIR/feature-gate-abi.rs:85:12 | LL | extern "amdgpu-kernel" fn im9() {} | ^^^^^^^^^^^^^^^ @@ -408,7 +444,7 @@ LL | extern "amdgpu-kernel" fn im9() {} = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:82:12 + --> $DIR/feature-gate-abi.rs:86:12 | LL | extern "efiapi" fn im10() {} | ^^^^^^^^ @@ -416,8 +452,17 @@ LL | extern "efiapi" fn im10() {} = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-abi.rs:87:12 + | +LL | extern "wasm" fn im11() {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:86:18 + --> $DIR/feature-gate-abi.rs:91:18 | LL | type A1 = extern "rust-intrinsic" fn(); | ^^^^^^^^^^^^^^^^ @@ -425,7 +470,7 @@ LL | type A1 = extern "rust-intrinsic" fn(); = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:87:18 + --> $DIR/feature-gate-abi.rs:92:18 | LL | type A2 = extern "platform-intrinsic" fn(); | ^^^^^^^^^^^^^^^^^^^^ @@ -434,7 +479,7 @@ LL | type A2 = extern "platform-intrinsic" fn(); = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:88:18 + --> $DIR/feature-gate-abi.rs:93:18 | LL | type A3 = extern "vectorcall" fn(); | ^^^^^^^^^^^^ @@ -442,7 +487,7 @@ LL | type A3 = extern "vectorcall" fn(); = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:89:18 + --> $DIR/feature-gate-abi.rs:94:18 | LL | type A4 = extern "rust-call" fn(_: ()); | ^^^^^^^^^^^ @@ -451,7 +496,7 @@ LL | type A4 = extern "rust-call" fn(_: ()); = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:90:18 + --> $DIR/feature-gate-abi.rs:95:18 | LL | type A5 = extern "msp430-interrupt" fn(); | ^^^^^^^^^^^^^^^^^^ @@ -460,16 +505,16 @@ LL | type A5 = extern "msp430-interrupt" fn(); = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:91:18 + --> $DIR/feature-gate-abi.rs:96:18 | -LL | type A6 = extern "ptx-kernel" fn (); +LL | type A6 = extern "ptx-kernel" fn(); | ^^^^^^^^^^^^ | = note: see issue #38788 for more information = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:92:18 + --> $DIR/feature-gate-abi.rs:97:18 | LL | type A7 = extern "x86-interrupt" fn(); | ^^^^^^^^^^^^^^^ @@ -478,7 +523,7 @@ LL | type A7 = extern "x86-interrupt" fn(); = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:93:18 + --> $DIR/feature-gate-abi.rs:98:18 | LL | type A8 = extern "thiscall" fn(); | ^^^^^^^^^^ @@ -486,7 +531,7 @@ LL | type A8 = extern "thiscall" fn(); = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:94:18 + --> $DIR/feature-gate-abi.rs:99:18 | LL | type A9 = extern "amdgpu-kernel" fn(); | ^^^^^^^^^^^^^^^ @@ -495,7 +540,7 @@ LL | type A9 = extern "amdgpu-kernel" fn(); = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:95:19 + --> $DIR/feature-gate-abi.rs:100:19 | LL | type A10 = extern "efiapi" fn(); | ^^^^^^^^ @@ -503,8 +548,17 @@ LL | type A10 = extern "efiapi" fn(); = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-abi.rs:101:19 + | +LL | type A11 = extern "wasm" fn(); + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + error[E0658]: intrinsics are subject to change - --> $DIR/feature-gate-abi.rs:98:8 + --> $DIR/feature-gate-abi.rs:104:8 | LL | extern "rust-intrinsic" {} | ^^^^^^^^^^^^^^^^ @@ -512,7 +566,7 @@ LL | extern "rust-intrinsic" {} = help: add `#![feature(intrinsics)]` to the crate attributes to enable error[E0658]: platform intrinsics are experimental and possibly buggy - --> $DIR/feature-gate-abi.rs:99:8 + --> $DIR/feature-gate-abi.rs:105:8 | LL | extern "platform-intrinsic" {} | ^^^^^^^^^^^^^^^^^^^^ @@ -521,7 +575,7 @@ LL | extern "platform-intrinsic" {} = help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable error[E0658]: vectorcall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:100:8 + --> $DIR/feature-gate-abi.rs:106:8 | LL | extern "vectorcall" {} | ^^^^^^^^^^^^ @@ -529,7 +583,7 @@ LL | extern "vectorcall" {} = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable error[E0658]: rust-call ABI is subject to change - --> $DIR/feature-gate-abi.rs:101:8 + --> $DIR/feature-gate-abi.rs:107:8 | LL | extern "rust-call" {} | ^^^^^^^^^^^ @@ -538,7 +592,7 @@ LL | extern "rust-call" {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable error[E0658]: msp430-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:102:8 + --> $DIR/feature-gate-abi.rs:108:8 | LL | extern "msp430-interrupt" {} | ^^^^^^^^^^^^^^^^^^ @@ -547,7 +601,7 @@ LL | extern "msp430-interrupt" {} = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable error[E0658]: PTX ABIs are experimental and subject to change - --> $DIR/feature-gate-abi.rs:103:8 + --> $DIR/feature-gate-abi.rs:109:8 | LL | extern "ptx-kernel" {} | ^^^^^^^^^^^^ @@ -556,7 +610,7 @@ LL | extern "ptx-kernel" {} = help: add `#![feature(abi_ptx)]` to the crate attributes to enable error[E0658]: x86-interrupt ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:104:8 + --> $DIR/feature-gate-abi.rs:110:8 | LL | extern "x86-interrupt" {} | ^^^^^^^^^^^^^^^ @@ -565,7 +619,7 @@ LL | extern "x86-interrupt" {} = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable error[E0658]: thiscall is experimental and subject to change - --> $DIR/feature-gate-abi.rs:105:8 + --> $DIR/feature-gate-abi.rs:111:8 | LL | extern "thiscall" {} | ^^^^^^^^^^ @@ -573,7 +627,7 @@ LL | extern "thiscall" {} = help: add `#![feature(abi_thiscall)]` to the crate attributes to enable error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:106:8 + --> $DIR/feature-gate-abi.rs:112:8 | LL | extern "amdgpu-kernel" {} | ^^^^^^^^^^^^^^^ @@ -582,7 +636,7 @@ LL | extern "amdgpu-kernel" {} = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable error[E0658]: efiapi ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:107:8 + --> $DIR/feature-gate-abi.rs:113:8 | LL | extern "efiapi" {} | ^^^^^^^^ @@ -590,14 +644,23 @@ LL | extern "efiapi" {} = note: see issue #65815 for more information = help: add `#![feature(abi_efiapi)]` to the crate attributes to enable +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-abi.rs:114:8 + | +LL | extern "wasm" {} + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:28:32 + --> $DIR/feature-gate-abi.rs:29:32 | LL | extern "rust-intrinsic" fn m1(); | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:30:36 + --> $DIR/feature-gate-abi.rs:31:36 | LL | extern "platform-intrinsic" fn m2(); | ^^ @@ -615,29 +678,29 @@ LL | extern "platform-intrinsic" fn f2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:55:37 + --> $DIR/feature-gate-abi.rs:58:37 | LL | extern "rust-intrinsic" fn m1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:57:41 + --> $DIR/feature-gate-abi.rs:60:41 | LL | extern "platform-intrinsic" fn m2() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:71:38 + --> $DIR/feature-gate-abi.rs:75:38 | LL | extern "rust-intrinsic" fn im1() {} | ^^ error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:73:42 + --> $DIR/feature-gate-abi.rs:77:42 | LL | extern "platform-intrinsic" fn im2() {} | ^^ -error: aborting due to 76 previous errors +error: aborting due to 83 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-wasm_abi.rs b/src/test/ui/feature-gates/feature-gate-wasm_abi.rs new file mode 100644 index 0000000000000..8c8de0763658e --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-wasm_abi.rs @@ -0,0 +1,7 @@ +extern "wasm" fn foo() { + //~^ ERROR: wasm ABI is experimental and subject to change +} + +fn main() { + foo(); +} diff --git a/src/test/ui/feature-gates/feature-gate-wasm_abi.stderr b/src/test/ui/feature-gates/feature-gate-wasm_abi.stderr new file mode 100644 index 0000000000000..c4113fd6af979 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-wasm_abi.stderr @@ -0,0 +1,12 @@ +error[E0658]: wasm ABI is experimental and subject to change + --> $DIR/feature-gate-wasm_abi.rs:1:8 + | +LL | extern "wasm" fn foo() { + | ^^^^^^ + | + = note: see issue #83788 for more information + = help: add `#![feature(wasm_abi)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/parser/issue-8537.stderr b/src/test/ui/parser/issue-8537.stderr index 85e2b77d867b9..5a29ce2221fc2 100644 --- a/src/test/ui/parser/issue-8537.stderr +++ b/src/test/ui/parser/issue-8537.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize` LL | "invalid-ab_isize" | ^^^^^^^^^^^^^^^^^^ invalid ABI | - = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted + = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted error: aborting due to previous error