Skip to content

Commit

Permalink
Auto merge of #38097 - Mark-Simulacrum:fn-sig-slice, r=eddyb
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Dec 6, 2016
2 parents f7c93c0 + 296ec5f commit ff261d3
Show file tree
Hide file tree
Showing 44 changed files with 264 additions and 291 deletions.
4 changes: 2 additions & 2 deletions src/librustc/middle/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for ExprVisitor<'a, 'gcx, 'tcx> {
let typ = self.infcx.tcx.tables().node_id_to_type(expr.id);
match typ.sty {
ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
let from = bare_fn_ty.sig.0.inputs[0];
let to = bare_fn_ty.sig.0.output;
let from = bare_fn_ty.sig.skip_binder().inputs()[0];
let to = bare_fn_ty.sig.skip_binder().output();
self.check_transmute(expr.span, from, to, expr.id);
}
_ => {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// The `Self` type is erased, so it should not appear in list of
// arguments or return type apart from the receiver.
let ref sig = self.item_type(method.def_id).fn_sig();
for &input_ty in &sig.0.inputs[1..] {
for input_ty in &sig.skip_binder().inputs()[1..] {
if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
return Some(MethodViolationCode::ReferencesSelf);
}
}
if self.contains_illegal_self_type_reference(trait_def_id, sig.0.output) {
if self.contains_illegal_self_type_reference(trait_def_id, sig.output().skip_binder()) {
return Some(MethodViolationCode::ReferencesSelf);
}

Expand Down
14 changes: 3 additions & 11 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1368,21 +1368,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
ty::TyFnDef(.., &ty::BareFnTy {
unsafety: hir::Unsafety::Normal,
abi: Abi::Rust,
sig: ty::Binder(ty::FnSig {
inputs: _,
output: _,
variadic: false
})
ref sig,
}) |
ty::TyFnPtr(&ty::BareFnTy {
unsafety: hir::Unsafety::Normal,
abi: Abi::Rust,
sig: ty::Binder(ty::FnSig {
inputs: _,
output: _,
variadic: false
})
}) => {
ref sig
}) if !sig.variadic() => {
candidates.vec.push(FnPointerCandidate);
}

Expand Down
7 changes: 4 additions & 3 deletions src/librustc/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,14 +487,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)>
{
let arguments_tuple = match tuple_arguments {
TupleArgumentsFlag::No => sig.0.inputs[0],
TupleArgumentsFlag::Yes => self.intern_tup(&sig.0.inputs[..]),
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
TupleArgumentsFlag::Yes =>
self.intern_tup(sig.skip_binder().inputs()),
};
let trait_ref = ty::TraitRef {
def_id: fn_trait_def_id,
substs: self.mk_substs_trait(self_ty, &[arguments_tuple]),
};
ty::Binder((trait_ref, sig.0.output))
ty::Binder((trait_ref, sig.skip_binder().output()))
}
}

Expand Down
11 changes: 11 additions & 0 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1542,6 +1542,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}

pub fn mk_fn_sig<I>(self, inputs: I, output: I::Item, variadic: bool)
-> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output
where I: Iterator,
I::Item: InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>
{
inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig {
inputs_and_output: self.intern_type_list(xs),
variadic: variadic
})
}

pub fn mk_existential_predicates<I: InternAs<[ExistentialPredicate<'tcx>],
&'tcx Slice<ExistentialPredicate<'tcx>>>>(self, iter: I)
-> I::Output {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/fast_reject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
Some(TupleSimplifiedType(tys.len()))
}
ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => {
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
Some(FunctionSimplifiedType(f.sig.skip_binder().inputs().len()))
}
ty::TyProjection(_) | ty::TyParam(_) => {
if can_simplify_params {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ impl FlagComputation {
fn add_fn_sig(&mut self, fn_sig: &ty::PolyFnSig) {
let mut computation = FlagComputation::new();

computation.add_tys(&fn_sig.0.inputs);
computation.add_ty(fn_sig.0.output);
computation.add_tys(fn_sig.skip_binder().inputs());
computation.add_ty(fn_sig.skip_binder().output());

self.add_bound_computation(&computation);
}
Expand Down
42 changes: 20 additions & 22 deletions src/librustc/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ use ty::subst::{Kind, Substs};
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::error::{ExpectedFound, TypeError};
use std::rc::Rc;
use std::iter;
use syntax::abi;
use hir as ast;
use rustc_data_structures::accumulate_vec::AccumulateVec;

pub type RelateResult<'tcx, T> = Result<T, TypeError<'tcx>>;

Expand Down Expand Up @@ -185,32 +187,28 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
expected_found(relation, &a.variadic, &b.variadic)));
}

let inputs = relate_arg_vecs(relation,
&a.inputs,
&b.inputs)?;
let output = relation.relate(&a.output, &b.output)?;
if a.inputs().len() != b.inputs().len() {
return Err(TypeError::ArgCount);
}

Ok(ty::FnSig {inputs: inputs,
output: output,
variadic: a.variadic})
let inputs_and_output = a.inputs().iter().cloned()
.zip(b.inputs().iter().cloned())
.map(|x| (x, false))
.chain(iter::once(((a.output(), b.output()), true)))
.map(|((a, b), is_output)| {
if is_output {
relation.relate(&a, &b)
} else {
relation.relate_with_variance(ty::Contravariant, &a, &b)
}
}).collect::<Result<AccumulateVec<[_; 8]>, _>>()?;
Ok(ty::FnSig {
inputs_and_output: relation.tcx().intern_type_list(&inputs_and_output),
variadic: a.variadic
})
}
}

