about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-08-10 09:24:27 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-08-10 10:00:05 -0400
commit1341e669b1ef6151ad54361b4a999dca264dba4b (patch)
tree2c3aa51927f805640d155ed8a1af42191087a3fa /src
parenta77dfcc79fe3e7e1a10ae4dccfd4b2e5e0e49195 (diff)
downloadrust-1341e669b1ef6151ad54361b4a999dca264dba4b.tar.gz
rust-1341e669b1ef6151ad54361b4a999dca264dba4b.zip
skip trivial `T: Sized` predicates
Diffstat (limited to 'src')
-rw-r--r--src/librustc/traits/query/type_op/prove_predicate.rs18
-rw-r--r--src/librustc/ty/sty.rs35
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 96b4edce86b..6adafb8602c 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.