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.
This commit is contained in:
parent
8640998869
commit
c4717cc9d1
89 changed files with 298 additions and 201 deletions
|
@ -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());
|
||||
|
|
|
@ -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",
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
@ -793,8 +793,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),
|
||||
|
@ -1061,7 +1061,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,
|
||||
|
@ -1844,10 +1844,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![
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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`"),
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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(_)
|
||||
|
|
|
@ -1398,7 +1398,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
| ty::RawPtr(_, _)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(_)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Never
|
||||
| ty::Foreign(_) => {}
|
||||
|
||||
|
|
|
@ -2114,7 +2114,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
| ty::Bool
|
||||
| ty::Float(_)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(_)
|
||||
| ty::FnPtr(..)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Char
|
||||
| ty::Ref(..)
|
||||
|
@ -2171,7 +2171,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(_)
|
||||
|
@ -2333,7 +2333,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
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue