Skip to content

Commit 8a2c568

Browse files
committed
Impl HIR FnSig for #[splat]
1 parent 09a3713 commit 8a2c568

26 files changed

Lines changed: 205 additions & 33 deletions

File tree

compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,11 +388,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
388388
fn param_info(&self, def_id: DefId) -> ParamInfo {
389389
let sig = self.tcx.fn_sig(def_id).skip_binder().skip_binder();
390390

391-
// FIXME(splat): use `sig.splatted()` once FnSig has it
392391
ParamInfo {
393392
param_count: sig.inputs().len() + usize::from(sig.c_variadic()),
394393
c_variadic: sig.c_variadic(),
395-
splatted: None,
394+
splatted: sig.splatted(),
396395
}
397396
}
398397

compiler/rustc_hir_analysis/src/check/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,11 +445,13 @@ fn fn_sig_suggestion<'tcx>(
445445
predicates: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
446446
assoc: ty::AssocItem,
447447
) -> String {
448+
let splatted_arg_index = sig.splatted().map(usize::from);
448449
let args = sig
449450
.inputs()
450451
.iter()
451452
.enumerate()
452453
.map(|(i, ty)| {
454+
let splat = if splatted_arg_index == Some(i) { "#[splat] " } else { "" };
453455
let arg_ty = match ty.kind() {
454456
ty::Param(_) if assoc.is_method() && i == 0 => "self".to_string(),
455457
ty::Ref(reg, ref_ty, mutability) if i == 0 => {
@@ -478,7 +480,7 @@ fn fn_sig_suggestion<'tcx>(
478480
}
479481
}
480482
};
481-
Some(format!("{arg_ty}"))
483+
Some(format!("{splat}{arg_ty}"))
482484
})
483485
.chain(std::iter::once(if sig.c_variadic() { Some("...".to_string()) } else { None }))
484486
.flatten()

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1713,7 +1713,16 @@ fn check_fn_or_method<'tcx>(
17131713
let span = tcx.def_span(def_id);
17141714
let has_implicit_self = hir_decl.implicit_self().has_implicit_self();
17151715
let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });
1716-
// FIXME(splat): use `sig.splatted()` once FnSig has it
1716+
// FIXME(splat): support the rest of closure splatting, or replace this code with an error
1717+
if let Some(mut splatted_arg_index) = sig.splatted() {
1718+
let mut inputs_count = sig.inputs().len();
1719+
if has_implicit_self {
1720+
splatted_arg_index = splatted_arg_index.strict_sub(1);
1721+
inputs_count = inputs_count.strict_sub(1);
1722+
}
1723+
debug!(?splatted_arg_index, ?inputs_count, ?has_implicit_self, ?sig);
1724+
sig = sig.set_splatted(Some(splatted_arg_index), inputs_count).unwrap();
1725+
}
17171726
// Check that the argument is a tuple and is sized
17181727
if let Some(ty) = inputs.next() {
17191728
wfcx.register_bound(

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3498,11 +3498,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
34983498
debug!(?output_ty);
34993499

35003500
debug!(?abi, ?safety, ?decl.fn_decl_kind, input_tys_len = ?input_tys.len());
3501-
// FIXME(splat): use `set_splatted()` once FnSig has it
35023501
let fn_sig_kind = FnSigKind::default()
35033502
.set_abi(abi)
35043503
.set_safety(safety)
3505-
.set_c_variadic(decl.fn_decl_kind.c_variadic());
3504+
.set_c_variadic(decl.fn_decl_kind.c_variadic())
3505+
.set_splatted(decl.fn_decl_kind.splatted(), input_tys.len())
3506+
.unwrap();
35063507
let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, fn_sig_kind);
35073508
let fn_ptr_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
35083509

compiler/rustc_hir_typeck/src/closure.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
720720
// in this binder we are creating.
721721
assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST));
722722
let bound_sig = expected_sig.sig.map_bound(|sig| {
723+
// Ignore splatting, it is unsupported on closures.
723724
let fn_sig_kind = FnSigKind::default()
724725
.set_abi(ExternAbi::RustCall)
725726
.set_safety(hir::Safety::Safe)

compiler/rustc_hir_typeck/src/errors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ impl IntoDiagArg for ReturnLikeStatementKind {
100100
}
101101
}
102102

103+
// FIXME(splat): add "non-splatted" to all 4 instances of this error message
103104
#[derive(Diagnostic)]
104105
#[diag("functions with the \"rust-call\" ABI must take a single non-self tuple argument")]
105106
pub(crate) struct RustCallIncorrectArgs {

compiler/rustc_lint/src/foreign_modules.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,14 @@ fn structurally_same_type_impl<'tcx>(
329329
let a_sig = tcx.instantiate_bound_regions_with_erased(a_poly_sig);
330330
let b_sig = tcx.instantiate_bound_regions_with_erased(b_poly_sig);
331331

332+
// FIXME(splat): Is splatting ever repr(C)?
333+
// Can two splatted functions to have the same structure?
334+
// Can a splatted and non-splatted function have the same structure?
335+
// For now, we require splatting to match exactly.
336+
if a_sig.splatted() != b_sig.splatted() {
337+
return false;
338+
}
339+
332340
(a_sig.abi(), a_sig.safety(), a_sig.c_variadic())
333341
== (b_sig.abi(), b_sig.safety(), b_sig.c_variadic())
334342
&& a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {

compiler/rustc_middle/src/ty/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,6 +2091,8 @@ impl<'tcx> TyCtxt<'tcx> {
20912091
ty::Tuple(params) => *params,
20922092
_ => bug!(),
20932093
};
2094+
// Ignore splatting, it is unsupported on closures.
2095+
assert!(s.splatted().is_none());
20942096
self.mk_fn_sig(
20952097
params,
20962098
s.output(),

compiler/rustc_middle/src/ty/error.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,20 @@ impl<'tcx> TypeError<'tcx> {
9696
if values.found { "variadic" } else { "non-variadic" }
9797
)
9898
.into(),
99+
TypeError::SplatMismatch(ref values) => format!(
100+
"expected fn with {}, found fn with {}",
101+
if let Some(index) = values.expected {
102+
format!("arg {index} splatted")
103+
} else {
104+
"no splatted arg".to_string()
105+
},
106+
if let Some(index) = values.found {
107+
format!("arg {index} splatted")
108+
} else {
109+
"no splatted arg".to_string()
110+
}
111+
)
112+
.into(),
99113
TypeError::ProjectionMismatched(ref values) => format!(
100114
"expected `{}`, found `{}`",
101115
tcx.def_path_str(values.expected),

compiler/rustc_public/src/unstable/convert/internal.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ impl RustcInternal for FnSig {
312312
tables: &mut Tables<'_, BridgeTys>,
313313
tcx: impl InternalCx<'tcx>,
314314
) -> Self::T<'tcx> {
315+
// FIXME(splat): When `#[splat]` is complete (or stable), add splatted to the public FnSig
315316
let fn_sig_kind = rustc_ty::FnSigKind::default()
316317
.set_abi(self.abi.internal(tables, tcx))
317318
.set_safety(self.safety.internal(tables, tcx))

0 commit comments

Comments
 (0)