Remove some allocations
This commit is contained in:
parent
c81aa68afe
commit
1bbc255ec5
@ -12,7 +12,10 @@
|
||||
},
|
||||
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 @@ fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||
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,
|
||||
|
@ -2427,7 +2427,7 @@ pub fn impls_future(&self, db: &dyn HirDatabase) -> bool {
|
||||
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 @@ pub fn normalize_trait_assoc_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,
|
||||
|
@ -10,6 +10,7 @@
|
||||
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 @@ fn next(&mut self) -> Option<Self::Item> {
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
@ -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 @@ fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatu
|
||||
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 =
|
||||
|
@ -6,6 +6,7 @@
|
||||
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 @@ fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereC
|
||||
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.
|
||||
|
@ -50,6 +50,7 @@
|
||||
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,
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
};
|
||||
use hir_expand::{hygiene::Hygiene, name::Name};
|
||||
use itertools::Itertools;
|
||||
use syntax::SmolStr;
|
||||
|
||||
use crate::{
|
||||
const_from_placeholder_idx,
|
||||
@ -774,8 +775,9 @@ fn is_sized_trait(self, trait_: TraitId, db: &dyn DefDatabase) -> bool {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
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 @@ fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> CoerceResult {
|
||||
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);
|
||||
|
@ -28,7 +28,7 @@
|
||||
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 @@ pub(crate) fn lower_type_bound(
|
||||
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 @@ fn lower_impl_trait(
|
||||
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| {
|
||||
|
@ -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()
|
||||
|
@ -9,6 +9,7 @@
|
||||
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 @@ fn lang_item_name(self) -> &'static str {
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -18,6 +18,8 @@
|
||||
};
|
||||
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 @@
|
||||
|
||||
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) {
|
||||
|
@ -193,6 +193,11 @@ pub fn iter_eq_by<I, I2, F>(this: I2, other: I, mut eq: F) -> bool
|
||||
}
|
||||
}
|
||||
|
||||
/// 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::*;
|
||||
|
Loading…
Reference in New Issue
Block a user