diff options
author | Shotaro Yamada <[email protected]> | 2019-10-14 04:56:18 +0100 |
---|---|---|
committer | Shotaro Yamada <[email protected]> | 2019-10-14 06:25:05 +0100 |
commit | f8d4cdc170bead42db3ffa647318ecf2bd6430e7 (patch) | |
tree | 2c020016af1fd5239fdad65b816b4cccea97df41 | |
parent | 77f2dd96a122e59a8d8df8afb53a741df9b1af76 (diff) |
Avoid cloning `Arc<[T]>` into a vec if possible
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 36 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/unify.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/util.rs | 19 |
5 files changed, 55 insertions, 31 deletions
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 9cbd9a8ae..ca261e8f5 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -51,6 +51,7 @@ mod lang_item; | |||
51 | mod generics; | 51 | mod generics; |
52 | mod resolve; | 52 | mod resolve; |
53 | pub mod diagnostics; | 53 | pub mod diagnostics; |
54 | mod util; | ||
54 | 55 | ||
55 | mod code_model; | 56 | mod code_model; |
56 | 57 | ||
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index d161735e8..fc4909d11 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -17,8 +17,8 @@ use std::sync::Arc; | |||
17 | use std::{fmt, iter, mem}; | 17 | use std::{fmt, iter, mem}; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, Crate, DefWithBody, GenericParams, | 20 | db::HirDatabase, expr::ExprId, type_ref::Mutability, util::make_mut_arc_slice, Adt, Crate, |
21 | HasGenericParams, Name, Trait, TypeAlias, | 21 | DefWithBody, GenericParams, HasGenericParams, Name, Trait, TypeAlias, |
22 | }; | 22 | }; |
23 | use display::{HirDisplay, HirFormatter}; | 23 | use display::{HirDisplay, HirFormatter}; |
24 | 24 | ||
@@ -308,12 +308,11 @@ impl Substs { | |||
308 | } | 308 | } |
309 | 309 | ||
310 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 310 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
311 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 311 | make_mut_arc_slice(&mut self.0, |s| { |
312 | let mut v: Vec<_> = self.0.iter().cloned().collect(); | 312 | for t in s { |
313 | for t in &mut v { | 313 | t.walk_mut(f); |
314 | t.walk_mut(f); | 314 | } |
315 | } | 315 | }); |
316 | self.0 = v.into(); | ||
317 | } | 316 | } |
318 | 317 | ||
319 | pub fn as_single(&self) -> &Ty { | 318 | pub fn as_single(&self) -> &Ty { |
@@ -541,12 +540,11 @@ impl TypeWalk for FnSig { | |||
541 | } | 540 | } |
542 | 541 | ||
543 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 542 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
544 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 543 | make_mut_arc_slice(&mut self.params_and_return, |s| { |
545 | let mut v: Vec<_> = self.params_and_return.iter().cloned().collect(); | 544 | for t in s { |
546 | for t in &mut v { | 545 | t.walk_mut(f); |
547 | t.walk_mut(f); | 546 | } |
548 | } | 547 | }); |
549 | self.params_and_return = v.into(); | ||
550 | } | 548 | } |
551 | } | 549 | } |
552 | 550 | ||
@@ -756,11 +754,11 @@ impl TypeWalk for Ty { | |||
756 | p_ty.parameters.walk_mut(f); | 754 | p_ty.parameters.walk_mut(f); |
757 | } | 755 | } |
758 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | 756 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { |
759 | let mut v: Vec<_> = predicates.iter().cloned().collect(); | 757 | make_mut_arc_slice(predicates, |s| { |
760 | for p in &mut v { | 758 | for p in s { |
761 | p.walk_mut(f); | 759 | p.walk_mut(f); |
762 | } | 760 | } |
763 | *predicates = v.into(); | 761 | }); |
764 | } | 762 | } |
765 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | 763 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} |
766 | } | 764 | } |
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs index d161aa6b3..5e86ed260 100644 --- a/crates/ra_hir/src/ty/infer/unify.rs +++ b/crates/ra_hir/src/ty/infer/unify.rs | |||
@@ -6,6 +6,7 @@ use crate::ty::{ | |||
6 | Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, | 6 | Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, |
7 | TypeWalk, | 7 | TypeWalk, |
8 | }; | 8 | }; |
9 | use crate::util::make_mut_arc_slice; | ||
9 | 10 | ||
10 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 11 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
11 | pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b, D> | 12 | pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b, D> |
@@ -74,10 +75,13 @@ where | |||
74 | }) | 75 | }) |
75 | } | 76 | } |
76 | 77 | ||
77 | fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef { | 78 | fn do_canonicalize_trait_ref(&mut self, mut trait_ref: TraitRef) -> TraitRef { |
78 | let substs = | 79 | make_mut_arc_slice(&mut trait_ref.substs.0, |tys| { |
79 | trait_ref.substs.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect(); | 80 | for ty in tys { |
80 | TraitRef { trait_: trait_ref.trait_, substs: Substs(substs) } | 81 | *ty = self.do_canonicalize_ty(ty.clone()); |
82 | } | ||
83 | }); | ||
84 | trait_ref | ||
81 | } | 85 | } |
82 | 86 | ||
83 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 87 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { |
@@ -87,10 +91,13 @@ where | |||
87 | } | 91 | } |
88 | } | 92 | } |
89 | 93 | ||
90 | fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy { | 94 | fn do_canonicalize_projection_ty(&mut self, mut projection_ty: ProjectionTy) -> ProjectionTy { |
91 | let params = | 95 | make_mut_arc_slice(&mut projection_ty.parameters.0, |params| { |
92 | projection_ty.parameters.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect(); | 96 | for ty in params { |
93 | ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: Substs(params) } | 97 | *ty = self.do_canonicalize_ty(ty.clone()); |
98 | } | ||
99 | }); | ||
100 | projection_ty | ||
94 | } | 101 | } |
95 | 102 | ||
96 | fn do_canonicalize_projection_predicate( | 103 | fn do_canonicalize_projection_predicate( |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index a604c02e2..003aa9bab 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -392,10 +392,9 @@ impl TraitRef { | |||
392 | ) -> Self { | 392 | ) -> Self { |
393 | let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); | 393 | let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); |
394 | if let Some(self_ty) = explicit_self_ty { | 394 | if let Some(self_ty) = explicit_self_ty { |
395 | // FIXME this could be nicer | 395 | crate::util::make_mut_arc_slice(&mut substs.0, |substs| { |
396 | let mut substs_vec = substs.0.to_vec(); | 396 | substs[0] = self_ty; |
397 | substs_vec[0] = self_ty; | 397 | }); |
398 | substs.0 = substs_vec.into(); | ||
399 | } | 398 | } |
400 | TraitRef { trait_: resolved, substs } | 399 | TraitRef { trait_: resolved, substs } |
401 | } | 400 | } |
diff --git a/crates/ra_hir/src/util.rs b/crates/ra_hir/src/util.rs new file mode 100644 index 000000000..46f423c91 --- /dev/null +++ b/crates/ra_hir/src/util.rs | |||
@@ -0,0 +1,19 @@ | |||
1 | //! Internal utility functions. | ||
2 | |||
3 | use std::sync::Arc; | ||
4 | |||
5 | /// Helper for mutating `Arc<[T]>` (i.e. `Arc::make_mut` for Arc slices). | ||
6 | /// The underlying values are cloned if there are other strong references. | ||
7 | pub(crate) fn make_mut_arc_slice<T: Clone, R>( | ||
8 | a: &mut Arc<[T]>, | ||
9 | f: impl FnOnce(&mut [T]) -> R, | ||
10 | ) -> R { | ||
11 | if let Some(s) = Arc::get_mut(a) { | ||
12 | f(s) | ||
13 | } else { | ||
14 | let mut v = a.to_vec(); | ||
15 | let r = f(&mut v); | ||
16 | *a = Arc::from(v); | ||
17 | r | ||
18 | } | ||
19 | } | ||