Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
}

Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,11 +445,13 @@ fn fn_sig_suggestion<'tcx>(
predicates: impl IntoIterator<Item = (ty::Clause<'tcx>, 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 => {
Expand Down Expand Up @@ -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()
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_lint/src/foreign_modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_middle/src/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_public/src/unstable/convert/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_symbol_mangling/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
}
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_type_ir/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub enum TypeError<I: Interner> {
ArgumentSorts(ExpectedFound<I::Ty>, usize),
Traits(ExpectedFound<I::TraitId>),
VariadicMismatch(ExpectedFound<bool>),
SplatMismatch(ExpectedFound<Option<u16>>),

/// Instantiating a type variable with the given type would have
/// created a cycle (because it appears somewhere within that
Expand Down Expand Up @@ -76,7 +77,7 @@ impl<I: Interner> TypeError<I> {
match self {
CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | PolarityMismatch(_) | Mismatch
| AbiMismatch(_) | ArraySize(_) | ArgumentSorts(..) | Sorts(_)
| VariadicMismatch(_) | TargetFeatureCast(_) => false,
| VariadicMismatch(_) | SplatMismatch(_) | TargetFeatureCast(_) => false,

Mutability
| ArgumentMutability(_)
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_type_ir/src/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ impl<I: Interner> Relate<I> for ty::FnSig<I> {
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() {
Expand Down
Loading
Loading