diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 44dd26180bd16..3eb73e73ff854 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -388,11 +388,10 @@ impl<'hir> LoweringContext<'_, 'hir> { fn param_info(&self, def_id: DefId) -> ParamInfo { let sig = self.tcx.fn_sig(def_id).skip_binder().skip_binder(); - // FIXME(splat): use `sig.splatted()` once FnSig has it ParamInfo { param_count: sig.inputs().len() + usize::from(sig.c_variadic()), c_variadic: sig.c_variadic(), - splatted: None, + splatted: sig.splatted(), } } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index f1a1abf0e635e..e140e7d18c589 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -445,11 +445,13 @@ fn fn_sig_suggestion<'tcx>( predicates: impl IntoIterator, Span)>, assoc: ty::AssocItem, ) -> String { + let splatted_arg_index = sig.splatted().map(usize::from); let args = sig .inputs() .iter() .enumerate() .map(|(i, ty)| { + let splat = if splatted_arg_index == Some(i) { "#[splat] " } else { "" }; let arg_ty = match ty.kind() { ty::Param(_) if assoc.is_method() && i == 0 => "self".to_string(), ty::Ref(reg, ref_ty, mutability) if i == 0 => { @@ -478,7 +480,7 @@ fn fn_sig_suggestion<'tcx>( } } }; - Some(format!("{arg_ty}")) + Some(format!("{splat}{arg_ty}")) }) .chain(std::iter::once(if sig.c_variadic() { Some("...".to_string()) } else { None })) .flatten() diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index cbb82271b5c99..96b86b03cd1d8 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1713,7 +1713,16 @@ fn check_fn_or_method<'tcx>( let span = tcx.def_span(def_id); let has_implicit_self = hir_decl.implicit_self().has_implicit_self(); let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 }); - // FIXME(splat): use `sig.splatted()` once FnSig has it + // FIXME(splat): support the rest of closure splatting, or replace this code with an error + if let Some(mut splatted_arg_index) = sig.splatted() { + let mut inputs_count = sig.inputs().len(); + if has_implicit_self { + splatted_arg_index = splatted_arg_index.strict_sub(1); + inputs_count = inputs_count.strict_sub(1); + } + debug!(?splatted_arg_index, ?inputs_count, ?has_implicit_self, ?sig); + sig = sig.set_splatted(Some(splatted_arg_index), inputs_count).unwrap(); + } // Check that the argument is a tuple and is sized if let Some(ty) = inputs.next() { wfcx.register_bound( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index bc3e526a362a8..9fa3ec2007f08 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -3498,11 +3498,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?output_ty); debug!(?abi, ?safety, ?decl.fn_decl_kind, input_tys_len = ?input_tys.len()); - // FIXME(splat): use `set_splatted()` once FnSig has it let fn_sig_kind = FnSigKind::default() .set_abi(abi) .set_safety(safety) - .set_c_variadic(decl.fn_decl_kind.c_variadic()); + .set_c_variadic(decl.fn_decl_kind.c_variadic()) + .set_splatted(decl.fn_decl_kind.splatted(), input_tys.len()) + .unwrap(); let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, fn_sig_kind); let fn_ptr_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 763d2a27e6cc0..585f6bd57ac57 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -720,6 +720,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // in this binder we are creating. assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST)); let bound_sig = expected_sig.sig.map_bound(|sig| { + // Ignore splatting, it is unsupported on closures. let fn_sig_kind = FnSigKind::default() .set_abi(ExternAbi::RustCall) .set_safety(hir::Safety::Safe) diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index a9a819935287c..a5c39bd1584a1 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -100,6 +100,7 @@ impl IntoDiagArg for ReturnLikeStatementKind { } } +// FIXME(splat): add "non-splatted" to all 4 instances of this error message #[derive(Diagnostic)] #[diag("functions with the \"rust-call\" ABI must take a single non-self tuple argument")] pub(crate) struct RustCallIncorrectArgs { diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index df12502c7e5a8..24293347a145b 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -329,6 +329,14 @@ fn structurally_same_type_impl<'tcx>( let a_sig = tcx.instantiate_bound_regions_with_erased(a_poly_sig); let b_sig = tcx.instantiate_bound_regions_with_erased(b_poly_sig); + // FIXME(splat): Is splatting ever repr(C)? + // Can two splatted functions to have the same structure? + // Can a splatted and non-splatted function have the same structure? + // For now, we require splatting to match exactly. + if a_sig.splatted() != b_sig.splatted() { + return false; + } + (a_sig.abi(), a_sig.safety(), a_sig.c_variadic()) == (b_sig.abi(), b_sig.safety(), b_sig.c_variadic()) && a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d6bf72e215e7c..e88cd91a1f63a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2091,6 +2091,8 @@ impl<'tcx> TyCtxt<'tcx> { ty::Tuple(params) => *params, _ => bug!(), }; + // Ignore splatting, it is unsupported on closures. + assert!(s.splatted().is_none()); self.mk_fn_sig( params, s.output(), diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 81cd3efffc9d4..18bcc7992fbb1 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -96,6 +96,20 @@ impl<'tcx> TypeError<'tcx> { if values.found { "variadic" } else { "non-variadic" } ) .into(), + TypeError::SplatMismatch(ref values) => format!( + "expected fn with {}, found fn with {}", + if let Some(index) = values.expected { + format!("arg {index} splatted") + } else { + "no splatted arg".to_string() + }, + if let Some(index) = values.found { + format!("arg {index} splatted") + } else { + "no splatted arg".to_string() + } + ) + .into(), TypeError::ProjectionMismatched(ref values) => format!( "expected `{}`, found `{}`", tcx.def_path_str(values.expected), diff --git a/compiler/rustc_public/src/unstable/convert/internal.rs b/compiler/rustc_public/src/unstable/convert/internal.rs index 81b32f4da10f6..181498443073d 100644 --- a/compiler/rustc_public/src/unstable/convert/internal.rs +++ b/compiler/rustc_public/src/unstable/convert/internal.rs @@ -312,6 +312,7 @@ impl RustcInternal for FnSig { tables: &mut Tables<'_, BridgeTys>, tcx: impl InternalCx<'tcx>, ) -> Self::T<'tcx> { + // FIXME(splat): When `#[splat]` is complete (or stable), add splatted to the public FnSig let fn_sig_kind = rustc_ty::FnSigKind::default() .set_abi(self.abi.internal(tables, tcx)) .set_safety(self.safety.internal(tables, tcx)) diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c6624a7820559..be8c7369465ba 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -576,6 +576,7 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> { } } } + // FIXME(splat): should splatted arguments be part of symbol mangling? for &ty in sig.inputs() { ty.print(p)?; } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index c9e2312895820..f529f475738a2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -829,9 +829,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // ^^^^^ let len1 = sig1.inputs().len(); let len2 = sig2.inputs().len(); + let splatted_arg_index1 = sig1.splatted().map(usize::from); + let splatted_arg_index2 = sig2.splatted().map(usize::from); if len1 == len2 { for (i, (l, r)) in iter::zip(sig1.inputs(), sig2.inputs()).enumerate() { self.push_comma(&mut values.0, &mut values.1, i); + if Some(i) == splatted_arg_index1 { + values.0.push("#[splat]", splatted_arg_index1 != splatted_arg_index2); + values.0.push_normal(" "); + } + if Some(i) == splatted_arg_index2 { + values.1.push("#[splat]", splatted_arg_index1 != splatted_arg_index2); + values.1.push_normal(" "); + } let (x1, x2) = self.cmp(*l, *r); (values.0).0.extend(x1.0); (values.1).0.extend(x2.0); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 6cc3c797391fe..05c7f5fdff6fa 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4960,6 +4960,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let fn_sig @ ty::FnSig { .. } = fn_ty.fn_sig(tcx).skip_binder() + // FIXME(splat): this might need to change if the Fn* traits start using/supporting splat && fn_sig.abi() == ExternAbi::Rust && !fn_sig.c_variadic() && fn_sig.safety() == hir::Safety::Safe diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index 15fbd985d9630..56c0851a18d3c 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -41,6 +41,7 @@ pub enum TypeError { ArgumentSorts(ExpectedFound, usize), Traits(ExpectedFound), VariadicMismatch(ExpectedFound), + SplatMismatch(ExpectedFound>), /// Instantiating a type variable with the given type would have /// created a cycle (because it appears somewhere within that @@ -76,7 +77,7 @@ impl TypeError { match self { CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | PolarityMismatch(_) | Mismatch | AbiMismatch(_) | ArraySize(_) | ArgumentSorts(..) | Sorts(_) - | VariadicMismatch(_) | TargetFeatureCast(_) => false, + | VariadicMismatch(_) | SplatMismatch(_) | TargetFeatureCast(_) => false, Mutability | ArgumentMutability(_) diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 73870378f5ca0..cc386fd802470 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -169,6 +169,10 @@ impl Relate for ty::FnSig { return Err(TypeError::AbiMismatch(ExpectedFound::new(a.abi(), b.abi()))); }; + if a.splatted() != b.splatted() { + return Err(TypeError::SplatMismatch(ExpectedFound::new(a.splatted(), b.splatted()))); + } + let a_inputs = a.inputs(); let b_inputs = b.inputs(); if a_inputs.len() != b_inputs.len() { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 784a91424156f..68551c9b940bf 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -757,8 +757,19 @@ pub struct TypeAndMut { impl Eq for TypeAndMut {} +/// Error type for splatted argument index errors. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SplattedArgIndexError { + /// The splatted argument index is invalid. + /// Currently the only unsupported index is `u16::MAX`, which is used to indicate that no argument + /// is splatted. + InvalidIndex { splatted_arg_index: u16 }, + + /// The splatted argument index is outside the bounds of the function arguments. + OutOfBounds { splatted_arg_index: u16, args_len: u16 }, +} + /// Contains the packed non-type fields of a function signature. -// FIXME(splat): add the splatted argument index as a u16 #[derive_where(Copy, Clone, PartialEq, Eq, Hash; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr( @@ -772,8 +783,15 @@ pub struct FnSigKind { #[type_visitable(ignore)] #[type_foldable(identity)] flags: u8, + + /// Which function argument is splatted into multiple arguments in callers, if any? + /// Splatting the `u16::MAX`th argument is not supported, because it likely pushes the caller + /// over the fn args limit. (And spending an extra byte on an edge case is not worth the perf.) + #[lift(identity)] #[type_visitable(ignore)] #[type_foldable(identity)] + splatted: u16, + _marker: PhantomData I>, } @@ -791,12 +809,29 @@ impl fmt::Debug for FnSigKind { if self.c_variadic() { f.field(&"CVariadic"); - }; + } + + if let Some(index) = self.splatted() { + f.field(&format!("Splatted({})", index)); + } f.finish() } } +impl Default for FnSigKind { + /// Create a new FnSigKind with the "Rust" ABI, "Unsafe" safety, and no C-style variadic or splatted arguments. + /// To modify these flags, use the `set_*` methods, for readability. + + fn default() -> Self { + Self { flags: 0, splatted: 0, _marker: PhantomData } + .set_abi(ExternAbi::Rust) + .set_safety(I::Safety::unsafe_mode()) + .set_c_variadic(false) + .set_no_splatted_args() + } +} + impl FnSigKind { /// Mask for the `ExternAbi` variant, including the unwind flag. const EXTERN_ABI_MASK: u8 = 0b111111; @@ -807,19 +842,30 @@ impl FnSigKind { /// Bitflag for a trailing C-style variadic argument. const C_VARIADIC_FLAG: u8 = 1 << 7; - /// Create a new FnSigKind with the "Rust" ABI, "Unsafe" safety, and no C-style variadic argument. - /// To modify these flags, use the `set_*` methods, for readability. - // FIXME: use Default instead when that trait is const stable. - pub fn default() -> Self { - Self { flags: 0, _marker: PhantomData } - .set_abi(ExternAbi::Rust) - .set_safety(I::Safety::unsafe_mode()) - .set_c_variadic(false) - } + /// The marker index for "no splatted arguments". + /// Must have the same value as `FnDeclFlags::NO_SPLATTED_ARG_INDEX` and `rustc_ast::FnDecl::NO_SPLATTED_ARG_INDEX`. + /// + /// This is an implementation detail, which should only be used in low-level encoding. + pub const NO_SPLATTED_ARG_INDEX: u16 = u16::MAX; - /// Create a new FnSigKind with the given ABI, safety, and C-style variadic flag. - pub fn new(abi: ExternAbi, safety: I::Safety, c_variadic: bool) -> Self { - Self::default().set_abi(abi).set_safety(safety).set_c_variadic(c_variadic) + /// Create a new FnSigKind with the given ABI, safety, C-style variadic, and splatted argument index. + pub fn new( + abi: ExternAbi, + safety: I::Safety, + c_variadic: bool, + splatted: Option, + args_len: usize, + ) -> Result { + Self::default() + .set_abi(abi) + .set_safety(safety) + .set_c_variadic(c_variadic) + .set_splatted(splatted, args_len) + } + + /// Create a new safe FnSigKind with the `extern "Rust"` ABI, that isn't C-style variadic or splatted. + pub fn dummy() -> Self { + Self::default().set_safety(I::Safety::safe()) } /// Set the ABI, including the unwind flag. @@ -858,6 +904,40 @@ impl FnSigKind { self } + /// Set the splatted argument index. + /// The number of function arguments is used for error checking. + #[must_use = "this method does not modify the receiver"] + pub fn set_splatted( + mut self, + splatted: Option, + args_len: usize, + ) -> Result { + if let Some(splatted_arg_index) = splatted { + if splatted_arg_index == Self::NO_SPLATTED_ARG_INDEX { + // This index value is used as a marker for "no splatting", so it is unsupported. + return Err(SplattedArgIndexError::InvalidIndex { splatted_arg_index }); + } else if splatted_arg_index as usize >= args_len { + return Err(SplattedArgIndexError::OutOfBounds { + splatted_arg_index, + args_len: args_len as u16, + }); + } + + self.splatted = splatted_arg_index; + } else { + self.splatted = Self::NO_SPLATTED_ARG_INDEX; + } + + Ok(self) + } + + /// Set the splatted argument index to "no splatted arguments". + #[must_use = "this method does not modify the receiver"] + pub fn set_no_splatted_args(mut self) -> Self { + self.splatted = Self::NO_SPLATTED_ARG_INDEX; + self + } + /// Get the ABI, including the unwind flag. pub fn abi(self) -> ExternAbi { let abi_index = self.flags & Self::EXTERN_ABI_MASK; @@ -878,6 +958,11 @@ impl FnSigKind { pub fn c_variadic(self) -> bool { self.flags & Self::C_VARIADIC_FLAG != 0 } + + /// Get the index of the splatted argument, if any. + pub fn splatted(self) -> Option { + if self.splatted == Self::NO_SPLATTED_ARG_INDEX { None } else { Some(self.splatted) } + } } #[derive_where(Clone, Copy, PartialEq, Hash; I: Interner)] @@ -908,8 +993,21 @@ impl FnSig { !self.c_variadic() && self.safety().is_safe() && self.abi() == ExternAbi::Rust } + /// Set the safety flag. + #[must_use = "this method does not modify the receiver"] pub fn set_safety(self, safety: I::Safety) -> Self { - Self { fn_sig_kind: FnSigKind::new(self.abi(), safety, self.c_variadic()), ..self } + Self { fn_sig_kind: self.fn_sig_kind.set_safety(safety), ..self } + } + + /// Set the splatted argument index. + /// The number of function arguments is used for error checking. + #[must_use = "this method does not modify the receiver"] + pub fn set_splatted( + self, + splatted: Option, + args_len: usize, + ) -> Result { + Ok(Self { fn_sig_kind: self.fn_sig_kind.set_splatted(splatted, args_len)?, ..self }) } pub fn safety(self) -> I::Safety { @@ -924,11 +1022,14 @@ impl FnSig { self.fn_sig_kind.c_variadic() } + pub fn splatted(self) -> Option { + self.fn_sig_kind.splatted() + } + + /// Create a new safe FnSig with no arguments or return type, using the `extern "Rust"` ABI, + /// that isn't C-style variadic or splatted. pub fn dummy() -> Self { - Self { - inputs_and_output: Default::default(), - fn_sig_kind: FnSigKind::new(ExternAbi::Rust, I::Safety::safe(), false), - } + Self { inputs_and_output: Default::default(), fn_sig_kind: FnSigKind::dummy() } } } @@ -961,6 +1062,10 @@ impl ty::Binder> { self.skip_binder().c_variadic() } + pub fn splatted(self) -> Option { + self.skip_binder().splatted() + } + pub fn safety(self) -> I::Safety { self.skip_binder().safety() } @@ -996,6 +1101,9 @@ impl fmt::Debug for FnSig { if i > 0 { write!(f, ", ")?; } + if Some(i) == fn_sig_kind.splatted().map(usize::from) { + write!(f, "#[splat] ")?; + } write!(f, "{ty:?}")?; } if fn_sig_kind.c_variadic() { @@ -1157,8 +1265,9 @@ impl FnHeader { self.fn_sig_kind.abi() } + /// Create a new safe FnHeader with the `extern "Rust"` ABI, that isn't C-style variadic or splatted. pub fn dummy() -> Self { - Self { fn_sig_kind: FnSigKind::new(ExternAbi::Rust, I::Safety::safe(), false) } + Self { fn_sig_kind: FnSigKind::dummy() } } } diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index b688a001f73fa..9453d30ce91c9 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -364,7 +364,7 @@ pub struct CoroutineClosureSignature { // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types // never actually differ. But we save them rather than recreating them // from scratch just for good measure. - /// Always safe, RustCall, non-c-variadic + /// Always safe, RustCall, non-c-variadic, non-splatted #[type_visitable(ignore)] #[type_foldable(identity)] pub fn_sig_kind: FnSigKind, diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 730c7d9fac611..58fe7dc541fc3 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -406,6 +406,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let sig = this.tcx.mk_fn_sig( args.iter().map(|a| a.layout.ty), dest.layout.ty, + // FIXME(splat): Do we need to set splatted here? + // (Currently this also ignores c_variadic) FnSigKind::default().set_abi(caller_abi).set_safety(rustc_hir::Safety::Safe), ); let caller_fn_abi = this.fn_abi_of_fn_ptr(ty::Binder::dummy(sig), ty::List::empty())?; diff --git a/src/tools/miri/src/shims/sig.rs b/src/tools/miri/src/shims/sig.rs index 68b13a6ed58a0..99673319240fe 100644 --- a/src/tools/miri/src/shims/sig.rs +++ b/src/tools/miri/src/shims/sig.rs @@ -274,7 +274,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { inputs_and_output.push(shim_sig.ret); let fn_sig_binder = Binder::dummy(FnSig { inputs_and_output: this.machine.tcx.mk_type_list(&inputs_and_output), - // Safety does not matter for the ABI. + // Safety and splatted do not matter for the ABI. fn_sig_kind: FnSigKind::default() .set_abi(shim_sig.abi) .set_safety(rustc_hir::Safety::Safe), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/callee.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/callee.rs index 057ba7fa868fe..a661731e60f46 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/callee.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/callee.rs @@ -173,6 +173,8 @@ impl<'db> InferenceContext<'_, 'db> { // impl forces the closure kind to `FnOnce` i.e. `u8`. let kind_ty = autoderef.ctx().table.next_ty_var(call_expr.into()); let interner = autoderef.ctx().interner(); + + // Ignore splatting, it is unsupported on closures. let call_sig = interner.mk_fn_sig( [coroutine_closure_sig.tupled_inputs_ty], coroutine_closure_sig.to_coroutine( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index cc48ba06dbfc5..1fddfc09c666f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -464,6 +464,7 @@ pub fn callable_sig_from_fn_trait<'db>( args.tuple_fields(), ret, false, + // FIXME(splat): handle splatted arguments Safety::Safe, ExternAbi::Rust, )); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index fae63ddc2deae..d63ac7f7a0ed4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -637,6 +637,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { fn_.abi, if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe }, fn_.is_varargs, + // FIXME(splat): handle splatted arguments ), inputs_and_output: Tys::new_from_slice(&args), }), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs index b466fe0f1810b..ba20c8adac4e6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs @@ -2235,6 +2235,7 @@ impl<'db> DbInterner<'db> { self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate) } + // FIXME: add splat support when the experiment is complete pub fn mk_fn_sig( self, inputs: I, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs index fe31d44207dff..d57d824e325fe 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs @@ -1514,6 +1514,7 @@ impl<'db> DbInterner<'db> { TyKind::Tuple(params) => params, _ => panic!(), }; + // Ignore splatting, it is unsupported on closures. self.mk_fn_sig(params, s.output(), s.c_variadic(), safety, ExternAbi::Rust) }) } diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index f88fdf7509c76..d4d86cc9c4500 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h27f62b2d0b2beac6E) +error: symbol-name(_ZN5basic4main17had1822273ff65b1bE) --> $DIR/basic.rs:8:1 | LL | #[rustc_dump_symbol_name] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h27f62b2d0b2beac6) +error: demangling(basic::main::had1822273ff65b1b) --> $DIR/basic.rs:8:1 | LL | #[rustc_dump_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index c1fc9f4b1cea1..2b29917356ce6 100644 --- a/tests/ui/symbol-names/issue-60925.legacy.stderr +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h1eb769490ff06e77E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h7de75f168fb45cf7E) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_dump_symbol_name] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h1eb769490ff06e77) +error: demangling(issue_60925::foo::Foo::foo::h7de75f168fb45cf7) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_dump_symbol_name]