2019-01-08 23:47:12 +00:00
|
|
|
//! HIR (previously known as descriptors) provides a high-level object oriented
|
|
|
|
//! access to Rust code.
|
2018-11-28 00:42:26 +00:00
|
|
|
//!
|
|
|
|
//! The principal difference between HIR and syntax trees is that HIR is bound
|
|
|
|
//! to a particular crate instance. That is, it has cfg flags and features
|
2019-01-08 23:47:12 +00:00
|
|
|
//! applied. So, the relation between syntax and HIR is many-to-one.
|
2020-03-23 12:00:51 +00:00
|
|
|
//!
|
|
|
|
//! HIR is the public API of the all of the compiler logic above syntax trees.
|
|
|
|
//! It is written in "OO" style. Each type is self contained (as in, it knows it's
|
|
|
|
//! parents and full context). It should be "clean code".
|
|
|
|
//!
|
2020-08-13 14:36:55 +00:00
|
|
|
//! `hir_*` crates are the implementation of the compiler logic.
|
2020-03-23 12:00:51 +00:00
|
|
|
//! They are written in "ECS" style, with relatively little abstractions.
|
2020-03-23 12:04:50 +00:00
|
|
|
//! Many types are not self-contained, and explicitly use local indexes, arenas, etc.
|
2020-03-23 12:00:51 +00:00
|
|
|
//!
|
2020-08-13 14:36:55 +00:00
|
|
|
//! `hir` is what insulates the "we don't know how to actually write an incremental compiler"
|
2020-03-23 12:00:51 +00:00
|
|
|
//! from the ide with completions, hovers, etc. It is a (soft, internal) boundary:
|
2021-06-14 04:57:10 +00:00
|
|
|
//! <https://www.tedinski.com/2018/02/06/system-boundaries.html>.
|
2018-11-28 00:42:26 +00:00
|
|
|
|
2019-09-30 08:58:53 +00:00
|
|
|
#![recursion_limit = "512"]
|
|
|
|
|
2020-02-18 17:35:10 +00:00
|
|
|
mod semantics;
|
2020-02-28 16:27:49 +00:00
|
|
|
mod source_analyzer;
|
2018-11-28 00:42:26 +00:00
|
|
|
|
2019-10-31 15:45:10 +00:00
|
|
|
mod from_id;
|
2020-08-25 10:56:01 +00:00
|
|
|
mod attrs;
|
2019-12-08 11:57:13 +00:00
|
|
|
mod has_source;
|
2019-09-16 10:48:54 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub mod diagnostics;
|
|
|
|
pub mod db;
|
2022-01-12 18:56:47 +00:00
|
|
|
pub mod symbols;
|
2021-03-08 19:08:30 +00:00
|
|
|
|
2021-03-14 09:36:04 +00:00
|
|
|
mod display;
|
|
|
|
|
2022-03-20 13:45:28 +00:00
|
|
|
use std::{iter, ops::ControlFlow, sync::Arc};
|
2021-03-08 19:08:30 +00:00
|
|
|
|
|
|
|
use arrayvec::ArrayVec;
|
2022-03-09 10:26:06 +00:00
|
|
|
use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId, ProcMacroKind};
|
2021-03-08 19:08:30 +00:00
|
|
|
use either::Either;
|
|
|
|
use hir_def::{
|
|
|
|
adt::{ReprKind, VariantData},
|
2021-06-12 14:39:46 +00:00
|
|
|
body::{BodyDiagnostic, SyntheticSyntax},
|
2021-03-08 19:08:30 +00:00
|
|
|
expr::{BindingAnnotation, LabelId, Pat, PatId},
|
2022-01-12 18:56:47 +00:00
|
|
|
item_tree::ItemTreeNode,
|
2021-03-08 19:08:30 +00:00
|
|
|
lang_item::LangItemTarget,
|
2022-01-11 13:34:25 +00:00
|
|
|
nameres::{self, diagnostics::DefDiagnostic},
|
2021-03-08 19:08:30 +00:00
|
|
|
per_ns::PerNs,
|
|
|
|
resolver::{HasResolver, Resolver},
|
2022-01-12 18:56:47 +00:00
|
|
|
src::HasSource as _,
|
|
|
|
AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
|
|
|
|
FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
|
2022-03-09 10:26:06 +00:00
|
|
|
LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
|
|
|
|
TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
|
2021-03-08 19:08:30 +00:00
|
|
|
};
|
2022-03-08 22:51:48 +00:00
|
|
|
use hir_expand::{name::name, MacroCallKind};
|
2021-03-08 19:08:30 +00:00
|
|
|
use hir_ty::{
|
2021-05-14 07:59:30 +00:00
|
|
|
autoderef,
|
2022-03-24 08:36:27 +00:00
|
|
|
consteval::{unknown_const_as_generic, ComputedExpr, ConstEvalError, ConstExt},
|
2021-06-12 16:28:19 +00:00
|
|
|
diagnostics::BodyValidationDiagnostic,
|
2021-06-12 19:05:23 +00:00
|
|
|
method_resolution::{self, TyFingerprint},
|
2021-03-15 20:28:21 +00:00
|
|
|
primitive::UintTy,
|
2021-04-05 19:56:40 +00:00
|
|
|
subst_prefix,
|
2021-04-04 18:27:40 +00:00
|
|
|
traits::FnTrait,
|
2021-03-21 19:05:38 +00:00
|
|
|
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
|
2022-03-09 18:50:24 +00:00
|
|
|
DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind, QuantifiedWhereClause,
|
|
|
|
Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt,
|
|
|
|
TyKind, TyVariableKind, WhereClause,
|
2021-03-08 19:08:30 +00:00
|
|
|
};
|
2021-03-15 16:43:46 +00:00
|
|
|
use itertools::Itertools;
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
use nameres::diagnostics::DefDiagnosticKind;
|
2021-06-12 14:49:41 +00:00
|
|
|
use once_cell::unsync::Lazy;
|
2021-03-08 19:08:30 +00:00
|
|
|
use rustc_hash::FxHashSet;
|
2021-12-29 13:35:59 +00:00
|
|
|
use stdx::{format_to, impl_from, never};
|
2021-03-08 19:08:30 +00:00
|
|
|
use syntax::{
|
2022-01-07 17:51:10 +00:00
|
|
|
ast::{self, HasAttrs as _, HasDocComments, HasName},
|
2022-02-20 23:02:10 +00:00
|
|
|
AstNode, AstPtr, SmolStr, SyntaxNodePtr, T,
|
2021-03-08 19:08:30 +00:00
|
|
|
};
|
|
|
|
|
2021-06-13 19:05:47 +00:00
|
|
|
use crate::db::{DefDatabase, HirDatabase};
|
2021-03-08 19:08:30 +00:00
|
|
|
|
2019-10-29 12:53:25 +00:00
|
|
|
pub use crate::{
|
2020-08-26 16:56:41 +00:00
|
|
|
attrs::{HasAttrs, Namespace},
|
2021-06-13 11:41:19 +00:00
|
|
|
diagnostics::{
|
2022-03-20 15:26:48 +00:00
|
|
|
AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, IncorrectCase, InvalidDeriveTarget,
|
|
|
|
MacroError, MalformedDerive, MismatchedArgCount, MissingFields, MissingMatchArms,
|
|
|
|
MissingUnsafe, NoSuchField, ReplaceFilterMapNextWithFindMap, TypeMismatch,
|
|
|
|
UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall,
|
|
|
|
UnresolvedModule, UnresolvedProcMacro,
|
2021-06-13 11:41:19 +00:00
|
|
|
},
|
2019-12-08 11:57:13 +00:00
|
|
|
has_source::HasSource,
|
2022-05-05 20:21:42 +00:00
|
|
|
semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits},
|
2018-11-28 00:42:26 +00:00
|
|
|
};
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
// Be careful with these re-exports.
|
|
|
|
//
|
|
|
|
// `hir` is the boundary between the compiler and the IDE. It should try hard to
|
|
|
|
// isolate the compiler from the ide, to allow the two to be refactored
|
|
|
|
// independently. Re-exporting something from the compiler is the sure way to
|
|
|
|
// breach the boundary.
|
|
|
|
//
|
|
|
|
// Generally, a refactoring which *removes* a name from this list is a good
|
|
|
|
// idea!
|
|
|
|
pub use {
|
2021-05-07 20:35:43 +00:00
|
|
|
cfg::{CfgAtom, CfgExpr, CfgOptions},
|
2021-03-08 19:08:30 +00:00
|
|
|
hir_def::{
|
|
|
|
adt::StructKind,
|
2021-03-19 20:23:57 +00:00
|
|
|
attr::{Attr, Attrs, AttrsWithOwner, Documentation},
|
2021-12-03 19:28:15 +00:00
|
|
|
builtin_attr::AttributeTemplate,
|
2021-03-08 19:08:30 +00:00
|
|
|
find_path::PrefixKind,
|
|
|
|
import_map,
|
2022-01-12 18:56:47 +00:00
|
|
|
nameres::ModuleSource,
|
2021-03-08 19:08:30 +00:00
|
|
|
path::{ModPath, PathKind},
|
|
|
|
type_ref::{Mutability, TypeRef},
|
|
|
|
visibility::Visibility,
|
|
|
|
},
|
|
|
|
hir_expand::{
|
2021-03-08 19:14:52 +00:00
|
|
|
name::{known, Name},
|
2022-01-13 15:18:05 +00:00
|
|
|
ExpandResult, HirFileId, InFile, MacroFile, Origin,
|
2021-03-08 19:08:30 +00:00
|
|
|
},
|
|
|
|
hir_ty::display::HirDisplay,
|
2019-11-24 11:02:08 +00:00
|
|
|
};
|
2020-08-13 21:52:14 +00:00
|
|
|
|
|
|
|
// These are negative re-exports: pub using these names is forbidden, they
|
|
|
|
// should remain private to hir internals.
|
|
|
|
#[allow(unused)]
|
2021-03-08 19:14:52 +00:00
|
|
|
use {
|
|
|
|
hir_def::path::Path,
|
|
|
|
hir_expand::{hygiene::Hygiene, name::AsName},
|
|
|
|
};
|
2021-03-08 19:08:30 +00:00
|
|
|
|
|
|
|
/// hir::Crate describes a single crate. It's the main interface with which
|
|
|
|
/// a crate's dependencies interact. Mostly, it should be just a proxy for the
|
|
|
|
/// root module.
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Crate {
|
|
|
|
pub(crate) id: CrateId,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct CrateDependency {
|
|
|
|
pub krate: Crate,
|
|
|
|
pub name: Name,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Crate {
|
2021-11-22 17:44:46 +00:00
|
|
|
pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin {
|
|
|
|
db.crate_graph()[self.id].origin.clone()
|
|
|
|
}
|
|
|
|
|
2022-03-26 20:22:35 +00:00
|
|
|
pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
matches!(self.origin(db), CrateOrigin::Lang(_))
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
|
|
|
|
db.crate_graph()[self.id]
|
|
|
|
.dependencies
|
|
|
|
.iter()
|
|
|
|
.map(|dep| {
|
|
|
|
let krate = Crate { id: dep.crate_id };
|
|
|
|
let name = dep.as_name();
|
2022-03-31 09:12:08 +00:00
|
|
|
CrateDependency { krate, name }
|
2021-03-08 19:08:30 +00:00
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
|
|
|
|
let crate_graph = db.crate_graph();
|
|
|
|
crate_graph
|
|
|
|
.iter()
|
|
|
|
.filter(|&krate| {
|
|
|
|
crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id)
|
|
|
|
})
|
|
|
|
.map(|id| Crate { id })
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2022-04-09 11:40:48 +00:00
|
|
|
pub fn transitive_reverse_dependencies(
|
|
|
|
self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
) -> impl Iterator<Item = Crate> {
|
|
|
|
db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id })
|
2021-03-15 16:43:46 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn root_module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
let def_map = db.crate_def_map(self.id);
|
|
|
|
Module { id: def_map.module_id(def_map.root()) }
|
|
|
|
}
|
|
|
|
|
2022-01-12 19:19:10 +00:00
|
|
|
pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
|
|
|
|
let def_map = db.crate_def_map(self.id);
|
|
|
|
def_map.modules().map(|(id, _)| def_map.module_id(id).into()).collect()
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
|
|
|
|
db.crate_graph()[self.id].root_file_id
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn edition(self, db: &dyn HirDatabase) -> Edition {
|
|
|
|
db.crate_graph()[self.id].edition
|
|
|
|
}
|
|
|
|
|
2021-10-30 14:17:04 +00:00
|
|
|
pub fn version(self, db: &dyn HirDatabase) -> Option<String> {
|
|
|
|
db.crate_graph()[self.id].version.clone()
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> {
|
|
|
|
db.crate_graph()[self.id].display_name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn query_external_importables(
|
|
|
|
self,
|
|
|
|
db: &dyn DefDatabase,
|
|
|
|
query: import_map::Query,
|
2022-03-08 22:51:48 +00:00
|
|
|
) -> impl Iterator<Item = Either<ModuleDef, Macro>> {
|
2021-06-10 20:03:16 +00:00
|
|
|
let _p = profile::span("query_external_importables");
|
2021-07-28 15:39:04 +00:00
|
|
|
import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| {
|
|
|
|
match ItemInNs::from(item) {
|
|
|
|
ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id),
|
|
|
|
ItemInNs::Macros(mac_id) => Either::Right(mac_id),
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
|
|
|
|
db.crate_graph().iter().map(|id| Crate { id }).collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Try to get the root URL of the documentation of a crate.
|
|
|
|
pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
|
|
|
|
// Look for #![doc(html_root_url = "...")]
|
|
|
|
let attrs = db.attrs(AttrDefId::ModuleId(self.root_module(db).into()));
|
2022-05-04 15:41:29 +00:00
|
|
|
let doc_url = attrs.by_key("doc").find_string_value_in_tt("html_root_url");
|
2021-03-08 19:08:30 +00:00
|
|
|
doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
|
|
|
|
}
|
2021-05-07 20:35:43 +00:00
|
|
|
|
|
|
|
pub fn cfg(&self, db: &dyn HirDatabase) -> CfgOptions {
|
|
|
|
db.crate_graph()[self.id].cfg_options.clone()
|
|
|
|
}
|
2021-05-30 13:52:19 +00:00
|
|
|
|
2021-05-31 19:45:01 +00:00
|
|
|
pub fn potential_cfg(&self, db: &dyn HirDatabase) -> CfgOptions {
|
|
|
|
db.crate_graph()[self.id].potential_cfg_options.clone()
|
2021-05-30 13:52:19 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Module {
|
|
|
|
pub(crate) id: ModuleId,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The defs which can be visible in the module.
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub enum ModuleDef {
|
|
|
|
Module(Module),
|
|
|
|
Function(Function),
|
|
|
|
Adt(Adt),
|
|
|
|
// Can't be directly declared, but can be imported.
|
|
|
|
Variant(Variant),
|
|
|
|
Const(Const),
|
|
|
|
Static(Static),
|
|
|
|
Trait(Trait),
|
|
|
|
TypeAlias(TypeAlias),
|
|
|
|
BuiltinType(BuiltinType),
|
2022-03-08 22:51:48 +00:00
|
|
|
Macro(Macro),
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
impl_from!(
|
|
|
|
Module,
|
|
|
|
Function,
|
|
|
|
Adt(Struct, Enum, Union),
|
|
|
|
Variant,
|
|
|
|
Const,
|
|
|
|
Static,
|
|
|
|
Trait,
|
|
|
|
TypeAlias,
|
2022-03-08 22:51:48 +00:00
|
|
|
BuiltinType,
|
|
|
|
Macro
|
2021-03-08 19:08:30 +00:00
|
|
|
for ModuleDef
|
|
|
|
);
|
|
|
|
|
|
|
|
impl From<VariantDef> for ModuleDef {
|
|
|
|
fn from(var: VariantDef) -> Self {
|
|
|
|
match var {
|
|
|
|
VariantDef::Struct(t) => Adt::from(t).into(),
|
|
|
|
VariantDef::Union(t) => Adt::from(t).into(),
|
|
|
|
VariantDef::Variant(t) => t.into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ModuleDef {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
|
|
|
|
match self {
|
|
|
|
ModuleDef::Module(it) => it.parent(db),
|
|
|
|
ModuleDef::Function(it) => Some(it.module(db)),
|
|
|
|
ModuleDef::Adt(it) => Some(it.module(db)),
|
|
|
|
ModuleDef::Variant(it) => Some(it.module(db)),
|
|
|
|
ModuleDef::Const(it) => Some(it.module(db)),
|
|
|
|
ModuleDef::Static(it) => Some(it.module(db)),
|
|
|
|
ModuleDef::Trait(it) => Some(it.module(db)),
|
|
|
|
ModuleDef::TypeAlias(it) => Some(it.module(db)),
|
2022-03-08 22:51:48 +00:00
|
|
|
ModuleDef::Macro(it) => Some(it.module(db)),
|
2021-03-08 19:08:30 +00:00
|
|
|
ModuleDef::BuiltinType(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> {
|
2021-07-20 14:00:44 +00:00
|
|
|
let mut segments = vec![self.name(db)?];
|
2021-03-08 19:08:30 +00:00
|
|
|
for m in self.module(db)?.path_to_root(db) {
|
2021-07-20 14:00:44 +00:00
|
|
|
segments.extend(m.name(db))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
segments.reverse();
|
2021-07-20 14:00:44 +00:00
|
|
|
Some(segments.into_iter().join("::"))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-07-20 15:03:39 +00:00
|
|
|
pub fn canonical_module_path(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
) -> Option<impl Iterator<Item = Module>> {
|
|
|
|
self.module(db).map(|it| it.path_to_root(db).into_iter().rev())
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
|
2021-11-10 21:02:50 +00:00
|
|
|
let name = match self {
|
|
|
|
ModuleDef::Module(it) => it.name(db)?,
|
|
|
|
ModuleDef::Const(it) => it.name(db)?,
|
|
|
|
ModuleDef::Adt(it) => it.name(db),
|
|
|
|
ModuleDef::Trait(it) => it.name(db),
|
|
|
|
ModuleDef::Function(it) => it.name(db),
|
|
|
|
ModuleDef::Variant(it) => it.name(db),
|
|
|
|
ModuleDef::TypeAlias(it) => it.name(db),
|
2021-03-08 19:08:30 +00:00
|
|
|
ModuleDef::Static(it) => it.name(db),
|
2022-03-08 23:41:54 +00:00
|
|
|
ModuleDef::Macro(it) => it.name(db),
|
2021-11-10 21:02:50 +00:00
|
|
|
ModuleDef::BuiltinType(it) => it.name(),
|
|
|
|
};
|
|
|
|
Some(name)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 18:09:03 +00:00
|
|
|
pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> {
|
2021-03-08 19:08:30 +00:00
|
|
|
let id = match self {
|
|
|
|
ModuleDef::Adt(it) => match it {
|
|
|
|
Adt::Struct(it) => it.id.into(),
|
|
|
|
Adt::Enum(it) => it.id.into(),
|
|
|
|
Adt::Union(it) => it.id.into(),
|
|
|
|
},
|
|
|
|
ModuleDef::Trait(it) => it.id.into(),
|
|
|
|
ModuleDef::Function(it) => it.id.into(),
|
|
|
|
ModuleDef::TypeAlias(it) => it.id.into(),
|
|
|
|
ModuleDef::Module(it) => it.id.into(),
|
|
|
|
ModuleDef::Const(it) => it.id.into(),
|
|
|
|
ModuleDef::Static(it) => it.id.into(),
|
2021-06-13 18:09:03 +00:00
|
|
|
_ => return Vec::new(),
|
2021-03-08 19:08:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let module = match self.module(db) {
|
|
|
|
Some(it) => it,
|
2021-06-13 18:09:03 +00:00
|
|
|
None => return Vec::new(),
|
2021-03-08 19:08:30 +00:00
|
|
|
};
|
|
|
|
|
2021-06-13 18:09:03 +00:00
|
|
|
let mut acc = Vec::new();
|
2021-08-27 21:21:21 +00:00
|
|
|
|
|
|
|
match self.as_def_with_body() {
|
|
|
|
Some(def) => {
|
|
|
|
def.diagnostics(db, &mut acc);
|
|
|
|
}
|
|
|
|
None => {
|
2021-11-20 16:19:19 +00:00
|
|
|
for diag in hir_ty::diagnostics::incorrect_case(db, module.id.krate(), id) {
|
2021-08-27 21:21:21 +00:00
|
|
|
acc.push(diag.into())
|
|
|
|
}
|
|
|
|
}
|
2021-06-12 19:05:23 +00:00
|
|
|
}
|
2021-08-27 21:21:21 +00:00
|
|
|
|
2021-06-13 18:09:03 +00:00
|
|
|
acc
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-07-28 13:59:02 +00:00
|
|
|
|
2021-08-27 21:21:21 +00:00
|
|
|
pub fn as_def_with_body(self) -> Option<DefWithBody> {
|
|
|
|
match self {
|
|
|
|
ModuleDef::Function(it) => Some(it.into()),
|
|
|
|
ModuleDef::Const(it) => Some(it.into()),
|
|
|
|
ModuleDef::Static(it) => Some(it.into()),
|
|
|
|
|
|
|
|
ModuleDef::Module(_)
|
|
|
|
| ModuleDef::Adt(_)
|
|
|
|
| ModuleDef::Variant(_)
|
|
|
|
| ModuleDef::Trait(_)
|
|
|
|
| ModuleDef::TypeAlias(_)
|
2022-03-08 22:51:48 +00:00
|
|
|
| ModuleDef::Macro(_)
|
2021-08-27 21:21:21 +00:00
|
|
|
| ModuleDef::BuiltinType(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-28 13:59:02 +00:00
|
|
|
pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
|
|
|
|
Some(match self {
|
|
|
|
ModuleDef::Module(it) => it.attrs(db),
|
|
|
|
ModuleDef::Function(it) => it.attrs(db),
|
|
|
|
ModuleDef::Adt(it) => it.attrs(db),
|
|
|
|
ModuleDef::Variant(it) => it.attrs(db),
|
|
|
|
ModuleDef::Const(it) => it.attrs(db),
|
|
|
|
ModuleDef::Static(it) => it.attrs(db),
|
|
|
|
ModuleDef::Trait(it) => it.attrs(db),
|
|
|
|
ModuleDef::TypeAlias(it) => it.attrs(db),
|
2022-03-08 22:51:48 +00:00
|
|
|
ModuleDef::Macro(it) => it.attrs(db),
|
2021-07-28 13:59:02 +00:00
|
|
|
ModuleDef::BuiltinType(_) => return None,
|
|
|
|
})
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-07-20 14:49:02 +00:00
|
|
|
impl HasVisibility for ModuleDef {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
match *self {
|
|
|
|
ModuleDef::Module(it) => it.visibility(db),
|
|
|
|
ModuleDef::Function(it) => it.visibility(db),
|
|
|
|
ModuleDef::Adt(it) => it.visibility(db),
|
|
|
|
ModuleDef::Const(it) => it.visibility(db),
|
|
|
|
ModuleDef::Static(it) => it.visibility(db),
|
|
|
|
ModuleDef::Trait(it) => it.visibility(db),
|
|
|
|
ModuleDef::TypeAlias(it) => it.visibility(db),
|
|
|
|
ModuleDef::Variant(it) => it.visibility(db),
|
2022-03-08 23:41:54 +00:00
|
|
|
ModuleDef::Macro(it) => it.visibility(db),
|
2021-07-20 14:49:02 +00:00
|
|
|
ModuleDef::BuiltinType(_) => Visibility::Public,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
impl Module {
|
|
|
|
/// Name of this module.
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
|
|
|
|
let def_map = self.id.def_map(db.upcast());
|
|
|
|
let parent = def_map[self.id.local_id].parent?;
|
|
|
|
def_map[parent].children.iter().find_map(|(name, module_id)| {
|
|
|
|
if *module_id == self.id.local_id {
|
|
|
|
Some(name.clone())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the crate this module is part of.
|
|
|
|
pub fn krate(self) -> Crate {
|
|
|
|
Crate { id: self.id.krate() }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Topmost parent of this module. Every module has a `crate_root`, but some
|
|
|
|
/// might be missing `krate`. This can happen if a module's file is not included
|
|
|
|
/// in the module tree of any target in `Cargo.toml`.
|
|
|
|
pub fn crate_root(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
let def_map = db.crate_def_map(self.id.krate());
|
|
|
|
Module { id: def_map.module_id(def_map.root()) }
|
|
|
|
}
|
|
|
|
|
2022-02-02 14:03:46 +00:00
|
|
|
pub fn is_crate_root(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
let def_map = db.crate_def_map(self.id.krate());
|
|
|
|
def_map.root() == self.id.local_id
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
/// Iterates over all child modules.
|
|
|
|
pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> {
|
|
|
|
let def_map = self.id.def_map(db.upcast());
|
|
|
|
let children = def_map[self.id.local_id]
|
|
|
|
.children
|
|
|
|
.iter()
|
|
|
|
.map(|(_, module_id)| Module { id: def_map.module_id(*module_id) })
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
children.into_iter()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Finds a parent module.
|
|
|
|
pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
|
|
|
|
// FIXME: handle block expressions as modules (their parent is in a different DefMap)
|
|
|
|
let def_map = self.id.def_map(db.upcast());
|
|
|
|
let parent_id = def_map[self.id.local_id].parent?;
|
|
|
|
Some(Module { id: def_map.module_id(parent_id) })
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
|
|
|
|
let mut res = vec![self];
|
|
|
|
let mut curr = self;
|
|
|
|
while let Some(next) = curr.parent(db) {
|
|
|
|
res.push(next);
|
|
|
|
curr = next
|
|
|
|
}
|
|
|
|
res
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a `ModuleScope`: a set of items, visible in this module.
|
|
|
|
pub fn scope(
|
|
|
|
self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
visible_from: Option<Module>,
|
|
|
|
) -> Vec<(Name, ScopeDef)> {
|
|
|
|
self.id.def_map(db.upcast())[self.id.local_id]
|
|
|
|
.scope
|
|
|
|
.entries()
|
|
|
|
.filter_map(|(name, def)| {
|
|
|
|
if let Some(m) = visible_from {
|
|
|
|
let filtered =
|
|
|
|
def.filter_visibility(|vis| vis.is_visible_from(db.upcast(), m.id));
|
|
|
|
if filtered.is_none() && !def.is_none() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some((name, filtered))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Some((name, def))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.flat_map(|(name, def)| {
|
|
|
|
ScopeDef::all_items(def).into_iter().map(move |item| (name.clone(), item))
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2021-06-13 19:05:47 +00:00
|
|
|
pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
|
2021-03-08 19:08:30 +00:00
|
|
|
let _p = profile::span("Module::diagnostics").detail(|| {
|
|
|
|
format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string()))
|
|
|
|
});
|
|
|
|
let def_map = self.id.def_map(db.upcast());
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
for diag in def_map.diagnostics() {
|
|
|
|
if diag.in_module != self.id.local_id {
|
|
|
|
// FIXME: This is accidentally quadratic.
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-11 13:34:25 +00:00
|
|
|
emit_def_diagnostic(db, acc, diag);
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
for decl in self.declarations(db) {
|
|
|
|
match decl {
|
2021-06-13 12:27:15 +00:00
|
|
|
ModuleDef::Module(m) => {
|
2021-03-08 19:08:30 +00:00
|
|
|
// Only add diagnostics from inline modules
|
|
|
|
if def_map[m.id.local_id].origin.is_inline() {
|
2021-06-13 19:05:47 +00:00
|
|
|
m.diagnostics(db, acc)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-13 18:09:03 +00:00
|
|
|
_ => acc.extend(decl.diagnostics(db)),
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for impl_def in self.impl_defs(db) {
|
|
|
|
for item in impl_def.items(db) {
|
2021-08-27 21:21:21 +00:00
|
|
|
let def: DefWithBody = match item {
|
|
|
|
AssocItem::Function(it) => it.into(),
|
|
|
|
AssocItem::Const(it) => it.into(),
|
|
|
|
AssocItem::TypeAlias(_) => continue,
|
|
|
|
};
|
|
|
|
|
|
|
|
def.diagnostics(db, acc);
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
|
|
|
|
let def_map = self.id.def_map(db.upcast());
|
2021-09-24 18:41:24 +00:00
|
|
|
let scope = &def_map[self.id.local_id].scope;
|
|
|
|
scope
|
|
|
|
.declarations()
|
|
|
|
.map(ModuleDef::from)
|
|
|
|
.chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id))))
|
|
|
|
.collect()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-18 10:55:53 +00:00
|
|
|
pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
|
|
|
|
let def_map = self.id.def_map(db.upcast());
|
|
|
|
let scope = &def_map[self.id.local_id].scope;
|
|
|
|
scope.legacy_macros().map(|(_, it)| MacroId::from(it).into()).collect()
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
|
|
|
|
let def_map = self.id.def_map(db.upcast());
|
|
|
|
def_map[self.id.local_id].scope.impls().map(Impl::from).collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Finds a path that can be used to refer to the given item from within
|
|
|
|
/// this module, if possible.
|
|
|
|
pub fn find_use_path(self, db: &dyn DefDatabase, item: impl Into<ItemInNs>) -> Option<ModPath> {
|
2021-07-28 15:39:04 +00:00
|
|
|
hir_def::find_path::find_path(db, item.into().into(), self.into())
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Finds a path that can be used to refer to the given item from within
|
|
|
|
/// this module, if possible. This is used for returning import paths for use-statements.
|
|
|
|
pub fn find_use_path_prefixed(
|
|
|
|
self,
|
|
|
|
db: &dyn DefDatabase,
|
|
|
|
item: impl Into<ItemInNs>,
|
|
|
|
prefix_kind: PrefixKind,
|
|
|
|
) -> Option<ModPath> {
|
2021-07-28 15:39:04 +00:00
|
|
|
hir_def::find_path::find_path_prefixed(db, item.into().into(), self.into(), prefix_kind)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-11 13:34:25 +00:00
|
|
|
fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag: &DefDiagnostic) {
|
|
|
|
match &diag.kind {
|
2022-03-11 15:49:41 +00:00
|
|
|
DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
|
2022-01-11 13:34:25 +00:00
|
|
|
let decl = declaration.to_node(db.upcast());
|
|
|
|
acc.push(
|
|
|
|
UnresolvedModule {
|
|
|
|
decl: InFile::new(declaration.file_id, AstPtr::new(&decl)),
|
2022-03-11 15:49:41 +00:00
|
|
|
candidates: candidates.clone(),
|
2022-01-11 13:34:25 +00:00
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
DefDiagnosticKind::UnresolvedExternCrate { ast } => {
|
|
|
|
let item = ast.to_node(db.upcast());
|
|
|
|
acc.push(
|
|
|
|
UnresolvedExternCrate { decl: InFile::new(ast.file_id, AstPtr::new(&item)) }.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
DefDiagnosticKind::UnresolvedImport { id, index } => {
|
|
|
|
let file_id = id.file_id();
|
|
|
|
let item_tree = id.item_tree(db.upcast());
|
|
|
|
let import = &item_tree[id.value];
|
|
|
|
|
|
|
|
let use_tree = import.use_tree_to_ast(db.upcast(), file_id, *index);
|
|
|
|
acc.push(
|
|
|
|
UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
|
|
|
|
let item = ast.to_node(db.upcast());
|
|
|
|
acc.push(
|
|
|
|
InactiveCode {
|
|
|
|
node: ast.with_value(AstPtr::new(&item).into()),
|
|
|
|
cfg: cfg.clone(),
|
|
|
|
opts: opts.clone(),
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
DefDiagnosticKind::UnresolvedProcMacro { ast } => {
|
|
|
|
let mut precise_location = None;
|
2022-02-20 23:02:10 +00:00
|
|
|
let (node, macro_name) = match ast {
|
2022-01-11 13:34:25 +00:00
|
|
|
MacroCallKind::FnLike { ast_id, .. } => {
|
|
|
|
let node = ast_id.to_node(db.upcast());
|
|
|
|
(ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))), None)
|
|
|
|
}
|
2022-02-20 23:02:10 +00:00
|
|
|
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
|
2022-01-11 13:34:25 +00:00
|
|
|
let node = ast_id.to_node(db.upcast());
|
|
|
|
|
|
|
|
// Compute the precise location of the macro name's token in the derive
|
|
|
|
// list.
|
2022-02-20 23:02:10 +00:00
|
|
|
let token = (|| {
|
|
|
|
let derive_attr = node.attrs().nth(*derive_attr_index as usize)?;
|
|
|
|
derive_attr
|
|
|
|
.syntax()
|
|
|
|
.children_with_tokens()
|
|
|
|
.filter_map(|elem| match elem {
|
2022-01-11 13:34:25 +00:00
|
|
|
syntax::NodeOrToken::Token(tok) => Some(tok),
|
2022-02-20 23:02:10 +00:00
|
|
|
_ => None,
|
|
|
|
})
|
|
|
|
.group_by(|t| t.kind() == T![,])
|
|
|
|
.into_iter()
|
2022-02-21 12:43:42 +00:00
|
|
|
.filter(|&(comma, _)| !comma)
|
2022-02-20 23:02:10 +00:00
|
|
|
.nth(*derive_index as usize)
|
|
|
|
.and_then(|(_, mut g)| g.find(|t| t.kind() == T![ident]))
|
|
|
|
})();
|
|
|
|
precise_location = token.as_ref().map(|tok| tok.text_range());
|
2022-01-11 13:34:25 +00:00
|
|
|
(
|
|
|
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
|
2022-02-20 23:02:10 +00:00
|
|
|
token.as_ref().map(ToString::to_string),
|
2022-01-11 13:34:25 +00:00
|
|
|
)
|
|
|
|
}
|
2022-02-20 23:02:10 +00:00
|
|
|
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
|
2022-01-11 13:34:25 +00:00
|
|
|
let node = ast_id.to_node(db.upcast());
|
|
|
|
let attr = node
|
|
|
|
.doc_comments_and_attrs()
|
|
|
|
.nth((*invoc_attr_index) as usize)
|
2022-01-30 21:18:32 +00:00
|
|
|
.and_then(Either::left)
|
2022-01-11 13:34:25 +00:00
|
|
|
.unwrap_or_else(|| panic!("cannot find attribute #{}", invoc_attr_index));
|
|
|
|
(
|
|
|
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
|
2022-02-20 23:02:10 +00:00
|
|
|
attr.path()
|
|
|
|
.and_then(|path| path.segment())
|
|
|
|
.and_then(|seg| seg.name_ref())
|
|
|
|
.as_ref()
|
|
|
|
.map(ToString::to_string),
|
2022-01-11 13:34:25 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
};
|
2022-02-20 23:02:10 +00:00
|
|
|
acc.push(UnresolvedProcMacro { node, precise_location, macro_name }.into());
|
2022-01-11 13:34:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
|
|
|
|
let node = ast.to_node(db.upcast());
|
|
|
|
acc.push(
|
|
|
|
UnresolvedMacroCall {
|
2022-04-27 18:03:57 +00:00
|
|
|
macro_call: InFile::new(node.file_id, SyntaxNodePtr::new(&node.value)),
|
2022-01-11 13:34:25 +00:00
|
|
|
path: path.clone(),
|
2022-04-27 18:03:57 +00:00
|
|
|
is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
|
2022-01-11 13:34:25 +00:00
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
DefDiagnosticKind::MacroError { ast, message } => {
|
|
|
|
let node = match ast {
|
|
|
|
MacroCallKind::FnLike { ast_id, .. } => {
|
|
|
|
let node = ast_id.to_node(db.upcast());
|
|
|
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
|
|
|
|
}
|
|
|
|
MacroCallKind::Derive { ast_id, .. } => {
|
|
|
|
// FIXME: point to the attribute instead, this creates very large diagnostics
|
|
|
|
let node = ast_id.to_node(db.upcast());
|
|
|
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
|
|
|
|
}
|
|
|
|
MacroCallKind::Attr { ast_id, .. } => {
|
|
|
|
// FIXME: point to the attribute instead, this creates very large diagnostics
|
|
|
|
let node = ast_id.to_node(db.upcast());
|
|
|
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
|
|
|
|
}
|
|
|
|
};
|
|
|
|
acc.push(MacroError { node, message: message.clone() }.into());
|
|
|
|
}
|
|
|
|
|
|
|
|
DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
|
|
|
|
let node = ast.to_node(db.upcast());
|
|
|
|
// Must have a name, otherwise we wouldn't emit it.
|
|
|
|
let name = node.name().expect("unimplemented builtin macro with no name");
|
|
|
|
acc.push(
|
|
|
|
UnimplementedBuiltinMacro {
|
|
|
|
node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&name))),
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
DefDiagnosticKind::InvalidDeriveTarget { ast, id } => {
|
|
|
|
let node = ast.to_node(db.upcast());
|
|
|
|
let derive = node.attrs().nth(*id as usize);
|
|
|
|
match derive {
|
|
|
|
Some(derive) => {
|
|
|
|
acc.push(
|
|
|
|
InvalidDeriveTarget {
|
|
|
|
node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
None => stdx::never!("derive diagnostic on item without derive attribute"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DefDiagnosticKind::MalformedDerive { ast, id } => {
|
|
|
|
let node = ast.to_node(db.upcast());
|
|
|
|
let derive = node.attrs().nth(*id as usize);
|
|
|
|
match derive {
|
|
|
|
Some(derive) => {
|
|
|
|
acc.push(
|
|
|
|
MalformedDerive {
|
|
|
|
node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
None => stdx::never!("derive diagnostic on item without derive attribute"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-20 14:11:09 +00:00
|
|
|
impl HasVisibility for Module {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
let def_map = self.id.def_map(db.upcast());
|
|
|
|
let module_data = &def_map[self.id.local_id];
|
|
|
|
module_data.visibility
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Field {
|
|
|
|
pub(crate) parent: VariantDef,
|
|
|
|
pub(crate) id: LocalFieldId,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
|
|
pub enum FieldSource {
|
|
|
|
Named(ast::RecordField),
|
|
|
|
Pos(ast::TupleField),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Field {
|
|
|
|
pub fn name(&self, db: &dyn HirDatabase) -> Name {
|
|
|
|
self.parent.variant_data(db).fields()[self.id].name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the type as in the signature of the struct (i.e., with
|
2021-05-23 16:10:40 +00:00
|
|
|
/// placeholder types for type parameters). Only use this in the context of
|
2021-05-23 21:54:35 +00:00
|
|
|
/// the field definition.
|
2021-04-30 08:52:31 +00:00
|
|
|
pub fn ty(&self, db: &dyn HirDatabase) -> Type {
|
2021-03-08 19:08:30 +00:00
|
|
|
let var_id = self.parent.into();
|
|
|
|
let generic_def_id: GenericDefId = match self.parent {
|
|
|
|
VariantDef::Struct(it) => it.id.into(),
|
|
|
|
VariantDef::Union(it) => it.id.into(),
|
|
|
|
VariantDef::Variant(it) => it.parent.id.into(),
|
|
|
|
};
|
2022-03-09 18:50:24 +00:00
|
|
|
let substs = TyBuilder::placeholder_subst(db, generic_def_id);
|
2021-12-19 16:58:39 +00:00
|
|
|
let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new(db, var_id, ty)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
|
|
|
|
self.parent
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasVisibility for Field {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
let variant_data = self.parent.variant_data(db);
|
|
|
|
let visibility = &variant_data.fields()[self.id].visibility;
|
|
|
|
let parent_id: hir_def::VariantId = self.parent.into();
|
|
|
|
visibility.resolve(db.upcast(), &parent_id.resolver(db.upcast()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Struct {
|
|
|
|
pub(crate) id: StructId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Struct {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
2021-03-09 18:09:02 +00:00
|
|
|
Module { id: self.id.lookup(db.upcast()).container }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
db.struct_data(self.id).name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
|
|
|
db.struct_data(self.id)
|
|
|
|
.variant_data
|
|
|
|
.fields()
|
|
|
|
.iter()
|
|
|
|
.map(|(id, _)| Field { parent: self.into(), id })
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::from_def(db, self.id)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> {
|
|
|
|
db.struct_data(self.id).repr.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
|
|
|
|
self.variant_data(db).kind()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
|
|
|
|
db.struct_data(self.id).variant_data.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-15 16:05:03 +00:00
|
|
|
impl HasVisibility for Struct {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
db.struct_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Union {
|
|
|
|
pub(crate) id: UnionId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Union {
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
db.union_data(self.id).name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
2021-03-09 18:09:02 +00:00
|
|
|
Module { id: self.id.lookup(db.upcast()).container }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::from_def(db, self.id)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
|
|
|
db.union_data(self.id)
|
|
|
|
.variant_data
|
|
|
|
.fields()
|
|
|
|
.iter()
|
|
|
|
.map(|(id, _)| Field { parent: self.into(), id })
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
|
|
|
|
db.union_data(self.id).variant_data.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-15 16:05:03 +00:00
|
|
|
impl HasVisibility for Union {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
db.union_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Enum {
|
|
|
|
pub(crate) id: EnumId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Enum {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
2021-03-09 18:09:02 +00:00
|
|
|
Module { id: self.id.lookup(db.upcast()).container }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
db.enum_data(self.id).name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
|
|
|
|
db.enum_data(self.id).variants.iter().map(|(id, _)| Variant { parent: self, id }).collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::from_def(db, self.id)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-15 16:05:03 +00:00
|
|
|
impl HasVisibility for Enum {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
db.enum_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Variant {
|
|
|
|
pub(crate) parent: Enum,
|
|
|
|
pub(crate) id: LocalEnumVariantId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Variant {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
self.parent.module(db)
|
|
|
|
}
|
2021-05-23 13:45:26 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum {
|
|
|
|
self.parent
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
db.enum_data(self.parent.id).variants[self.id].name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
|
|
|
self.variant_data(db)
|
|
|
|
.fields()
|
|
|
|
.iter()
|
|
|
|
.map(|(id, _)| Field { parent: self.into(), id })
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
|
|
|
|
self.variant_data(db).kind()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
|
|
|
|
db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-20 14:02:16 +00:00
|
|
|
/// Variants inherit visibility from the parent enum.
|
|
|
|
impl HasVisibility for Variant {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
self.parent_enum(db).visibility(db)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
/// A Data Type
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub enum Adt {
|
|
|
|
Struct(Struct),
|
|
|
|
Union(Union),
|
|
|
|
Enum(Enum),
|
|
|
|
}
|
|
|
|
impl_from!(Struct, Union, Enum for Adt);
|
|
|
|
|
|
|
|
impl Adt {
|
|
|
|
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
let subst = db.generic_defaults(self.into());
|
2022-03-09 18:50:24 +00:00
|
|
|
subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
|
|
|
|
GenericArgData::Ty(x) => x.is_unknown(),
|
|
|
|
_ => false,
|
|
|
|
})
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Turns this ADT into a type. Any type parameters of the ADT will be
|
|
|
|
/// turned into unknown types, which is good for e.g. finding the most
|
|
|
|
/// general set of completions, but will not look very nice when printed.
|
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
|
|
|
let id = AdtId::from(self);
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::from_def(db, id)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-20 18:20:16 +00:00
|
|
|
/// Turns this ADT into a type with the given type parameters. This isn't
|
|
|
|
/// the greatest API, FIXME find a better one.
|
|
|
|
pub fn ty_with_args(self, db: &dyn HirDatabase, args: &[Type]) -> Type {
|
|
|
|
let id = AdtId::from(self);
|
|
|
|
let mut it = args.iter().map(|t| t.ty.clone());
|
|
|
|
let ty = TyBuilder::def_ty(db, id.into())
|
|
|
|
.fill(|x| {
|
|
|
|
let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
|
|
|
|
match x {
|
|
|
|
ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
|
2022-03-20 23:08:12 +00:00
|
|
|
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
|
2022-03-20 18:20:16 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.build();
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new(db, id, ty)
|
2022-03-20 18:20:16 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
match self {
|
|
|
|
Adt::Struct(s) => s.module(db),
|
|
|
|
Adt::Union(s) => s.module(db),
|
|
|
|
Adt::Enum(e) => e.module(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
match self {
|
|
|
|
Adt::Struct(s) => s.name(db),
|
|
|
|
Adt::Union(u) => u.name(db),
|
|
|
|
Adt::Enum(e) => e.name(db),
|
|
|
|
}
|
|
|
|
}
|
2022-03-20 18:20:16 +00:00
|
|
|
|
|
|
|
pub fn as_enum(&self) -> Option<Enum> {
|
|
|
|
if let Self::Enum(v) = self {
|
|
|
|
Some(*v)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-06-22 18:22:36 +00:00
|
|
|
impl HasVisibility for Adt {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
match self {
|
|
|
|
Adt::Struct(it) => it.visibility(db),
|
|
|
|
Adt::Union(it) => it.visibility(db),
|
|
|
|
Adt::Enum(it) => it.visibility(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub enum VariantDef {
|
|
|
|
Struct(Struct),
|
|
|
|
Union(Union),
|
|
|
|
Variant(Variant),
|
|
|
|
}
|
|
|
|
impl_from!(Struct, Union, Variant for VariantDef);
|
|
|
|
|
|
|
|
impl VariantDef {
|
|
|
|
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
|
|
|
|
match self {
|
|
|
|
VariantDef::Struct(it) => it.fields(db),
|
|
|
|
VariantDef::Union(it) => it.fields(db),
|
|
|
|
VariantDef::Variant(it) => it.fields(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
match self {
|
|
|
|
VariantDef::Struct(it) => it.module(db),
|
|
|
|
VariantDef::Union(it) => it.module(db),
|
|
|
|
VariantDef::Variant(it) => it.module(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(&self, db: &dyn HirDatabase) -> Name {
|
|
|
|
match self {
|
|
|
|
VariantDef::Struct(s) => s.name(db),
|
|
|
|
VariantDef::Union(u) => u.name(db),
|
|
|
|
VariantDef::Variant(e) => e.name(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
|
|
|
|
match self {
|
|
|
|
VariantDef::Struct(it) => it.variant_data(db),
|
|
|
|
VariantDef::Union(it) => it.variant_data(db),
|
|
|
|
VariantDef::Variant(it) => it.variant_data(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The defs which have a body.
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub enum DefWithBody {
|
|
|
|
Function(Function),
|
|
|
|
Static(Static),
|
|
|
|
Const(Const),
|
|
|
|
}
|
|
|
|
impl_from!(Function, Const, Static for DefWithBody);
|
|
|
|
|
|
|
|
impl DefWithBody {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
match self {
|
|
|
|
DefWithBody::Const(c) => c.module(db),
|
|
|
|
DefWithBody::Function(f) => f.module(db),
|
|
|
|
DefWithBody::Static(s) => s.module(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
|
|
|
|
match self {
|
|
|
|
DefWithBody::Function(f) => Some(f.name(db)),
|
2021-11-10 21:02:50 +00:00
|
|
|
DefWithBody::Static(s) => Some(s.name(db)),
|
2021-03-08 19:08:30 +00:00
|
|
|
DefWithBody::Const(c) => c.name(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-27 21:21:21 +00:00
|
|
|
/// Returns the type this def's body has to evaluate to.
|
|
|
|
pub fn body_type(self, db: &dyn HirDatabase) -> Type {
|
|
|
|
match self {
|
|
|
|
DefWithBody::Function(it) => it.ret_type(db),
|
|
|
|
DefWithBody::Static(it) => it.ty(db),
|
|
|
|
DefWithBody::Const(it) => it.ty(db),
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-05-14 02:36:12 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 19:05:47 +00:00
|
|
|
pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
|
2021-03-08 19:08:30 +00:00
|
|
|
let krate = self.module(db).id.krate();
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
|
2022-01-11 13:34:25 +00:00
|
|
|
let (body, source_map) = db.body_with_source_map(self.into());
|
|
|
|
|
|
|
|
for (_, def_map) in body.blocks(db.upcast()) {
|
|
|
|
for diag in def_map.diagnostics() {
|
|
|
|
emit_def_diagnostic(db, acc, diag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
for diag in source_map.diagnostics() {
|
|
|
|
match diag {
|
2021-06-13 14:29:25 +00:00
|
|
|
BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push(
|
|
|
|
InactiveCode { node: node.clone(), cfg: cfg.clone(), opts: opts.clone() }
|
|
|
|
.into(),
|
|
|
|
),
|
2021-06-13 15:41:04 +00:00
|
|
|
BodyDiagnostic::MacroError { node, message } => acc.push(
|
|
|
|
MacroError {
|
|
|
|
node: node.clone().map(|it| it.into()),
|
|
|
|
message: message.to_string(),
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
),
|
2021-06-13 14:51:44 +00:00
|
|
|
BodyDiagnostic::UnresolvedProcMacro { node } => acc.push(
|
|
|
|
UnresolvedProcMacro {
|
|
|
|
node: node.clone().map(|it| it.into()),
|
|
|
|
precise_location: None,
|
|
|
|
macro_name: None,
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
),
|
2021-06-13 14:06:36 +00:00
|
|
|
BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push(
|
2022-04-27 18:03:57 +00:00
|
|
|
UnresolvedMacroCall {
|
|
|
|
macro_call: node.clone().map(|ast_ptr| ast_ptr.into()),
|
|
|
|
path: path.clone(),
|
|
|
|
is_bang: true,
|
|
|
|
}
|
|
|
|
.into(),
|
2021-06-13 14:06:36 +00:00
|
|
|
),
|
internal: move diagnostics to hir
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
2021-05-23 20:31:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-27 21:21:21 +00:00
|
|
|
let infer = db.infer(self.into());
|
|
|
|
let source_map = Lazy::new(|| db.body_with_source_map(self.into()).1);
|
2021-06-12 14:17:23 +00:00
|
|
|
for d in &infer.diagnostics {
|
|
|
|
match d {
|
|
|
|
hir_ty::InferenceDiagnostic::NoSuchField { expr } => {
|
|
|
|
let field = source_map.field_syntax(*expr);
|
2021-06-13 16:45:16 +00:00
|
|
|
acc.push(NoSuchField { field }.into())
|
2021-06-12 14:17:23 +00:00
|
|
|
}
|
|
|
|
hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
|
2021-06-13 16:51:19 +00:00
|
|
|
let expr = source_map
|
2021-06-12 14:17:23 +00:00
|
|
|
.expr_syntax(*expr)
|
|
|
|
.expect("break outside of loop in synthetic syntax");
|
2021-06-13 16:51:19 +00:00
|
|
|
acc.push(BreakOutsideOfLoop { expr }.into())
|
2021-06-12 14:17:23 +00:00
|
|
|
}
|
2022-03-27 17:10:31 +00:00
|
|
|
hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
|
|
|
|
match source_map.expr_syntax(*call_expr) {
|
|
|
|
Ok(source_ptr) => acc.push(
|
|
|
|
MismatchedArgCount {
|
|
|
|
call_expr: source_ptr,
|
|
|
|
expected: *expected,
|
|
|
|
found: *found,
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
),
|
|
|
|
Err(SyntheticSyntax) => (),
|
|
|
|
}
|
|
|
|
}
|
2021-06-12 14:17:23 +00:00
|
|
|
}
|
|
|
|
}
|
2022-03-20 15:26:48 +00:00
|
|
|
for (expr, mismatch) in infer.expr_type_mismatches() {
|
2022-03-21 16:00:03 +00:00
|
|
|
let expr = match source_map.expr_syntax(expr) {
|
|
|
|
Ok(expr) => expr,
|
|
|
|
Err(SyntheticSyntax) => continue,
|
|
|
|
};
|
2022-03-20 15:26:48 +00:00
|
|
|
acc.push(
|
|
|
|
TypeMismatch {
|
|
|
|
expr,
|
2022-04-15 18:14:35 +00:00
|
|
|
expected: Type::new(db, DefWithBodyId::from(self), mismatch.expected.clone()),
|
|
|
|
actual: Type::new(db, DefWithBodyId::from(self), mismatch.actual.clone()),
|
2022-03-20 15:26:48 +00:00
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
2021-06-12 14:17:23 +00:00
|
|
|
|
2021-08-27 21:21:21 +00:00
|
|
|
for expr in hir_ty::diagnostics::missing_unsafe(db, self.into()) {
|
2021-06-12 14:49:41 +00:00
|
|
|
match source_map.expr_syntax(expr) {
|
2021-06-13 17:00:27 +00:00
|
|
|
Ok(expr) => acc.push(MissingUnsafe { expr }.into()),
|
2021-06-12 14:39:46 +00:00
|
|
|
Err(SyntheticSyntax) => {
|
2021-06-12 16:28:19 +00:00
|
|
|
// FIXME: Here and eslwhere in this file, the `expr` was
|
|
|
|
// desugared, report or assert that this doesn't happen.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-27 21:21:21 +00:00
|
|
|
for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) {
|
2021-06-12 16:28:19 +00:00
|
|
|
match diagnostic {
|
2021-06-13 12:48:54 +00:00
|
|
|
BodyValidationDiagnostic::RecordMissingFields {
|
|
|
|
record,
|
2021-06-12 16:28:19 +00:00
|
|
|
variant,
|
|
|
|
missed_fields,
|
2021-06-13 12:48:54 +00:00
|
|
|
} => {
|
|
|
|
let variant_data = variant.variant_data(db.upcast());
|
|
|
|
let missed_fields = missed_fields
|
|
|
|
.into_iter()
|
|
|
|
.map(|idx| variant_data.fields()[idx].name.clone())
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
match record {
|
|
|
|
Either::Left(record_expr) => match source_map.expr_syntax(record_expr) {
|
|
|
|
Ok(source_ptr) => {
|
|
|
|
let root = source_ptr.file_syntax(db.upcast());
|
|
|
|
if let ast::Expr::RecordExpr(record_expr) =
|
|
|
|
&source_ptr.value.to_node(&root)
|
|
|
|
{
|
2021-10-03 12:51:30 +00:00
|
|
|
if record_expr.record_expr_field_list().is_some() {
|
2021-06-13 12:48:54 +00:00
|
|
|
acc.push(
|
|
|
|
MissingFields {
|
|
|
|
file: source_ptr.file_id,
|
|
|
|
field_list_parent: Either::Left(AstPtr::new(
|
|
|
|
record_expr,
|
|
|
|
)),
|
|
|
|
field_list_parent_path: record_expr
|
|
|
|
.path()
|
|
|
|
.map(|path| AstPtr::new(&path)),
|
|
|
|
missed_fields,
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
)
|
2021-06-13 12:27:15 +00:00
|
|
|
}
|
2021-06-13 12:48:54 +00:00
|
|
|
}
|
2021-06-12 16:28:19 +00:00
|
|
|
}
|
2021-06-13 12:48:54 +00:00
|
|
|
Err(SyntheticSyntax) => (),
|
|
|
|
},
|
|
|
|
Either::Right(record_pat) => match source_map.pat_syntax(record_pat) {
|
|
|
|
Ok(source_ptr) => {
|
|
|
|
if let Some(expr) = source_ptr.value.as_ref().left() {
|
|
|
|
let root = source_ptr.file_syntax(db.upcast());
|
|
|
|
if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
|
2021-10-03 12:51:30 +00:00
|
|
|
if record_pat.record_pat_field_list().is_some() {
|
2021-06-13 12:48:54 +00:00
|
|
|
acc.push(
|
|
|
|
MissingFields {
|
|
|
|
file: source_ptr.file_id,
|
|
|
|
field_list_parent: Either::Right(AstPtr::new(
|
|
|
|
&record_pat,
|
|
|
|
)),
|
|
|
|
field_list_parent_path: record_pat
|
|
|
|
.path()
|
|
|
|
.map(|path| AstPtr::new(&path)),
|
|
|
|
missed_fields,
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2021-06-12 16:28:19 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-13 12:48:54 +00:00
|
|
|
Err(SyntheticSyntax) => (),
|
|
|
|
},
|
2021-06-12 16:28:19 +00:00
|
|
|
}
|
2021-06-13 12:48:54 +00:00
|
|
|
}
|
2021-06-12 16:28:19 +00:00
|
|
|
BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => {
|
|
|
|
if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) {
|
2021-06-13 17:32:54 +00:00
|
|
|
acc.push(
|
|
|
|
ReplaceFilterMapNextWithFindMap {
|
|
|
|
file: next_source_ptr.file_id,
|
|
|
|
next_expr: next_source_ptr.value,
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
2021-06-12 16:28:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
BodyValidationDiagnostic::MissingMatchArms { match_expr } => {
|
|
|
|
match source_map.expr_syntax(match_expr) {
|
|
|
|
Ok(source_ptr) => {
|
|
|
|
let root = source_ptr.file_syntax(db.upcast());
|
|
|
|
if let ast::Expr::MatchExpr(match_expr) =
|
|
|
|
&source_ptr.value.to_node(&root)
|
|
|
|
{
|
2022-01-17 15:52:53 +00:00
|
|
|
if let Some(match_expr) = match_expr.expr() {
|
2021-06-13 18:44:31 +00:00
|
|
|
acc.push(
|
|
|
|
MissingMatchArms {
|
|
|
|
file: source_ptr.file_id,
|
|
|
|
match_expr: AstPtr::new(&match_expr),
|
|
|
|
}
|
|
|
|
.into(),
|
2022-01-17 15:52:53 +00:00
|
|
|
);
|
2021-06-12 16:28:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(SyntheticSyntax) => (),
|
|
|
|
}
|
|
|
|
}
|
2021-06-12 14:39:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-27 21:21:21 +00:00
|
|
|
let def: ModuleDef = match self {
|
|
|
|
DefWithBody::Function(it) => it.into(),
|
|
|
|
DefWithBody::Static(it) => it.into(),
|
|
|
|
DefWithBody::Const(it) => it.into(),
|
|
|
|
};
|
2021-11-20 16:19:19 +00:00
|
|
|
for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
|
2021-06-13 18:09:03 +00:00
|
|
|
acc.push(diag.into())
|
2021-06-12 19:05:23 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-08-27 21:21:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Function {
|
|
|
|
pub(crate) id: FunctionId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Function {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
self.id.lookup(db.upcast()).module(db.upcast()).into()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
db.function_data(self.id).name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get this function's return type
|
|
|
|
pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
|
|
|
|
let resolver = self.id.resolver(db.upcast());
|
2022-04-12 15:40:31 +00:00
|
|
|
let substs = TyBuilder::placeholder_subst(db, self.id);
|
|
|
|
let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
|
|
|
|
let ty = callable_sig.ret().clone();
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new_with_resolver_inner(db, &resolver, ty)
|
2021-08-27 21:21:21 +00:00
|
|
|
}
|
|
|
|
|
2022-04-14 12:44:17 +00:00
|
|
|
pub fn async_ret_type(self, db: &dyn HirDatabase) -> Option<Type> {
|
|
|
|
if !self.is_async(db) {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let resolver = self.id.resolver(db.upcast());
|
|
|
|
let substs = TyBuilder::placeholder_subst(db, self.id);
|
|
|
|
let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
|
|
|
|
let ret_ty = callable_sig.ret().clone();
|
|
|
|
for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
|
|
|
|
if let WhereClause::AliasEq(output_eq) = pred.into_value_and_skipped_binders().0 {
|
|
|
|
return Type::new_with_resolver_inner(db, &resolver, output_eq.ty).into();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
never!("Async fn ret_type should be impl Future");
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2022-05-06 13:44:41 +00:00
|
|
|
pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.function_data(self.id).has_self_param()
|
|
|
|
}
|
|
|
|
|
2021-08-27 21:21:21 +00:00
|
|
|
pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
|
2022-05-06 13:44:41 +00:00
|
|
|
self.has_self_param(db).then(|| SelfParam { func: self.id })
|
2021-08-27 21:21:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> {
|
|
|
|
let environment = db.trait_environment(self.id.into());
|
2022-04-16 14:18:42 +00:00
|
|
|
let substs = TyBuilder::placeholder_subst(db, self.id);
|
|
|
|
let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
|
|
|
|
callable_sig
|
|
|
|
.params()
|
2021-08-27 21:21:21 +00:00
|
|
|
.iter()
|
|
|
|
.enumerate()
|
2022-04-16 14:18:42 +00:00
|
|
|
.map(|(idx, ty)| {
|
|
|
|
let ty = Type { env: environment.clone(), ty: ty.clone() };
|
2021-08-27 21:21:21 +00:00
|
|
|
Param { func: self, ty, idx }
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
|
|
|
|
if self.self_param(db).is_none() {
|
|
|
|
return None;
|
|
|
|
}
|
2022-03-12 15:10:30 +00:00
|
|
|
Some(self.params_without_self(db))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param> {
|
|
|
|
let environment = db.trait_environment(self.id.into());
|
2022-04-16 14:18:42 +00:00
|
|
|
let substs = TyBuilder::placeholder_subst(db, self.id);
|
|
|
|
let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
|
2022-03-12 15:10:30 +00:00
|
|
|
let skip = if db.function_data(self.id).has_self_param() { 1 } else { 0 };
|
2022-04-16 14:18:42 +00:00
|
|
|
callable_sig
|
|
|
|
.params()
|
2022-03-12 15:10:30 +00:00
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.skip(skip)
|
2022-04-16 14:18:42 +00:00
|
|
|
.map(|(idx, ty)| {
|
|
|
|
let ty = Type { env: environment.clone(), ty: ty.clone() };
|
2022-03-12 15:10:30 +00:00
|
|
|
Param { func: self, ty, idx }
|
|
|
|
})
|
|
|
|
.collect()
|
2021-08-27 21:21:21 +00:00
|
|
|
}
|
|
|
|
|
2021-10-14 19:49:46 +00:00
|
|
|
pub fn is_const(self, db: &dyn HirDatabase) -> bool {
|
2022-04-07 16:33:03 +00:00
|
|
|
db.function_data(self.id).has_const_kw()
|
2021-10-14 19:49:46 +00:00
|
|
|
}
|
|
|
|
|
2021-08-27 21:21:21 +00:00
|
|
|
pub fn is_async(self, db: &dyn HirDatabase) -> bool {
|
2022-04-07 16:33:03 +00:00
|
|
|
db.function_data(self.id).has_async_kw()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_unsafe_to_call(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
hir_ty::is_fn_unsafe_to_call(db, self.id)
|
2021-08-27 21:21:21 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
|
|
|
|
/// Whether this function declaration has a definition.
|
|
|
|
///
|
|
|
|
/// This is false in the case of required (not provided) trait methods.
|
|
|
|
pub fn has_body(self, db: &dyn HirDatabase) -> bool {
|
2021-04-03 18:58:42 +00:00
|
|
|
db.function_data(self.id).has_body()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-09 00:13:38 +00:00
|
|
|
pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option<Macro> {
|
|
|
|
let function_data = db.function_data(self.id);
|
|
|
|
let attrs = &function_data.attrs;
|
|
|
|
// FIXME: Store this in FunctionData flags?
|
|
|
|
if !(attrs.is_proc_macro()
|
|
|
|
|| attrs.is_proc_macro_attribute()
|
|
|
|
|| attrs.is_proc_macro_derive())
|
|
|
|
{
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let loc = self.id.lookup(db.upcast());
|
|
|
|
let def_map = db.crate_def_map(loc.krate(db).into());
|
2022-03-09 10:26:06 +00:00
|
|
|
def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() })
|
2022-02-11 21:06:03 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
/// A textual representation of the HIR of this function for debugging purposes.
|
|
|
|
pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
|
|
|
|
let body = db.body(self.id.into());
|
|
|
|
|
|
|
|
let mut result = String::new();
|
|
|
|
format_to!(result, "HIR expressions in the body of `{}`:\n", self.name(db));
|
|
|
|
for (id, expr) in body.exprs.iter() {
|
|
|
|
format_to!(result, "{:?}: {:?}\n", id, expr);
|
|
|
|
}
|
|
|
|
|
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note: logically, this belongs to `hir_ty`, but we are not using it there yet.
|
|
|
|
pub enum Access {
|
|
|
|
Shared,
|
|
|
|
Exclusive,
|
|
|
|
Owned,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<hir_ty::Mutability> for Access {
|
|
|
|
fn from(mutability: hir_ty::Mutability) -> Access {
|
|
|
|
match mutability {
|
|
|
|
hir_ty::Mutability::Not => Access::Shared,
|
|
|
|
hir_ty::Mutability::Mut => Access::Exclusive,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-23 15:50:36 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2021-03-08 19:08:30 +00:00
|
|
|
pub struct Param {
|
2021-03-14 12:03:39 +00:00
|
|
|
func: Function,
|
|
|
|
/// The index in parameter list, including self parameter.
|
|
|
|
idx: usize,
|
2021-03-08 19:08:30 +00:00
|
|
|
ty: Type,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Param {
|
|
|
|
pub fn ty(&self) -> &Type {
|
|
|
|
&self.ty
|
|
|
|
}
|
2021-03-14 12:03:39 +00:00
|
|
|
|
2021-12-20 14:24:37 +00:00
|
|
|
pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
|
|
|
|
db.function_data(self.func.id).params[self.idx].0.clone()
|
|
|
|
}
|
|
|
|
|
2022-04-08 22:55:45 +00:00
|
|
|
pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
|
2021-03-23 15:50:36 +00:00
|
|
|
let parent = DefWithBodyId::FunctionId(self.func.into());
|
|
|
|
let body = db.body(parent);
|
2022-04-08 22:55:45 +00:00
|
|
|
let pat_id = body.params[self.idx];
|
|
|
|
if let Pat::Bind { .. } = &body[pat_id] {
|
|
|
|
Some(Local { parent, pat_id: body.params[self.idx] })
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2021-03-23 15:50:36 +00:00
|
|
|
}
|
|
|
|
|
2021-03-14 12:03:39 +00:00
|
|
|
pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
|
2021-03-23 15:50:36 +00:00
|
|
|
self.source(db).and_then(|p| p.value.pat())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Param>> {
|
|
|
|
let InFile { file_id, value } = self.func.source(db)?;
|
|
|
|
let params = value.param_list()?;
|
2021-03-14 12:03:39 +00:00
|
|
|
if params.self_param().is_some() {
|
2021-03-23 15:50:36 +00:00
|
|
|
params.params().nth(self.idx.checked_sub(1)?)
|
2021-03-14 12:03:39 +00:00
|
|
|
} else {
|
2021-03-23 15:50:36 +00:00
|
|
|
params.params().nth(self.idx)
|
2021-03-14 12:03:39 +00:00
|
|
|
}
|
2021-03-23 15:50:36 +00:00
|
|
|
.map(|value| InFile { file_id, value })
|
2021-03-14 12:03:39 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct SelfParam {
|
|
|
|
func: FunctionId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SelfParam {
|
|
|
|
pub fn access(self, db: &dyn HirDatabase) -> Access {
|
|
|
|
let func_data = db.function_data(self.func);
|
|
|
|
func_data
|
|
|
|
.params
|
|
|
|
.first()
|
2021-12-20 14:24:37 +00:00
|
|
|
.map(|(_, param)| match &**param {
|
2021-03-08 19:08:30 +00:00
|
|
|
TypeRef::Reference(.., mutability) => match mutability {
|
|
|
|
hir_def::type_ref::Mutability::Shared => Access::Shared,
|
|
|
|
hir_def::type_ref::Mutability::Mut => Access::Exclusive,
|
|
|
|
},
|
|
|
|
_ => Access::Owned,
|
|
|
|
})
|
|
|
|
.unwrap_or(Access::Owned)
|
|
|
|
}
|
2021-03-07 00:56:07 +00:00
|
|
|
|
|
|
|
pub fn display(self, db: &dyn HirDatabase) -> &'static str {
|
|
|
|
match self.access(db) {
|
|
|
|
Access::Shared => "&self",
|
|
|
|
Access::Exclusive => "&mut self",
|
|
|
|
Access::Owned => "self",
|
|
|
|
}
|
|
|
|
}
|
2021-03-23 16:39:43 +00:00
|
|
|
|
|
|
|
pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> {
|
|
|
|
let InFile { file_id, value } = Function::from(self.func).source(db)?;
|
|
|
|
value
|
|
|
|
.param_list()
|
|
|
|
.and_then(|params| params.self_param())
|
|
|
|
.map(|value| InFile { file_id, value })
|
|
|
|
}
|
2021-12-21 23:18:39 +00:00
|
|
|
|
|
|
|
pub fn ty(&self, db: &dyn HirDatabase) -> Type {
|
2022-04-16 14:18:42 +00:00
|
|
|
let substs = TyBuilder::placeholder_subst(db, self.func);
|
|
|
|
let callable_sig =
|
|
|
|
db.callable_item_signature(self.func.into()).substitute(Interner, &substs);
|
2021-12-21 23:18:39 +00:00
|
|
|
let environment = db.trait_environment(self.func.into());
|
2022-04-16 14:18:42 +00:00
|
|
|
let ty = callable_sig.params()[0].clone();
|
|
|
|
Type { env: environment, ty }
|
2021-12-21 23:18:39 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl HasVisibility for Function {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
2022-03-17 16:02:58 +00:00
|
|
|
db.function_visibility(self.id)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Const {
|
|
|
|
pub(crate) id: ConstId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Const {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
|
|
|
|
db.const_data(self.id).name.clone()
|
|
|
|
}
|
2021-03-15 16:05:03 +00:00
|
|
|
|
2021-11-17 07:00:24 +00:00
|
|
|
pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
|
2021-11-17 17:53:24 +00:00
|
|
|
self.source(db)?.value.body()
|
2021-11-17 07:00:24 +00:00
|
|
|
}
|
|
|
|
|
2021-08-03 18:47:51 +00:00
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
|
|
|
let data = db.const_data(self.id);
|
|
|
|
let resolver = self.id.resolver(db.upcast());
|
|
|
|
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
|
|
|
|
let ty = ctx.lower_ty(&data.type_ref);
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new_with_resolver_inner(db, &resolver, ty)
|
2021-03-15 16:05:03 +00:00
|
|
|
}
|
2021-12-04 22:21:36 +00:00
|
|
|
|
|
|
|
pub fn eval(self, db: &dyn HirDatabase) -> Result<ComputedExpr, ConstEvalError> {
|
2022-03-20 13:45:28 +00:00
|
|
|
db.const_eval(self.id)
|
2021-12-04 22:21:36 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl HasVisibility for Const {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
2022-03-17 16:02:58 +00:00
|
|
|
db.const_visibility(self.id)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Static {
|
|
|
|
pub(crate) id: StaticId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Static {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
|
|
|
|
}
|
|
|
|
|
2021-11-10 21:02:50 +00:00
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
2021-03-08 19:08:30 +00:00
|
|
|
db.static_data(self.id).name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.static_data(self.id).mutable
|
|
|
|
}
|
2021-08-03 18:47:51 +00:00
|
|
|
|
2021-11-18 04:47:07 +00:00
|
|
|
pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
|
|
|
|
self.source(db)?.value.body()
|
|
|
|
}
|
|
|
|
|
2021-08-03 18:47:51 +00:00
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
|
|
|
let data = db.static_data(self.id);
|
|
|
|
let resolver = self.id.resolver(db.upcast());
|
|
|
|
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
|
|
|
|
let ty = ctx.lower_ty(&data.type_ref);
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new_with_resolver_inner(db, &resolver, ty)
|
2021-08-03 18:47:51 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-03-15 16:05:03 +00:00
|
|
|
impl HasVisibility for Static {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
db.static_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Trait {
|
|
|
|
pub(crate) id: TraitId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Trait {
|
2022-01-06 12:31:36 +00:00
|
|
|
pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
|
|
|
|
db.lang_item(krate.into(), name.to_smol_str())
|
|
|
|
.and_then(LangItemTarget::as_trait)
|
|
|
|
.map(Into::into)
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
2021-03-09 18:09:02 +00:00
|
|
|
Module { id: self.id.lookup(db.upcast()).container }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
db.trait_data(self.id).name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
|
|
|
|
db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
|
2021-03-15 16:05:03 +00:00
|
|
|
db.trait_data(self.id).is_auto
|
|
|
|
}
|
2021-05-23 11:43:23 +00:00
|
|
|
|
|
|
|
pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.trait_data(self.id).is_unsafe
|
|
|
|
}
|
2021-03-15 16:05:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl HasVisibility for Trait {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
db.trait_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct TypeAlias {
|
|
|
|
pub(crate) id: TypeAliasId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TypeAlias {
|
|
|
|
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
let subst = db.generic_defaults(self.id.into());
|
2022-03-09 18:50:24 +00:00
|
|
|
subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
|
|
|
|
GenericArgData::Ty(x) => x.is_unknown(),
|
|
|
|
_ => false,
|
|
|
|
})
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
|
2021-04-01 17:46:43 +00:00
|
|
|
db.type_alias_data(self.id).type_ref.as_deref().cloned()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::from_def(db, self.id)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
db.type_alias_data(self.id).name.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasVisibility for TypeAlias {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
let function_data = db.type_alias_data(self.id);
|
|
|
|
let visibility = &function_data.visibility;
|
|
|
|
visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct BuiltinType {
|
|
|
|
pub(crate) inner: hir_def::builtin_type::BuiltinType,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BuiltinType {
|
2021-09-29 12:04:32 +00:00
|
|
|
pub fn str() -> BuiltinType {
|
|
|
|
BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
|
|
|
|
}
|
|
|
|
|
2022-03-26 20:22:35 +00:00
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
|
|
|
Type::new_for_crate(db.crate_graph().iter().next().unwrap(), TyBuilder::builtin(self.inner))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self) -> Name {
|
|
|
|
self.inner.as_name()
|
|
|
|
}
|
2022-01-04 14:59:00 +00:00
|
|
|
|
|
|
|
pub fn is_int(&self) -> bool {
|
|
|
|
matches!(self.inner, hir_def::builtin_type::BuiltinType::Int(_))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_uint(&self) -> bool {
|
|
|
|
matches!(self.inner, hir_def::builtin_type::BuiltinType::Uint(_))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_float(&self) -> bool {
|
|
|
|
matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_char(&self) -> bool {
|
|
|
|
matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
|
|
|
|
}
|
|
|
|
|
2022-05-03 16:27:25 +00:00
|
|
|
pub fn is_bool(&self) -> bool {
|
|
|
|
matches!(self.inner, hir_def::builtin_type::BuiltinType::Bool)
|
|
|
|
}
|
|
|
|
|
2022-01-04 14:59:00 +00:00
|
|
|
pub fn is_str(&self) -> bool {
|
|
|
|
matches!(self.inner, hir_def::builtin_type::BuiltinType::Str)
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-03-22 14:56:59 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub enum MacroKind {
|
2021-05-29 18:32:57 +00:00
|
|
|
/// `macro_rules!` or Macros 2.0 macro.
|
2021-03-22 14:56:59 +00:00
|
|
|
Declarative,
|
2021-05-29 18:32:57 +00:00
|
|
|
/// A built-in or custom derive.
|
2021-03-22 14:56:59 +00:00
|
|
|
Derive,
|
2021-05-29 18:32:57 +00:00
|
|
|
/// A built-in function-like macro.
|
2021-03-22 14:56:59 +00:00
|
|
|
BuiltIn,
|
2021-05-29 18:32:57 +00:00
|
|
|
/// A procedural attribute macro.
|
|
|
|
Attr,
|
|
|
|
/// A function-like procedural macro.
|
|
|
|
ProcMacro,
|
2021-03-22 14:56:59 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
2022-03-08 22:51:48 +00:00
|
|
|
pub struct Macro {
|
|
|
|
pub(crate) id: MacroId,
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 22:51:48 +00:00
|
|
|
impl Macro {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
Module { id: self.id.module(db.upcast()) }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 23:41:54 +00:00
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
match self.id {
|
|
|
|
MacroId::Macro2Id(id) => db.macro2_data(id).name.clone(),
|
|
|
|
MacroId::MacroRulesId(id) => db.macro_rules_data(id).name.clone(),
|
|
|
|
MacroId::ProcMacroId(id) => db.proc_macro_data(id).name.clone(),
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-18 10:55:53 +00:00
|
|
|
pub fn is_macro_export(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
matches!(self.id, MacroId::MacroRulesId(id) if db.macro_rules_data(id).macro_export)
|
|
|
|
}
|
|
|
|
|
2022-03-08 22:51:48 +00:00
|
|
|
pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
|
|
|
|
match self.id {
|
|
|
|
MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
|
2022-03-09 10:26:06 +00:00
|
|
|
MacroExpander::Declarative => MacroKind::Declarative,
|
|
|
|
MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
|
|
|
|
MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
|
|
|
|
MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
|
2022-03-08 22:51:48 +00:00
|
|
|
},
|
|
|
|
MacroId::MacroRulesId(it) => match it.lookup(db.upcast()).expander {
|
2022-03-09 10:26:06 +00:00
|
|
|
MacroExpander::Declarative => MacroKind::Declarative,
|
|
|
|
MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
|
|
|
|
MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
|
|
|
|
MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
|
2022-03-08 22:51:48 +00:00
|
|
|
},
|
|
|
|
MacroId::ProcMacroId(it) => match it.lookup(db.upcast()).kind {
|
2022-03-09 10:26:06 +00:00
|
|
|
ProcMacroKind::CustomDerive => MacroKind::Derive,
|
|
|
|
ProcMacroKind::FuncLike => MacroKind::ProcMacro,
|
|
|
|
ProcMacroKind::Attr => MacroKind::Attr,
|
2022-03-08 22:51:48 +00:00
|
|
|
},
|
2021-03-22 14:56:59 +00:00
|
|
|
}
|
2021-03-21 19:08:08 +00:00
|
|
|
}
|
2021-06-08 15:31:47 +00:00
|
|
|
|
2022-03-08 22:51:48 +00:00
|
|
|
pub fn is_fn_like(&self, db: &dyn HirDatabase) -> bool {
|
|
|
|
match self.kind(db) {
|
2021-06-08 15:31:47 +00:00
|
|
|
MacroKind::Declarative | MacroKind::BuiltIn | MacroKind::ProcMacro => true,
|
|
|
|
MacroKind::Attr | MacroKind::Derive => false,
|
|
|
|
}
|
|
|
|
}
|
2021-12-05 14:57:28 +00:00
|
|
|
|
2022-03-08 22:51:48 +00:00
|
|
|
pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> bool {
|
|
|
|
match self.id {
|
2022-03-12 14:30:07 +00:00
|
|
|
MacroId::Macro2Id(it) => {
|
|
|
|
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInDerive(_))
|
|
|
|
}
|
|
|
|
MacroId::MacroRulesId(it) => {
|
|
|
|
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInDerive(_))
|
|
|
|
}
|
2022-03-08 22:51:48 +00:00
|
|
|
MacroId::ProcMacroId(_) => false,
|
|
|
|
}
|
2022-02-21 11:57:57 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 22:51:48 +00:00
|
|
|
pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
|
|
|
|
matches!(self.kind(db), MacroKind::Attr)
|
2021-12-05 14:57:28 +00:00
|
|
|
}
|
2022-03-10 20:22:13 +00:00
|
|
|
|
|
|
|
pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
|
|
|
|
matches!(self.kind(db), MacroKind::Derive)
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 23:41:54 +00:00
|
|
|
impl HasVisibility for Macro {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
match self.id {
|
|
|
|
MacroId::Macro2Id(id) => {
|
|
|
|
let data = db.macro2_data(id);
|
|
|
|
let visibility = &data.visibility;
|
|
|
|
visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
|
|
|
|
}
|
|
|
|
MacroId::MacroRulesId(_) => Visibility::Public,
|
|
|
|
MacroId::ProcMacroId(_) => Visibility::Public,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-28 15:39:04 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
|
|
|
pub enum ItemInNs {
|
|
|
|
Types(ModuleDef),
|
|
|
|
Values(ModuleDef),
|
2022-03-08 22:51:48 +00:00
|
|
|
Macros(Macro),
|
2021-07-28 15:39:04 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 22:51:48 +00:00
|
|
|
impl From<Macro> for ItemInNs {
|
|
|
|
fn from(it: Macro) -> Self {
|
2021-07-28 15:39:04 +00:00
|
|
|
Self::Macros(it)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ModuleDef> for ItemInNs {
|
|
|
|
fn from(module_def: ModuleDef) -> Self {
|
|
|
|
match module_def {
|
|
|
|
ModuleDef::Static(_) | ModuleDef::Const(_) | ModuleDef::Function(_) => {
|
|
|
|
ItemInNs::Values(module_def)
|
|
|
|
}
|
|
|
|
_ => ItemInNs::Types(module_def),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ItemInNs {
|
|
|
|
pub fn as_module_def(self) -> Option<ModuleDef> {
|
|
|
|
match self {
|
|
|
|
ItemInNs::Types(id) | ItemInNs::Values(id) => Some(id),
|
|
|
|
ItemInNs::Macros(_) => None,
|
|
|
|
}
|
|
|
|
}
|
2021-07-28 17:22:59 +00:00
|
|
|
|
|
|
|
/// Returns the crate defining this item (or `None` if `self` is built-in).
|
|
|
|
pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
|
|
|
|
match self {
|
|
|
|
ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate()),
|
2022-03-08 22:51:48 +00:00
|
|
|
ItemInNs::Macros(id) => Some(id.module(db).krate()),
|
2021-07-28 17:22:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
|
|
|
|
match self {
|
|
|
|
ItemInNs::Types(it) | ItemInNs::Values(it) => it.attrs(db),
|
|
|
|
ItemInNs::Macros(it) => Some(it.attrs(db)),
|
|
|
|
}
|
|
|
|
}
|
2021-07-28 15:39:04 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
/// Invariant: `inner.as_assoc_item(db).is_some()`
|
|
|
|
/// We do not actively enforce this invariant.
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub enum AssocItem {
|
|
|
|
Function(Function),
|
|
|
|
Const(Const),
|
|
|
|
TypeAlias(TypeAlias),
|
|
|
|
}
|
2021-02-28 22:05:22 +00:00
|
|
|
#[derive(Debug)]
|
2021-03-08 19:08:30 +00:00
|
|
|
pub enum AssocItemContainer {
|
|
|
|
Trait(Trait),
|
|
|
|
Impl(Impl),
|
|
|
|
}
|
|
|
|
pub trait AsAssocItem {
|
|
|
|
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AsAssocItem for Function {
|
|
|
|
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
|
|
|
|
as_assoc_item(db, AssocItem::Function, self.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl AsAssocItem for Const {
|
|
|
|
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
|
|
|
|
as_assoc_item(db, AssocItem::Const, self.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl AsAssocItem for TypeAlias {
|
|
|
|
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
|
|
|
|
as_assoc_item(db, AssocItem::TypeAlias, self.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl AsAssocItem for ModuleDef {
|
|
|
|
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
|
|
|
|
match self {
|
|
|
|
ModuleDef::Function(it) => it.as_assoc_item(db),
|
|
|
|
ModuleDef::Const(it) => it.as_assoc_item(db),
|
|
|
|
ModuleDef::TypeAlias(it) => it.as_assoc_item(db),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn as_assoc_item<ID, DEF, CTOR, AST>(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option<AssocItem>
|
|
|
|
where
|
|
|
|
ID: Lookup<Data = AssocItemLoc<AST>>,
|
|
|
|
DEF: From<ID>,
|
|
|
|
CTOR: FnOnce(DEF) -> AssocItem,
|
|
|
|
AST: ItemTreeNode,
|
|
|
|
{
|
|
|
|
match id.lookup(db.upcast()).container {
|
2021-12-07 16:31:26 +00:00
|
|
|
ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
|
|
|
|
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AssocItem {
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
|
|
|
|
match self {
|
|
|
|
AssocItem::Function(it) => Some(it.name(db)),
|
|
|
|
AssocItem::Const(it) => it.name(db),
|
|
|
|
AssocItem::TypeAlias(it) => Some(it.name(db)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
match self {
|
|
|
|
AssocItem::Function(f) => f.module(db),
|
|
|
|
AssocItem::Const(c) => c.module(db),
|
|
|
|
AssocItem::TypeAlias(t) => t.module(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn container(self, db: &dyn HirDatabase) -> AssocItemContainer {
|
|
|
|
let container = match self {
|
|
|
|
AssocItem::Function(it) => it.id.lookup(db.upcast()).container,
|
|
|
|
AssocItem::Const(it) => it.id.lookup(db.upcast()).container,
|
|
|
|
AssocItem::TypeAlias(it) => it.id.lookup(db.upcast()).container,
|
|
|
|
};
|
|
|
|
match container {
|
2021-12-07 16:31:26 +00:00
|
|
|
ItemContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
|
|
|
|
ItemContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
|
|
|
|
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
|
|
|
|
panic!("invalid AssocItem")
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn containing_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
|
|
|
|
match self.container(db) {
|
|
|
|
AssocItemContainer::Trait(t) => Some(t),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2021-06-11 17:23:59 +00:00
|
|
|
|
|
|
|
pub fn containing_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> {
|
|
|
|
match self.container(db) {
|
|
|
|
AssocItemContainer::Impl(i) => i.trait_(db),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn containing_trait_or_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> {
|
|
|
|
match self.container(db) {
|
|
|
|
AssocItemContainer::Trait(t) => Some(t),
|
|
|
|
AssocItemContainer::Impl(i) => i.trait_(db),
|
|
|
|
}
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl HasVisibility for AssocItem {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
match self {
|
|
|
|
AssocItem::Function(f) => f.visibility(db),
|
|
|
|
AssocItem::Const(c) => c.visibility(db),
|
|
|
|
AssocItem::TypeAlias(t) => t.visibility(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-01 18:40:31 +00:00
|
|
|
impl From<AssocItem> for ModuleDef {
|
|
|
|
fn from(assoc: AssocItem) -> Self {
|
|
|
|
match assoc {
|
|
|
|
AssocItem::Function(it) => ModuleDef::Function(it),
|
|
|
|
AssocItem::Const(it) => ModuleDef::Const(it),
|
|
|
|
AssocItem::TypeAlias(it) => ModuleDef::TypeAlias(it),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
|
|
|
pub enum GenericDef {
|
|
|
|
Function(Function),
|
|
|
|
Adt(Adt),
|
|
|
|
Trait(Trait),
|
|
|
|
TypeAlias(TypeAlias),
|
|
|
|
Impl(Impl),
|
|
|
|
// enum variants cannot have generics themselves, but their parent enums
|
|
|
|
// can, and this makes some code easier to write
|
|
|
|
Variant(Variant),
|
|
|
|
// consts can have type parameters from their parents (i.e. associated consts of traits)
|
|
|
|
Const(Const),
|
|
|
|
}
|
|
|
|
impl_from!(
|
|
|
|
Function,
|
|
|
|
Adt(Struct, Enum, Union),
|
|
|
|
Trait,
|
|
|
|
TypeAlias,
|
|
|
|
Impl,
|
|
|
|
Variant,
|
|
|
|
Const
|
|
|
|
for GenericDef
|
|
|
|
);
|
|
|
|
|
|
|
|
impl GenericDef {
|
|
|
|
pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
|
|
|
|
let generics = db.generic_params(self.into());
|
2022-03-09 18:50:24 +00:00
|
|
|
let ty_params = generics.type_or_consts.iter().map(|(local_id, _)| {
|
2021-12-29 13:35:59 +00:00
|
|
|
let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
|
|
|
|
match toc.split(db) {
|
|
|
|
Either::Left(x) => GenericParam::ConstParam(x),
|
|
|
|
Either::Right(x) => GenericParam::TypeParam(x),
|
|
|
|
}
|
|
|
|
});
|
2021-03-08 19:08:30 +00:00
|
|
|
let lt_params = generics
|
|
|
|
.lifetimes
|
|
|
|
.iter()
|
|
|
|
.map(|(local_id, _)| LifetimeParam {
|
|
|
|
id: LifetimeParamId { parent: self.into(), local_id },
|
|
|
|
})
|
|
|
|
.map(GenericParam::LifetimeParam);
|
2022-03-18 18:56:34 +00:00
|
|
|
lt_params.chain(ty_params).collect()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-12-29 13:35:59 +00:00
|
|
|
pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
|
2021-03-08 19:08:30 +00:00
|
|
|
let generics = db.generic_params(self.into());
|
|
|
|
generics
|
2022-03-09 18:50:24 +00:00
|
|
|
.type_or_consts
|
2021-03-08 19:08:30 +00:00
|
|
|
.iter()
|
2021-12-29 13:35:59 +00:00
|
|
|
.map(|(local_id, _)| TypeOrConstParam {
|
|
|
|
id: TypeOrConstParamId { parent: self.into(), local_id },
|
|
|
|
})
|
2021-03-08 19:08:30 +00:00
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-04 18:49:08 +00:00
|
|
|
/// A single local definition.
|
|
|
|
///
|
|
|
|
/// If the definition of this is part of a "MultiLocal", that is a local that has multiple declarations due to or-patterns
|
|
|
|
/// then this only references a single one of those.
|
|
|
|
/// To retrieve the other locals you should use [`Local::associated_locals`]
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Local {
|
|
|
|
pub(crate) parent: DefWithBodyId,
|
|
|
|
pub(crate) pat_id: PatId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Local {
|
|
|
|
pub fn is_param(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
let src = self.source(db);
|
|
|
|
match src.value {
|
2022-02-26 14:06:11 +00:00
|
|
|
Either::Left(pat) => pat
|
|
|
|
.syntax()
|
|
|
|
.ancestors()
|
|
|
|
.map(|it| it.kind())
|
|
|
|
.take_while(|&kind| ast::Pat::can_cast(kind) || ast::Param::can_cast(kind))
|
|
|
|
.any(ast::Param::can_cast),
|
|
|
|
Either::Right(_) => true,
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-23 16:39:43 +00:00
|
|
|
pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
|
|
|
|
match self.parent {
|
|
|
|
DefWithBodyId::FunctionId(func) if self.is_self(db) => Some(SelfParam { func }),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-26 14:06:11 +00:00
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
2021-03-17 00:27:56 +00:00
|
|
|
let body = db.body(self.parent);
|
2021-03-08 19:08:30 +00:00
|
|
|
match &body[self.pat_id] {
|
2022-02-26 14:06:11 +00:00
|
|
|
Pat::Bind { name, .. } => name.clone(),
|
|
|
|
_ => {
|
|
|
|
stdx::never!("hir::Local is missing a name!");
|
|
|
|
Name::missing()
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_self(self, db: &dyn HirDatabase) -> bool {
|
2022-02-26 14:06:11 +00:00
|
|
|
self.name(db) == name![self]
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
|
2021-03-17 00:27:56 +00:00
|
|
|
let body = db.body(self.parent);
|
2021-03-09 15:33:41 +00:00
|
|
|
matches!(&body[self.pat_id], Pat::Bind { mode: BindingAnnotation::Mutable, .. })
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-07-31 04:42:47 +00:00
|
|
|
pub fn is_ref(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
let body = db.body(self.parent);
|
2021-08-04 06:12:41 +00:00
|
|
|
matches!(
|
|
|
|
&body[self.pat_id],
|
|
|
|
Pat::Bind { mode: BindingAnnotation::Ref | BindingAnnotation::RefMut, .. }
|
|
|
|
)
|
2021-07-31 04:42:47 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
|
|
|
|
self.parent.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
self.parent(db).module(db)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
2021-03-17 00:27:56 +00:00
|
|
|
let def = self.parent;
|
2021-03-08 19:08:30 +00:00
|
|
|
let infer = db.infer(def);
|
|
|
|
let ty = infer[self.pat_id].clone();
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new(db, def, ty)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-04 18:49:08 +00:00
|
|
|
pub fn associated_locals(self, db: &dyn HirDatabase) -> Box<[Local]> {
|
|
|
|
let body = db.body(self.parent);
|
|
|
|
body.ident_patterns_for(&self.pat_id)
|
|
|
|
.iter()
|
|
|
|
.map(|&pat_id| Local { parent: self.parent, pat_id })
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// If this local is part of a multi-local, retrieve the representative local.
|
|
|
|
/// That is the local that references are being resolved to.
|
|
|
|
pub fn representative(self, db: &dyn HirDatabase) -> Local {
|
|
|
|
let body = db.body(self.parent);
|
|
|
|
Local { pat_id: body.pattern_representative(self.pat_id), ..self }
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::IdentPat, ast::SelfParam>> {
|
2021-03-17 00:27:56 +00:00
|
|
|
let (_body, source_map) = db.body_with_source_map(self.parent);
|
2021-03-08 19:08:30 +00:00
|
|
|
let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm...
|
|
|
|
let root = src.file_syntax(db.upcast());
|
2022-03-04 18:49:08 +00:00
|
|
|
src.map(|ast| match ast {
|
|
|
|
Either::Left(it) => Either::Left(it.cast().unwrap().to_node(&root)),
|
|
|
|
Either::Right(it) => Either::Right(it.to_node(&root)),
|
2021-03-08 19:08:30 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-06 13:56:50 +00:00
|
|
|
// FIXME: Wrong name? This is could also be a registered attribute
|
2021-12-03 15:32:14 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
2022-01-06 13:56:50 +00:00
|
|
|
pub struct BuiltinAttr {
|
|
|
|
krate: Option<CrateId>,
|
|
|
|
idx: usize,
|
|
|
|
}
|
2021-12-03 15:32:14 +00:00
|
|
|
|
|
|
|
impl BuiltinAttr {
|
2022-01-06 13:56:50 +00:00
|
|
|
// FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
|
|
|
|
pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
|
|
|
|
if let builtin @ Some(_) = Self::builtin(name) {
|
|
|
|
return builtin;
|
|
|
|
}
|
|
|
|
let idx = db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)?;
|
|
|
|
Some(BuiltinAttr { krate: Some(krate.id), idx })
|
|
|
|
}
|
|
|
|
|
2022-03-31 09:12:08 +00:00
|
|
|
fn builtin(name: &str) -> Option<Self> {
|
2022-01-06 13:56:50 +00:00
|
|
|
hir_def::builtin_attr::INERT_ATTRIBUTES
|
|
|
|
.iter()
|
|
|
|
.position(|tool| tool.name == name)
|
|
|
|
.map(|idx| BuiltinAttr { krate: None, idx })
|
2021-12-03 15:32:14 +00:00
|
|
|
}
|
2021-12-03 16:10:56 +00:00
|
|
|
|
2022-01-06 13:56:50 +00:00
|
|
|
pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
|
2021-12-03 16:10:56 +00:00
|
|
|
// FIXME: Return a `Name` here
|
2022-01-06 13:56:50 +00:00
|
|
|
match self.krate {
|
|
|
|
Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx].clone(),
|
|
|
|
None => SmolStr::new(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].name),
|
|
|
|
}
|
2021-12-03 16:10:56 +00:00
|
|
|
}
|
2021-12-03 19:28:15 +00:00
|
|
|
|
2022-01-06 13:56:50 +00:00
|
|
|
pub fn template(&self, _: &dyn HirDatabase) -> Option<AttributeTemplate> {
|
|
|
|
match self.krate {
|
|
|
|
Some(_) => None,
|
|
|
|
None => Some(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].template),
|
|
|
|
}
|
2021-12-03 19:28:15 +00:00
|
|
|
}
|
2021-12-03 15:32:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
2022-01-06 13:56:50 +00:00
|
|
|
pub struct ToolModule {
|
|
|
|
krate: Option<CrateId>,
|
|
|
|
idx: usize,
|
|
|
|
}
|
2021-12-03 15:32:14 +00:00
|
|
|
|
2021-12-03 16:15:19 +00:00
|
|
|
impl ToolModule {
|
2022-01-06 13:56:50 +00:00
|
|
|
// FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
|
|
|
|
pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
|
|
|
|
if let builtin @ Some(_) = Self::builtin(name) {
|
|
|
|
return builtin;
|
|
|
|
}
|
|
|
|
let idx = db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)?;
|
|
|
|
Some(ToolModule { krate: Some(krate.id), idx })
|
2021-12-03 15:32:14 +00:00
|
|
|
}
|
2021-12-03 16:10:56 +00:00
|
|
|
|
2022-03-31 09:12:08 +00:00
|
|
|
fn builtin(name: &str) -> Option<Self> {
|
2022-01-06 13:56:50 +00:00
|
|
|
hir_def::builtin_attr::TOOL_MODULES
|
|
|
|
.iter()
|
|
|
|
.position(|&tool| tool == name)
|
|
|
|
.map(|idx| ToolModule { krate: None, idx })
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
|
2021-12-03 16:10:56 +00:00
|
|
|
// FIXME: Return a `Name` here
|
2022-01-06 13:56:50 +00:00
|
|
|
match self.krate {
|
|
|
|
Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx].clone(),
|
|
|
|
None => SmolStr::new(hir_def::builtin_attr::TOOL_MODULES[self.idx]),
|
|
|
|
}
|
2021-12-03 16:10:56 +00:00
|
|
|
}
|
2021-12-03 15:32:14 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Label {
|
|
|
|
pub(crate) parent: DefWithBodyId,
|
|
|
|
pub(crate) label_id: LabelId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Label {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
self.parent(db).module(db)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
|
|
|
|
self.parent.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
2021-03-17 00:27:56 +00:00
|
|
|
let body = db.body(self.parent);
|
2021-03-08 19:08:30 +00:00
|
|
|
body[self.label_id].name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn source(self, db: &dyn HirDatabase) -> InFile<ast::Label> {
|
2021-03-17 00:27:56 +00:00
|
|
|
let (_body, source_map) = db.body_with_source_map(self.parent);
|
2021-03-08 19:08:30 +00:00
|
|
|
let src = source_map.label_syntax(self.label_id);
|
|
|
|
let root = src.file_syntax(db.upcast());
|
|
|
|
src.map(|ast| ast.to_node(&root))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub enum GenericParam {
|
|
|
|
TypeParam(TypeParam),
|
|
|
|
ConstParam(ConstParam),
|
2021-12-29 13:35:59 +00:00
|
|
|
LifetimeParam(LifetimeParam),
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-12-29 13:35:59 +00:00
|
|
|
impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);
|
2021-03-08 19:08:30 +00:00
|
|
|
|
|
|
|
impl GenericParam {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
match self {
|
|
|
|
GenericParam::TypeParam(it) => it.module(db),
|
|
|
|
GenericParam::ConstParam(it) => it.module(db),
|
2021-12-29 13:35:59 +00:00
|
|
|
GenericParam::LifetimeParam(it) => it.module(db),
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
match self {
|
|
|
|
GenericParam::TypeParam(it) => it.name(db),
|
|
|
|
GenericParam::ConstParam(it) => it.name(db),
|
2021-12-29 13:35:59 +00:00
|
|
|
GenericParam::LifetimeParam(it) => it.name(db),
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct TypeParam {
|
|
|
|
pub(crate) id: TypeParamId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TypeParam {
|
2021-12-29 13:35:59 +00:00
|
|
|
pub fn merge(self) -> TypeOrConstParam {
|
|
|
|
TypeOrConstParam { id: self.id.into() }
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
2021-12-29 13:35:59 +00:00
|
|
|
self.merge().name(db)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
2021-12-29 13:35:59 +00:00
|
|
|
self.id.parent().module(db.upcast()).into()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-18 18:56:34 +00:00
|
|
|
/// Is this type parameter implicitly introduced (eg. `Self` in a trait or an `impl Trait`
|
|
|
|
/// argument)?
|
|
|
|
pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
let params = db.generic_params(self.id.parent());
|
|
|
|
let data = ¶ms.type_or_consts[self.id.local_id()];
|
|
|
|
match data.type_param().unwrap().provenance {
|
|
|
|
hir_def::generics::TypeParamProvenance::TypeParamList => false,
|
|
|
|
hir_def::generics::TypeParamProvenance::TraitSelf
|
|
|
|
| hir_def::generics::TypeParamProvenance::ArgumentImplTrait => true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
2021-12-29 13:35:59 +00:00
|
|
|
let resolver = self.id.parent().resolver(db.upcast());
|
|
|
|
let ty =
|
|
|
|
TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner);
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new_with_resolver_inner(db, &resolver, ty)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-03 11:43:15 +00:00
|
|
|
/// FIXME: this only lists trait bounds from the item defining the type
|
|
|
|
/// parameter, not additional bounds that might be added e.g. by a method if
|
|
|
|
/// the parameter comes from an impl!
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
|
2021-12-29 13:35:59 +00:00
|
|
|
db.generic_predicates_for_param(self.id.parent(), self.id.into(), None)
|
2021-06-07 11:59:01 +00:00
|
|
|
.iter()
|
2021-03-21 16:40:14 +00:00
|
|
|
.filter_map(|pred| match &pred.skip_binders().skip_binders() {
|
2021-03-20 09:46:36 +00:00
|
|
|
hir_ty::WhereClause::Implemented(trait_ref) => {
|
2021-03-18 20:53:19 +00:00
|
|
|
Some(Trait::from(trait_ref.hir_trait_id()))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
|
2021-12-29 13:35:59 +00:00
|
|
|
let params = db.generic_defaults(self.id.parent());
|
|
|
|
let local_idx = hir_ty::param_idx(db, self.id.into())?;
|
|
|
|
let resolver = self.id.parent().resolver(db.upcast());
|
2021-03-08 19:08:30 +00:00
|
|
|
let ty = params.get(local_idx)?.clone();
|
2022-03-09 18:50:24 +00:00
|
|
|
let subst = TyBuilder::placeholder_subst(db, self.id.parent());
|
2021-12-19 16:58:39 +00:00
|
|
|
let ty = ty.substitute(Interner, &subst_prefix(&subst, local_idx));
|
2022-03-09 18:50:24 +00:00
|
|
|
match ty.data(Interner) {
|
2022-04-15 18:14:35 +00:00
|
|
|
GenericArgData::Ty(x) => Some(Type::new_with_resolver_inner(db, &resolver, x.clone())),
|
2022-03-09 18:50:24 +00:00
|
|
|
_ => None,
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct LifetimeParam {
|
|
|
|
pub(crate) id: LifetimeParamId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LifetimeParam {
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
let params = db.generic_params(self.id.parent);
|
|
|
|
params.lifetimes[self.id.local_id].name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
self.id.parent.module(db.upcast()).into()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
|
|
|
|
self.id.parent.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct ConstParam {
|
|
|
|
pub(crate) id: ConstParamId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ConstParam {
|
2021-12-29 13:35:59 +00:00
|
|
|
pub fn merge(self) -> TypeOrConstParam {
|
|
|
|
TypeOrConstParam { id: self.id.into() }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
let params = db.generic_params(self.id.parent());
|
2022-03-09 18:50:24 +00:00
|
|
|
match params.type_or_consts[self.id.local_id()].name() {
|
2021-12-29 13:35:59 +00:00
|
|
|
Some(x) => x.clone(),
|
|
|
|
None => {
|
|
|
|
never!();
|
|
|
|
Name::missing()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
self.id.parent().module(db.upcast()).into()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
|
|
|
|
self.id.parent().into()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new(db, self.id.parent(), db.const_param_ty(self.id))
|
2021-12-29 13:35:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct TypeOrConstParam {
|
|
|
|
pub(crate) id: TypeOrConstParamId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TypeOrConstParam {
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
let params = db.generic_params(self.id.parent);
|
2022-03-09 18:50:24 +00:00
|
|
|
match params.type_or_consts[self.id.local_id].name() {
|
2021-12-29 13:35:59 +00:00
|
|
|
Some(n) => n.clone(),
|
|
|
|
_ => Name::missing(),
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
self.id.parent.module(db.upcast()).into()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
|
|
|
|
self.id.parent.into()
|
|
|
|
}
|
|
|
|
|
2021-12-29 13:35:59 +00:00
|
|
|
pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
|
|
|
|
let params = db.generic_params(self.id.parent);
|
2022-03-09 18:50:24 +00:00
|
|
|
match ¶ms.type_or_consts[self.id.local_id] {
|
2021-12-29 13:35:59 +00:00
|
|
|
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
|
2022-03-09 18:50:24 +00:00
|
|
|
Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
|
2021-12-29 13:35:59 +00:00
|
|
|
}
|
|
|
|
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
|
2022-03-09 18:50:24 +00:00
|
|
|
Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
|
2021-12-29 13:35:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
2021-12-29 13:35:59 +00:00
|
|
|
match self.split(db) {
|
|
|
|
Either::Left(x) => x.ty(db),
|
|
|
|
Either::Right(x) => x.ty(db),
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Impl {
|
|
|
|
pub(crate) id: ImplId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Impl {
|
|
|
|
pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> {
|
|
|
|
let inherent = db.inherent_impls_in_crate(krate.id);
|
|
|
|
let trait_ = db.trait_impls_in_crate(krate.id);
|
|
|
|
|
|
|
|
inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
|
|
|
|
}
|
2021-03-15 09:11:48 +00:00
|
|
|
|
2022-04-15 18:14:35 +00:00
|
|
|
pub fn all_for_type(db: &dyn HirDatabase, Type { ty, env }: Type) -> Vec<Impl> {
|
|
|
|
let def_crates = match method_resolution::def_crates(db, &ty, env.krate) {
|
2021-03-15 09:11:48 +00:00
|
|
|
Some(def_crates) => def_crates,
|
2021-03-15 13:31:55 +00:00
|
|
|
None => return Vec::new(),
|
2021-03-15 09:11:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let filter = |impl_def: &Impl| {
|
2021-03-29 15:46:33 +00:00
|
|
|
let self_ty = impl_def.self_ty(db);
|
|
|
|
let rref = self_ty.remove_ref();
|
|
|
|
ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
|
2021-03-15 09:11:48 +00:00
|
|
|
};
|
|
|
|
|
2021-04-07 17:35:24 +00:00
|
|
|
let fp = TyFingerprint::for_inherent_impl(&ty);
|
2021-10-03 12:53:01 +00:00
|
|
|
let fp = match fp {
|
|
|
|
Some(fp) => fp,
|
|
|
|
None => return Vec::new(),
|
2021-04-07 17:35:24 +00:00
|
|
|
};
|
|
|
|
|
2021-03-15 09:11:48 +00:00
|
|
|
let mut all = Vec::new();
|
2021-03-15 16:43:46 +00:00
|
|
|
def_crates.iter().for_each(|&id| {
|
2021-04-07 17:35:24 +00:00
|
|
|
all.extend(
|
|
|
|
db.inherent_impls_in_crate(id)
|
|
|
|
.for_self_ty(&ty)
|
2021-06-07 11:59:01 +00:00
|
|
|
.iter()
|
2021-04-07 17:35:24 +00:00
|
|
|
.cloned()
|
|
|
|
.map(Self::from)
|
|
|
|
.filter(filter),
|
|
|
|
)
|
2021-03-15 09:11:48 +00:00
|
|
|
});
|
2021-03-15 16:43:46 +00:00
|
|
|
for id in def_crates
|
|
|
|
.iter()
|
|
|
|
.flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
|
|
|
|
.map(|Crate { id }| id)
|
|
|
|
.chain(def_crates.iter().copied())
|
|
|
|
.unique()
|
|
|
|
{
|
2021-04-07 17:35:24 +00:00
|
|
|
all.extend(
|
|
|
|
db.trait_impls_in_crate(id)
|
|
|
|
.for_self_ty_without_blanket_impls(fp)
|
|
|
|
.map(Self::from)
|
|
|
|
.filter(filter),
|
|
|
|
);
|
2021-03-15 09:11:48 +00:00
|
|
|
}
|
|
|
|
all
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
|
|
|
|
let krate = trait_.module(db).krate();
|
|
|
|
let mut all = Vec::new();
|
2021-03-23 09:49:55 +00:00
|
|
|
for Crate { id } in krate.transitive_reverse_dependencies(db).into_iter() {
|
2021-03-15 09:11:48 +00:00
|
|
|
let impls = db.trait_impls_in_crate(id);
|
|
|
|
all.extend(impls.for_trait(trait_.id).map(Self::from))
|
|
|
|
}
|
|
|
|
all
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: the return type is wrong. This should be a hir version of
|
2021-06-01 23:16:59 +00:00
|
|
|
// `TraitRef` (to account for parameters and qualifiers)
|
|
|
|
pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
|
|
|
|
let trait_ref = db.impl_trait(self.id)?.skip_binders().clone();
|
|
|
|
let id = hir_ty::from_chalk_trait_id(trait_ref.trait_id);
|
|
|
|
Some(Trait { id })
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-03-29 15:46:33 +00:00
|
|
|
pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
|
2021-03-08 19:08:30 +00:00
|
|
|
let resolver = self.id.resolver(db.upcast());
|
2022-04-16 14:18:42 +00:00
|
|
|
let substs = TyBuilder::placeholder_subst(db, self.id);
|
|
|
|
let ty = db.impl_self_ty(self.id).substitute(Interner, &substs);
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new_with_resolver_inner(db, &resolver, ty)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
|
|
|
|
db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.impl_data(self.id).is_negative
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
2021-03-09 18:09:02 +00:00
|
|
|
self.id.lookup(db.upcast()).container.into()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
|
|
|
|
let src = self.source(db)?;
|
2022-02-21 12:34:05 +00:00
|
|
|
src.file_id.is_builtin_derive(db.upcast())
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
|
|
|
pub struct Type {
|
2021-03-21 19:19:07 +00:00
|
|
|
env: Arc<TraitEnvironment>,
|
|
|
|
ty: Ty,
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Type {
|
2022-03-31 09:12:08 +00:00
|
|
|
pub(crate) fn new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver, ty: Ty) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new_with_resolver_inner(db, resolver, ty)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2022-03-26 20:22:35 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub(crate) fn new_with_resolver_inner(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
resolver: &Resolver,
|
|
|
|
ty: Ty,
|
|
|
|
) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
let environment = resolver.generic_def().map_or_else(
|
|
|
|
|| Arc::new(TraitEnvironment::empty(resolver.krate())),
|
|
|
|
|d| db.trait_environment(d),
|
|
|
|
);
|
|
|
|
Type { env: environment, ty }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-26 20:22:35 +00:00
|
|
|
pub(crate) fn new_for_crate(krate: CrateId, ty: Ty) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type { env: Arc::new(TraitEnvironment::empty(krate)), ty }
|
2022-03-26 20:22:35 +00:00
|
|
|
}
|
|
|
|
|
2022-03-20 15:26:48 +00:00
|
|
|
pub fn reference(inner: &Type, m: Mutability) -> Type {
|
2022-03-20 23:08:12 +00:00
|
|
|
inner.derived(
|
|
|
|
TyKind::Ref(
|
|
|
|
if m.is_mut() { hir_ty::Mutability::Mut } else { hir_ty::Mutability::Not },
|
|
|
|
hir_ty::static_lifetime(),
|
|
|
|
inner.ty.clone(),
|
|
|
|
)
|
|
|
|
.intern(Interner),
|
|
|
|
)
|
2022-03-20 15:26:48 +00:00
|
|
|
}
|
|
|
|
|
2022-04-15 18:14:35 +00:00
|
|
|
fn new(db: &dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty) -> Type {
|
2021-03-08 19:08:30 +00:00
|
|
|
let resolver = lexical_env.resolver(db.upcast());
|
2022-04-15 18:14:35 +00:00
|
|
|
let environment = resolver.generic_def().map_or_else(
|
|
|
|
|| Arc::new(TraitEnvironment::empty(resolver.krate())),
|
|
|
|
|d| db.trait_environment(d),
|
|
|
|
);
|
|
|
|
Type { env: environment, ty }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-04-15 18:14:35 +00:00
|
|
|
fn from_def(db: &dyn HirDatabase, def: impl HasResolver + Into<TyDefId>) -> Type {
|
2021-04-03 20:18:02 +00:00
|
|
|
let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build();
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new(db, def, ty)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-10-20 20:35:31 +00:00
|
|
|
pub fn new_slice(ty: Type) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type { env: ty.env, ty: TyBuilder::slice(ty.ty) }
|
2021-09-29 12:04:32 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn is_unit(&self) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
matches!(self.ty.kind(Interner), TyKind::Tuple(0, ..))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-06-23 15:21:47 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn is_bool(&self) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-06-23 15:21:47 +00:00
|
|
|
pub fn is_never(&self) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
matches!(self.ty.kind(Interner), TyKind::Never)
|
2021-06-23 15:21:47 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn is_mutable_reference(&self) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
matches!(self.ty.kind(Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-07-31 04:42:47 +00:00
|
|
|
pub fn is_reference(&self) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
matches!(self.ty.kind(Interner), TyKind::Ref(..))
|
2021-07-31 04:42:47 +00:00
|
|
|
}
|
|
|
|
|
2022-03-20 15:26:48 +00:00
|
|
|
pub fn as_reference(&self) -> Option<(Type, Mutability)> {
|
|
|
|
let (ty, _lt, m) = self.ty.as_reference()?;
|
|
|
|
let m = Mutability::from_mutable(matches!(m, hir_ty::Mutability::Mut));
|
|
|
|
Some((self.derived(ty.clone()), m))
|
|
|
|
}
|
|
|
|
|
2022-02-24 09:50:12 +00:00
|
|
|
pub fn is_slice(&self) -> bool {
|
|
|
|
matches!(self.ty.kind(Interner), TyKind::Slice(..))
|
|
|
|
}
|
|
|
|
|
2021-03-15 19:46:59 +00:00
|
|
|
pub fn is_usize(&self) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
|
2021-03-15 19:46:59 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn remove_ref(&self) -> Option<Type> {
|
2021-12-19 16:58:39 +00:00
|
|
|
match &self.ty.kind(Interner) {
|
2021-03-14 16:40:55 +00:00
|
|
|
TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
|
2021-03-09 15:06:08 +00:00
|
|
|
_ => None,
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-05 20:55:12 +00:00
|
|
|
pub fn strip_references(&self) -> Type {
|
|
|
|
self.derived(self.ty.strip_references().clone())
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn is_unknown(&self) -> bool {
|
2021-03-21 19:19:07 +00:00
|
|
|
self.ty.is_unknown()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks that particular type `ty` implements `std::future::Future`.
|
|
|
|
/// This function is used in `.await` syntax completion.
|
|
|
|
pub fn impls_future(&self, db: &dyn HirDatabase) -> bool {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let std_future_trait = db
|
2022-04-15 18:14:35 +00:00
|
|
|
.lang_item(self.env.krate, SmolStr::new_inline("future_trait"))
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
.and_then(|it| it.as_trait());
|
2021-03-08 19:08:30 +00:00
|
|
|
let std_future_trait = match std_future_trait {
|
|
|
|
Some(it) => it,
|
|
|
|
None => return false,
|
|
|
|
};
|
|
|
|
|
2021-03-21 19:19:07 +00:00
|
|
|
let canonical_ty =
|
2021-12-19 16:58:39 +00:00
|
|
|
Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
method_resolution::implements_trait(&canonical_ty, db, self.env.clone(), std_future_trait)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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
|
|
|
|
/// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
|
|
|
|
pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool {
|
2022-04-15 18:14:35 +00:00
|
|
|
let fnonce_trait = match FnTrait::FnOnce.get_id(db, self.env.krate) {
|
2021-03-08 19:08:30 +00:00
|
|
|
Some(it) => it,
|
|
|
|
None => return false,
|
|
|
|
};
|
|
|
|
|
2021-03-21 19:19:07 +00:00
|
|
|
let canonical_ty =
|
2021-12-19 16:58:39 +00:00
|
|
|
Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
|
2021-03-08 19:08:30 +00:00
|
|
|
method_resolution::implements_trait_unique(
|
|
|
|
&canonical_ty,
|
|
|
|
db,
|
2021-03-21 19:19:07 +00:00
|
|
|
self.env.clone(),
|
2021-03-08 19:08:30 +00:00
|
|
|
fnonce_trait,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
|
2022-03-09 18:50:24 +00:00
|
|
|
let mut it = args.iter().map(|t| t.ty.clone());
|
2021-04-03 19:50:52 +00:00
|
|
|
let trait_ref = TyBuilder::trait_ref(db, trait_.id)
|
|
|
|
.push(self.ty.clone())
|
2022-03-09 18:50:24 +00:00
|
|
|
.fill(|x| {
|
|
|
|
let r = it.next().unwrap();
|
|
|
|
match x {
|
|
|
|
ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
|
|
|
|
ParamKind::Const(ty) => {
|
|
|
|
// FIXME: this code is not covered in tests.
|
|
|
|
unknown_const_as_generic(ty.clone())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2021-04-03 19:50:52 +00:00
|
|
|
.build();
|
2021-03-08 19:08:30 +00:00
|
|
|
|
|
|
|
let goal = Canonical {
|
2021-12-19 16:58:39 +00:00
|
|
|
value: hir_ty::InEnvironment::new(&self.env.env, trait_ref.cast(Interner)),
|
|
|
|
binders: CanonicalVarKinds::empty(Interner),
|
2021-03-08 19:08:30 +00:00
|
|
|
};
|
|
|
|
|
2022-04-15 18:14:35 +00:00
|
|
|
db.trait_solve(self.env.krate, goal).is_some()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn normalize_trait_assoc_type(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
args: &[Type],
|
|
|
|
alias: TypeAlias,
|
|
|
|
) -> Option<Type> {
|
2022-03-09 18:50:24 +00:00
|
|
|
let mut args = args.iter();
|
2021-04-03 19:50:52 +00:00
|
|
|
let projection = TyBuilder::assoc_type_projection(db, alias.id)
|
2021-03-21 19:19:07 +00:00
|
|
|
.push(self.ty.clone())
|
2022-03-09 18:50:24 +00:00
|
|
|
.fill(|x| {
|
|
|
|
// FIXME: this code is not covered in tests.
|
|
|
|
match x {
|
|
|
|
ParamKind::Type => {
|
|
|
|
GenericArgData::Ty(args.next().unwrap().ty.clone()).intern(Interner)
|
|
|
|
}
|
|
|
|
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
|
|
|
|
}
|
|
|
|
})
|
2021-03-08 19:08:30 +00:00
|
|
|
.build();
|
2021-04-07 18:47:04 +00:00
|
|
|
let goal = hir_ty::make_canonical(
|
2021-03-21 19:05:38 +00:00
|
|
|
InEnvironment::new(
|
2021-04-07 18:48:58 +00:00
|
|
|
&self.env.env,
|
2021-03-20 10:23:59 +00:00
|
|
|
AliasEq {
|
2021-04-03 19:50:52 +00:00
|
|
|
alias: AliasTy::Projection(projection),
|
2021-03-19 01:07:15 +00:00
|
|
|
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
|
2021-12-19 16:58:39 +00:00
|
|
|
.intern(Interner),
|
2021-03-20 10:23:59 +00:00
|
|
|
}
|
2021-12-19 16:58:39 +00:00
|
|
|
.cast(Interner),
|
2021-03-08 19:08:30 +00:00
|
|
|
),
|
2021-10-22 06:23:29 +00:00
|
|
|
[TyVariableKind::General].into_iter(),
|
2021-03-21 19:05:38 +00:00
|
|
|
);
|
2021-03-08 19:08:30 +00:00
|
|
|
|
2022-04-15 18:14:35 +00:00
|
|
|
match db.trait_solve(self.env.krate, goal)? {
|
2021-04-06 21:46:32 +00:00
|
|
|
Solution::Unique(s) => s
|
2021-04-01 19:04:02 +00:00
|
|
|
.value
|
2021-04-06 21:46:32 +00:00
|
|
|
.subst
|
2021-12-19 16:58:39 +00:00
|
|
|
.as_slice(Interner)
|
2021-04-01 19:04:02 +00:00
|
|
|
.first()
|
2021-12-19 16:58:39 +00:00
|
|
|
.map(|ty| self.derived(ty.assert_ty_ref(Interner).clone())),
|
2021-03-08 19:08:30 +00:00
|
|
|
Solution::Ambig(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
|
2022-04-15 18:14:35 +00:00
|
|
|
let lang_item = db.lang_item(self.env.krate, SmolStr::new_inline("copy"));
|
2021-03-08 19:08:30 +00:00
|
|
|
let copy_trait = match lang_item {
|
|
|
|
Some(LangItemTarget::TraitId(it)) => it,
|
|
|
|
_ => return false,
|
|
|
|
};
|
|
|
|
self.impls_trait(db, copy_trait.into(), &[])
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
|
2021-03-21 19:19:07 +00:00
|
|
|
let def = self.ty.callable_def(db);
|
2021-03-08 19:08:30 +00:00
|
|
|
|
2021-03-21 19:19:07 +00:00
|
|
|
let sig = self.ty.callable_sig(db)?;
|
2021-03-08 19:08:30 +00:00
|
|
|
Some(Callable { ty: self.clone(), sig, def, is_bound_method: false })
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_closure(&self) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
matches!(&self.ty.kind(Interner), TyKind::Closure { .. })
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_fn(&self) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
matches!(&self.ty.kind(Interner), TyKind::FnDef(..) | TyKind::Function { .. })
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-01-04 14:59:00 +00:00
|
|
|
pub fn is_array(&self) -> bool {
|
|
|
|
matches!(&self.ty.kind(Interner), TyKind::Array(..))
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
let adt_id = match *self.ty.kind(Interner) {
|
2021-06-07 11:59:01 +00:00
|
|
|
TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
|
2021-03-08 19:08:30 +00:00
|
|
|
_ => return false,
|
|
|
|
};
|
|
|
|
|
|
|
|
let adt = adt_id.into();
|
|
|
|
match adt {
|
|
|
|
Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)),
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_raw_ptr(&self) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
matches!(&self.ty.kind(Interner), TyKind::Raw(..))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn contains_unknown(&self) -> bool {
|
2021-03-21 19:19:07 +00:00
|
|
|
return go(&self.ty);
|
2021-03-08 19:08:30 +00:00
|
|
|
|
|
|
|
fn go(ty: &Ty) -> bool {
|
2021-12-19 16:58:39 +00:00
|
|
|
match ty.kind(Interner) {
|
2021-04-05 12:37:11 +00:00
|
|
|
TyKind::Error => true,
|
2021-03-14 16:40:55 +00:00
|
|
|
|
|
|
|
TyKind::Adt(_, substs)
|
|
|
|
| TyKind::AssociatedType(_, substs)
|
|
|
|
| TyKind::Tuple(_, substs)
|
|
|
|
| TyKind::OpaqueType(_, substs)
|
|
|
|
| TyKind::FnDef(_, substs)
|
2021-04-01 19:04:02 +00:00
|
|
|
| TyKind::Closure(_, substs) => {
|
2021-12-19 16:58:39 +00:00
|
|
|
substs.iter(Interner).filter_map(|a| a.ty(Interner)).any(go)
|
2021-04-01 19:04:02 +00:00
|
|
|
}
|
2021-03-14 16:40:55 +00:00
|
|
|
|
2021-05-14 07:59:30 +00:00
|
|
|
TyKind::Array(_ty, len) if len.is_unknown() => true,
|
2021-04-06 09:45:41 +00:00
|
|
|
TyKind::Array(ty, _)
|
2021-04-05 20:08:16 +00:00
|
|
|
| TyKind::Slice(ty)
|
|
|
|
| TyKind::Raw(_, ty)
|
|
|
|
| TyKind::Ref(_, _, ty) => go(ty),
|
2021-03-14 16:40:55 +00:00
|
|
|
|
|
|
|
TyKind::Scalar(_)
|
|
|
|
| TyKind::Str
|
|
|
|
| TyKind::Never
|
|
|
|
| TyKind::Placeholder(_)
|
|
|
|
| TyKind::BoundVar(_)
|
|
|
|
| TyKind::InferenceVar(_, _)
|
|
|
|
| TyKind::Dyn(_)
|
|
|
|
| TyKind::Function(_)
|
|
|
|
| TyKind::Alias(_)
|
2021-04-08 11:51:04 +00:00
|
|
|
| TyKind::Foreign(_)
|
|
|
|
| TyKind::Generator(..)
|
|
|
|
| TyKind::GeneratorWitness(..) => false,
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
|
2021-12-19 16:58:39 +00:00
|
|
|
let (variant_id, substs) = match self.ty.kind(Interner) {
|
2021-08-02 12:59:28 +00:00
|
|
|
TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), substs) => ((*s).into(), substs),
|
|
|
|
TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), substs) => ((*u).into(), substs),
|
2021-03-08 19:08:30 +00:00
|
|
|
_ => return Vec::new(),
|
|
|
|
};
|
|
|
|
|
|
|
|
db.field_types(variant_id)
|
|
|
|
.iter()
|
|
|
|
.map(|(local_id, ty)| {
|
|
|
|
let def = Field { parent: variant_id.into(), id: local_id };
|
2021-12-19 16:58:39 +00:00
|
|
|
let ty = ty.clone().substitute(Interner, substs);
|
2021-03-08 19:08:30 +00:00
|
|
|
(def, self.derived(ty))
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
|
2021-12-19 16:58:39 +00:00
|
|
|
if let TyKind::Tuple(_, substs) = &self.ty.kind(Interner) {
|
2021-04-01 19:04:02 +00:00
|
|
|
substs
|
2021-12-19 16:58:39 +00:00
|
|
|
.iter(Interner)
|
|
|
|
.map(|ty| self.derived(ty.assert_ty_ref(Interner).clone()))
|
2021-04-01 19:04:02 +00:00
|
|
|
.collect()
|
2021-03-08 19:08:30 +00:00
|
|
|
} else {
|
|
|
|
Vec::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a {
|
2021-12-10 18:18:21 +00:00
|
|
|
self.autoderef_(db).map(move |ty| self.derived(ty))
|
|
|
|
}
|
|
|
|
|
2022-03-20 15:19:02 +00:00
|
|
|
fn autoderef_<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Ty> + 'a {
|
2021-03-08 19:08:30 +00:00
|
|
|
// There should be no inference vars in types passed here
|
2021-09-30 14:57:15 +00:00
|
|
|
let canonical = hir_ty::replace_errors_with_variables(&self.ty);
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let environment = self.env.clone();
|
|
|
|
autoderef(db, environment, canonical).map(|canonical| canonical.value)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// This would be nicer if it just returned an iterator, but that runs into
|
|
|
|
// lifetime problems, because we need to borrow temp `CrateImplDefs`.
|
|
|
|
pub fn iterate_assoc_items<T>(
|
2022-01-06 14:42:29 +00:00
|
|
|
&self,
|
2021-03-08 19:08:30 +00:00
|
|
|
db: &dyn HirDatabase,
|
|
|
|
krate: Crate,
|
|
|
|
mut callback: impl FnMut(AssocItem) -> Option<T>,
|
|
|
|
) -> Option<T> {
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
let mut slot = None;
|
|
|
|
self.iterate_assoc_items_dyn(db, krate, &mut |assoc_item_id| {
|
|
|
|
slot = callback(assoc_item_id.into());
|
|
|
|
slot.is_some()
|
|
|
|
});
|
|
|
|
slot
|
|
|
|
}
|
|
|
|
|
|
|
|
fn iterate_assoc_items_dyn(
|
2022-01-06 14:42:29 +00:00
|
|
|
&self,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
db: &dyn HirDatabase,
|
|
|
|
krate: Crate,
|
|
|
|
callback: &mut dyn FnMut(AssocItemId) -> bool,
|
|
|
|
) {
|
|
|
|
let def_crates = match method_resolution::def_crates(db, &self.ty, krate.id) {
|
|
|
|
Some(it) => it,
|
|
|
|
None => return,
|
|
|
|
};
|
|
|
|
for krate in def_crates {
|
2021-03-08 19:08:30 +00:00
|
|
|
let impls = db.inherent_impls_in_crate(krate);
|
|
|
|
|
2021-03-21 19:19:07 +00:00
|
|
|
for impl_def in impls.for_self_ty(&self.ty) {
|
2021-03-08 19:08:30 +00:00
|
|
|
for &item in db.impl_data(*impl_def).items.iter() {
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
if callback(item) {
|
|
|
|
return;
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-30 08:55:59 +00:00
|
|
|
pub fn type_arguments(&self) -> impl Iterator<Item = Type> + '_ {
|
2021-03-08 19:08:30 +00:00
|
|
|
self.ty
|
|
|
|
.strip_references()
|
2021-04-07 15:26:01 +00:00
|
|
|
.as_adt()
|
2021-03-08 19:08:30 +00:00
|
|
|
.into_iter()
|
2021-12-19 16:58:39 +00:00
|
|
|
.flat_map(|(_, substs)| substs.iter(Interner))
|
|
|
|
.filter_map(|arg| arg.ty(Interner).cloned())
|
2021-04-01 19:04:02 +00:00
|
|
|
.map(move |ty| self.derived(ty))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn iterate_method_candidates<T>(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
scope: &SemanticsScope,
|
|
|
|
// FIXME this can be retrieved from `scope`, except autoimport uses this
|
|
|
|
// to specify a different set, so the method needs to be split
|
2021-03-08 19:08:30 +00:00
|
|
|
traits_in_scope: &FxHashSet<TraitId>,
|
2022-02-01 22:29:40 +00:00
|
|
|
with_local_impls: Option<Module>,
|
2021-03-08 19:08:30 +00:00
|
|
|
name: Option<&Name>,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
mut callback: impl FnMut(Function) -> Option<T>,
|
2021-03-08 19:08:30 +00:00
|
|
|
) -> Option<T> {
|
2021-06-10 20:03:16 +00:00
|
|
|
let _p = profile::span("iterate_method_candidates");
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
let mut slot = None;
|
2022-01-06 14:42:29 +00:00
|
|
|
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
self.iterate_method_candidates_dyn(
|
|
|
|
db,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
scope,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
traits_in_scope,
|
2022-02-01 22:29:40 +00:00
|
|
|
with_local_impls,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
name,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
&mut |assoc_item_id| {
|
2021-09-11 17:49:10 +00:00
|
|
|
if let AssocItemId::FunctionId(func) = assoc_item_id {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
if let Some(res) = callback(func.into()) {
|
2021-09-11 17:49:10 +00:00
|
|
|
slot = Some(res);
|
|
|
|
return ControlFlow::Break(());
|
|
|
|
}
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
}
|
2021-09-11 17:49:10 +00:00
|
|
|
ControlFlow::Continue(())
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
},
|
|
|
|
);
|
|
|
|
slot
|
|
|
|
}
|
|
|
|
|
|
|
|
fn iterate_method_candidates_dyn(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
scope: &SemanticsScope,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
traits_in_scope: &FxHashSet<TraitId>,
|
2022-02-01 22:29:40 +00:00
|
|
|
with_local_impls: Option<Module>,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
name: Option<&Name>,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
) {
|
2021-03-08 19:08:30 +00:00
|
|
|
// There should be no inference vars in types passed here
|
2021-09-27 16:44:27 +00:00
|
|
|
let canonical = hir_ty::replace_errors_with_variables(&self.ty);
|
2021-03-08 19:08:30 +00:00
|
|
|
|
2022-03-31 09:12:08 +00:00
|
|
|
let krate = scope.krate();
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let environment = scope.resolver().generic_def().map_or_else(
|
|
|
|
|| Arc::new(TraitEnvironment::empty(krate.id)),
|
|
|
|
|d| db.trait_environment(d),
|
|
|
|
);
|
2021-03-08 19:08:30 +00:00
|
|
|
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
method_resolution::iterate_method_candidates_dyn(
|
2021-03-08 19:08:30 +00:00
|
|
|
&canonical,
|
|
|
|
db,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
environment,
|
2021-03-08 19:08:30 +00:00
|
|
|
traits_in_scope,
|
2022-02-01 22:29:40 +00:00
|
|
|
with_local_impls.and_then(|b| b.id.containing_block()).into(),
|
2021-03-08 19:08:30 +00:00
|
|
|
name,
|
|
|
|
method_resolution::LookupMode::MethodCall,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
&mut |_adj, id| callback(id),
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
);
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn iterate_path_candidates<T>(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
scope: &SemanticsScope,
|
2021-03-08 19:08:30 +00:00
|
|
|
traits_in_scope: &FxHashSet<TraitId>,
|
2022-02-01 22:29:40 +00:00
|
|
|
with_local_impls: Option<Module>,
|
2021-03-08 19:08:30 +00:00
|
|
|
name: Option<&Name>,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
mut callback: impl FnMut(AssocItem) -> Option<T>,
|
2021-03-08 19:08:30 +00:00
|
|
|
) -> Option<T> {
|
2021-06-10 20:03:16 +00:00
|
|
|
let _p = profile::span("iterate_path_candidates");
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
let mut slot = None;
|
|
|
|
self.iterate_path_candidates_dyn(
|
|
|
|
db,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
scope,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
traits_in_scope,
|
2022-02-01 22:29:40 +00:00
|
|
|
with_local_impls,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
name,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
&mut |assoc_item_id| {
|
|
|
|
if let Some(res) = callback(assoc_item_id.into()) {
|
2021-09-11 17:49:10 +00:00
|
|
|
slot = Some(res);
|
|
|
|
return ControlFlow::Break(());
|
|
|
|
}
|
|
|
|
ControlFlow::Continue(())
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
},
|
|
|
|
);
|
|
|
|
slot
|
|
|
|
}
|
|
|
|
|
|
|
|
fn iterate_path_candidates_dyn(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
scope: &SemanticsScope,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
traits_in_scope: &FxHashSet<TraitId>,
|
2022-02-01 22:29:40 +00:00
|
|
|
with_local_impls: Option<Module>,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
name: Option<&Name>,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
) {
|
2021-05-23 10:52:41 +00:00
|
|
|
let canonical = hir_ty::replace_errors_with_variables(&self.ty);
|
2021-03-08 19:08:30 +00:00
|
|
|
|
2022-03-31 09:12:08 +00:00
|
|
|
let krate = scope.krate();
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
let environment = scope.resolver().generic_def().map_or_else(
|
|
|
|
|| Arc::new(TraitEnvironment::empty(krate.id)),
|
|
|
|
|d| db.trait_environment(d),
|
|
|
|
);
|
2021-03-08 19:08:30 +00:00
|
|
|
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
method_resolution::iterate_path_candidates(
|
2021-03-08 19:08:30 +00:00
|
|
|
&canonical,
|
|
|
|
db,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
environment,
|
2021-03-08 19:08:30 +00:00
|
|
|
traits_in_scope,
|
2022-02-01 22:29:40 +00:00
|
|
|
with_local_impls.and_then(|b| b.id.containing_block()).into(),
|
2021-03-08 19:08:30 +00:00
|
|
|
name,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 16:44:03 +00:00
|
|
|
&mut |id| callback(id),
|
internal: improve compile times a bit
before after for cargo llvm-lines -q --lib --release -p ide_ssr | head -n 24
Lines Copies Function name
----- ------ -------------
297146 (100%) 12748 (100%) (TOTAL)
5970 (2.0%) 47 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.6%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
4080 (1.4%) 30 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3933 (1.3%) 69 (0.5%) alloc::raw_vec::RawVec<T,A>::current_memory
3668 (1.2%) 89 (0.7%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
3500 (1.2%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3436 (1.2%) 33 (0.3%) hashbrown::raw::RawTable<T,A>::find
3415 (1.1%) 17 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
3400 (1.1%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
2840 (1.0%) 20 (0.2%) alloc::raw_vec::RawVec<T,A>::allocate_in
2700 (0.9%) 30 (0.2%) core::alloc::layout::Layout::array
2666 (0.9%) 86 (0.7%) core::ptr::metadata::from_raw_parts_mut
2495 (0.8%) 50 (0.4%) core::option::Option<T>::map
2354 (0.8%) 38 (0.3%) alloc::alloc::box_free
2302 (0.8%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2146 (0.7%) 45 (0.4%) core::mem::replace
2070 (0.7%) 69 (0.5%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1979 (0.7%) 16 (0.1%) hashbrown::map::HashMap<K,V,S,A>::insert
1926 (0.6%) 18 (0.1%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1922 (0.6%) 62 (0.5%) core::fmt::ArgumentV1::new
1885 (0.6%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
Lines Copies Function name
----- ------ -------------
261717 (100%) 11666 (100%) (TOTAL)
5239 (2.0%) 42 (0.4%) core::iter::traits::iterator::Iterator::try_fold
4750 (1.8%) 27 (0.2%) hashbrown::raw::RawTable<T,A>::resize
3933 (1.5%) 69 (0.6%) alloc::raw_vec::RawVec<T,A>::current_memory
3536 (1.4%) 26 (0.2%) alloc::raw_vec::RawVec<T,A>::grow_amortized
3500 (1.3%) 50 (0.4%) hashbrown::raw::RawTable<T,A>::drop_elements
3400 (1.3%) 50 (0.4%) <hashbrown::raw::RawIterRange<T> as core::iter::traits::iterator::Iterator>::next
3124 (1.2%) 30 (0.3%) hashbrown::raw::RawTable<T,A>::find
2812 (1.1%) 14 (0.1%) hashbrown::raw::RawTable<T,A>::rehash_in_place
2604 (1.0%) 84 (0.7%) core::ptr::metadata::from_raw_parts_mut
2340 (0.9%) 26 (0.2%) core::alloc::layout::Layout::array
2302 (0.9%) 7 (0.1%) ide_ssr::parsing::RuleBuilder::try_add
2272 (0.9%) 16 (0.1%) alloc::raw_vec::RawVec<T,A>::allocate_in
2201 (0.8%) 35 (0.3%) alloc::alloc::box_free
2104 (0.8%) 44 (0.4%) core::mem::replace
2079 (0.8%) 42 (0.4%) <core::result::Result<T,E> as core::ops::try_trait::Try>::branch
2070 (0.8%) 69 (0.6%) <alloc::raw_vec::RawVec<T,A> as core::ops::drop::Drop>::drop
1926 (0.7%) 18 (0.2%) <core::iter::adapters::zip::Zip<A,B> as core::iter::adapters::zip::ZipImpl<A,B>>::next
1885 (0.7%) 13 (0.1%) alloc::raw_vec::RawVec<T,A>::shrink
1833 (0.7%) 13 (0.1%) hashbrown::raw::RawTable<T,A>::shrink_to
1771 (0.7%) 91 (0.8%) core::ptr::read
1701 (0.6%) 35 (0.3%) core::option::Option<T>::map
2021-08-29 15:49:16 +00:00
|
|
|
);
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_adt(&self) -> Option<Adt> {
|
2021-03-21 19:19:07 +00:00
|
|
|
let (adt, _subst) = self.ty.as_adt()?;
|
2021-03-08 19:08:30 +00:00
|
|
|
Some(adt.into())
|
|
|
|
}
|
|
|
|
|
2021-05-08 20:34:55 +00:00
|
|
|
pub fn as_builtin(&self) -> Option<BuiltinType> {
|
|
|
|
self.ty.as_builtin().map(|inner| BuiltinType { inner })
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn as_dyn_trait(&self) -> Option<Trait> {
|
2021-03-21 19:19:07 +00:00
|
|
|
self.ty.dyn_trait().map(Into::into)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-04-15 20:31:42 +00:00
|
|
|
/// If a type can be represented as `dyn Trait`, returns all traits accessible via this type,
|
|
|
|
/// or an empty iterator otherwise.
|
|
|
|
pub fn applicable_inherent_traits<'a>(
|
|
|
|
&'a self,
|
|
|
|
db: &'a dyn HirDatabase,
|
|
|
|
) -> impl Iterator<Item = Trait> + 'a {
|
2021-06-10 20:03:16 +00:00
|
|
|
let _p = profile::span("applicable_inherent_traits");
|
2021-12-10 18:18:21 +00:00
|
|
|
self.autoderef_(db)
|
|
|
|
.filter_map(|ty| ty.dyn_trait())
|
2021-04-15 20:31:42 +00:00
|
|
|
.flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
|
|
|
|
.map(Trait::from)
|
|
|
|
}
|
|
|
|
|
2021-12-10 18:18:21 +00:00
|
|
|
pub fn env_traits<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Trait> + 'a {
|
|
|
|
let _p = profile::span("env_traits");
|
|
|
|
self.autoderef_(db)
|
2021-12-19 16:58:39 +00:00
|
|
|
.filter(|ty| matches!(ty.kind(Interner), TyKind::Placeholder(_)))
|
2021-12-10 18:18:21 +00:00
|
|
|
.flat_map(|ty| {
|
|
|
|
self.env
|
|
|
|
.traits_in_scope_from_clauses(ty)
|
|
|
|
.flat_map(|t| hir_ty::all_super_traits(db.upcast(), t))
|
|
|
|
})
|
|
|
|
.map(Trait::from)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
|
2021-03-21 19:19:07 +00:00
|
|
|
self.ty.impl_trait_bounds(db).map(|it| {
|
2021-12-10 18:18:21 +00:00
|
|
|
it.into_iter().filter_map(|pred| match pred.skip_binders() {
|
|
|
|
hir_ty::WhereClause::Implemented(trait_ref) => {
|
|
|
|
Some(Trait::from(trait_ref.hir_trait_id()))
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
})
|
2021-03-08 19:08:30 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
|
2021-03-21 19:19:07 +00:00
|
|
|
self.ty.associated_type_parent_trait(db).map(Into::into)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn derived(&self, ty: Ty) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type { env: self.env.clone(), ty }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
|
|
|
|
// TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
|
|
|
|
// We need a different order here.
|
|
|
|
|
|
|
|
fn walk_substs(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
type_: &Type,
|
2021-03-15 20:02:34 +00:00
|
|
|
substs: &Substitution,
|
2021-03-08 19:08:30 +00:00
|
|
|
cb: &mut impl FnMut(Type),
|
|
|
|
) {
|
2021-12-19 16:58:39 +00:00
|
|
|
for ty in substs.iter(Interner).filter_map(|a| a.ty(Interner)) {
|
2021-03-08 19:08:30 +00:00
|
|
|
walk_type(db, &type_.derived(ty.clone()), cb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn walk_bounds(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
type_: &Type,
|
2021-03-21 12:22:22 +00:00
|
|
|
bounds: &[QuantifiedWhereClause],
|
2021-03-08 19:08:30 +00:00
|
|
|
cb: &mut impl FnMut(Type),
|
|
|
|
) {
|
|
|
|
for pred in bounds {
|
2021-06-07 11:59:01 +00:00
|
|
|
if let WhereClause::Implemented(trait_ref) = pred.skip_binders() {
|
|
|
|
cb(type_.clone());
|
|
|
|
// skip the self type. it's likely the type we just got the bounds from
|
2021-12-19 16:58:39 +00:00
|
|
|
for ty in
|
|
|
|
trait_ref.substitution.iter(Interner).skip(1).filter_map(|a| a.ty(Interner))
|
2021-06-07 11:59:01 +00:00
|
|
|
{
|
|
|
|
walk_type(db, &type_.derived(ty.clone()), cb);
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
|
2021-03-21 19:19:07 +00:00
|
|
|
let ty = type_.ty.strip_references();
|
2021-12-19 16:58:39 +00:00
|
|
|
match ty.kind(Interner) {
|
2021-04-07 15:26:01 +00:00
|
|
|
TyKind::Adt(_, substs) => {
|
2021-03-08 19:08:30 +00:00
|
|
|
cb(type_.derived(ty.clone()));
|
2021-06-13 03:54:16 +00:00
|
|
|
walk_substs(db, type_, substs, cb);
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-04-07 15:26:01 +00:00
|
|
|
TyKind::AssociatedType(_, substs) => {
|
2021-06-07 11:59:01 +00:00
|
|
|
if ty.associated_type_parent_trait(db).is_some() {
|
2021-03-08 19:08:30 +00:00
|
|
|
cb(type_.derived(ty.clone()));
|
|
|
|
}
|
2021-06-13 03:54:16 +00:00
|
|
|
walk_substs(db, type_, substs, cb);
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-04-07 15:26:01 +00:00
|
|
|
TyKind::OpaqueType(_, subst) => {
|
2021-03-08 19:08:30 +00:00
|
|
|
if let Some(bounds) = ty.impl_trait_bounds(db) {
|
|
|
|
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
|
|
|
|
}
|
2021-04-07 15:26:01 +00:00
|
|
|
|
|
|
|
walk_substs(db, type_, subst, cb);
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-03-13 13:44:51 +00:00
|
|
|
TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
|
2021-03-08 19:08:30 +00:00
|
|
|
if let Some(bounds) = ty.impl_trait_bounds(db) {
|
|
|
|
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
|
|
|
|
}
|
|
|
|
|
2021-03-14 15:33:27 +00:00
|
|
|
walk_substs(db, type_, &opaque_ty.substitution, cb);
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-03-13 13:44:51 +00:00
|
|
|
TyKind::Placeholder(_) => {
|
2021-03-08 19:08:30 +00:00
|
|
|
if let Some(bounds) = ty.impl_trait_bounds(db) {
|
|
|
|
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
|
|
|
|
}
|
|
|
|
}
|
2021-03-13 13:44:51 +00:00
|
|
|
TyKind::Dyn(bounds) => {
|
2021-03-21 12:22:22 +00:00
|
|
|
walk_bounds(
|
|
|
|
db,
|
|
|
|
&type_.derived(ty.clone()),
|
|
|
|
bounds.bounds.skip_binders().interned(),
|
|
|
|
cb,
|
|
|
|
);
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-04-05 20:08:16 +00:00
|
|
|
TyKind::Ref(_, _, ty)
|
|
|
|
| TyKind::Raw(_, ty)
|
2021-04-06 09:45:41 +00:00
|
|
|
| TyKind::Array(ty, _)
|
2021-04-05 20:08:16 +00:00
|
|
|
| TyKind::Slice(ty) => {
|
2021-03-14 16:40:55 +00:00
|
|
|
walk_type(db, &type_.derived(ty.clone()), cb);
|
|
|
|
}
|
|
|
|
|
2021-04-07 15:26:01 +00:00
|
|
|
TyKind::FnDef(_, substs)
|
|
|
|
| TyKind::Tuple(_, substs)
|
|
|
|
| TyKind::Closure(.., substs) => {
|
2021-06-13 03:54:16 +00:00
|
|
|
walk_substs(db, type_, substs, cb);
|
2021-04-07 15:26:01 +00:00
|
|
|
}
|
|
|
|
TyKind::Function(hir_ty::FnPointer { substitution, .. }) => {
|
|
|
|
walk_substs(db, type_, &substitution.0, cb);
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
walk_type(db, self, &mut cb);
|
|
|
|
}
|
2021-03-16 15:45:46 +00:00
|
|
|
|
2021-05-15 18:18:54 +00:00
|
|
|
pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool {
|
2021-05-23 10:52:41 +00:00
|
|
|
let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone()));
|
2022-03-20 15:19:02 +00:00
|
|
|
hir_ty::could_unify(db, self.env.clone(), &tys)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn could_coerce_to(&self, db: &dyn HirDatabase, to: &Type) -> bool {
|
|
|
|
let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone()));
|
|
|
|
hir_ty::could_coerce(db, self.env.clone(), &tys)
|
2021-03-16 15:45:46 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: closures
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Callable {
|
|
|
|
ty: Type,
|
|
|
|
sig: CallableSig,
|
|
|
|
def: Option<CallableDefId>,
|
|
|
|
pub(crate) is_bound_method: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum CallableKind {
|
|
|
|
Function(Function),
|
|
|
|
TupleStruct(Struct),
|
|
|
|
TupleEnumVariant(Variant),
|
|
|
|
Closure,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Callable {
|
|
|
|
pub fn kind(&self) -> CallableKind {
|
|
|
|
match self.def {
|
|
|
|
Some(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
|
|
|
|
Some(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
|
|
|
|
Some(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
|
|
|
|
None => CallableKind::Closure,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
|
|
|
|
let func = match self.def {
|
|
|
|
Some(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
|
|
|
|
_ => return None,
|
|
|
|
};
|
|
|
|
let src = func.lookup(db.upcast()).source(db.upcast());
|
|
|
|
let param_list = src.value.param_list()?;
|
|
|
|
param_list.self_param()
|
|
|
|
}
|
|
|
|
pub fn n_params(&self) -> usize {
|
|
|
|
self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
|
|
|
|
}
|
|
|
|
pub fn params(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
|
|
|
|
let types = self
|
|
|
|
.sig
|
|
|
|
.params()
|
|
|
|
.iter()
|
|
|
|
.skip(if self.is_bound_method { 1 } else { 0 })
|
|
|
|
.map(|ty| self.ty.derived(ty.clone()));
|
|
|
|
let patterns = match self.def {
|
|
|
|
Some(CallableDefId::FunctionId(func)) => {
|
|
|
|
let src = func.lookup(db.upcast()).source(db.upcast());
|
|
|
|
src.value.param_list().map(|param_list| {
|
|
|
|
param_list
|
|
|
|
.self_param()
|
|
|
|
.map(|it| Some(Either::Left(it)))
|
|
|
|
.filter(|_| !self.is_bound_method)
|
|
|
|
.into_iter()
|
|
|
|
.chain(param_list.params().map(|it| it.pat().map(Either::Right)))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
|
|
|
|
}
|
|
|
|
pub fn return_type(&self) -> Type {
|
|
|
|
self.ty.derived(self.sig.ret().clone())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// For IDE only
|
2021-12-21 13:07:48 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
2021-03-08 19:08:30 +00:00
|
|
|
pub enum ScopeDef {
|
|
|
|
ModuleDef(ModuleDef),
|
|
|
|
GenericParam(GenericParam),
|
|
|
|
ImplSelfType(Impl),
|
|
|
|
AdtSelfType(Adt),
|
|
|
|
Local(Local),
|
2021-03-20 23:59:45 +00:00
|
|
|
Label(Label),
|
2021-03-08 19:08:30 +00:00
|
|
|
Unknown,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ScopeDef {
|
2021-03-25 19:03:20 +00:00
|
|
|
pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
|
2021-03-08 19:08:30 +00:00
|
|
|
let mut items = ArrayVec::new();
|
|
|
|
|
|
|
|
match (def.take_types(), def.take_values()) {
|
|
|
|
(Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())),
|
|
|
|
(None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())),
|
|
|
|
(Some(m1), Some(m2)) => {
|
|
|
|
// Some items, like unit structs and enum variants, are
|
|
|
|
// returned as both a type and a value. Here we want
|
|
|
|
// to de-duplicate them.
|
|
|
|
if m1 != m2 {
|
|
|
|
items.push(ScopeDef::ModuleDef(m1.into()));
|
|
|
|
items.push(ScopeDef::ModuleDef(m2.into()));
|
|
|
|
} else {
|
|
|
|
items.push(ScopeDef::ModuleDef(m1.into()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(None, None) => {}
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(macro_def_id) = def.take_macros() {
|
2022-03-08 22:51:48 +00:00
|
|
|
items.push(ScopeDef::ModuleDef(ModuleDef::Macro(macro_def_id.into())));
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if items.is_empty() {
|
|
|
|
items.push(ScopeDef::Unknown);
|
|
|
|
}
|
|
|
|
|
|
|
|
items
|
|
|
|
}
|
2021-07-28 13:59:02 +00:00
|
|
|
|
|
|
|
pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
|
|
|
|
match self {
|
|
|
|
ScopeDef::ModuleDef(it) => it.attrs(db),
|
|
|
|
ScopeDef::GenericParam(it) => Some(it.attrs(db)),
|
|
|
|
ScopeDef::ImplSelfType(_)
|
|
|
|
| ScopeDef::AdtSelfType(_)
|
|
|
|
| ScopeDef::Local(_)
|
|
|
|
| ScopeDef::Label(_)
|
|
|
|
| ScopeDef::Unknown => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
|
|
|
|
match self {
|
|
|
|
ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate()),
|
|
|
|
ScopeDef::GenericParam(it) => Some(it.module(db).krate()),
|
|
|
|
ScopeDef::ImplSelfType(_) => None,
|
|
|
|
ScopeDef::AdtSelfType(it) => Some(it.module(db).krate()),
|
|
|
|
ScopeDef::Local(it) => Some(it.module(db).krate()),
|
|
|
|
ScopeDef::Label(it) => Some(it.module(db).krate()),
|
|
|
|
ScopeDef::Unknown => None,
|
|
|
|
}
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-02-28 22:05:22 +00:00
|
|
|
impl From<ItemInNs> for ScopeDef {
|
|
|
|
fn from(item: ItemInNs) -> Self {
|
|
|
|
match item {
|
2021-09-03 14:00:50 +00:00
|
|
|
ItemInNs::Types(id) => ScopeDef::ModuleDef(id),
|
|
|
|
ItemInNs::Values(id) => ScopeDef::ModuleDef(id),
|
2022-03-08 22:51:48 +00:00
|
|
|
ItemInNs::Macros(id) => ScopeDef::ModuleDef(ModuleDef::Macro(id)),
|
2021-02-28 22:05:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub trait HasVisibility {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
|
|
|
|
fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
|
|
|
|
let vis = self.visibility(db);
|
|
|
|
vis.is_visible_from(db.upcast(), module.id)
|
|
|
|
}
|
|
|
|
}
|
2021-07-23 13:36:43 +00:00
|
|
|
|
|
|
|
/// Trait for obtaining the defining crate of an item.
|
|
|
|
pub trait HasCrate {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: hir_def::HasModule> HasCrate for T {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db.upcast()).krate().into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasCrate for AssocItem {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasCrate for Field {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.parent_def(db).module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasCrate for Function {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
2021-10-13 13:08:40 +00:00
|
|
|
|
2021-11-16 12:25:23 +00:00
|
|
|
impl HasCrate for Const {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasCrate for TypeAlias {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-13 13:08:40 +00:00
|
|
|
impl HasCrate for Type {
|
|
|
|
fn krate(&self, _db: &dyn HirDatabase) -> Crate {
|
2022-04-15 18:14:35 +00:00
|
|
|
self.env.krate.into()
|
2021-10-13 13:08:40 +00:00
|
|
|
}
|
|
|
|
}
|
2022-03-08 23:41:54 +00:00
|
|
|
|
|
|
|
impl HasCrate for Macro {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|