mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 21:54:42 +00:00
Remove some allocations
This commit is contained in:
parent
c81aa68afe
commit
1bbc255ec5
13 changed files with 78 additions and 58 deletions
|
@ -12,7 +12,10 @@ use hir_ty::{
|
||||||
},
|
},
|
||||||
Interner, TraitRefExt, WhereClause,
|
Interner, TraitRefExt, WhereClause,
|
||||||
};
|
};
|
||||||
use syntax::ast::{self, HasName};
|
use syntax::{
|
||||||
|
ast::{self, HasName},
|
||||||
|
SmolStr,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
|
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();
|
bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect();
|
||||||
let krate = self.id.parent.krate(f.db).id;
|
let krate = self.id.parent.krate(f.db).id;
|
||||||
let sized_trait =
|
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() {
|
let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() {
|
||||||
WhereClause::Implemented(it) => Some(it.hir_trait_id()) == sized_trait,
|
WhereClause::Implemented(it) => Some(it.hir_trait_id()) == sized_trait,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
@ -2427,7 +2427,7 @@ impl Type {
|
||||||
let krate = self.krate;
|
let krate = self.krate;
|
||||||
|
|
||||||
let std_future_trait =
|
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 {
|
let std_future_trait = match std_future_trait {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => return false,
|
None => return false,
|
||||||
|
@ -2516,7 +2516,7 @@ impl Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
|
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 {
|
let copy_trait = match lang_item {
|
||||||
Some(LangItemTarget::TraitId(it)) => it,
|
Some(LangItemTarget::TraitId(it)) => it,
|
||||||
_ => return false,
|
_ => return false,
|
||||||
|
|
|
@ -10,6 +10,7 @@ use chalk_ir::{cast::Cast, fold::Fold, interner::HasInterner, VariableKind};
|
||||||
use hir_def::lang_item::LangItemTarget;
|
use hir_def::lang_item::LangItemTarget;
|
||||||
use hir_expand::name::name;
|
use hir_expand::name::name;
|
||||||
use limit::Limit;
|
use limit::Limit;
|
||||||
|
use syntax::SmolStr;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -71,7 +72,10 @@ impl Iterator for Autoderef<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (kind, new_ty) = if let Some(derefed) = builtin_deref(&self.ty.value) {
|
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 {
|
} else {
|
||||||
(
|
(
|
||||||
AutoderefKind::Overloaded,
|
AutoderefKind::Overloaded,
|
||||||
|
@ -110,15 +114,17 @@ pub(crate) fn deref(
|
||||||
) -> Option<Canonical<Ty>> {
|
) -> Option<Canonical<Ty>> {
|
||||||
let _p = profile::span("deref");
|
let _p = profile::span("deref");
|
||||||
match builtin_deref(&ty.goal.value) {
|
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),
|
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) {
|
match ty.kind(&Interner) {
|
||||||
TyKind::Ref(.., ty) => Some(ty.clone()),
|
TyKind::Ref(.., ty) => Some(ty),
|
||||||
TyKind::Raw(.., ty) => Some(ty.clone()),
|
TyKind::Raw(.., ty) => Some(ty),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,7 +135,7 @@ fn deref_by_trait(
|
||||||
ty: InEnvironment<&Canonical<Ty>>,
|
ty: InEnvironment<&Canonical<Ty>>,
|
||||||
) -> Option<Canonical<Ty>> {
|
) -> Option<Canonical<Ty>> {
|
||||||
let _p = profile::span("deref_by_trait");
|
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,
|
LangItemTarget::TraitId(it) => it,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use cov_mark::hit;
|
use cov_mark::hit;
|
||||||
|
use syntax::SmolStr;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds};
|
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(..) => {
|
crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
|
||||||
if let Some((future_trait, future_output)) = self
|
if let Some((future_trait, future_output)) = self
|
||||||
.db
|
.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(|item| item.as_trait())
|
||||||
.and_then(|trait_| {
|
.and_then(|trait_| {
|
||||||
let alias =
|
let alias =
|
||||||
|
@ -419,7 +420,7 @@ pub(crate) fn associated_ty_data_query(
|
||||||
if !ctx.unsized_types.borrow().contains(&self_ty) {
|
if !ctx.unsized_types.borrow().contains(&self_ty) {
|
||||||
let sized_trait = resolver
|
let sized_trait = resolver
|
||||||
.krate()
|
.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));
|
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
|
||||||
let sized_bound = sized_trait.into_iter().map(|sized_trait| {
|
let sized_bound = sized_trait.into_iter().map(|sized_trait| {
|
||||||
let trait_bound =
|
let trait_bound =
|
||||||
|
|
|
@ -6,6 +6,7 @@ use hir_def::{
|
||||||
type_ref::Rawness,
|
type_ref::Rawness,
|
||||||
FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId,
|
FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId,
|
||||||
};
|
};
|
||||||
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
|
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) => {
|
ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
|
||||||
let krate = def.module(db.upcast()).krate();
|
let krate = def.module(db.upcast()).krate();
|
||||||
if let Some(future_trait) = db
|
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())
|
.and_then(|item| item.as_trait())
|
||||||
{
|
{
|
||||||
// This is only used by type walking.
|
// This is only used by type walking.
|
||||||
|
|
|
@ -50,6 +50,7 @@ use std::{
|
||||||
use hir_def::{EnumVariantId, HasModule, LocalFieldId, VariantId};
|
use hir_def::{EnumVariantId, HasModule, LocalFieldId, VariantId};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use stdx::never;
|
use stdx::never;
|
||||||
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{AdtId, Interner, Scalar, Ty, TyExt, TyKind};
|
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 {
|
fn adt_is_box(adt: hir_def::AdtId, cx: &MatchCheckCtx<'_>) -> bool {
|
||||||
use hir_def::lang_item::LangItemTarget;
|
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(),
|
Some(LangItemTarget::StructId(box_id)) => adt == box_id.into(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ use hir_def::{
|
||||||
};
|
};
|
||||||
use hir_expand::{hygiene::Hygiene, name::Name};
|
use hir_expand::{hygiene::Hygiene, name::Name};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
const_from_placeholder_idx,
|
const_from_placeholder_idx,
|
||||||
|
@ -774,8 +775,9 @@ impl SizedByDefault {
|
||||||
match self {
|
match self {
|
||||||
Self::NotSized => false,
|
Self::NotSized => false,
|
||||||
Self::Sized { anchor } => {
|
Self::Sized { anchor } => {
|
||||||
let sized_trait =
|
let sized_trait = db
|
||||||
db.lang_item(anchor, "sized".into()).and_then(|lang_item| lang_item.as_trait());
|
.lang_item(anchor, SmolStr::new_inline("sized"))
|
||||||
|
.and_then(|lang_item| lang_item.as_trait());
|
||||||
Some(trait_) == sized_trait
|
Some(trait_) == sized_trait
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ use std::iter;
|
||||||
use chalk_ir::{cast::Cast, Goal, Mutability, TyVariableKind};
|
use chalk_ir::{cast::Cast, Goal, Mutability, TyVariableKind};
|
||||||
use hir_def::{expr::ExprId, lang_item::LangItemTarget};
|
use hir_def::{expr::ExprId, lang_item::LangItemTarget};
|
||||||
use stdx::always;
|
use stdx::always;
|
||||||
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
autoderef::{Autoderef, AutoderefKind},
|
autoderef::{Autoderef, AutoderefKind},
|
||||||
|
@ -536,7 +537,8 @@ impl<'a> InferenceContext<'a> {
|
||||||
reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
|
reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
|
||||||
|
|
||||||
let krate = self.resolver.krate().unwrap();
|
let krate = self.resolver.krate().unwrap();
|
||||||
let coerce_unsized_trait = match self.db.lang_item(krate, "coerce_unsized".into()) {
|
let coerce_unsized_trait =
|
||||||
|
match self.db.lang_item(krate, SmolStr::new_inline("coerce_unsized")) {
|
||||||
Some(LangItemTarget::TraitId(trait_)) => trait_,
|
Some(LangItemTarget::TraitId(trait_)) => trait_,
|
||||||
_ => return Err(TypeError),
|
_ => return Err(TypeError),
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,7 +28,7 @@ use la_arena::ArenaMap;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use stdx::impl_from;
|
use stdx::impl_from;
|
||||||
use syntax::ast;
|
use syntax::{ast, SmolStr};
|
||||||
|
|
||||||
use crate::all_super_traits;
|
use crate::all_super_traits;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -797,7 +797,7 @@ impl<'a> TyLoweringContext<'a> {
|
||||||
let sized_trait = self
|
let sized_trait = self
|
||||||
.resolver
|
.resolver
|
||||||
.krate()
|
.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());
|
.and_then(|lang_item| lang_item.as_trait());
|
||||||
// Don't lower associated type bindings as the only possible relaxed trait bound
|
// Don't lower associated type bindings as the only possible relaxed trait bound
|
||||||
// `?Sized` has no of them.
|
// `?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 krate = func.lookup(ctx.db.upcast()).module(ctx.db.upcast()).krate();
|
||||||
let sized_trait = ctx
|
let sized_trait = ctx
|
||||||
.db
|
.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));
|
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
|
||||||
let sized_clause = sized_trait.map(|trait_id| {
|
let sized_clause = sized_trait.map(|trait_id| {
|
||||||
let clause = WhereClause::Implemented(TraitRef {
|
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 generic_args = &substitution.as_slice(&Interner)[is_trait_def as usize..];
|
||||||
let sized_trait = resolver
|
let sized_trait = resolver
|
||||||
.krate()
|
.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));
|
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
|
||||||
|
|
||||||
sized_trait.into_iter().flat_map(move |sized_trait| {
|
sized_trait.into_iter().flat_map(move |sized_trait| {
|
||||||
|
|
|
@ -541,9 +541,10 @@ pub fn iterate_method_candidates_dyn(
|
||||||
// types*.
|
// types*.
|
||||||
|
|
||||||
let deref_chain = autoderef_method_receiver(db, krate, ty);
|
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(
|
iterate_method_candidates_with_autoref(
|
||||||
&deref_chain[i..],
|
deref_chain,
|
||||||
db,
|
db,
|
||||||
env.clone(),
|
env.clone(),
|
||||||
krate,
|
krate,
|
||||||
|
@ -551,9 +552,8 @@ pub fn iterate_method_candidates_dyn(
|
||||||
visible_from_module,
|
visible_from_module,
|
||||||
name,
|
name,
|
||||||
callback,
|
callback,
|
||||||
)?;
|
)
|
||||||
}
|
})
|
||||||
ControlFlow::Continue(())
|
|
||||||
}
|
}
|
||||||
LookupMode::Path => {
|
LookupMode::Path => {
|
||||||
// No autoderef for path lookups
|
// 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
|
// if ty is `dyn Trait`, the trait doesn't need to be in scope
|
||||||
let inherent_trait =
|
let inherent_trait =
|
||||||
self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
|
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) {
|
let env_traits = matches!(self_ty.value.kind(&Interner), TyKind::Placeholder(_))
|
||||||
TyKind::Placeholder(_) => {
|
|
||||||
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
|
// 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())
|
env.traits_in_scope_from_clauses(self_ty.value.clone())
|
||||||
.flat_map(|t| all_super_traits(db.upcast(), t))
|
.flat_map(|t| all_super_traits(db.upcast(), t))
|
||||||
.collect()
|
})
|
||||||
}
|
.into_iter()
|
||||||
_ => Vec::new(),
|
.flatten();
|
||||||
};
|
|
||||||
let traits = inherent_trait.chain(env_traits).chain(traits_in_scope.iter().copied());
|
let traits = inherent_trait.chain(env_traits).chain(traits_in_scope.iter().copied());
|
||||||
|
|
||||||
'traits: for t in traits {
|
'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
|
// trait, but if we find out it doesn't, we'll skip the rest of the
|
||||||
// iteration
|
// iteration
|
||||||
let mut known_implemented = false;
|
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`,
|
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
|
||||||
// since only inherent methods should be included into visibility checking.
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
if !known_implemented {
|
if !known_implemented {
|
||||||
|
@ -761,7 +760,7 @@ fn iterate_trait_method_candidates(
|
||||||
}
|
}
|
||||||
known_implemented = true;
|
known_implemented = true;
|
||||||
// FIXME: we shouldn't be ignoring the binders here
|
// FIXME: we shouldn't be ignoring the binders here
|
||||||
callback(self_ty, *item)?
|
callback(self_ty, item)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ControlFlow::Continue(())
|
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
|
// 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
|
// resolving a method call on an array with a known len
|
||||||
let array_impls = {
|
let array_impls = {
|
||||||
if let TyKind::Array(parameters, array_len) = self_ty.kind(&Interner) {
|
match self_ty.kind(&Interner) {
|
||||||
if !array_len.is_unknown() {
|
TyKind::Array(parameters, array_len) if !array_len.is_unknown() => {
|
||||||
let unknown_array_len_ty =
|
let unknown_array_len_ty =
|
||||||
TyKind::Array(parameters.clone(), consteval::usize_const(None))
|
TyKind::Array(parameters.clone(), consteval::usize_const(None));
|
||||||
.intern(&Interner);
|
|
||||||
|
|
||||||
Some(impls.for_self_ty(&unknown_array_len_ty))
|
Some(impls.for_self_ty(&unknown_array_len_ty.intern(&Interner)))
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
} else {
|
_ => None,
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
@ -9,6 +9,7 @@ use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver};
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use hir_def::{lang_item::LangItemTarget, TraitId};
|
use hir_def::{lang_item::LangItemTarget, TraitId};
|
||||||
use stdx::panic_context;
|
use stdx::panic_context;
|
||||||
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment,
|
db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment,
|
||||||
|
@ -169,7 +170,7 @@ pub enum FnTrait {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FnTrait {
|
impl FnTrait {
|
||||||
fn lang_item_name(self) -> &'static str {
|
const fn lang_item_name(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
FnTrait::FnOnce => "fn_once",
|
FnTrait::FnOnce => "fn_once",
|
||||||
FnTrait::FnMut => "fn_mut",
|
FnTrait::FnMut => "fn_mut",
|
||||||
|
@ -178,7 +179,7 @@ impl FnTrait {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_id(&self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
|
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 {
|
match target {
|
||||||
LangItemTarget::TraitId(t) => Some(t),
|
LangItemTarget::TraitId(t) => Some(t),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -18,6 +18,8 @@ use hir_def::{
|
||||||
};
|
};
|
||||||
use hir_expand::name::{name, Name};
|
use hir_expand::name::{name, Name};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, ChalkTraitId, Interner, Substitution, TraitRef, TraitRefExt, TyKind,
|
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> {
|
pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: CrateId) -> impl Iterator<Item = TraitId> {
|
||||||
[
|
[
|
||||||
db.lang_item(krate, "fn".into()),
|
db.lang_item(krate, SmolStr::new_inline("fn")),
|
||||||
db.lang_item(krate, "fn_mut".into()),
|
db.lang_item(krate, SmolStr::new_inline("fn_mut")),
|
||||||
db.lang_item(krate, "fn_once".into()),
|
db.lang_item(krate, SmolStr::new_inline("fn_once")),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
.flat_map(|it| it.as_trait())
|
.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);
|
let resolver = trait_.resolver(db);
|
||||||
// returning the iterator directly doesn't easily work because of
|
// returning the iterator directly doesn't easily work because of
|
||||||
// lifetime problems, but since there usually shouldn't be more than a
|
// 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
|
/// Returns an iterator over the whole super trait hierarchy (including the
|
||||||
/// trait itself).
|
/// 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
|
// 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;`)
|
// (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;
|
let mut i = 0;
|
||||||
while i < result.len() {
|
while let Some(&t) = result.get(i) {
|
||||||
let t = result[i];
|
|
||||||
// yeah this is quadratic, but trait hierarchies should be flat
|
// yeah this is quadratic, but trait hierarchies should be flat
|
||||||
// enough that this doesn't matter
|
// enough that this doesn't matter
|
||||||
for tt in direct_super_traits(db, t) {
|
for tt in direct_super_traits(db, t) {
|
||||||
|
|
|
@ -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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in a new issue