Skip to content

Commit 99b3454

Browse files
Enforce rust-check ABI in signatures, calls
1 parent 2786acc commit 99b3454

File tree

7 files changed

+44
-39
lines changed

7 files changed

+44
-39
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_middle::ty::{GenericArgKind, InternalSubsts};
2121
use rustc_session::parse::feature_err;
2222
use rustc_span::symbol::{sym, Ident, Symbol};
2323
use rustc_span::{Span, DUMMY_SP};
24+
use rustc_target::spec::abi::Abi;
2425
use rustc_trait_selection::autoderef::Autoderef;
2526
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
2627
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
@@ -1542,6 +1543,27 @@ fn check_fn_or_method<'tcx>(
15421543
sig.output(),
15431544
hir_decl.output.span(),
15441545
);
1546+
1547+
if sig.abi == Abi::RustCall {
1548+
let span = tcx.def_span(def_id);
1549+
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
1550+
let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });
1551+
// Check that the argument is a tuple
1552+
if let Some(ty) = inputs.next() {
1553+
wfcx.register_bound(
1554+
ObligationCause::new(span, wfcx.body_id, ObligationCauseCode::RustCall),
1555+
wfcx.param_env,
1556+
*ty,
1557+
tcx.require_lang_item(hir::LangItem::Tuple, Some(span)),
1558+
);
1559+
} else {
1560+
tcx.sess.span_err(span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
1561+
}
1562+
// No more inputs other than the `self` type and the tuple type
1563+
if inputs.next().is_some() {
1564+
tcx.sess.span_err(span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
1565+
}
1566+
}
15451567
}
15461568

15471569
/// Basically `check_associated_type_bounds`, but separated for now and should be

compiler/rustc_hir_typeck/src/callee.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
471471
def_id,
472472
);
473473

474+
if fn_sig.abi == abi::Abi::RustCall {
475+
let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span);
476+
if let Some(ty) = fn_sig.inputs().last().copied() {
477+
self.register_bound(
478+
ty,
479+
self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)),
480+
traits::ObligationCause::new(sp, self.body_id, traits::RustCall),
481+
);
482+
} else {
483+
self.tcx.sess.span_err(
484+
sp,
485+
"functions with the \"rust-call\" ABI must take a single non-self tuple argument",
486+
);
487+
}
488+
}
489+
474490
fn_sig.output()
475491
}
476492

compiler/rustc_hir_typeck/src/check.rs

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ use rustc_hir as hir;
66
use rustc_hir::def::DefKind;
77
use rustc_hir::intravisit::Visitor;
88
use rustc_hir::lang_items::LangItem;
9-
use rustc_hir::{ImplicitSelfKind, ItemKind, Node};
109
use rustc_hir_analysis::check::fn_maybe_err;
1110
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1211
use rustc_infer::infer::RegionVariableOrigin;
1312
use rustc_middle::ty::{self, Ty, TyCtxt};
1413
use rustc_span::def_id::LocalDefId;
15-
use rustc_target::spec::abi::Abi;
1614
use rustc_trait_selection::traits;
1715
use std::cell::RefCell;
1816

@@ -56,41 +54,6 @@ pub(super) fn check_fn<'a, 'tcx>(
5654

5755
fn_maybe_err(tcx, span, fn_sig.abi);
5856

59-
if fn_sig.abi == Abi::RustCall {
60-
let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
61-
62-
let err = || {
63-
let item = match tcx.hir().get(fn_id) {
64-
Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header),
65-
Node::ImplItem(hir::ImplItem {
66-
kind: hir::ImplItemKind::Fn(header, ..), ..
67-
}) => Some(header),
68-
Node::TraitItem(hir::TraitItem {
69-
kind: hir::TraitItemKind::Fn(header, ..),
70-
..
71-
}) => Some(header),
72-
// Closures are RustCall, but they tuple their arguments, so shouldn't be checked
73-
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None,
74-
node => bug!("Item being checked wasn't a function/closure: {:?}", node),
75-
};
76-
77-
if let Some(header) = item {
78-
tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
79-
}
80-
};
81-
82-
if fn_sig.inputs().len() != expected_args {
83-
err()
84-
} else {
85-
// FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
86-
// This will probably require wide-scale changes to support a TupleKind obligation
87-
// We can't resolve this without knowing the type of the param
88-
if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
89-
err()
90-
}
91-
}
92-
}
93-
9457
if body.generator_kind.is_some() && can_be_generator.is_some() {
9558
let yield_ty = fcx
9659
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
136136
tuple_arguments,
137137
Some(method.def_id),
138138
);
139+
139140
method.sig.output()
140141
}
141142

compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'
458458
/// # fn f(x: (isize, isize)) {}
459459
/// f((1, 2));
460460
/// ```
461-
#[derive(Clone, Eq, PartialEq)]
461+
#[derive(Copy, Clone, Eq, PartialEq)]
462462
enum TupleArgumentsFlag {
463463
DontTupleArguments,
464464
TupleArguments,

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ pub enum ObligationCauseCode<'tcx> {
438438
},
439439

440440
AscribeUserTypeProvePredicate(Span),
441+
442+
RustCall,
441443
}
442444

443445
/// The 'location' at which we try to perform HIR-based wf checking.

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2407,7 +2407,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
24072407
| ObligationCauseCode::CheckAssociatedTypeBounds { .. }
24082408
| ObligationCauseCode::LetElse
24092409
| ObligationCauseCode::BinOp { .. }
2410-
| ObligationCauseCode::AscribeUserTypeProvePredicate(..) => {}
2410+
| ObligationCauseCode::AscribeUserTypeProvePredicate(..)
2411+
| ObligationCauseCode::RustCall => {}
24112412
ObligationCauseCode::SliceOrArrayElem => {
24122413
err.note("slice and array elements must have `Sized` type");
24132414
}

0 commit comments

Comments
 (0)