fn relate_arg_vecs<'a, 'gcx, 'tcx, R>(relation: &mut R,
a_args: &[Ty<'tcx>],
b_args: &[Ty<'tcx>])
-> RelateResult<'tcx, Vec<Ty<'tcx>>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
if a_args.len() != b_args.len() {
return Err(TypeError::ArgCount);
}

a_args.iter().zip(b_args)
.map(|(a, b)| relation.relate_with_variance(ty::Contravariant, a, b))
.collect()
}

impl<'tcx> Relate<'tcx> for ast::Unsafety {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &ast::Unsafety,
Expand Down
24 changes: 12 additions & 12 deletions src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoBorrow<'a> {
impl<'a, 'tcx> Lift<'tcx> for ty::FnSig<'a> {
type Lifted = ty::FnSig<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
tcx.lift(&self.inputs[..]).and_then(|inputs| {
tcx.lift(&self.output).map(|output| {
ty::FnSig {
inputs: inputs,
output: output,
variadic: self.variadic
}
})
tcx.lift(&self.inputs_and_output).map(|x| {
ty::FnSig {
inputs_and_output: x,
variadic: self.variadic
}
})
}
}
Expand Down Expand Up @@ -589,17 +586,20 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> {

impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::FnSig { inputs: self.inputs.fold_with(folder),
output: self.output.fold_with(folder),
variadic: self.variadic }
let inputs_and_output = self.inputs_and_output.fold_with(folder);
ty::FnSig {
inputs_and_output: folder.tcx().intern_type_list(&inputs_and_output),
variadic: self.variadic,
}
}

fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
folder.fold_fn_sig(self)
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.inputs.visit_with(visitor) || self.output.visit_with(visitor)
self.inputs().iter().any(|i| i.visit_with(visitor)) ||
self.output().visit_with(visitor)
}
}

Expand Down
23 changes: 16 additions & 7 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,22 +563,31 @@ pub struct ClosureTy<'tcx> {
/// - `variadic` indicates whether this is a variadic function. (only true for foreign fns)
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct FnSig<'tcx> {
pub inputs: Vec<Ty<'tcx>>,
pub output: Ty<'tcx>,
pub inputs_and_output: &'tcx Slice<Ty<'tcx>>,
pub variadic: bool
}

impl<'tcx> FnSig<'tcx> {
pub fn inputs(&self) -> &[Ty<'tcx>] {
&self.inputs_and_output[..self.inputs_and_output.len() - 1]
}

pub fn output(&self) -> Ty<'tcx> {
self.inputs_and_output[self.inputs_and_output.len() - 1]
}
}

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(&self) -> Binder<&[Ty<'tcx>]> {
Binder(self.skip_binder().inputs())
}
pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> {
self.map_bound_ref(|fn_sig| fn_sig.inputs[index])
self.map_bound_ref(|fn_sig| fn_sig.inputs()[index])
}
pub fn output(&self) -> ty::Binder<Ty<'tcx>> {
self.map_bound_ref(|fn_sig| fn_sig.output.clone())
self.map_bound_ref(|fn_sig| fn_sig.output().clone())
}
pub fn variadic(&self) -> bool {
self.skip_binder().variadic
Expand Down Expand Up @@ -1243,7 +1252,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}

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

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc
self.hash(f.unsafety);
self.hash(f.abi);
self.hash(f.sig.variadic());
self.hash(f.sig.inputs().skip_binder().len());
self.hash(f.sig.skip_binder().inputs().len());
}
TyDynamic(ref data, ..) => {
if let Some(p) = data.principal() {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,6 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
}

fn push_sig_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, sig: &ty::PolyFnSig<'tcx>) {
stack.push(sig.0.output);
stack.extend(sig.0.inputs.iter().cloned().rev());
stack.push(sig.skip_binder().output());
stack.extend(sig.skip_binder().inputs().iter().cloned().rev());
}
4 changes: 2 additions & 2 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ impl<'tcx> fmt::Debug for ty::InstantiatedPredicates<'tcx> {
impl<'tcx> fmt::Display for ty::FnSig<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "fn")?;
fn_sig(f, &self.inputs, self.variadic, self.output)
fn_sig(f, self.inputs(), self.variadic, self.output())
}
}

