diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs index 33dc3210f0881..e1b3b3c436dab 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 { + // 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 96b4edce86b30..6adafb8602c9a 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.