Auto merge of #53248 - nikomatsakis:nll-trivial-sized-predicate, r=eddyb

skip trivial `Sized` predicates

This came to about a 2% win for me in cargo. Small, but hey.

r? @eddyb
This commit is contained in:
bors 2018-08-19 15:22:18 +00:00
commit bfc3b20663
2 changed files with 51 additions and 2 deletions

View File

@ -27,9 +27,23 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ProvePredicate<'tcx> {
type QueryResult = ();
fn try_fast_path(
_tcx: TyCtxt<'_, 'gcx, 'tcx>,
_key: &ParamEnvAnd<'tcx, Self>,
tcx: TyCtxt<'_, 'gcx, 'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResult> {
// Proving Sized, very often on "obviously sized" types like
// `&T`, accounts for about 60% percentage of the predicates
// we have to prove. No need to canonicalize and all that for
// such cases.
if let Predicate::Trait(trait_ref) = key.value.predicate {
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
if trait_ref.def_id() == sized_def_id {
if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) {
return Some(());
}
}
}
}
None
}

View File

@ -1852,6 +1852,41 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
_ => bug!("cannot convert type `{:?}` to a closure kind", self),
}
}
/// Fast path helper for testing if a type is `Sized`.
///
/// Returning true means the type is known to be sized. Returning
/// `false` means nothing -- could be sized, might not be.
pub fn is_trivially_sized(&self, tcx: TyCtxt<'_, '_, 'tcx>) -> bool {
match self.sty {
ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
ty::TyChar | ty::TyRef(..) | ty::TyGenerator(..) |
ty::TyGeneratorWitness(..) | ty::TyArray(..) | ty::TyClosure(..) |
ty::TyNever | ty::TyError =>
true,
ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) =>
false,
ty::TyTuple(tys) =>
tys.iter().all(|ty| ty.is_trivially_sized(tcx)),
ty::TyAdt(def, _substs) =>
def.sized_constraint(tcx).is_empty(),
ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => false,
ty::TyInfer(ty::TyVar(_)) => false,
ty::TyInfer(ty::CanonicalTy(_)) |
ty::TyInfer(ty::FreshTy(_)) |
ty::TyInfer(ty::FreshIntTy(_)) |
ty::TyInfer(ty::FreshFloatTy(_)) =>
bug!("is_trivially_sized applied to unexpected type: {:?}", self),
}
}
}
/// Typed constant value.