about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-12-10 19:02:51 +0000
committerGitHub <noreply@github.com>2021-12-10 19:02:51 +0000
commit021d5821befc2e0a0d7d164b345f93d8dfaac52a (patch)
tree9363db584b6448e81ca4e137c61f0547ae95f30d
parentbcc720f22ffeab3d5d7f0ecf5f6f441f83ff10f9 (diff)
parent1bbc255ec59118e4e971dc65468b5a0c9955f9b4 (diff)
downloadrust-021d5821befc2e0a0d7d164b345f93d8dfaac52a.tar.gz
rust-021d5821befc2e0a0d7d164b345f93d8dfaac52a.zip
Merge #10981
10981: internal: Remove some allocations r=Veykril a=Veykril

bors r+

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
-rw-r--r--crates/hir/src/display.rs8
-rw-r--r--crates/hir/src/lib.rs4
-rw-r--r--crates/hir_ty/src/autoderef.rs18
-rw-r--r--crates/hir_ty/src/chalk_db.rs5
-rw-r--r--crates/hir_ty/src/chalk_ext.rs3
-rw-r--r--crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs3
-rw-r--r--crates/hir_ty/src/display.rs6
-rw-r--r--crates/hir_ty/src/infer/coerce.rs10
-rw-r--r--crates/hir_ty/src/lower.rs8
-rw-r--r--crates/hir_ty/src/method_resolution.rs43
-rw-r--r--crates/hir_ty/src/traits.rs5
-rw-r--r--crates/hir_ty/src/utils.rs18
-rw-r--r--crates/stdx/src/lib.rs5
13 files changed, 78 insertions, 58 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 38bbf417971..17465dc2b04 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -12,7 +12,10 @@ use hir_ty::{
     },
     Interner, TraitRefExt, WhereClause,
 };
