1
Fork 0

Auto merge of #99943 - compiler-errors:tuple-trait, r=jackh726

Implement `std::marker::Tuple`, use it in `extern "rust-call"` and `Fn`-family traits

Implements rust-lang/compiler-team#537

I made a few opinionated decisions in this implementation, specifically:
1. Enforcing `extern "rust-call"` on fn items during wfcheck,
2. Enforcing this for all functions (not just ones that have bodies),
3. Gating this `Tuple` marker trait behind its own feature, instead of grouping it into (e.g.) `unboxed_closures`.

Still needing to be done:
1. Enforce that `extern "rust-call"` `fn`-ptrs are well-formed only if they have 1/2 args and the second one implements `Tuple`. (Doing this would fix ICE in #66696.)
2. Deny all explicit/user `impl`s of the `Tuple` trait, kinda like `Sized`.
3. Fixing `Tuple` trait built-in impl for chalk, so that chalkification tests are un-broken.

Open questions:
1. Does this need t-lang or t-libs signoff?

Fixes #99820
This commit is contained in:
bors 2022-11-06 17:48:33 +00:00
commit 7eef946fc0
53 changed files with 843 additions and 244 deletions

View file

@ -700,6 +700,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}
if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() {
match obligation.cause.code().peel_derives() {
ObligationCauseCode::RustCall => {
err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument");
}
ObligationCauseCode::BindingObligation(def_id, _)
| ObligationCauseCode::ItemObligation(def_id)
if ty::ClosureKind::from_def_id(tcx, *def_id).is_some() =>
{
err.code(rustc_errors::error_code!(E0059));
err.set_primary_message(format!(
"type parameter to bare `{}` trait must be a tuple",
tcx.def_path_str(*def_id)
));
}
_ => {}
}
}
if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait()
&& predicate_is_const
{
@ -848,12 +867,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
}
let is_fn_trait = [
self.tcx.lang_items().fn_trait(),
self.tcx.lang_items().fn_mut_trait(),
self.tcx.lang_items().fn_once_trait(),
]
.contains(&Some(trait_ref.def_id()));
let is_fn_trait =
ty::ClosureKind::from_def_id(tcx, trait_ref.def_id()).is_some();
let is_target_feature_fn = if let ty::FnDef(def_id, _) =
*trait_ref.skip_binder().self_ty().kind()
{

View file

@ -2407,7 +2407,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| ObligationCauseCode::CheckAssociatedTypeBounds { .. }
| ObligationCauseCode::LetElse
| ObligationCauseCode::BinOp { .. }
| ObligationCauseCode::AscribeUserTypeProvePredicate(..) => {}
| ObligationCauseCode::AscribeUserTypeProvePredicate(..)
| ObligationCauseCode::RustCall => {}
ObligationCauseCode::SliceOrArrayElem => {
err.note("slice and array elements must have `Sized` type");
}