Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ty::FnSig to contain a &'tcx Slice<Ty<'tcx>> #38097

Merged
merged 2 commits into from
Dec 6, 2016

Conversation

Mark-Simulacrum
Copy link
Member

@Mark-Simulacrum Mark-Simulacrum commented Dec 1, 2016

We refactor this in order to achieve the following wins:

  • Decrease the size of FnSig (Vec + bool: 32, &Slice + bool: 24).
  • Potentially decrease total allocated memory due to arena-allocating FnSig inputs/output; since they are allocated in the type list arena, other users of type lists can reuse the same allocation for an equivalent type list.
  • Remove the last part of the type system which needs drop glue (Refactor TraitObject to Slice<ExistentialPredicate> #37965 removed the other remaining part). This makes arenas containing FnSig faster to drop (since we don't need to drop a Vec for each one), and makes reusing them without clearing/dropping potentially possible.

r? @eddyb

variadic: a.variadic})
let inputs_and_output = a.inputs().into_iter().cloned()
.zip(b.inputs().into_iter().cloned())
.zip(iter::repeat(false))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be done with .map.

.map(|i| i.fold_with(folder))
.collect::<AccumulateVec<[_; 8]>>();
ty::FnSig {
inputs_and_output: folder.tcx().intern_type_list(&inputs_and_output),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just fold the list wholesale.

pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>;

impl<'tcx> PolyFnSig<'tcx> {
pub fn inputs(&self) -> ty::Binder<Vec<Ty<'tcx>>> {
self.map_bound_ref(|fn_sig| fn_sig.inputs.clone())
pub fn inputs<'a>(&'a self) -> Binder<&[Ty<'tcx>]> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The elision abuse here looks odd.

@@ -1243,10 +1252,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}

// Type accessors for substructures of types
pub fn fn_args(&self) -> ty::Binder<Vec<Ty<'tcx>>> {
self.fn_sig().inputs()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could keep this returning a slice.

};
let tuple_input_ty = tcx.intern_tup(sig.inputs());
let sig = tcx.mk_fn_sig(
iter::once(bare_fn_ty_maybe_ref).chain(iter::once(tuple_input_ty)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're using iter::once a bit too much - try arrays instead.

..sig
});
let sig = sig.map_bound(|sig| tcx.mk_fn_sig(
iter::once(env_ty).chain(sig.inputs().into_iter().cloned()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you avoid .into_iter() on slices? It's just .iter().

@@ -1595,7 +1595,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// checking for here would be considered early bound
// anyway.)
let inputs = bare_fn_ty.sig.inputs();
let late_bound_in_args = tcx.collect_constrained_late_bound_regions(&inputs);
let late_bound_in_args = tcx.collect_constrained_late_bound_regions(
&inputs.map_bound(|i| i.to_owned()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would this be needed? Looks like a bug?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeFoldable isn't implemented for &[Ty<'tcx>], which is what we have, so we need to cast it to a vector in order to pass it here. This is rather unfortunate, but I'm not sure how much we can do. It may be worth pointing out that the use is a visit_with on it, so it's possible this can be refactored into passing either the slice or an iterator to solve this problem. I can look into that if you'd like.

@KalitaAlexey
Copy link
Contributor

What is purpose of this?

@Mark-Simulacrum
Copy link
Member Author

I believe there are a couple of purposes:

  • Decreasing the size of FnSig
    • Vec + bool: 32, &Slice + bool: 24.
  • Potentially decrease total allocated memory due to arena-allocating FnSig inputs/output; since they are allocated in the type list arena, other users of type lists can reuse the same allocation for an equivalent type list.
  • Remove the last part of the type system which needs drop glue (Refactor TraitObject to Slice<ExistentialPredicate> #37965 removed the other remaining part)

@eddyb may be able to suggest other reasons.


@eddyb Ready for another review pass.

@bors
Copy link
Contributor

bors commented Dec 2, 2016

☔ The latest upstream changes (presumably #38053) made this pull request unmergeable. Please resolve the merge conflicts.

@Mark-Simulacrum
Copy link
Member Author

Rebased.

}),
sig: ty::Binder(tcx.mk_fn_sig(
iter::once(tcx.types.isize)
.chain(iter::once(tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8)))),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use slice iterators, here and elsewhere?

@eddyb
Copy link
Member

eddyb commented Dec 2, 2016

@Mark-Simulacrum Can you move the contents of that comment into the description? You may also want to mention that the drop glue thing is about arenas, both in terms of cost of dropping/reusing the temporary ones currently and experiments with unified arenas in the future.

@eddyb
Copy link
Member

eddyb commented Dec 2, 2016

@rust-lang/compiler Any objections? This is ready to land otherwise, modulo a few "style" tweaks.

@Mark-Simulacrum
Copy link
Member Author

Fixed style nit (I couldn't find any other places I chained iter::once together).

Added the comment for reasons why we want this to the description.

@bors
Copy link
Contributor

bors commented Dec 6, 2016

☔ The latest upstream changes (presumably #38121) made this pull request unmergeable. Please resolve the merge conflicts.

@Mark-Simulacrum
Copy link
Member Author

Rebased.

@eddyb
Copy link
Member

eddyb commented Dec 6, 2016

@bors r+

@bors
Copy link
Contributor

bors commented Dec 6, 2016

📌 Commit 296ec5f has been approved by eddyb

@bors
Copy link
Contributor

bors commented Dec 6, 2016

⌛ Testing commit 296ec5f with merge ff261d3...

bors added a commit that referenced this pull request Dec 6, 2016
Refactor ty::FnSig to contain a &'tcx Slice<Ty<'tcx>>

We refactor this in order to achieve the following wins:

 - Decrease the size of `FnSig` (`Vec` + `bool`: 32, `&Slice` + `bool`: 24).
 - Potentially decrease total allocated memory due to arena-allocating `FnSig` inputs/output; since they are allocated in the type list arena, other users of type lists can reuse the same allocation for an equivalent type list.
 - Remove the last part of the type system which needs drop glue (#37965 removed the other remaining part). This makes arenas containing `FnSig` faster to drop (since we don't need to drop a Vec for each one), and makes reusing them without clearing/dropping potentially possible.

r? @eddyb
@bors bors merged commit 296ec5f into rust-lang:master Dec 6, 2016
@michaelwoerister
Copy link
Member

Nice!

@Mark-Simulacrum Mark-Simulacrum deleted the fn-sig-slice branch December 27, 2016 00:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants