aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShotaro Yamada <[email protected]>2019-10-14 04:56:18 +0100
committerShotaro Yamada <[email protected]>2019-10-14 06:25:05 +0100
commitf8d4cdc170bead42db3ffa647318ecf2bd6430e7 (patch)
tree2c020016af1fd5239fdad65b816b4cccea97df41
parent77f2dd96a122e59a8d8df8afb53a741df9b1af76 (diff)
Avoid cloning `Arc<[T]>` into a vec if possible
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/ty.rs36
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs23
-rw-r--r--crates/ra_hir/src/ty/lower.rs7
-rw-r--r--crates/ra_hir/src/util.rs19
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;
51mod generics; 51mod generics;
52mod resolve; 52mod resolve;
53pub mod diagnostics; 53pub mod diagnostics;
54mod util;
54 55
55mod code_model; 56mod 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;
17use std::{fmt, iter, mem}; 17use std::{fmt, iter, mem};
18 18
19use crate::{ 19use 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};
23use display::{HirDisplay, HirFormatter}; 23use 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};
9use crate::util::make_mut_arc_slice;
9 10
10impl<'a, D: HirDatabase> InferenceContext<'a, D> { 11impl<'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
3use 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.
7pub(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}