]> git.lizzy.rs Git - rust.git/commitdiff
Merge #4489
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>
Sat, 16 May 2020 23:06:23 +0000 (23:06 +0000)
committerGitHub <noreply@github.com>
Sat, 16 May 2020 23:06:23 +0000 (23:06 +0000)
4489: Memory allocation optimization r=matklad a=simonvandel

I did some profiling using DHAT, and this was what I could easily optimize without much knowledge of the codebase.

This speeds up analysis-stats on rust-analyser by ~4% on my local machine.

**Benchmark**
➜  rust-analyzer-base git:(master) hyperfine --min-runs=2 '/home/simon/Documents/rust-analyzer/target/release/rust-analyzer analysis-stats .' '/home/simon/Documents/rust-analyzer-base/target/release/rust-analyzer analysis-stats .'
Benchmark #1: /home/simon/Documents/rust-analyzer/target/release/rust-analyzer analysis-stats .
  Time (mean ± σ):     49.621 s ±  0.317 s    [User: 48.725 s, System: 0.792 s]
  Range (min … max):   49.397 s … 49.846 s    2 runs

Benchmark #2: /home/simon/Documents/rust-analyzer-base/target/release/rust-analyzer analysis-stats .
  Time (mean ± σ):     51.764 s ±  0.045 s    [User: 50.882 s, System: 0.756 s]
  Range (min … max):   51.733 s … 51.796 s    2 runs

Summary
  '/home/simon/Documents/rust-analyzer/target/release/rust-analyzer analysis-stats .' ran
    1.04 ± 0.01 times faster than '/home/simon/Documents/rust-analyzer-base/target/release/rust-analyzer analysis-stats .'

Co-authored-by: Simon Vandel Sillesen <simon.vandel@gmail.com>
crates/ra_hir_ty/src/lib.rs
crates/ra_hir_ty/src/method_resolution.rs
crates/ra_hir_ty/src/tests/method_resolution.rs

index ccc4348f4269b447ad0dc2524d9b6e98d96ed751..daea02f8811a40918caa3230f7f2c9d574eff8f9 100644 (file)
@@ -808,15 +808,13 @@ pub fn substs(&self) -> Option<Substs> {
         }
     }
 
-    /// If this is an `impl Trait` or `dyn Trait`, returns that trait.
-    pub fn inherent_trait(&self) -> Option<TraitId> {
+    /// If this is a `dyn Trait`, returns that trait.
+    pub fn dyn_trait(&self) -> Option<TraitId> {
         match self {
-            Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
-                predicates.iter().find_map(|pred| match pred {
-                    GenericPredicate::Implemented(tr) => Some(tr.trait_),
-                    _ => None,
-                })
-            }
+            Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred {
+                GenericPredicate::Implemented(tr) => Some(tr.trait_),
+                _ => None,
+            }),
             _ => None,
         }
     }
index 657284fd018ae3da455f24dbe946b8ad55a7e964..0851e16a89b23df478ff3afbd62eeaebe4a536e6 100644 (file)
@@ -408,8 +408,9 @@ fn iterate_trait_method_candidates<T>(
     receiver_ty: Option<&Canonical<Ty>>,
     mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
 ) -> Option<T> {
-    // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
-    let inherent_trait = self_ty.value.inherent_trait().into_iter();
+    // if ty is `dyn Trait`, the trait doesn't need to be in scope
+    let inherent_trait =
+        self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
     let env_traits = if let Ty::Placeholder(_) = self_ty.value {
         // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
         env.trait_predicates_for_self_ty(&self_ty.value)
@@ -601,11 +602,6 @@ pub fn implements_trait(
     krate: CrateId,
     trait_: TraitId,
 ) -> bool {
-    if ty.value.inherent_trait() == Some(trait_) {
-        // FIXME this is a bit of a hack, since Chalk should say the same thing
-        // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
-        return true;
-    }
     let goal = generic_implements_goal(db, env, trait_, ty.clone());
     let solution = db.trait_solve(krate, goal);
 
index 67f964ab5d7ac5a32b72eace4bff90be286ff039..9c2c9e1d28386893c9368ef8e58ebbe7637c2324 100644 (file)
@@ -1096,3 +1096,34 @@ impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {}
     );
     assert_eq!(t, "()");
 }
+
+#[test]
+fn dyn_trait_super_trait_not_in_scope() {
+    assert_snapshot!(
+        infer(r#"
+mod m {
+    pub trait SuperTrait {
+        fn foo(&self) -> u32 { 0 }
+    }
+}
+trait Trait: m::SuperTrait {}
+
+struct S;
+impl m::SuperTrait for S {}
+impl Trait for S {}
+
+fn test(d: &dyn Trait) {
+    d.foo();
+}
+"#),
+        @r###"
+    52..56 'self': &Self
+    65..70 '{ 0 }': u32
+    67..68 '0': u32
+    177..178 'd': &dyn Trait
+    192..208 '{     ...o(); }': ()
+    198..199 'd': &dyn Trait
+    198..205 'd.foo()': u32
+    "###
+    );
+}