-use syntax::ast::{self, HasName};
+use syntax::{
+    ast::{self, HasName},
+    SmolStr,
+};
 
 use crate::{
     Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
@@ -247,7 +250,8 @@ impl HirDisplay for TypeParam {
             bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect();
         let krate = self.id.parent.krate(f.db).id;
         let sized_trait =
-            f.db.lang_item(krate, "sized".into()).and_then(|lang_item| lang_item.as_trait());
+            f.db.lang_item(krate, SmolStr::new_inline("sized"))
+                .and_then(|lang_item| lang_item.as_trait());
         let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() {
             WhereClause::Implemented(it) => Some(it.hir_trait_id()) == sized_trait,
             _ => false,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 3739e522a18..7add0f4a436 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2427,7 +2427,7 @@ impl Type {
         let krate = self.krate;
 
         let std_future_trait =
-            db.lang_item(krate, "future_trait".into()).and_then(|it| it.as_trait());
+            db.lang_item(krate, SmolStr::new_inline("future_trait")).and_then(|it| it.as_trait());
         let std_future_trait = match std_future_trait {
             Some(it) => it,
             None => return false,
@@ -2516,7 +2516,7 @@ impl Type {
     }
 
     pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
-        let lang_item = db.lang_item(self.krate, SmolStr::new("copy"));
+        let lang_item = db.lang_item(self.krate, SmolStr::new_inline("copy"));
         let copy_trait = match lang_item {
             Some(LangItemTarget::TraitId(it)) => it,
             _ => return false,
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index 1eb54905078..2d3d16cda0e 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -10,6 +10,7 @@ use chalk_ir::{cast::Cast, fold::Fold, interner::HasInterner, VariableKind};
 use hir_def::lang_item::LangItemTarget;
 use hir_expand::name::name;
 use limit::Limit;
+use syntax::SmolStr;
 use tracing::{info, warn};
 
 use crate::{
@@ -71,7 +72,10 @@ impl Iterator for Autoderef<'_> {
         }
 
         let (kind, new_ty) = if let Some(derefed) = builtin_deref(&self.ty.value) {
-            (AutoderefKind::Builtin, Canonical { value: derefed, binders: self.ty.binders.clone() })
+            (
+                AutoderefKind::Builtin,
+                Canonical { value: derefed.clone(), binders: self.ty.binders.clone() },
+            )
         } else {
             (
                 AutoderefKind::Overloaded,
@@ -110,15 +114,17 @@ pub(crate) fn deref(
 ) -> Option<Canonical<Ty>> {
     let _p = profile::span("deref");
     match builtin_deref(&ty.goal.value) {
-        Some(derefed) => Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }),
+        Some(derefed) => {
+            Some(Canonical { value: derefed.clone(), binders: ty.goal.binders.clone() })
+        }
         None => deref_by_trait(db, krate, ty),
     }
 }
 
-fn builtin_deref(ty: &Ty) -> Option<Ty> {
+fn builtin_deref(ty: &Ty) -> Option<&Ty> {
     match ty.kind(&Interner) {
-        TyKind::Ref(.., ty) => Some(ty.clone()),
-        TyKind::Raw(.., ty) => Some(ty.clone()),
+        TyKind::Ref(.., ty) => Some(ty),
+        TyKind::Raw(.., ty) => Some(ty),
         _ => None,
     }
 }
@@ -129,7 +135,7 @@ fn deref_by_trait(
     ty: InEnvironment<&Canonical<Ty>>,
 ) -> Option<Canonical<Ty>> {
     let _p = profile::span("deref_by_trait");
-    let deref_trait = match db.lang_item(krate, "deref".into())? {
+    let deref_trait = match db.lang_item(krate, SmolStr::new_inline("deref"))? {
         LangItemTarget::TraitId(it) => it,
         _ => return None,
     };
diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs
index dc5dcd163c3..4a7b2d73637 100644
--- a/crates/hir_ty/src/chalk_db.rs
+++ b/crates/hir_ty/src/chalk_db.rs
@@ -3,6 +3,7 @@
 use std::sync::Arc;
 
 use cov_mark::hit;
+use syntax::SmolStr;
 use tracing::debug;
 
 use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds};
@@ -213,7 +214,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
             crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
                 if let Some((future_trait, future_output)) = self
                     .db
-                    .lang_item(self.krate, "future_trait".into())
+                    .lang_item(self.krate, SmolStr::new_inline("future_trait"))
                     .and_then(|item| item.as_trait())
                     .and_then(|trait_| {
                         let alias =
@@ -419,7 +420,7 @@ pub(crate) fn associated_ty_data_query(
     if !ctx.unsized_types.borrow().contains(&self_ty) {
         let sized_trait = resolver
             .krate()
-            .and_then(|krate| db.lang_item(krate, "sized".into()))
+            .and_then(|krate| db.lang_item(krate, SmolStr::new_inline("sized")))
             .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
         let sized_bound = sized_trait.into_iter().map(|sized_trait| {
             let trait_bound =
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
index 653c4d5ec84..97d1ad0f9cd 100644
--- a/crates/hir_ty/src/chalk_ext.rs
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -6,6 +6,7 @@ use hir_def::{
     type_ref::Rawness,
     FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId,
 };
+use syntax::SmolStr;
 
 use crate::{
     db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
@@ -187,7 +188,7 @@ impl TyExt for Ty {
                     ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
                         let krate = def.module(db.upcast()).krate();
                         if let Some(future_trait) = db
-                            .lang_item(krate, "future_trait".into())
+                            .lang_item(krate, SmolStr::new_inline("future_trait"))
                             .and_then(|item| item.as_trait())
                         {
                             // This is only used by type walking.
diff --git a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs
index f9439c706e3..f268746809e 100644
--- a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs
+++ b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs
@@ -50,6 +50,7 @@ use std::{
 use hir_def::{EnumVariantId, HasModule, LocalFieldId, VariantId};
 use smallvec::{smallvec, SmallVec};
 use stdx::never;
+use syntax::SmolStr;
 
 use crate::{AdtId, Interner, Scalar, Ty, TyExt, TyKind};
 
@@ -905,7 +906,7 @@ fn is_field_list_non_exhaustive(variant_id: VariantId, cx: &MatchCheckCtx<'_>) -
 
 fn adt_is_box(adt: hir_def::AdtId, cx: &MatchCheckCtx<'_>) -> bool {
     use hir_def::lang_item::LangItemTarget;
-    match cx.db.lang_item(cx.module.krate(), "owned_box".into()) {
+    match cx.db.lang_item(cx.module.krate(), SmolStr::new_inline("owned_box")) {
         Some(LangItemTarget::StructId(box_id)) => adt == box_id.into(),
         _ => false,
     }
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 307323690a5..c09f8db86e3 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -20,6 +20,7 @@ use hir_def::{
 };
 use hir_expand::{hygiene::Hygiene, name::Name};
 use itertools::Itertools;
+use syntax::SmolStr;
 
 use crate::{
     const_from_placeholder_idx,
@@ -774,8 +775,9 @@ impl SizedByDefault {
         match self {
             Self::NotSized => false,
             Self::Sized { anchor } => {
-                let sized_trait =
-                    db.lang_item(anchor, "sized".into()).and_then(|lang_item| lang_item.as_trait());
+                let sized_trait = db
+                    .lang_item(anchor, SmolStr::new_inline("sized"))
+                    .and_then(|lang_item| lang_item.as_trait());
                 Some(trait_) == sized_trait
             }
         }
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 4d7ac6fd85f..aebff59113e 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -10,6 +10,7 @@ use std::iter;
 use chalk_ir::{cast::Cast, Goal, Mutability, TyVariableKind};
 use hir_def::{expr::ExprId, lang_item::LangItemTarget};
 use stdx::always;
+use syntax::SmolStr;
 
 use crate::{
     autoderef::{Autoderef, AutoderefKind},
@@ -536,10 +537,11 @@ impl<'a> InferenceContext<'a> {
             reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
 
         let krate = self.resolver.krate().unwrap();
-        let coerce_unsized_trait = match self.db.lang_item(krate, "coerce_unsized".into()) {
-            Some(LangItemTarget::TraitId(trait_)) => trait_,
-            _ => return Err(TypeError),
-        };
+        let coerce_unsized_trait =
+            match self.db.lang_item(krate, SmolStr::new_inline("coerce_unsized")) {
+                Some(LangItemTarget::TraitId(trait_)) => trait_,
+                _ => return Err(TypeError),
+            };
 
         let coerce_unsized_tref = {
             let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait);
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index f7e2af46d29..7373c9eb8b4 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -28,7 +28,7 @@ use la_arena::ArenaMap;
 use rustc_hash::FxHashSet;
 use smallvec::SmallVec;
 use stdx::impl_from;
-use syntax::ast;
+use syntax::{ast, SmolStr};
 
 use crate::all_super_traits;
 use crate::{
@@ -797,7 +797,7 @@ impl<'a> TyLoweringContext<'a> {
                 let sized_trait = self
                     .resolver
                     .krate()
-                    .and_then(|krate| self.db.lang_item(krate, "sized".into()))
+                    .and_then(|krate| self.db.lang_item(krate, SmolStr::new_inline("sized")))
                     .and_then(|lang_item| lang_item.as_trait());
                 // Don't lower associated type bindings as the only possible relaxed trait bound
                 // `?Sized` has no of them.
@@ -895,7 +895,7 @@ impl<'a> TyLoweringContext<'a> {
                 let krate = func.lookup(ctx.db.upcast()).module(ctx.db.upcast()).krate();
                 let sized_trait = ctx
                     .db
-                    .lang_item(krate, "sized".into())
+                    .lang_item(krate, SmolStr::new_inline("sized"))
                     .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
                 let sized_clause = sized_trait.map(|trait_id| {
                     let clause = WhereClause::Implemented(TraitRef {
@@ -1200,7 +1200,7 @@ fn implicitly_sized_clauses<'a>(
     let generic_args = &substitution.as_slice(&Interner)[is_trait_def as usize..];
     let sized_trait = resolver
         .krate()
-        .and_then(|krate| db.lang_item(krate, "sized".into()))
+        .and_then(|krate| db.lang_item(krate, SmolStr::new_inline("sized")))
         .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
 
     sized_trait.into_iter().flat_map(move |sized_trait| {
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 6af39828be5..1549a40c91d 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -541,9 +541,10 @@ pub fn iterate_method_candidates_dyn(
             // types*.
 
             let deref_chain = autoderef_method_receiver(db, krate, ty);
-            for i in 0..deref_chain.len() {
+            let mut deref_chains = stdx::slice_tails(&deref_chain);
+            deref_chains.try_for_each(|deref_chain| {
                 iterate_method_candidates_with_autoref(
-                    &deref_chain[i..],
+                    deref_chain,
                     db,
                     env.clone(),
                     krate,
@@ -551,9 +552,8 @@ pub fn iterate_method_candidates_dyn(
                     visible_from_module,
                     name,
                     callback,
-                )?;
-            }
-            ControlFlow::Continue(())
+                )
+            })
         }
         LookupMode::Path => {
             // No autoderef for path lookups
@@ -716,15 +716,14 @@ fn iterate_trait_method_candidates(
     // 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 = match self_ty.value.kind(&Interner) {
-        TyKind::Placeholder(_) => {
-            // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
+    let env_traits = matches!(self_ty.value.kind(&Interner), TyKind::Placeholder(_))
+        // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
+        .then(|| {
             env.traits_in_scope_from_clauses(self_ty.value.clone())
                 .flat_map(|t| all_super_traits(db.upcast(), t))
-                .collect()
-        }
-        _ => Vec::new(),
-    };
+        })
+        .into_iter()
+        .flatten();
     let traits = inherent_trait.chain(env_traits).chain(traits_in_scope.iter().copied());
 
     'traits: for t in traits {
@@ -747,10 +746,10 @@ fn iterate_trait_method_candidates(
         // trait, but if we find out it doesn't, we'll skip the rest of the
         // iteration
         let mut known_implemented = false;
-        for (_name, item) in data.items.iter() {
+        for &(_, item) in data.items.iter() {
             // Don't pass a `visible_from_module` down to `is_valid_candidate`,
             // since only inherent methods should be included into visibility checking.
-            if !is_valid_candidate(db, env.clone(), name, receiver_ty, *item, self_ty, None) {
+            if !is_valid_candidate(db, env.clone(), name, receiver_ty, item, self_ty, None) {
                 continue;
             }
             if !known_implemented {
@@ -761,7 +760,7 @@ fn iterate_trait_method_candidates(
             }
             known_implemented = true;
             // FIXME: we shouldn't be ignoring the binders here
-            callback(self_ty, *item)?
+            callback(self_ty, item)?
         }
     }
     ControlFlow::Continue(())
@@ -774,18 +773,14 @@ fn filter_inherent_impls_for_self_ty<'i>(
     // inherent methods on arrays are fingerprinted as [T; {unknown}], so we must also consider them when
     // resolving a method call on an array with a known len
     let array_impls = {
-        if let TyKind::Array(parameters, array_len) = self_ty.kind(&Interner) {
-            if !array_len.is_unknown() {
+        match self_ty.kind(&Interner) {
+            TyKind::Array(parameters, array_len) if !array_len.is_unknown() => {
                 let unknown_array_len_ty =
-                    TyKind::Array(parameters.clone(), consteval::usize_const(None))
-                        .intern(&Interner);
+                    TyKind::Array(parameters.clone(), consteval::usize_const(None));
 
-                Some(impls.for_self_ty(&unknown_array_len_ty))
-            } else {
-                None
+                Some(impls.for_self_ty(&unknown_array_len_ty.intern(&Interner)))
             }
-        } else {
-            None
+            _ => None,
         }
     }
     .into_iter()
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index 3876a9da269..0d135651c78 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -9,6 +9,7 @@ use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver};
 use base_db::CrateId;
 use hir_def::{lang_item::LangItemTarget, TraitId};
 use stdx::panic_context;
+use syntax::SmolStr;
 
 use crate::{
     db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment,
@@ -169,7 +170,7 @@ pub enum FnTrait {
 }
 
 impl FnTrait {
-    fn lang_item_name(self) -> &'static str {
+    const fn lang_item_name(self) -> &'static str {
         match self {
             FnTrait::FnOnce => "fn_once",
             FnTrait::FnMut => "fn_mut",
@@ -178,7 +179,7 @@ impl FnTrait {
     }
 
     pub fn get_id(&self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
-        let target = db.lang_item(krate, self.lang_item_name().into())?;
+        let target = db.lang_item(krate, SmolStr::new_inline(self.lang_item_name()))?;
         match target {
             LangItemTarget::TraitId(t) => Some(t),
             _ => None,
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index a0837377c6e..f36a5f89871 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -18,6 +18,8 @@ use hir_def::{
 };
 use hir_expand::name::{name, Name};
 use rustc_hash::FxHashSet;
+use smallvec::{smallvec, SmallVec};
+use syntax::SmolStr;
 
 use crate::{
     db::HirDatabase, ChalkTraitId, Interner, Substitution, TraitRef, TraitRefExt, TyKind,
@@ -26,16 +28,16 @@ use crate::{
 
 pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: CrateId) -> impl Iterator<Item = TraitId> {
     [
-        db.lang_item(krate, "fn".into()),
-        db.lang_item(krate, "fn_mut".into()),
-        db.lang_item(krate, "fn_once".into()),
+        db.lang_item(krate, SmolStr::new_inline("fn")),
+        db.lang_item(krate, SmolStr::new_inline("fn_mut")),
+        db.lang_item(krate, SmolStr::new_inline("fn_once")),
     ]
     .into_iter()
     .flatten()
     .flat_map(|it| it.as_trait())
 }
 
-fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
+fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
     let resolver = trait_.resolver(db);
     // returning the iterator directly doesn't easily work because of
     // lifetime problems, but since there usually shouldn't be more than a
@@ -100,13 +102,13 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
 
 /// Returns an iterator over the whole super trait hierarchy (including the
 /// trait itself).
-pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
+pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
     // we need to take care a bit here to avoid infinite loops in case of cycles
     // (i.e. if we have `trait A: B; trait B: A;`)
-    let mut result = vec![trait_];
+
+    let mut result = smallvec![trait_];
     let mut i = 0;
-    while i < result.len() {
-        let t = result[i];
+    while let Some(&t) = result.get(i) {
         // yeah this is quadratic, but trait hierarchies should be flat
         // enough that this doesn't matter
         for tt in direct_super_traits(db, t) {
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index ee23f579345..e33b45cc8ef 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -193,6 +193,11 @@ where
     }
 }
 
+/// Returns all final segments of the argument, longest first.
+pub fn slice_tails<T>(this: &[T]) -> impl Iterator<Item = &[T]> {
+    (0..this.len()).map(|i| &this[i..])
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;