Expand Down Expand Up @@ -625,7 +625,7 @@ impl fmt::Debug for ty::RegionVid {

impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({:?}; variadic: {})->{:?}", self.inputs, self.variadic, self.output)
write!(f, "({:?}; variadic: {})->{:?}", self.inputs(), self.variadic, self.output())
}
}

Expand Down
7 changes: 1 addition & 6 deletions src/librustc_driver/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,15 +265,10 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
}

pub fn t_fn(&self, input_tys: &[Ty<'tcx>], output_ty: Ty<'tcx>) -> Ty<'tcx> {
let input_args = input_tys.iter().cloned().collect();
self.infcx.tcx.mk_fn_ptr(self.infcx.tcx.mk_bare_fn(ty::BareFnTy {
unsafety: hir::Unsafety::Normal,
abi: Abi::Rust,
sig: ty::Binder(ty::FnSig {
inputs: input_args,
output: output_ty,
variadic: false,
}),
sig: ty::Binder(self.infcx.tcx.mk_fn_sig(input_tys.iter().cloned(), output_ty, false)),
}))
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1084,8 +1084,8 @@ impl LateLintPass for MutableTransmutes {
let typ = cx.tcx.tables().node_id_to_type(expr.id);
match typ.sty {
ty::TyFnDef(.., ref bare_fn) if bare_fn.abi == RustIntrinsic => {
let from = bare_fn.sig.0.inputs[0];
let to = bare_fn.sig.0.output;
let from = bare_fn.sig.skip_binder().inputs()[0];
let to = bare_fn.sig.skip_binder().output();
return Some((&from.sty, &to.sty));
}
_ => (),
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_lint/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,16 +603,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}

let sig = cx.erase_late_bound_regions(&bare_fn.sig);
if !sig.output.is_nil() {
let r = self.check_type_for_ffi(cache, sig.output);
if !sig.output().is_nil() {
let r = self.check_type_for_ffi(cache, sig.output());
match r {
FfiSafe => {}
_ => {
return r;
}
}
}
for arg in sig.inputs {
for arg in sig.inputs() {
let r = self.check_type_for_ffi(cache, arg);
match r {
FfiSafe => {}
Expand Down Expand Up @@ -678,12 +678,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
let sig = self.cx.tcx.item_type(def_id).fn_sig();
let sig = self.cx.tcx.erase_late_bound_regions(&sig);

for (&input_ty, input_hir) in sig.inputs.iter().zip(&decl.inputs) {
self.check_type_for_ffi_and_report_errors(input_hir.ty.span, &input_ty);
for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
self.check_type_for_ffi_and_report_errors(input_hir.ty.span, input_ty);
}

if let hir::Return(ref ret_hir) = decl.output {
let ret_ty = sig.output;
let ret_ty = sig.output();
if !ret_ty.is_nil() {
self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty);
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/build/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let diverges = match ty.sty {
ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => {
// FIXME(canndrew): This is_never should probably be an is_uninhabited
f.sig.0.output.is_never()
f.sig.skip_binder().output().is_never()
}
_ => false
};
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/hair/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
span_bug!(expr.span, "method call has late-bound regions")
});

assert_eq!(sig.inputs.len(), 2);
assert_eq!(sig.inputs().len(), 2);

let tupled_args = Expr {
ty: sig.inputs[1],
ty: sig.inputs()[1],
temp_lifetime: temp_lifetime,
span: expr.span,
kind: ExprKind::Tuple {
Expand Down
Loading

0 comments on commit ff261d3

Please sign in to comment.