diff options
| author | bors <bors@rust-lang.org> | 2018-08-19 15:22:18 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-08-19 15:22:18 +0000 |
| commit | bfc3b20663e1abfff0499332f9168f60c3269c33 (patch) | |
| tree | c22755becd28fc70f67068cd8b5a6dbaafd6653c /src | |
| parent | b355906919927ab3c879becd14392f023af883a1 (diff) | |
| parent | 1341e669b1ef6151ad54361b4a999dca264dba4b (diff) | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/traits/query/type_op/prove_predicate.rs | 18 | ||||
| -rw-r--r-- | src/librustc/ty/sty.rs | 35 |
2 files changed, 51 insertions, 2 deletions
diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs index 33dc3210f08..e1b3b3c436d 100644 --- a/src/librustc/traits/query/type_op/prove_predicate.rs +++ b/src/librustc/traits/query/type_op/prove_predicate.rs @@ -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 } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 65e31f21792..226388c9efa 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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. |
