Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
-rw-r--r--crates/hir/src/lib.rs118
1 files changed, 77 insertions, 41 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 00b4db5437..db3121d3cd 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -54,11 +54,11 @@ use hir_def::{
per_ns::PerNs,
resolver::{HasResolver, Resolver},
type_ref::TypesSourceMap,
- AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, CrateRootModuleId,
- DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId,
- HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup,
- MacroExpander, ModuleId, StaticId, StructId, SyntheticSyntax, TraitAliasId, TraitId, TupleId,
- TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
+ AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId,
+ CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId,
+ GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId,
+ LifetimeParamId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
+ SyntheticSyntax, TraitAliasId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
};
use hir_expand::{
attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError,
@@ -83,7 +83,7 @@ use itertools::Itertools;
use nameres::diagnostics::DefDiagnosticKind;
use rustc_hash::FxHashSet;
use smallvec::SmallVec;
-use span::{Edition, EditionedFileId, FileId, MacroCallId, SyntaxContextId};
+use span::{Edition, EditionedFileId, FileId, MacroCallId};
use stdx::{format_to, impl_from, never};
use syntax::{
ast::{self, HasAttrs as _, HasGenericParams, HasName},
@@ -127,7 +127,7 @@ pub use {
ImportPathConfig,
// FIXME: This is here since some queries take it as input that are used
// outside of hir.
- {AdtId, MacroId, ModuleDefId},
+ {ModuleDefId, TraitId},
},
hir_expand::{
attrs::{Attr, AttrId},
@@ -775,29 +775,16 @@ impl Module {
AssocItemId::ConstId(id) => !db.const_data(id).has_body,
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(),
});
- impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().filter_map(
- |&item| {
- Some((
- item,
- match item {
- AssocItemId::FunctionId(it) => db.function_data(it).name.clone(),
- AssocItemId::ConstId(it) => {
- db.const_data(it).name.as_ref()?.clone()
- }
- AssocItemId::TypeAliasId(it) => db.type_alias_data(it).name.clone(),
- },
- ))
- },
- ));
+ impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().cloned());
let redundant = impl_assoc_items_scratch
.iter()
- .filter(|(id, name)| {
+ .filter(|(name, id)| {
!items.iter().any(|(impl_name, impl_item)| {
discriminant(impl_item) == discriminant(id) && impl_name == name
})
})
- .map(|(item, name)| (name.clone(), AssocItem::from(*item)));
+ .map(|(name, item)| (name.clone(), AssocItem::from(*item)));
for (name, assoc_item) in redundant {
acc.push(
TraitImplRedundantAssocItems {
@@ -812,7 +799,7 @@ impl Module {
let missing: Vec<_> = required_items
.filter(|(name, id)| {
- !impl_assoc_items_scratch.iter().any(|(impl_item, impl_name)| {
+ !impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| {
discriminant(impl_item) == discriminant(id) && impl_name == name
})
})
@@ -844,7 +831,7 @@ impl Module {
source_map,
);
- for &item in db.impl_data(impl_def.id).items.iter() {
+ for &(_, item) in db.impl_data(impl_def.id).items.iter() {
AssocItem::from(item).diagnostics(db, acc, style_lints);
}
}
@@ -3000,6 +2987,10 @@ impl Macro {
matches!(self.id, MacroId::MacroRulesId(id) if db.macro_rules_data(id).macro_export)
}
+ pub fn is_proc_macro(self) -> bool {
+ matches!(self.id, MacroId::ProcMacroId(_))
+ }
+
pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
match self.id {
MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
@@ -3046,14 +3037,23 @@ impl Macro {
MacroId::Macro2Id(it) => {
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
}
- MacroId::MacroRulesId(_) | MacroId::ProcMacroId(_) => false,
+ MacroId::MacroRulesId(it) => {
+ matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
+ }
+ MacroId::ProcMacroId(_) => false,
}
}
pub fn is_asm_or_global_asm(&self, db: &dyn HirDatabase) -> bool {
- matches!(self.id, MacroId::Macro2Id(it) if {
- matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm())
- })
+ match self.id {
+ MacroId::Macro2Id(it) => {
+ matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm())
+ }
+ MacroId::MacroRulesId(it) => {
+ matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm())
+ }
+ MacroId::ProcMacroId(_) => false,
+ }
}
pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
@@ -3902,6 +3902,10 @@ impl ToolModule {
db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone(),
)
}
+
+ pub fn krate(&self) -> Crate {
+ Crate { id: self.krate }
+ }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -4290,7 +4294,7 @@ impl Impl {
}
pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
- db.impl_data(self.id).items.iter().map(|&it| it.into()).collect()
+ db.impl_data(self.id).items.iter().map(|&(_, it)| it.into()).collect()
}
pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
@@ -4731,6 +4735,14 @@ impl Type {
Some((self.derived(ty.clone()), m))
}
+ pub fn add_reference(&self, mutability: Mutability) -> Type {
+ let ty_mutability = match mutability {
+ Mutability::Shared => hir_ty::Mutability::Not,
+ Mutability::Mut => hir_ty::Mutability::Mut,
+ };
+ self.derived(TyKind::Ref(ty_mutability, error_lifetime(), self.ty.clone()).intern(Interner))
+ }
+
pub fn is_slice(&self) -> bool {
matches!(self.ty.kind(Interner), TyKind::Slice(..))
}
@@ -4786,9 +4798,9 @@ impl Type {
}
/// Checks that particular type `ty` implements `std::future::IntoFuture` or
- /// `std::future::Future`.
+ /// `std::future::Future` and returns the `Output` associated type.
/// This function is used in `.await` syntax completion.
- pub fn impls_into_future(&self, db: &dyn HirDatabase) -> bool {
+ pub fn into_future_output(&self, db: &dyn HirDatabase) -> Option<Type> {
let trait_ = db
.lang_item(self.env.krate, LangItem::IntoFutureIntoFuture)
.and_then(|it| {
@@ -4800,16 +4812,18 @@ impl Type {
.or_else(|| {
let future_trait = db.lang_item(self.env.krate, LangItem::Future)?;
future_trait.as_trait()
- });
-
- let trait_ = match trait_ {
- Some(it) => it,
- None => return false,
- };
+ })?;
let canonical_ty =
Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
- method_resolution::implements_trait(&canonical_ty, db, &self.env, trait_)
+ if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) {
+ return None;
+ }
+
+ let output_assoc_type = db
+ .trait_data(trait_)
+ .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?;
+ self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
}
/// This does **not** resolve `IntoFuture`, only `Future`.
@@ -4824,10 +4838,31 @@ impl Type {
let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?;
let iterator_item = db
.trait_data(iterator_trait)
- .associated_type_by_name(&Name::new_symbol(sym::Item.clone(), SyntaxContextId::ROOT))?;
+ .associated_type_by_name(&Name::new_symbol_root(sym::Item.clone()))?;
self.normalize_trait_assoc_type(db, &[], iterator_item.into())
}
+ /// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
+ pub fn into_iterator_iter(self, db: &dyn HirDatabase) -> Option<Type> {
+ let trait_ = db.lang_item(self.env.krate, LangItem::IntoIterIntoIter).and_then(|it| {
+ let into_iter_fn = it.as_function()?;
+ let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
+ let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
+ Some(into_iter_trait.id)
+ })?;
+
+ let canonical_ty =
+ Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
+ if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) {
+ return None;
+ }
+
+ let into_iter_assoc_type = db
+ .trait_data(trait_)
+ .associated_type_by_name(&Name::new_symbol_root(sym::IntoIter.clone()))?;
+ self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
+ }
+
/// Checks that particular type `ty` implements `std::ops::FnOnce`.
///
/// This function can be used to check if a particular type is callable, since FnOnce is a
@@ -5117,7 +5152,7 @@ impl Type {
let impls = db.inherent_impls_in_crate(krate);
for impl_def in impls.for_self_ty(&self.ty) {
- for &item in db.impl_data(*impl_def).items.iter() {
+ for &(_, item) in db.impl_data(*impl_def).items.iter() {
if callback(item) {
return;
}
@@ -5535,6 +5570,7 @@ impl Type {
walk_substs(db, type_, &opaque_ty.substitution, cb);
}
TyKind::Placeholder(_) => {
+ cb(type_.derived(ty.clone()));
if let Some(bounds) = ty.impl_trait_bounds(db) {
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
}