Auto merge of #128812 - nnethercote:shrink-TyKind-FnPtr, r=compiler-errors

Shrink `TyKind::FnPtr`.

By splitting the `FnSig` within `TyKind::FnPtr` into `FnSigTys` and `FnHeader`, which can be packed more efficiently. This reduces the size of the hot `TyKind` type from 32 bytes to 24 bytes on 64-bit platforms. This reduces peak memory usage by a few percent on some benchmarks. It also reduces cache misses and page faults similarly, though this doesn't translate to clear cycles or wall-time improvements on CI.

r? `@compiler-errors`
This commit is contained in:
bors 2024-08-14 00:56:53 +00:00
commit e9c965df7b
89 changed files with 315 additions and 231 deletions

View File

@ -3989,7 +3989,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
} else {
let ty = self.infcx.tcx.type_of(self.mir_def_id()).instantiate_identity();
match ty.kind() {
ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig(
ty::FnDef(_, _) | ty::FnPtr(..) => self.annotate_fn_sig(
self.mir_def_id(),
self.infcx.tcx.fn_sig(self.mir_def_id()).instantiate_identity(),
),

View File

@ -1644,7 +1644,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
| ty::Pat(_, _)
| ty::Slice(_)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::CoroutineClosure(_, _)
@ -1689,7 +1689,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(_, _, _)
| ty::CoroutineWitness(..)
| ty::Never

View File

@ -1364,7 +1364,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
debug!("func_ty.kind: {:?}", func_ty.kind());
let sig = match func_ty.kind() {
ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx),
ty::FnDef(..) | ty::FnPtr(..) => func_ty.fn_sig(tcx),
_ => {
span_mirbug!(self, term, "call to non-function {:?}", func_ty);
return;
@ -2411,7 +2411,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let ty_left = left.ty(body, tcx);
match ty_left.kind() {
// Types with regions are comparable if they have a common super-type.
ty::RawPtr(_, _) | ty::FnPtr(_) => {
ty::RawPtr(_, _) | ty::FnPtr(..) => {
let ty_right = right.ty(body, tcx);
let common_ty = self.infcx.next_ty_var(body.source_info(location).span);
self.sub_types(

View File

@ -69,7 +69,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Typ
FloatTy::F64 => types::F64,
FloatTy::F128 => unimplemented!("f16_f128"),
},
ty::FnPtr(_) => pointer_ty(tcx),
ty::FnPtr(..) => pointer_ty(tcx),
ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => {
if has_ptr_meta(tcx, *pointee_ty) {
return None;

View File

@ -874,7 +874,7 @@ pub(crate) fn assert_assignable<'tcx>(
(ty::Ref(_, a, _), ty::RawPtr(b, _)) | (ty::RawPtr(a, _), ty::Ref(_, b, _)) => {
assert_assignable(fx, *a, *b, limit - 1);
}
(ty::FnPtr(_), ty::FnPtr(_)) => {
(ty::FnPtr(..), ty::FnPtr(..)) => {
let from_sig = fx.tcx.normalize_erasing_late_bound_regions(
ParamEnv::reveal_all(),
from_ty.fn_sig(fx.tcx),

View File

@ -213,9 +213,8 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
// NOTE: we cannot remove this match like in the LLVM codegen because the call
// to fn_ptr_backend_type handle the on-stack attribute.
// TODO(antoyo): find a less hackish way to hande the on-stack attribute.
ty::FnPtr(sig) => {
cx.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
}
ty::FnPtr(sig_tys, hdr) => cx
.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig_tys.with(hdr), ty::List::empty())),
_ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO),
};
cx.scalar_types.borrow_mut().insert(self.ty, ty);

View File

@ -456,7 +456,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
{
build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id)
}
ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id),
ty::FnDef(..) | ty::FnPtr(..) => build_subroutine_type_di_node(cx, unique_type_id),
ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id),
ty::CoroutineClosure(..) => build_closure_env_di_node(cx, unique_type_id),
ty::Coroutine(..) => enums::build_coroutine_di_node(cx, unique_type_id),

View File

@ -331,7 +331,7 @@ fn push_debuginfo_type_name<'tcx>(
output.push(')');
}
}
ty::FnDef(..) | ty::FnPtr(_) => {
ty::FnDef(..) | ty::FnPtr(..) => {
// We've encountered a weird 'recursive type'
// Currently, the only way to generate such a type
// is by using 'impl trait':

View File

@ -846,7 +846,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
),
None,
),
ty::FnPtr(_) => (None, Some(callee.immediate())),
ty::FnPtr(..) => (None, Some(callee.immediate())),
_ => bug!("{} is not callable", callee.layout.ty),
};

View File

@ -171,7 +171,7 @@ struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
impl<'ck, 'mir, 'tcx> TypeVisitor<TyCtxt<'tcx>> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
fn visit_ty(&mut self, t: Ty<'tcx>) {
match t.kind() {
ty::FnPtr(_) => {}
ty::FnPtr(..) => {}
ty::Ref(_, _, hir::Mutability::Mut) => {
self.checker.check_op(ops::mut_ref::MutRef(self.kind));
t.super_visit_with(self)
@ -726,7 +726,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
let (mut callee, mut fn_args) = match *fn_ty.kind() {
ty::FnDef(def_id, fn_args) => (def_id, fn_args),
ty::FnPtr(_) => {
ty::FnPtr(..) => {
self.check_op(ops::FnCallIndirect);
return;
}

View File

@ -132,7 +132,7 @@ fn const_to_valtree_inner<'tcx>(
// Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to
// agree with runtime equality tests.
ty::FnPtr(_) => Err(ValTreeCreationError::NonSupportedType(ty)),
ty::FnPtr(..) => Err(ValTreeCreationError::NonSupportedType(ty)),
ty::Ref(_, _, _) => {
let derefd_place = ecx.deref_pointer(place)?;
@ -353,7 +353,7 @@ pub fn valtree_to_const_value<'tcx>(
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Str
| ty::Slice(_)
| ty::Dynamic(..) => bug!("no ValTree should have been created for type {:?}", ty.kind()),

View File

@ -97,7 +97,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
let src = self.read_immediate(src)?;
match cast_ty.kind() {
ty::FnPtr(_) => {
ty::FnPtr(..) => {
// No change to value
self.write_immediate(*src, dest)?;
}
@ -230,7 +230,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
src: &ImmTy<'tcx, M::Provenance>,
cast_to: TyAndLayout<'tcx>,
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
assert_matches!(src.layout.ty.kind(), ty::RawPtr(_, _) | ty::FnPtr(_));
assert_matches!(src.layout.ty.kind(), ty::RawPtr(_, _) | ty::FnPtr(..));
assert!(cast_to.ty.is_integral());
let scalar = src.to_scalar();

View File

@ -81,7 +81,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::CoroutineClosure(_, _)

View File

@ -483,7 +483,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
| ty::Bool
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::RawPtr(..)
| ty::Char
| ty::Ref(..)

View File

@ -424,7 +424,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty));
let (callee, fn_abi, with_caller_location) = match *func.layout.ty.kind() {
ty::FnPtr(_sig) => {
ty::FnPtr(..) => {
let fn_ptr = self.read_pointer(&func)?;
let fn_val = self.get_ptr_fn(fn_ptr)?;
(fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false)

View File

@ -616,7 +616,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
self.check_safe_pointer(value, PointerKind::Ref(*mutbl))?;
Ok(true)
}
ty::FnPtr(_sig) => {
ty::FnPtr(..) => {
let value = self.read_scalar(value, ExpectedKind::FnPtr)?;
// If we check references recursively, also check that this points to a function.

View File

@ -35,7 +35,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
| ty::Slice(_)
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Never
| ty::Tuple(_)
| ty::Dynamic(_, _, _) => self.pretty_print_type(ty),

View File

@ -68,7 +68,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
ty::Float(FloatTy::F128) => Some(InlineAsmType::F128),
ty::FnPtr(_) => Some(asm_ty_isize),
ty::FnPtr(..) => Some(asm_ty_isize),
ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize),
ty::Adt(adt, args) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields;

View File

@ -951,7 +951,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
} else {
let mut diag = match ty.kind() {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()),
ty::FnPtr(_) => tcx.dcx().struct_span_err(
ty::FnPtr(..) => tcx.dcx().struct_span_err(
hir_ty.span,
"using function pointers as const generic parameters is forbidden",
),

View File

@ -172,7 +172,7 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::RawPtr(_, _)
| ty::Ref(..)
| ty::Never
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Tuple(..) => self.check_primitive_impl(id, self_ty),
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) | ty::Param(_) => {
Err(self.tcx.dcx().emit_err(errors::InherentNominal { span: item_span }))

View File

@ -317,8 +317,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraint(current, data.index, variance);
}
ty::FnPtr(sig) => {
self.add_constraints_from_sig(current, sig, variance);
ty::FnPtr(sig_tys, hdr) => {
self.add_constraints_from_sig(current, sig_tys.with(hdr), variance);
}
ty::Error(_) => {

View File

@ -137,7 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the callee is a bare function or a closure, then we're all set.
match *adjusted_ty.kind() {
ty::FnDef(..) | ty::FnPtr(_) => {
ty::FnDef(..) | ty::FnPtr(..) => {
let adjustments = self.adjust_steps(autoderef);
self.apply_adjustments(callee_expr, adjustments);
return Some(CallStep::Builtin(adjusted_ty));
@ -467,7 +467,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(fn_sig, Some(def_id))
}
// FIXME(effects): these arms should error because we can't enforce them
ty::FnPtr(sig) => (sig, None),
ty::FnPtr(sig_tys, hdr) => (sig_tys.with(hdr), None),
_ => {
for arg in arg_exprs {
self.check_expr(arg);

View File

@ -336,9 +336,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.into_iter()
.map(|obl| (obl.predicate, obl.cause.span)),
),
ty::FnPtr(sig) => match closure_kind {
ty::FnPtr(sig_tys, hdr) => match closure_kind {
hir::ClosureKind::Closure => {
let expected_sig = ExpectedSig { cause_span: None, sig };
let expected_sig = ExpectedSig { cause_span: None, sig: sig_tys.with(hdr) };
(Some(expected_sig), Some(ty::ClosureKind::Fn))
}
hir::ClosureKind::Coroutine(_) | hir::ClosureKind::CoroutineClosure(_) => {

View File

@ -225,10 +225,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// items to drop the unsafe qualifier.
self.coerce_from_fn_item(a, b)
}
ty::FnPtr(a_f) => {
ty::FnPtr(a_sig_tys, a_hdr) => {
// We permit coercion of fn pointers to drop the
// unsafe qualifier.
self.coerce_from_fn_pointer(a, a_f, b)
self.coerce_from_fn_pointer(a, a_sig_tys.with(a_hdr), b)
}
ty::Closure(closure_def_id_a, args_a) => {
// Non-capturing closures are coercible to
@ -788,9 +788,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
self.commit_if_ok(|snapshot| {
let outer_universe = self.infcx.universe();
let result = if let ty::FnPtr(fn_ty_b) = b.kind()
&& let (hir::Safety::Safe, hir::Safety::Unsafe) =
(fn_ty_a.safety(), fn_ty_b.safety())
let result = if let ty::FnPtr(_, hdr_b) = b.kind()
&& let (hir::Safety::Safe, hir::Safety::Unsafe) = (fn_ty_a.safety(), hdr_b.safety)
{
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
self.unify_and(unsafe_a, b, to_unsafe)
@ -842,7 +841,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
match b.kind() {
ty::FnPtr(b_sig) => {
ty::FnPtr(_, b_hdr) => {
let a_sig = a.fn_sig(self.tcx);
if let ty::FnDef(def_id, _) = *a.kind() {
// Intrinsics are not coercible to function pointers
@ -852,7 +851,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396).
if b_sig.safety() == hir::Safety::Safe
if b_hdr.safety == hir::Safety::Safe
&& !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
{
return Err(TypeError::TargetFeatureCast(def_id));
@ -910,7 +909,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
//
// All we care here is if any variable is being captured and not the exact paths,
// so we check `upvars_mentioned` for root variables being captured.
ty::FnPtr(fn_ty)
ty::FnPtr(_, hdr)
if self
.tcx
.upvars_mentioned(closure_def_id_a.expect_local())
@ -923,7 +922,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// or
// `unsafe fn(arg0,arg1,...) -> _`
let closure_sig = args_a.as_closure().sig();
let safety = fn_ty.safety();
let safety = hdr.safety;
let pointer_ty =
Ty::new_fn_ptr(self.tcx, self.tcx.signature_unclosure(closure_sig, safety));
debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty);

View File

@ -1530,7 +1530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Int(_) | ty::Uint(_) => Some(ty),
ty::Char => Some(tcx.types.u8),
ty::RawPtr(..) => Some(tcx.types.usize),
ty::FnDef(..) | ty::FnPtr(_) => Some(tcx.types.usize),
ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
_ => None,
});
opt_ty.unwrap_or_else(|| self.next_int_var())

View File

@ -604,7 +604,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
found: Ty<'tcx>,
) -> bool {
if let (ty::FnPtr(_), ty::Closure(def_id, _)) = (expected.kind(), found.kind()) {
if let (ty::FnPtr(..), ty::Closure(def_id, _)) = (expected.kind(), found.kind()) {
if let Some(upvars) = self.tcx.upvars_mentioned(*def_id) {
// Report upto four upvars being captured to reduce the amount error messages
// reported back to the user.

View File

@ -50,7 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Not all of these (e.g., unsafe fns) implement `FnOnce`,
// so we look for these beforehand.
// FIXME(async_closures): These don't impl `FnOnce` by default.
ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(..) => true,
// If it's not a simple function, look for things which implement `FnOnce`.
_ => {
let Some(fn_once) = tcx.lang_items().fn_once_trait() else {

View File

@ -438,7 +438,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
| ty::RawPtr(..)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(..)
| ty::Never
| ty::Tuple(..)

View File

@ -1022,7 +1022,7 @@ fn ty_is_known_nonnull<'tcx>(
let ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
match ty.kind() {
ty::FnPtr(_) => true,
ty::FnPtr(..) => true,
ty::Ref(..) => true,
ty::Adt(def, _) if def.is_box() && matches!(mode, CItemKind::Definition) => true,
ty::Adt(def, args) if def.repr().transparent() && !def.is_union() => {
@ -1473,7 +1473,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ty::Array(inner_ty, _) => self.check_type_for_ffi(cache, inner_ty),
ty::FnPtr(sig) => {
ty::FnPtr(sig_tys, hdr) => {
let sig = sig_tys.with(hdr);
if self.is_internal_abi(sig.abi()) {
return FfiUnsafe {
ty,
@ -1709,8 +1710,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
type Result = ControlFlow<Ty<'tcx>>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if let ty::FnPtr(sig) = ty.kind()
&& !self.visitor.is_internal_abi(sig.abi())
if let ty::FnPtr(_, hdr) = ty.kind()
&& !self.visitor.is_internal_abi(hdr.abi)
{
self.tys.push(ty);
}

View File

@ -427,7 +427,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(_, _, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)

View File

@ -130,7 +130,7 @@ impl<'tcx> Ty<'tcx> {
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
_ => "fn item".into(),
},
ty::FnPtr(_) => "fn pointer".into(),
ty::FnPtr(..) => "fn pointer".into(),
ty::Dynamic(inner, ..) if let Some(principal) = inner.principal() => {
format!("`dyn {}`", tcx.def_path_str(principal.def_id())).into()
}
@ -194,7 +194,7 @@ impl<'tcx> Ty<'tcx> {
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
_ => "fn item".into(),
},
ty::FnPtr(_) => "fn pointer".into(),
ty::FnPtr(..) => "fn pointer".into(),
ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) | ty::CoroutineClosure(..) => "closure".into(),
ty::Coroutine(def_id, ..) => {

View File

@ -250,9 +250,8 @@ impl FlagComputation {
self.add_args(args);
}
&ty::FnPtr(fn_sig) => self.bound_computation(fn_sig, |computation, fn_sig| {
computation.add_tys(fn_sig.inputs());
computation.add_ty(fn_sig.output());
&ty::FnPtr(sig_tys, _) => self.bound_computation(sig_tys, |computation, sig_tys| {
computation.add_tys(sig_tys.inputs_and_output);
}),
}
}

View File

@ -801,7 +801,7 @@ where
| ty::Int(_)
| ty::Uint(_)
| ty::Float(_)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Never
| ty::FnDef(..)
| ty::CoroutineWitness(..)
@ -986,9 +986,11 @@ where
safe: None,
})
}
ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
tcx.layout_of(param_env.and(Ty::new_fn_ptr(tcx, fn_sig))).ok().map(|layout| {
PointeeInfo { size: layout.size, align: layout.align.abi, safe: None }
ty::FnPtr(..) if offset.bytes() == 0 => {
tcx.layout_of(param_env.and(this.ty)).ok().map(|layout| PointeeInfo {
size: layout.size,
align: layout.align.abi,
safe: None,
})
}
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {

View File

@ -2150,6 +2150,6 @@ mod size_asserts {
use super::*;
// tidy-alphabetical-start
static_assert_size!(PredicateKind<'_>, 32);
static_assert_size!(WithCachedTypeInfo<TyKind<'_>>, 56);
static_assert_size!(WithCachedTypeInfo<TyKind<'_>>, 48);
// tidy-alphabetical-end
}

View File

@ -290,7 +290,7 @@ fn characteristic_def_id_of_type_cached<'a>(
| ty::Int(_)
| ty::Uint(_)
| ty::Str
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Alias(..)
| ty::Placeholder(..)
| ty::Param(_)

View File

@ -696,7 +696,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
p!(print(sig), " {{", print_value_path(def_id, args), "}}");
}
}
ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
ty::FnPtr(ref sig_tys, hdr) => p!(print(sig_tys.with(hdr))),
ty::Infer(infer_ty) => {
if self.should_print_verbose() {
p!(write("{:?}", ty.kind()));
@ -1678,7 +1678,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
}
}
}
ty::FnPtr(_) => {
ty::FnPtr(..) => {
// FIXME: We should probably have a helper method to share code with the "Byte strings"
// printing above (which also has to handle pointers to all sorts of things).
if let Some(GlobalAlloc::Function { instance, .. }) =
@ -1741,7 +1741,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
p!(write("{:?}", char::try_from(int).unwrap()))
}
// Pointer types
ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(_) => {
ty::Ref(..) | ty::RawPtr(_, _) | ty::FnPtr(..) => {
let data = int.to_bits(self.tcx().data_layout.pointer_size);
self.typed_value(
|this| {

View File

@ -374,7 +374,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
),
ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?),
ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?),
ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?),
ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.try_fold_with(folder)?, hdr),
ty::Ref(r, ty, mutbl) => {
ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl)
}
@ -424,7 +424,7 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
}
ty::Tuple(ts) => ts.visit_with(visitor),
ty::FnDef(_, args) => args.visit_with(visitor),
ty::FnPtr(ref f) => f.visit_with(visitor),
ty::FnPtr(ref sig_tys, _) => sig_tys.visit_with(visitor),
ty::Ref(r, ty, _) => {
try_visit!(r.visit_with(visitor));
ty.visit_with(visitor)

View File

@ -658,7 +658,8 @@ impl<'tcx> Ty<'tcx> {
#[inline]
pub fn new_fn_ptr(tcx: TyCtxt<'tcx>, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
Ty::new(tcx, FnPtr(fty))
let (sig_tys, hdr) = fty.split();
Ty::new(tcx, FnPtr(sig_tys, hdr))
}
#[inline]
@ -1182,7 +1183,7 @@ impl<'tcx> Ty<'tcx> {
| Float(_)
| Uint(_)
| FnDef(..)
| FnPtr(_)
| FnPtr(..)
| RawPtr(_, _)
| Infer(IntVar(_) | FloatVar(_))
)
@ -1333,7 +1334,7 @@ impl<'tcx> Ty<'tcx> {
pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
match self.kind() {
FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args),
FnPtr(f) => *f,
FnPtr(sig_tys, hdr) => sig_tys.with(*hdr),
Error(_) => {
// ignore errors (#54954)
Binder::dummy(ty::FnSig {
@ -1352,12 +1353,12 @@ impl<'tcx> Ty<'tcx> {
#[inline]
pub fn is_fn(self) -> bool {
matches!(self.kind(), FnDef(..) | FnPtr(_))
matches!(self.kind(), FnDef(..) | FnPtr(..))
}
#[inline]
pub fn is_fn_ptr(self) -> bool {
matches!(self.kind(), FnPtr(_))
matches!(self.kind(), FnPtr(..))
}
#[inline]
@ -1599,7 +1600,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Bool
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::RawPtr(..)
| ty::Char
| ty::Ref(..)
@ -1791,7 +1792,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Bool
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::RawPtr(..)
| ty::Char
| ty::Ref(..)
@ -1941,7 +1942,7 @@ impl<'tcx> Ty<'tcx> {
| RawPtr(_, _)
| Ref(_, _, _)
| FnDef(_, _)
| FnPtr(_)
| FnPtr(..)
| Dynamic(_, _, _)
| Closure(_, _)
| CoroutineClosure(_, _)
@ -1955,9 +1956,12 @@ impl<'tcx> Ty<'tcx> {
}
impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
fn split_inputs_and_output(self) -> (&'tcx [Ty<'tcx>], Ty<'tcx>) {
let (output, inputs) = self.split_last().unwrap();
(inputs, *output)
fn inputs(self) -> &'tcx [Ty<'tcx>] {
self.split_last().unwrap().1
}
fn output(self) -> Ty<'tcx> {
*self.split_last().unwrap().0
}
}
@ -1969,6 +1973,6 @@ mod size_asserts {
use super::*;
// tidy-alphabetical-start
static_assert_size!(ty::RegionKind<'_>, 24);
static_assert_size!(ty::TyKind<'_>, 32);
static_assert_size!(ty::TyKind<'_>, 24);
// tidy-alphabetical-end
}

View File

@ -1272,7 +1272,7 @@ impl<'tcx> Ty<'tcx> {
| ty::RawPtr(_, _)
| ty::FnDef(..)
| ty::Error(_)
| ty::FnPtr(_) => true,
| ty::FnPtr(..) => true,
ty::Tuple(fields) => fields.iter().all(Self::is_trivially_freeze),
ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => ty.is_trivially_freeze(),
ty::Adt(..)
@ -1312,7 +1312,7 @@ impl<'tcx> Ty<'tcx> {
| ty::RawPtr(_, _)
| ty::FnDef(..)
| ty::Error(_)
| ty::FnPtr(_) => true,
| ty::FnPtr(..) => true,
ty::Tuple(fields) => fields.iter().all(Self::is_trivially_unpin),
ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => ty.is_trivially_unpin(),
ty::Adt(..)
@ -1351,7 +1351,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Ref(..)
| ty::RawPtr(..)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_)) => AsyncDropGlueMorphology::Noop,
@ -1534,7 +1534,7 @@ impl<'tcx> Ty<'tcx> {
ty::Pat(..) | ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true,
// Raw pointers use bitwise comparison.
ty::RawPtr(_, _) | ty::FnPtr(_) => true,
ty::RawPtr(_, _) | ty::FnPtr(..) => true,
// Floating point numbers are not `Eq`.
ty::Float(_) => false,
@ -1665,7 +1665,7 @@ pub fn needs_drop_components_with_async<'tcx>(
| ty::Float(_)
| ty::Never
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Char
| ty::RawPtr(_, _)
| ty::Ref(..)
@ -1732,7 +1732,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
| ty::RawPtr(_, _)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Never
| ty::Foreign(_) => true,

View File

@ -189,9 +189,10 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
stack.extend(args.iter().rev());
}
ty::Tuple(ts) => stack.extend(ts.iter().rev().map(GenericArg::from)),
ty::FnPtr(sig) => {
stack.push(sig.skip_binder().output().into());
stack.extend(sig.skip_binder().inputs().iter().copied().rev().map(|ty| ty.into()));
ty::FnPtr(sig_tys, _hdr) => {
stack.extend(
sig_tys.skip_binder().inputs_and_output.iter().rev().map(|ty| ty.into()),
);
}
},
GenericArgKind::Lifetime(_) => {}

View File

@ -158,7 +158,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
| ty::Pat(_, _)
| ty::Slice(_)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(_, _, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
@ -201,7 +201,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(_, _, _)
| ty::CoroutineWitness(..)
| ty::Never

View File

@ -64,7 +64,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
let ty = func.ty(body, tcx);
let sig = ty.fn_sig(tcx);
let fn_def_id = match ty.kind() {
ty::FnPtr(_) => None,
ty::FnPtr(..) => None,
&ty::FnDef(def_id, _) => Some(def_id),
_ => span_bug!(span, "invalid callee of type {:?}", ty),
};

View File

@ -57,7 +57,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
};
let fn_def_id = match ty.kind() {
ty::FnPtr(_) => None,
ty::FnPtr(..) => None,
&ty::FnDef(def_id, _) => {
// Rust calls cannot themselves create foreign unwinds (even if they use a non-Rust ABI).
// So the leak of the foreign unwind into Rust can only be elsewhere, not here.

View File

@ -437,7 +437,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0)));
match self_ty.kind() {
ty::FnDef(..) | ty::FnPtr(_) => builder.copy_shim(),
ty::FnDef(..) | ty::FnPtr(..) => builder.copy_shim(),
ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
ty::CoroutineClosure(_, args) => {
builder.tuple_like_shim(dest, src, args.as_coroutine_closure().upvar_tys())

View File

@ -360,7 +360,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
| ty::Ref(_, _, _)
| ty::Pat(_, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(_, _, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)

View File

@ -334,7 +334,7 @@ where
| ty::Str
| ty::FnDef(..)
| ty::Pat(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Array(..)
| ty::Slice(..)
| ty::RawPtr(..)

View File

@ -533,7 +533,7 @@ where
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
@ -620,7 +620,7 @@ where
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Alias(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)

View File

@ -31,7 +31,7 @@ where
| ty::Bool
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Error(_)
| ty::Never
| ty::Char => Ok(vec![]),
@ -117,7 +117,7 @@ where
| ty::Bool
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::RawPtr(..)
| ty::Char
| ty::Ref(..)
@ -178,7 +178,7 @@ where
{
match ty.kind() {
// impl Copy/Clone for FnDef, FnPtr
ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Ok(vec![]),
ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(vec![]),
// Implementations are provided in core
ty::Uint(_)
@ -269,7 +269,8 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<I: Intern
}
}
// keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
ty::FnPtr(sig) => {
ty::FnPtr(sig_tys, hdr) => {
let sig = sig_tys.with(hdr);
if sig.is_fn_trait_compatible() {
Ok(Some(
sig.map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())),
@ -460,7 +461,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
ty::FnDef(def_id, _) => {
let sig = self_ty.fn_sig(cx);
if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
if sig.is_fn_trait_compatible() && !cx.has_target_features(def_id) {
fn_item_to_async_callable(cx, sig)
} else {
Err(NoSolution)
@ -468,7 +469,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
}
ty::FnPtr(..) => {
let sig = self_ty.fn_sig(cx);
if sig.skip_binder().is_fn_trait_compatible() {
if sig.is_fn_trait_compatible() {
fn_item_to_async_callable(cx, sig)
} else {
Err(NoSolution)

View File

@ -1145,7 +1145,7 @@ where
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(_, _)

View File

@ -127,14 +127,17 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
for meta_item in meta_items {
match meta_item.name_or_empty() {
sym::debug => {
let ty::FnPtr(sig) = ty.kind() else {
let ty::FnPtr(sig_tys, hdr) = ty.kind() else {
span_bug!(
meta_item.span(),
"`#[rustc_abi(debug)]` on a type alias requires function pointer type"
);
};
let abi = unwrap_fn_abi(
tcx.fn_abi_of_fn_ptr(param_env.and((*sig, /* extra_args */ ty::List::empty()))),
tcx.fn_abi_of_fn_ptr(
param_env
.and((sig_tys.with(*hdr), /* extra_args */ ty::List::empty())),
),
tcx,
item_def_id,
);
@ -155,7 +158,7 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
"`#[rustc_abi(assert_eq)]` on a type alias requires pair type"
);
};
let ty::FnPtr(sig1) = field1.kind() else {
let ty::FnPtr(sig_tys1, hdr1) = field1.kind() else {
span_bug!(
meta_item.span(),
"`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types"
@ -163,12 +166,13 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
};
let abi1 = unwrap_fn_abi(
tcx.fn_abi_of_fn_ptr(
param_env.and((*sig1, /* extra_args */ ty::List::empty())),
param_env
.and((sig_tys1.with(*hdr1), /* extra_args */ ty::List::empty())),
),
tcx,
item_def_id,
);
let ty::FnPtr(sig2) = field2.kind() else {
let ty::FnPtr(sig_tys2, hdr2) = field2.kind() else {
span_bug!(
meta_item.span(),
"`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types"
@ -176,7 +180,8 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
};
let abi2 = unwrap_fn_abi(
tcx.fn_abi_of_fn_ptr(
param_env.and((*sig2, /* extra_args */ ty::List::empty())),
param_env
.and((sig_tys2.with(*hdr2), /* extra_args */ ty::List::empty())),
),
tcx,
item_def_id,

View File

@ -413,7 +413,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
| ty::Foreign(_)
| ty::RawPtr(_, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Pat(_, _)
| ty::Dynamic(_, _, _)
| ty::Closure(..)

View File

@ -607,10 +607,15 @@ pub fn encode_ty<'tcx>(
typeid.push_str(&s);
}
ty::FnPtr(fn_sig) => {
ty::FnPtr(sig_tys, hdr) => {
// PF<return-type><parameter-type1..parameter-typeN>E
let mut s = String::from("P");
s.push_str(&encode_fnsig(tcx, &fn_sig.skip_binder(), dict, TypeIdOptions::empty()));
s.push_str(&encode_fnsig(
tcx,
&sig_tys.with(*hdr).skip_binder(),
dict,
TypeIdOptions::empty(),
));
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
typeid.push_str(&s);
}

View File

@ -131,7 +131,10 @@ impl RustcInternal for RigidTy {
RigidTy::FnDef(def, args) => {
rustc_ty::TyKind::FnDef(def.0.internal(tables, tcx), args.internal(tables, tcx))
}
RigidTy::FnPtr(sig) => rustc_ty::TyKind::FnPtr(sig.internal(tables, tcx)),
RigidTy::FnPtr(sig) => {
let (sig_tys, hdr) = sig.internal(tables, tcx).split();
rustc_ty::TyKind::FnPtr(sig_tys, hdr)
}
RigidTy::Closure(def, args) => {
rustc_ty::TyKind::Closure(def.0.internal(tables, tcx), args.internal(tables, tcx))
}

View File

@ -352,7 +352,9 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
ty::FnDef(def_id, generic_args) => {
TyKind::RigidTy(RigidTy::FnDef(tables.fn_def(*def_id), generic_args.stable(tables)))
}
ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))),
ty::FnPtr(sig_tys, hdr) => {
TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables)))
}
ty::Dynamic(existential_predicates, region, dyn_kind) => {
TyKind::RigidTy(RigidTy::Dynamic(
existential_predicates

View File

@ -427,7 +427,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
self.print_def_path(def_id, &[])?;
}
ty::FnPtr(sig) => {
ty::FnPtr(sig_tys, hdr) => {
let sig = sig_tys.with(hdr);
self.push("F");
self.in_binder(&sig, |cx, sig| {
if sig.safety == hir::Safety::Unsafe {

View File

@ -1087,9 +1087,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
values
}
(ty::FnDef(did1, args1), ty::FnPtr(sig2)) => {
(ty::FnDef(did1, args1), ty::FnPtr(sig_tys2, hdr2)) => {
let sig1 = self.tcx.fn_sig(*did1).instantiate(self.tcx, args1);
let mut values = self.cmp_fn_sig(&sig1, sig2);
let mut values = self.cmp_fn_sig(&sig1, &sig_tys2.with(*hdr2));
values.0.push_highlighted(format!(
" {{{}}}",
self.tcx.def_path_str_with_args(*did1, args1)
@ -1097,16 +1097,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
values
}
(ty::FnPtr(sig1), ty::FnDef(did2, args2)) => {
(ty::FnPtr(sig_tys1, hdr1), ty::FnDef(did2, args2)) => {
let sig2 = self.tcx.fn_sig(*did2).instantiate(self.tcx, args2);
let mut values = self.cmp_fn_sig(sig1, &sig2);
let mut values = self.cmp_fn_sig(&sig_tys1.with(*hdr1), &sig2);
values
.1
.push_normal(format!(" {{{}}}", self.tcx.def_path_str_with_args(*did2, args2)));
values
}
(ty::FnPtr(sig1), ty::FnPtr(sig2)) => self.cmp_fn_sig(sig1, sig2),
(ty::FnPtr(sig_tys1, hdr1), ty::FnPtr(sig_tys2, hdr2)) => {
self.cmp_fn_sig(&sig_tys1.with(*hdr1), &sig_tys2.with(*hdr2))
}
_ => {
let mut strs = (DiagStyledString::new(), DiagStyledString::new());

View File

@ -441,9 +441,9 @@ impl<T> Trait<T> for X {
}
}
}
(ty::FnPtr(sig), ty::FnDef(def_id, _))
| (ty::FnDef(def_id, _), ty::FnPtr(sig)) => {
if tcx.fn_sig(def_id).skip_binder().safety() < sig.safety() {
(ty::FnPtr(_, hdr), ty::FnDef(def_id, _))
| (ty::FnDef(def_id, _), ty::FnPtr(_, hdr)) => {
if tcx.fn_sig(def_id).skip_binder().safety() < hdr.safety {
diag.note(
"unsafe functions cannot be coerced into safe function pointers",
);

View File

@ -383,8 +383,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
return;
}
match (&expected_inner.kind(), &found_inner.kind()) {
(ty::FnPtr(sig), ty::FnDef(did, args)) => {
let expected_sig = &(self.normalize_fn_sig)(*sig);
(ty::FnPtr(sig_tys, hdr), ty::FnDef(did, args)) => {
let sig = sig_tys.with(*hdr);
let expected_sig = &(self.normalize_fn_sig)(sig);
let found_sig =
&(self.normalize_fn_sig)(self.tcx.fn_sig(*did).instantiate(self.tcx, args));
@ -402,11 +403,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name },
(true, true) => {
diag.subdiagnostic(FnItemsAreDistinct);
FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig }
FunctionPointerSuggestion::CastRef { span, fn_name, sig }
}
(false, false) => {
diag.subdiagnostic(FnItemsAreDistinct);
FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig }
FunctionPointerSuggestion::Cast { span, fn_name, sig }
}
};
diag.subdiagnostic(sugg);
@ -449,10 +450,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
diag.subdiagnostic(sug);
}
(ty::FnDef(did, args), ty::FnPtr(sig)) => {
(ty::FnDef(did, args), ty::FnPtr(sig_tys, hdr)) => {
let expected_sig =
&(self.normalize_fn_sig)(self.tcx.fn_sig(*did).instantiate(self.tcx, args));
let found_sig = &(self.normalize_fn_sig)(*sig);
let found_sig = &(self.normalize_fn_sig)(sig_tys.with(*hdr));
if !self.same_type_modulo_infer(*found_sig, *expected_sig) {
return;

View File

@ -375,7 +375,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let impl_candidates = self.find_similar_impl_candidates(leaf_trait_predicate);
suggested = if let &[cand] = &impl_candidates[..] {
let cand = cand.trait_ref;
if let (ty::FnPtr(_), ty::FnDef(..)) =
if let (ty::FnPtr(..), ty::FnDef(..)) =
(cand.self_ty().kind(), main_trait_ref.self_ty().skip_binder().kind())
{
err.span_suggestion(
@ -790,8 +790,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// is unimplemented is because async closures don't implement `Fn`/`FnMut`
// if they have captures.
if let Some(by_ref_captures) = by_ref_captures
&& let ty::FnPtr(sig) = by_ref_captures.kind()
&& !sig.skip_binder().output().is_unit()
&& let ty::FnPtr(sig_tys, _) = by_ref_captures.kind()
&& !sig_tys.skip_binder().output().is_unit()
{
let mut err = self.dcx().create_err(AsyncClosureNotFn {
span: self.tcx.def_span(closure_def_id),
@ -1057,7 +1057,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
"`{ty}` is forbidden as the type of a const generic parameter",
)
}
ty::FnPtr(_) => {
ty::FnPtr(..) => {
struct_span_code_err!(
self.dcx(),
span,
@ -1836,10 +1836,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if let &[cand] = &candidates[..] {
let (desc, mention_castable) =
match (cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) {
(ty::FnPtr(_), ty::FnDef(..)) => {
(ty::FnPtr(..), ty::FnDef(..)) => {
(" implemented for fn pointer `", ", cast using `as`")
}
(ty::FnPtr(_), _) => (" implemented for fn pointer `", ""),
(ty::FnPtr(..), _) => (" implemented for fn pointer `", ""),
_ => (" implemented for `", ""),
};
err.highlighted_help(vec![

View File

@ -1077,10 +1077,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let Some((def_id_or_name, output, inputs)) =
(self.autoderef_steps)(found).into_iter().find_map(|(found, _)| {
match *found.kind() {
ty::FnPtr(fn_sig) => Some((
ty::FnPtr(sig_tys, _) => Some((
DefIdOrName::Name("function pointer"),
fn_sig.output(),
fn_sig.inputs(),
sig_tys.output(),
sig_tys.inputs(),
)),
ty::FnDef(def_id, _) => {
let fn_sig = found.fn_sig(self.tcx);
@ -1977,20 +1977,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = cause else {
return;
};
let ty::FnPtr(expected) = expected.kind() else {
let ty::FnPtr(sig_tys, hdr) = expected.kind() else {
return;
};
let ty::FnPtr(found) = found.kind() else {
let expected = sig_tys.with(*hdr);
let ty::FnPtr(sig_tys, hdr) = found.kind() else {
return;
};
let found = sig_tys.with(*hdr);
let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) else {
return;
};
let hir::ExprKind::Path(path) = arg.kind else {
return;
};
let expected_inputs = self.tcx.instantiate_bound_regions_with_erased(*expected).inputs();
let found_inputs = self.tcx.instantiate_bound_regions_with_erased(*found).inputs();
let expected_inputs = self.tcx.instantiate_bound_regions_with_erased(expected).inputs();
let found_inputs = self.tcx.instantiate_bound_regions_with_erased(found).inputs();
let both_tys = expected_inputs.iter().copied().zip(found_inputs.iter().copied());
let arg_expr = |infcx: &InferCtxt<'tcx>, name, expected: Ty<'tcx>, found: Ty<'tcx>| {
@ -4790,13 +4792,13 @@ fn hint_missing_borrow<'tcx>(
}
let found_args = match found.kind() {
ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()),
ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()),
kind => {
span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
}
};
let expected_args = match expected.kind() {
ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()),
ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()),
kind => {
span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
}

View File

@ -1636,7 +1636,7 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>(
.generics_of(def_id)
.host_effect_index
.map_or(tcx.consts.true_, |idx| args.const_at(idx)),
ty::FnPtr(_) => tcx.consts.true_,
ty::FnPtr(..) => tcx.consts.true_,
_ => unreachable!("only expected FnPtr or FnDef in `confirm_fn_pointer_candidate`"),
};

View File

@ -33,7 +33,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
| ty::Float(_)
| ty::Never
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Char
| ty::CoroutineWitness(..)
| ty::RawPtr(_, _)
@ -224,7 +224,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
| ty::RawPtr(..)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::CoroutineWitness(..) => {
// these types never have a destructor
}

View File

@ -468,8 +468,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
candidates.vec.push(AsyncClosureCandidate);
}
// Provide an impl, but only for suitable `fn` pointers.
ty::FnPtr(sig) => {
if sig.is_fn_trait_compatible() {
ty::FnPtr(sig_tys, hdr) => {
if sig_tys.with(hdr).is_fn_trait_compatible() {
candidates.vec.push(AsyncClosureCandidate);
}
}
@ -535,8 +535,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
candidates.ambiguous = true; // Could wind up being a fn() type.
}
// Provide an impl, but only for suitable `fn` pointers.
ty::FnPtr(sig) => {
if sig.is_fn_trait_compatible() {
ty::FnPtr(sig_tys, hdr) => {
if sig_tys.with(hdr).is_fn_trait_compatible() {
candidates
.vec
.push(FnPointerCandidate { fn_host_effect: self.tcx().consts.true_ });
@ -819,7 +819,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::RawPtr(_, _)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
@ -1207,7 +1207,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::RawPtr(_, _)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Never
| ty::Foreign(_)
| ty::Array(..)
@ -1290,7 +1290,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::Pat(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(_, _, _)
| ty::Closure(..)
| ty::CoroutineClosure(..)
@ -1339,7 +1339,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let self_ty = self.infcx.resolve_vars_if_possible(obligation.self_ty());
match self_ty.skip_binder().kind() {
ty::FnPtr(_) => candidates.vec.push(BuiltinCandidate { has_nested: false }),
ty::FnPtr(..) => candidates.vec.push(BuiltinCandidate { has_nested: false }),
ty::Bool
| ty::Char
| ty::Int(_)

View File

@ -1398,7 +1398,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::RawPtr(_, _)
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Never
| ty::Foreign(_) => {}

View File

@ -2113,7 +2113,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
| ty::Bool
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::RawPtr(..)
| ty::Char
| ty::Ref(..)
@ -2170,7 +2170,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
use self::BuiltinImplConditions::{Ambiguous, None, Where};
match *self_ty.kind() {
ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Where(ty::Binder::dummy(Vec::new())),
ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Where(ty::Binder::dummy(Vec::new())),
ty::Uint(_)
| ty::Int(_)
@ -2332,7 +2332,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
| ty::Bool
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Error(_)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Never

View File

@ -812,7 +812,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
return upvars.visit_with(self);
}
ty::FnPtr(_) => {
ty::FnPtr(..) => {
// Let the visitor iterate into the argument/return
// types appearing in the fn signature.
}

View File

@ -248,7 +248,7 @@ fn resolve_associated_item<'tcx>(
if name == sym::clone {
let self_ty = trait_ref.self_ty();
match self_ty.kind() {
ty::FnDef(..) | ty::FnPtr(_) => (),
ty::FnDef(..) | ty::FnPtr(..) => (),
ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Closure(..)

View File

@ -184,7 +184,7 @@ fn layout_of_uncached<'tcx>(
ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)),
ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)),
ty::Float(fty) => scalar(Float(Float::from_float_ty(fty))),
ty::FnPtr(_) => {
ty::FnPtr(..) => {
let mut ptr = scalar_unit(Pointer(dl.instruction_address_space));
ptr.valid_range_mut().start = 1;
tcx.mk_layout(LayoutS::scalar(cx, ptr))

View File

@ -86,6 +86,7 @@ macro_rules! impl_binder_encode_decode {
#[cfg(feature = "nightly")]
impl_binder_encode_decode! {
ty::FnSig<I>,
ty::FnSigTys<I>,
ty::TraitPredicate<I>,
ty::ExistentialPredicate<I>,
ty::TraitRef<I>,
@ -247,21 +248,6 @@ impl<I: Interner, T> Binder<I, T> {
// `self.value` is equivalent to `self.skip_binder()`
if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
}
/// Splits the contents into two things that share the same binder
/// level as the original, returning two distinct binders.
///
/// `f` should consider bound regions at depth 1 to be free, and
/// anything it produces with bound regions at depth 1 will be
/// bound in the resulting return values.
pub fn split<U, V, F>(self, f: F) -> (Binder<I, U>, Binder<I, V>)
where
F: FnOnce(T) -> (U, V),
{
let Binder { value, bound_vars } = self;
let (u, v) = f(value);
(Binder { value: u, bound_vars }, Binder { value: v, bound_vars })
}
}
impl<I: Interner, T> Binder<I, Option<T>> {

View File

@ -135,7 +135,9 @@ pub fn simplify_type<I: Interner>(
ty::CoroutineWitness(def_id, _) => Some(SimplifiedType::CoroutineWitness(def_id)),
ty::Never => Some(SimplifiedType::Never),
ty::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())),
ty::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())),
ty::FnPtr(sig_tys, _hdr) => {
Some(SimplifiedType::Function(sig_tys.skip_binder().inputs().len()))
}
ty::Placeholder(..) => Some(SimplifiedType::Placeholder),
ty::Param(_) => match treat_params {
TreatParams::ForLookup => Some(SimplifiedType::Placeholder),
@ -307,17 +309,14 @@ impl<I: Interner> DeepRejectCtxt<I> {
obl_preds.principal_def_id() == impl_preds.principal_def_id()
)
}
ty::FnPtr(obl_sig) => match k {
ty::FnPtr(impl_sig) => {
let ty::FnSig { inputs_and_output, c_variadic, safety, abi } =
obl_sig.skip_binder();
let impl_sig = impl_sig.skip_binder();
ty::FnPtr(obl_sig_tys, obl_hdr) => match k {
ty::FnPtr(impl_sig_tys, impl_hdr) => {
let obl_sig_tys = obl_sig_tys.skip_binder().inputs_and_output;
let impl_sig_tys = impl_sig_tys.skip_binder().inputs_and_output;
abi == impl_sig.abi
&& c_variadic == impl_sig.c_variadic
&& safety == impl_sig.safety
&& inputs_and_output.len() == impl_sig.inputs_and_output.len()
&& iter::zip(inputs_and_output.iter(), impl_sig.inputs_and_output.iter())
obl_hdr == impl_hdr
&& obl_sig_tys.len() == impl_sig_tys.len()
&& iter::zip(obl_sig_tys.iter(), impl_sig_tys.iter())
.all(|(obl, imp)| self.types_may_unify(obl, imp))
}
_ => false,

View File

@ -133,12 +133,12 @@ pub trait Ty<I: Interner<Ty = Self>>:
}
fn is_fn_ptr(self) -> bool {
matches!(self.kind(), ty::FnPtr(_))
matches!(self.kind(), ty::FnPtr(..))
}
fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> {
match self.kind() {
ty::FnPtr(sig) => sig,
ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr),
ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, args),
ty::Error(_) => {
// ignore errors (#54954)
@ -181,7 +181,7 @@ pub trait Ty<I: Interner<Ty = Self>>:
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::CoroutineClosure(_, _)
@ -203,7 +203,9 @@ pub trait Ty<I: Interner<Ty = Self>>:
pub trait Tys<I: Interner<Tys = Self>>:
Copy + Debug + Hash + Eq + SliceLike<Item = I::Ty> + TypeFoldable<I> + Default
{
fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty);
fn inputs(self) -> I::FnInputTys;
fn output(self) -> I::Ty;
}
pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq + Relate<I> {

View File

@ -186,7 +186,7 @@ impl<I: Interner> TypeVisitor<I> for OutlivesCollector<'_, I> {
| ty::Slice(_)
| ty::RawPtr(_, _)
| ty::Ref(_, _, _)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Dynamic(_, _, _)
| ty::Tuple(_) => {
ty.super_visit_with(self);

View File

@ -524,8 +524,8 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
Ok(Ty::new_fn_def(cx, a_def_id, args))
}
(ty::FnPtr(a_fty), ty::FnPtr(b_fty)) => {
let fty = relation.relate(a_fty, b_fty)?;
(ty::FnPtr(a_sig_tys, a_hdr), ty::FnPtr(b_sig_tys, b_hdr)) => {
let fty = relation.relate(a_sig_tys.with(a_hdr), b_sig_tys.with(b_hdr))?;
Ok(Ty::new_fn_ptr(cx, fty))
}

View File

@ -143,7 +143,12 @@ pub enum TyKind<I: Interner> {
/// fn foo() -> i32 { 1 }
/// let bar: fn() -> i32 = foo;
/// ```
FnPtr(ty::Binder<I, FnSig<I>>),
///
/// These two fields are equivalent to a `ty::Binder<I, FnSig<I>>`. But by
/// splitting that into two pieces, we get a more compact data layout that
/// reduces the size of `TyKind` by 8 bytes. It is a very hot type, so it's
/// worth the mild inconvenience.
FnPtr(ty::Binder<I, FnSigTys<I>>, FnHeader<I>),
/// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`.
Dynamic(I::BoundExistentialPredicates, I::Region, DynKind),
@ -288,7 +293,7 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
RawPtr(ty, mutbl) => write!(f, "*{} {:?}", mutbl.ptr_str(), ty),
Ref(r, t, m) => write!(f, "&{:?} {}{:?}", r, m.prefix_str(), t),
FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&s).finish(),
FnPtr(s) => write!(f, "{s:?}"),
FnPtr(sig_tys, hdr) => write!(f, "{:?}", sig_tys.with(*hdr)),
Dynamic(p, r, repr) => match repr {
DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"),
DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"),
@ -868,16 +873,12 @@ pub struct FnSig<I: Interner> {
}
impl<I: Interner> FnSig<I> {
pub fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty) {
self.inputs_and_output.split_inputs_and_output()
}
pub fn inputs(self) -> I::FnInputTys {
self.split_inputs_and_output().0
self.inputs_and_output.inputs()
}
pub fn output(self) -> I::Ty {
self.split_inputs_and_output().1
self.inputs_and_output.output()
}
pub fn is_fn_trait_compatible(self) -> bool {
@ -922,6 +923,13 @@ impl<I: Interner> ty::Binder<I, FnSig<I>> {
pub fn is_fn_trait_compatible(&self) -> bool {
self.skip_binder().is_fn_trait_compatible()
}
// Used to split a single value into the two fields in `TyKind::FnPtr`.
pub fn split(self) -> (ty::Binder<I, FnSigTys<I>>, FnHeader<I>) {
let hdr =
FnHeader { c_variadic: self.c_variadic(), safety: self.safety(), abi: self.abi() };
(self.map_bound(|sig| FnSigTys { inputs_and_output: sig.inputs_and_output }), hdr)
}
}
impl<I: Interner> fmt::Debug for FnSig<I> {
@ -935,7 +943,7 @@ impl<I: Interner> fmt::Debug for FnSig<I> {
}
write!(f, "fn(")?;
let (inputs, output) = sig.split_inputs_and_output();
let inputs = sig.inputs();
for (i, ty) in inputs.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
@ -951,9 +959,69 @@ impl<I: Interner> fmt::Debug for FnSig<I> {
}
write!(f, ")")?;
let output = sig.output();
match output.kind() {
Tuple(list) if list.is_empty() => Ok(()),
_ => write!(f, " -> {:?}", sig.output()),
}
}
}
// This is just a `FnSig` without the `FnHeader` fields.
#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
pub struct FnSigTys<I: Interner> {
pub inputs_and_output: I::Tys,
}
impl<I: Interner> FnSigTys<I> {
pub fn inputs(self) -> I::FnInputTys {
self.inputs_and_output.inputs()
}
pub fn output(self) -> I::Ty {
self.inputs_and_output.output()
}
}
impl<I: Interner> ty::Binder<I, FnSigTys<I>> {
// Used to combine the two fields in `TyKind::FnPtr` into a single value.
pub fn with(self, hdr: FnHeader<I>) -> ty::Binder<I, FnSig<I>> {
self.map_bound(|sig_tys| FnSig {
inputs_and_output: sig_tys.inputs_and_output,
c_variadic: hdr.c_variadic,
safety: hdr.safety,
abi: hdr.abi,
})
}
#[inline]
pub fn inputs(self) -> ty::Binder<I, I::FnInputTys> {
self.map_bound(|sig_tys| sig_tys.inputs())
}
#[inline]
#[track_caller]
pub fn input(self, index: usize) -> ty::Binder<I, I::Ty> {
self.map_bound(|sig_tys| sig_tys.inputs().get(index).unwrap())
}
pub fn inputs_and_output(self) -> ty::Binder<I, I::Tys> {
self.map_bound(|sig_tys| sig_tys.inputs_and_output)
}
#[inline]
pub fn output(self) -> ty::Binder<I, I::Ty> {
self.map_bound(|sig_tys| sig_tys.output())
}
}
#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
pub struct FnHeader<I: Interner> {
pub c_variadic: bool,
pub safety: I::Safety,
pub abi: I::Abi,
}

View File

@ -197,7 +197,7 @@ impl<I: Interner> ClosureArgs<I> {
/// Extracts the signature from the closure.
pub fn sig(self) -> ty::Binder<I, ty::FnSig<I>> {
match self.sig_as_fn_ptr_ty().kind() {
ty::FnPtr(sig) => sig,
ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr),
ty => panic!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {ty:?}"),
}
}
@ -292,21 +292,23 @@ impl<I: Interner> CoroutineClosureArgs<I> {
pub fn coroutine_closure_sig(self) -> ty::Binder<I, CoroutineClosureSignature<I>> {
let interior = self.coroutine_witness_ty();
let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { panic!() };
sig.map_bound(|sig| {
let [resume_ty, tupled_inputs_ty] = *sig.inputs().as_slice() else {
let ty::FnPtr(sig_tys, hdr) = self.signature_parts_ty().kind() else { panic!() };
sig_tys.map_bound(|sig_tys| {
let [resume_ty, tupled_inputs_ty] = *sig_tys.inputs().as_slice() else {
panic!();
};
let [yield_ty, return_ty] = *sig.output().tuple_fields().as_slice() else { panic!() };
let [yield_ty, return_ty] = *sig_tys.output().tuple_fields().as_slice() else {
panic!()
};
CoroutineClosureSignature {
interior,
tupled_inputs_ty,
resume_ty,
yield_ty,
return_ty,
c_variadic: sig.c_variadic,
safety: sig.safety,
abi: sig.abi,
c_variadic: hdr.c_variadic,
safety: hdr.safety,
abi: hdr.abi,
}
})
}
@ -321,7 +323,7 @@ impl<I: Interner> CoroutineClosureArgs<I> {
pub fn has_self_borrows(&self) -> bool {
match self.coroutine_captures_by_ref_ty().kind() {
ty::FnPtr(sig) => sig
ty::FnPtr(sig_tys, _) => sig_tys
.skip_binder()
.visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST })
.is_break(),
@ -460,11 +462,11 @@ impl<I: Interner> CoroutineClosureSignature<I> {
) -> I::Ty {
match kind {
ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
let ty::FnPtr(sig) = coroutine_captures_by_ref_ty.kind() else {
let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else {
panic!();
};
let coroutine_captures_by_ref_ty =
sig.output().skip_binder().fold_with(&mut FoldEscapingRegions {
sig_tys.output().skip_binder().fold_with(&mut FoldEscapingRegions {
interner: cx,
region: env_region,
debruijn: ty::INNERMOST,

View File

@ -2069,7 +2069,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
Some(ContainerTy::Ref(r)),
)),
},
ty::FnDef(..) | ty::FnPtr(_) => {
ty::FnDef(..) | ty::FnPtr(..) => {
// FIXME: should we merge the outer and inner binders somehow?
let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
let decl = clean_poly_fn_sig(cx, None, sig);

View File

@ -495,7 +495,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
ty::RawPtr(_, _) => Res::Primitive(RawPointer),
ty::Ref(..) => Res::Primitive(Reference),
ty::FnDef(..) => panic!("type alias to a function definition"),
ty::FnPtr(_) => Res::Primitive(Fn),
ty::FnPtr(..) => Res::Primitive(Fn),
ty::Never => Res::Primitive(Never),
ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did, .. }, _)), _) | ty::Foreign(did) => {
Res::from_def_id(self.cx.tcx, did)

View File

@ -15,7 +15,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
}
match cast_from.kind() {
ty::FnDef(..) | ty::FnPtr(_) => {
ty::FnDef(..) | ty::FnPtr(..) => {
let mut applicability = Applicability::MaybeIncorrect;
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);

View File

@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
_ => { /* continue to checks */ },
}
if let ty::FnDef(..) | ty::FnPtr(_) = cast_from.kind() {
if let ty::FnDef(..) | ty::FnPtr(..) = cast_from.kind() {
let mut applicability = Applicability::MaybeIncorrect;
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "..", &mut applicability);

View File

@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
_ => return,
}
match cast_from.kind() {
ty::FnDef(..) | ty::FnPtr(_) => {
ty::FnDef(..) | ty::FnPtr(..) => {
let mut applicability = Applicability::MaybeIncorrect;
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability);

View File

@ -236,7 +236,7 @@ fn fn_sig_opt<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<PolyFnSig<'
// We can't use `Ty::fn_sig` because it automatically performs args, this may result in FNs.
match node_ty.kind() {
ty::FnDef(def_id, _) => Some(cx.tcx.fn_sig(*def_id).instantiate_identity()),
ty::FnPtr(fn_sig) => Some(*fn_sig),
ty::FnPtr(sig_tys, hdr) => Some(sig_tys.with(*hdr)),
_ => None,
}
}

View File

@ -872,7 +872,7 @@ impl TyCoercionStability {
| ty::Pat(..)
| ty::Float(_)
| ty::RawPtr(..)
| ty::FnPtr(_)
| ty::FnPtr(..)
| ty::Str
| ty::Slice(..)
| ty::Adt(..)

View File

@ -158,7 +158,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc
cx.tcx.fn_sig(def).skip_binder().skip_binder()
},
ty::FnPtr(sig) => sig.skip_binder(),
ty::FnPtr(sig_tys, hdr) => sig_tys.with(*hdr).skip_binder(),
ty::Closure(_, subs) => cx
.tcx
.signature_unclosure(subs.as_closure().sig(), Safety::Safe)

View File

@ -58,7 +58,7 @@ fn try_get_caller_ty_name_and_method_name(
fn is_map_to_option(cx: &LateContext<'_>, map_arg: &Expr<'_>) -> bool {
let map_closure_ty = cx.typeck_results().expr_ty(map_arg);
match map_closure_ty.kind() {
ty::Closure(_, _) | ty::FnDef(_, _) | ty::FnPtr(_) => {
ty::Closure(_, _) | ty::FnDef(_, _) | ty::FnPtr(..) => {
let map_closure_sig = match map_closure_ty.kind() {
ty::Closure(_, args) => args.as_closure().sig(),
_ => map_closure_ty.fn_sig(cx.tcx),

View File

@ -166,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
ExprKind::Call(func, _) => {
let typ = self.cx.typeck_results().expr_ty(func);
match typ.kind() {
ty::FnDef(..) | ty::FnPtr(_) => {
ty::FnDef(..) | ty::FnPtr(..) => {
let sig = typ.fn_sig(self.cx.tcx);
if self.cx.tcx.instantiate_bound_regions_with_erased(sig).output().kind() == &ty::Never {
self.report_diverging_sub_expr(e);

View File

@ -130,7 +130,7 @@ fn collect_unsafe_exprs<'tcx>(
ExprKind::Call(path_expr, _) => {
let sig = match *cx.typeck_results().expr_ty(path_expr).kind() {
ty::FnDef(id, _) => cx.tcx.fn_sig(id).skip_binder(),
ty::FnPtr(sig) => sig,
ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr),
_ => return Continue(Descend::Yes),
};
if sig.safety() == Safety::Unsafe {

View File

@ -79,7 +79,7 @@ fn check_arguments<'tcx>(
fn_kind: &str,
) {
match type_definition.kind() {
ty::FnDef(..) | ty::FnPtr(_) => {
ty::FnDef(..) | ty::FnPtr(..) => {
let parameters = type_definition.fn_sig(cx.tcx).skip_binder().inputs();
for (argument, parameter) in iter::zip(arguments, parameters) {
match parameter.kind() {

View File

@ -541,7 +541,7 @@ pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) {
/// Returns `true` if the given type is an `unsafe` function.
pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
match ty.kind() {
ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).safety() == Safety::Unsafe,
ty::FnDef(..) | ty::FnPtr(..) => ty.fn_sig(cx.tcx).safety() == Safety::Unsafe,
_ => false,
}
}
@ -721,7 +721,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
cx.tcx.item_super_predicates(def_id).iter_instantiated(cx.tcx, args),
cx.tcx.opt_parent(def_id),
),
ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
ty::FnPtr(sig_tys, hdr) => Some(ExprFnSig::Sig(sig_tys.with(hdr), None)),
ty::Dynamic(bounds, _, _) => {
let lang_items = cx.tcx.lang_items();
match bounds.principal() {

View File

@ -441,7 +441,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe => {
self.is_unsafe = true;
},
ty::FnPtr(sig) if sig.safety() == Safety::Unsafe => self.is_unsafe = true,
ty::FnPtr(_, hdr) if hdr.safety == Safety::Unsafe => self.is_unsafe = true,
_ => walk_expr(self, e),
},
ExprKind::Path(ref p)