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 its
|
|
|
|
//! 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
|
|
|
|
2023-12-05 10:35:09 +00:00
|
|
|
#![warn(rust_2018_idioms, unused_lifetimes)]
|
2023-11-13 18:54:53 +00:00
|
|
|
#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
|
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
|
|
|
|
2020-08-25 10:56:01 +00:00
|
|
|
mod attrs;
|
2024-01-26 09:43:25 +00:00
|
|
|
mod from_id;
|
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 db;
|
2024-01-26 09:43:25 +00:00
|
|
|
pub mod diagnostics;
|
2022-01-12 18:56:47 +00:00
|
|
|
pub mod symbols;
|
2023-12-11 15:04:20 +00:00
|
|
|
pub mod term_search;
|
2021-03-08 19:08:30 +00:00
|
|
|
|
2021-03-14 09:36:04 +00:00
|
|
|
mod display;
|
|
|
|
|
2023-11-14 20:54:36 +00:00
|
|
|
use std::{iter, mem::discriminant, ops::ControlFlow};
|
2021-03-08 19:08:30 +00:00
|
|
|
|
|
|
|
use arrayvec::ArrayVec;
|
2024-03-19 15:53:34 +00:00
|
|
|
use base_db::{CrateDisplayName, CrateId, CrateOrigin, FileId};
|
2021-03-08 19:08:30 +00:00
|
|
|
use either::Either;
|
|
|
|
use hir_def::{
|
2021-06-12 14:39:46 +00:00
|
|
|
body::{BodyDiagnostic, SyntheticSyntax},
|
2023-03-13 08:42:24 +00:00
|
|
|
data::adt::VariantData,
|
|
|
|
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
|
|
|
|
hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
|
2024-02-10 10:37:59 +00:00
|
|
|
item_tree::ItemTreeNode,
|
2023-02-13 11:55:14 +00:00
|
|
|
lang_item::LangItemTarget,
|
2023-01-09 18:36:22 +00:00
|
|
|
layout::{self, ReprOptions, TargetDataLayout},
|
2023-07-17 13:49:15 +00:00
|
|
|
nameres::{self, diagnostics::DefDiagnostic},
|
2023-08-07 09:03:15 +00:00
|
|
|
path::ImportAlias,
|
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 _,
|
2023-08-07 09:03:15 +00:00
|
|
|
AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId,
|
2023-11-14 19:02:23 +00:00
|
|
|
EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule,
|
2024-01-15 09:24:14 +00:00
|
|
|
ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander,
|
2024-03-11 12:18:44 +00:00
|
|
|
ModuleId, StaticId, StructId, TraitAliasId, TraitId, TupleId, TypeAliasId, TypeOrConstParamId,
|
|
|
|
TypeParamId, UnionId,
|
2021-03-08 19:08:30 +00:00
|
|
|
};
|
2023-12-18 11:09:54 +00:00
|
|
|
use hir_expand::{attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, MacroCallKind};
|
2021-03-08 19:08:30 +00:00
|
|
|
use hir_ty::{
|
2023-11-14 17:09:28 +00:00
|
|
|
all_super_traits, autoderef, check_orphan_rules,
|
2024-01-30 08:51:28 +00:00
|
|
|
consteval::{try_const_usize, unknown_const_as_generic, ConstExt},
|
2024-02-10 14:36:26 +00:00
|
|
|
db::InternedClosure,
|
2021-06-12 16:28:19 +00:00
|
|
|
diagnostics::BodyValidationDiagnostic,
|
2024-03-08 12:35:44 +00:00
|
|
|
error_lifetime, known_const_to_ast,
|
2023-11-08 06:15:03 +00:00
|
|
|
layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
|
2021-06-12 19:05:23 +00:00
|
|
|
method_resolution::{self, TyFingerprint},
|
2024-02-25 16:57:03 +00:00
|
|
|
mir::{interpret_mir, MutBorrowKind},
|
2021-03-15 20:28:21 +00:00
|
|
|
primitive::UintTy,
|
2021-04-04 18:27:40 +00:00
|
|
|
traits::FnTrait,
|
2023-08-21 09:44:09 +00:00
|
|
|
AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
|
2024-01-30 08:51:28 +00:00
|
|
|
GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
|
|
|
|
TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId,
|
|
|
|
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-03-08 19:08:30 +00:00
|
|
|
use rustc_hash::FxHashSet;
|
2024-03-19 15:53:34 +00:00
|
|
|
use span::Edition;
|
2022-08-23 07:05:52 +00:00
|
|
|
use stdx::{impl_from, never};
|
2021-03-08 19:08:30 +00:00
|
|
|
use syntax::{
|
2023-12-09 20:02:51 +00:00
|
|
|
ast::{self, HasAttrs as _, HasName},
|
2024-01-17 12:43:18 +00:00
|
|
|
format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, T,
|
2021-03-08 19:08:30 +00:00
|
|
|
};
|
2023-06-05 09:04:23 +00:00
|
|
|
use triomphe::Arc;
|
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::{
|
2023-09-18 09:32:37 +00:00
|
|
|
attrs::{resolve_doc_path_on, HasAttrs},
|
2023-11-14 19:02:23 +00:00
|
|
|
diagnostics::*,
|
2019-12-08 11:57:13 +00:00
|
|
|
has_source::HasSource,
|
2023-12-03 19:20:38 +00:00
|
|
|
semantics::{
|
2024-02-28 14:55:33 +00:00
|
|
|
DescendPreference, PathResolution, Semantics, SemanticsImpl, SemanticsScope, TypeInfo,
|
|
|
|
VisibleTraits,
|
2023-12-03 19:20:38 +00:00
|
|
|
},
|
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::{
|
2023-09-18 09:32:37 +00:00
|
|
|
attr::{builtin::AttributeTemplate, AttrSourceMap, Attrs, AttrsWithOwner},
|
2021-12-03 19:28:15 +00:00
|
|
|
data::adt::StructKind,
|
2021-03-08 19:08:30 +00:00
|
|
|
find_path::PrefixKind,
|
|
|
|
import_map,
|
2023-02-13 11:55:14 +00:00
|
|
|
lang_item::LangItem,
|
2022-01-12 18:56:47 +00:00
|
|
|
nameres::{DefMap, ModuleSource},
|
2021-03-08 19:08:30 +00:00
|
|
|
path::{ModPath, PathKind},
|
2023-08-21 09:44:09 +00:00
|
|
|
per_ns::Namespace,
|
2021-03-08 19:08:30 +00:00
|
|
|
type_ref::{Mutability, TypeRef},
|
|
|
|
visibility::Visibility,
|
2023-01-09 18:36:22 +00:00
|
|
|
// FIXME: This is here since some queries take it as input that are used
|
|
|
|
// outside of hir.
|
2024-03-11 12:18:44 +00:00
|
|
|
{AdtId, MacroId, ModuleDefId},
|
2021-03-08 19:08:30 +00:00
|
|
|
},
|
|
|
|
hir_expand::{
|
2023-09-18 09:32:37 +00:00
|
|
|
attrs::{Attr, AttrId},
|
2024-03-04 10:10:06 +00:00
|
|
|
change::ChangeWithProcMacros,
|
2023-12-06 10:53:28 +00:00
|
|
|
hygiene::{marks_rev, SyntaxContextExt},
|
2021-03-08 19:14:52 +00:00
|
|
|
name::{known, Name},
|
2023-12-18 11:09:54 +00:00
|
|
|
proc_macro::ProcMacros,
|
2023-11-25 13:39:55 +00:00
|
|
|
tt, ExpandResult, HirFileId, HirFileIdExt, InFile, InMacroFile, InRealFile, MacroFileId,
|
2023-12-06 13:36:39 +00:00
|
|
|
MacroFileIdExt,
|
2021-03-08 19:08:30 +00:00
|
|
|
},
|
2023-01-09 18:36:22 +00:00
|
|
|
hir_ty::{
|
2024-01-30 08:51:28 +00:00
|
|
|
consteval::ConstEvalError,
|
2023-02-13 11:55:14 +00:00
|
|
|
display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
|
2023-01-09 18:36:22 +00:00
|
|
|
layout::LayoutError,
|
2024-01-30 08:51:28 +00:00
|
|
|
mir::{MirEvalError, MirLowerError},
|
2023-01-09 18:36:22 +00:00
|
|
|
PointerCast, Safety,
|
|
|
|
},
|
2023-12-01 12:46:46 +00:00
|
|
|
// FIXME: Properly encapsulate mir
|
|
|
|
hir_ty::{mir, Interner as ChalkTyInterner},
|
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,
|
2023-11-25 16:10:18 +00:00
|
|
|
hir_expand::{
|
|
|
|
name::AsName,
|
2023-12-18 12:30:41 +00:00
|
|
|
span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef},
|
2023-11-25 16:10:18 +00:00
|
|
|
},
|
2021-03-08 19:14:52 +00:00
|
|
|
};
|
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
|
|
|
}
|
|
|
|
|
2023-08-07 09:03:15 +00:00
|
|
|
pub fn root_module(self) -> Module {
|
|
|
|
Module { id: CrateRootModuleId::from(self.id).into() }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
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>> {
|
2024-04-17 00:07:56 +00:00
|
|
|
let _p = tracing::span!(tracing::Level::INFO, "query_external_importables").entered();
|
2024-01-22 00:00:13 +00:00
|
|
|
import_map::search_dependencies(db, self.into(), &query).into_iter().map(|item| {
|
2021-07-28 15:39:04 +00:00
|
|
|
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 = "...")]
|
2023-08-07 09:03:15 +00:00
|
|
|
let attrs = db.attrs(AttrDefId::ModuleId(self.root_module().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
|
|
|
|
2024-04-06 11:55:10 +00:00
|
|
|
pub fn cfg(&self, db: &dyn HirDatabase) -> Arc<CfgOptions> {
|
2021-05-07 20:35:43 +00:00
|
|
|
db.crate_graph()[self.id].cfg_options.clone()
|
|
|
|
}
|
2021-05-30 13:52:19 +00:00
|
|
|
|
2024-04-06 11:55:10 +00:00
|
|
|
pub fn potential_cfg(&self, db: &dyn HirDatabase) -> Arc<CfgOptions> {
|
2021-05-31 19:45:01 +00:00
|
|
|
let data = &db.crate_graph()[self.id];
|
|
|
|
data.potential_cfg_options.clone().unwrap_or_else(|| data.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),
|
2023-03-13 08:42:24 +00:00
|
|
|
TraitAlias(TraitAlias),
|
2021-03-08 19:08:30 +00:00
|
|
|
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,
|
2023-03-13 08:42:24 +00:00
|
|
|
TraitAlias,
|
2021-03-08 19:08:30 +00:00
|
|
|
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)),
|
2023-03-13 08:42:24 +00:00
|
|
|
ModuleDef::TraitAlias(it) => Some(it.module(db)),
|
2021-03-08 19:08:30 +00:00
|
|
|
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.iter().map(|it| it.display(db.upcast())).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),
|
2023-03-13 08:42:24 +00:00
|
|
|
ModuleDef::TraitAlias(it) => it.name(db),
|
2021-11-10 21:02:50 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2024-03-05 10:41:46 +00:00
|
|
|
pub fn diagnostics(self, db: &dyn HirDatabase, style_lints: bool) -> 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(),
|
2023-03-13 08:42:24 +00:00
|
|
|
ModuleDef::TraitAlias(it) => it.id.into(),
|
2021-03-08 19:08:30 +00:00
|
|
|
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(),
|
2024-01-15 09:24:14 +00:00
|
|
|
ModuleDef::Variant(it) => it.id.into(),
|
2022-10-11 07:37:35 +00:00
|
|
|
ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => 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) => {
|
2024-03-05 10:41:46 +00:00
|
|
|
def.diagnostics(db, &mut acc, style_lints);
|
2021-08-27 21:21:21 +00:00
|
|
|
}
|
|
|
|
None => {
|
2023-07-24 09:21:34 +00:00
|
|
|
for diag in hir_ty::diagnostics::incorrect_case(db, 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()),
|
2022-10-11 07:37:35 +00:00
|
|
|
ModuleDef::Variant(it) => Some(it.into()),
|
2021-08-27 21:21:21 +00:00
|
|
|
|
|
|
|
ModuleDef::Module(_)
|
|
|
|
| ModuleDef::Adt(_)
|
|
|
|
| ModuleDef::Trait(_)
|
2023-03-13 08:42:24 +00:00
|
|
|
| ModuleDef::TraitAlias(_)
|
2021-08-27 21:21:21 +00:00
|
|
|
| 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),
|
2023-03-13 08:42:24 +00:00
|
|
|
ModuleDef::TraitAlias(it) => it.attrs(db),
|
2021-07-28 13:59:02 +00:00
|
|
|
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),
|
2023-03-13 08:42:24 +00:00
|
|
|
ModuleDef::TraitAlias(it) => it.visibility(db),
|
2021-07-20 14:49:02 +00:00
|
|
|
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> {
|
2023-11-08 06:15:03 +00:00
|
|
|
self.id.name(db.upcast())
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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());
|
2023-06-19 06:14:04 +00:00
|
|
|
Module { id: def_map.crate_root().into() }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-02 14:03:46 +00:00
|
|
|
pub fn is_crate_root(self) -> bool {
|
|
|
|
DefMap::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
|
2023-02-13 11:55:14 +00:00
|
|
|
.values()
|
|
|
|
.map(|module_id| Module { id: def_map.module_id(*module_id) })
|
2021-03-08 19:08:30 +00:00
|
|
|
.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) })
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
/// Finds nearest non-block ancestor `Module` (`self` included).
|
|
|
|
pub fn nearest_non_block_module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
let mut id = self.id;
|
2023-07-17 13:49:15 +00:00
|
|
|
while id.is_block_module() {
|
|
|
|
id = id.containing_module(db.upcast()).expect("block without parent module");
|
2023-03-13 08:42:24 +00:00
|
|
|
}
|
2023-07-17 13:49:15 +00:00
|
|
|
Module { id }
|
2023-03-13 08:42:24 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2022-06-24 11:03:13 +00:00
|
|
|
/// Fills `acc` with the module's diagnostics.
|
2024-03-05 10:41:46 +00:00
|
|
|
pub fn diagnostics(
|
|
|
|
self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
acc: &mut Vec<AnyDiagnostic>,
|
|
|
|
style_lints: bool,
|
|
|
|
) {
|
2024-04-17 00:07:56 +00:00
|
|
|
let _p = tracing::span!(tracing::Level::INFO, "Module::diagnostics", name = ?self.name(db))
|
|
|
|
.entered();
|
2021-03-08 19:08:30 +00:00
|
|
|
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
|
|
|
}
|
2023-06-05 09:04:23 +00:00
|
|
|
|
2023-09-18 09:32:37 +00:00
|
|
|
for def in self.declarations(db) {
|
|
|
|
match def {
|
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() {
|
2024-03-05 10:41:46 +00:00
|
|
|
m.diagnostics(db, acc, style_lints)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2024-03-05 10:41:46 +00:00
|
|
|
acc.extend(def.diagnostics(db, style_lints))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-07-20 14:49:02 +00:00
|
|
|
ModuleDef::Trait(t) => {
|
2021-11-20 16:19:19 +00:00
|
|
|
for diag in db.trait_data_with_diagnostics(t.id).1.iter() {
|
2022-01-11 13:34:25 +00:00
|
|
|
emit_def_diagnostic(db, acc, diag);
|
2022-08-30 11:51:24 +00:00
|
|
|
}
|
2024-02-01 23:11:43 +00:00
|
|
|
|
|
|
|
for item in t.items(db) {
|
2024-03-05 10:41:46 +00:00
|
|
|
item.diagnostics(db, acc, style_lints);
|
2024-02-01 23:11:43 +00:00
|
|
|
}
|
|
|
|
|
2024-03-05 10:41:46 +00:00
|
|
|
acc.extend(def.diagnostics(db, style_lints))
|
2022-08-30 11:51:24 +00:00
|
|
|
}
|
2022-10-11 07:37:35 +00:00
|
|
|
ModuleDef::Adt(adt) => {
|
|
|
|
match adt {
|
|
|
|
Adt::Struct(s) => {
|
|
|
|
for diag in db.struct_data_with_diagnostics(s.id).1.iter() {
|
|
|
|
emit_def_diagnostic(db, acc, diag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Adt::Union(u) => {
|
|
|
|
for diag in db.union_data_with_diagnostics(u.id).1.iter() {
|
|
|
|
emit_def_diagnostic(db, acc, diag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Adt::Enum(e) => {
|
|
|
|
for v in e.variants(db) {
|
2024-03-05 10:41:46 +00:00
|
|
|
acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints));
|
2024-01-15 10:07:26 +00:00
|
|
|
for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() {
|
|
|
|
emit_def_diagnostic(db, acc, diag);
|
2024-01-15 09:24:14 +00:00
|
|
|
}
|
2022-10-11 07:37:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-03-05 10:41:46 +00:00
|
|
|
acc.extend(def.diagnostics(db, style_lints))
|
2022-10-11 07:37:35 +00:00
|
|
|
}
|
2022-03-08 22:51:48 +00:00
|
|
|
ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
|
2024-03-05 10:41:46 +00:00
|
|
|
_ => acc.extend(def.diagnostics(db, style_lints)),
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
2021-07-28 15:39:04 +00:00
|
|
|
self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m));
|
2021-03-08 19:08:30 +00:00
|
|
|
|
2023-03-20 06:31:01 +00:00
|
|
|
let inherent_impls = db.inherent_impls_in_crate(self.id.krate());
|
|
|
|
|
2023-11-14 20:54:36 +00:00
|
|
|
let mut impl_assoc_items_scratch = vec![];
|
2021-03-08 19:08:30 +00:00
|
|
|
for impl_def in self.impl_defs(db) {
|
2023-07-17 13:49:15 +00:00
|
|
|
let loc = impl_def.id.lookup(db.upcast());
|
|
|
|
let tree = loc.id.item_tree(db.upcast());
|
|
|
|
let node = &tree[loc.id.value];
|
|
|
|
let file_id = loc.id.file_id();
|
2023-12-06 13:36:39 +00:00
|
|
|
if file_id.macro_file().map_or(false, |it| it.is_builtin_derive(db.upcast())) {
|
2023-07-17 13:49:15 +00:00
|
|
|
// these expansion come from us, diagnosing them is a waste of resources
|
|
|
|
// FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
|
|
|
|
continue;
|
|
|
|
}
|
2023-11-14 19:02:23 +00:00
|
|
|
let ast_id_map = db.ast_id_map(file_id);
|
2023-07-17 13:49:15 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
for diag in db.impl_data_with_diagnostics(impl_def.id).1.iter() {
|
2022-01-11 13:34:25 +00:00
|
|
|
emit_def_diagnostic(db, acc, diag);
|
2022-08-30 11:51:24 +00:00
|
|
|
}
|
|
|
|
|
2023-03-20 06:31:01 +00:00
|
|
|
if inherent_impls.invalid_impls().contains(&impl_def.id) {
|
|
|
|
acc.push(IncoherentImpl { impl_: ast_id_map.get(node.ast_id()), file_id }.into())
|
|
|
|
}
|
|
|
|
|
2023-11-14 17:09:28 +00:00
|
|
|
if !impl_def.check_orphan_rules(db) {
|
|
|
|
acc.push(TraitImplOrphan { impl_: ast_id_map.get(node.ast_id()), file_id }.into())
|
|
|
|
}
|
|
|
|
|
2023-11-14 19:02:23 +00:00
|
|
|
let trait_ = impl_def.trait_(db);
|
|
|
|
let trait_is_unsafe = trait_.map_or(false, |t| t.is_unsafe(db));
|
|
|
|
let impl_is_negative = impl_def.is_negative(db);
|
|
|
|
let impl_is_unsafe = impl_def.is_unsafe(db);
|
|
|
|
|
|
|
|
let drop_maybe_dangle = (|| {
|
|
|
|
// FIXME: This can be simplified a lot by exposing hir-ty's utils.rs::Generics helper
|
|
|
|
let trait_ = trait_?;
|
|
|
|
let drop_trait = db.lang_item(self.krate().into(), LangItem::Drop)?.as_trait()?;
|
|
|
|
if drop_trait != trait_.into() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
let parent = impl_def.id.into();
|
|
|
|
let generic_params = db.generic_params(parent);
|
|
|
|
let lifetime_params = generic_params.lifetimes.iter().map(|(local_id, _)| {
|
|
|
|
GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id })
|
|
|
|
});
|
|
|
|
let type_params = generic_params
|
2024-04-06 12:29:40 +00:00
|
|
|
.iter_type_or_consts()
|
2023-11-14 19:02:23 +00:00
|
|
|
.filter(|(_, it)| it.type_param().is_some())
|
|
|
|
.map(|(local_id, _)| {
|
|
|
|
GenericParamId::TypeParamId(TypeParamId::from_unchecked(
|
|
|
|
TypeOrConstParamId { parent, local_id },
|
|
|
|
))
|
|
|
|
});
|
|
|
|
let res = type_params
|
|
|
|
.chain(lifetime_params)
|
|
|
|
.any(|p| db.attrs(AttrDefId::GenericParamId(p)).by_key("may_dangle").exists());
|
|
|
|
Some(res)
|
|
|
|
})()
|
|
|
|
.unwrap_or(false);
|
|
|
|
|
|
|
|
match (impl_is_unsafe, trait_is_unsafe, impl_is_negative, drop_maybe_dangle) {
|
|
|
|
// unsafe negative impl
|
|
|
|
(true, _, true, _) |
|
|
|
|
// unsafe impl for safe trait
|
|
|
|
(true, false, _, false) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(node.ast_id()), file_id, should_be_safe: true }.into()),
|
|
|
|
// safe impl for unsafe trait
|
|
|
|
(false, true, false, _) |
|
|
|
|
// safe impl of dangling drop
|
|
|
|
(false, false, _, true) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(node.ast_id()), file_id, should_be_safe: false }.into()),
|
|
|
|
_ => (),
|
|
|
|
};
|
|
|
|
|
2023-12-06 22:11:16 +00:00
|
|
|
// Negative impls can't have items, don't emit missing items diagnostic for them
|
|
|
|
if let (false, Some(trait_)) = (impl_is_negative, trait_) {
|
2023-11-14 20:54:36 +00:00
|
|
|
let items = &db.trait_data(trait_.into()).items;
|
|
|
|
let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
|
|
|
|
AssocItemId::FunctionId(it) => !db.function_data(it).has_body(),
|
2024-04-15 18:38:54 +00:00
|
|
|
AssocItemId::ConstId(id) => !db.const_data(id).has_body,
|
2023-11-14 20:54:36 +00:00
|
|
|
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(),
|
|
|
|
});
|
2023-11-16 14:27:21 +00:00
|
|
|
impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().filter_map(
|
2023-11-14 20:54:36 +00:00
|
|
|
|&item| {
|
2023-11-16 14:27:21 +00:00
|
|
|
Some((
|
2023-11-14 20:54:36 +00:00
|
|
|
item,
|
|
|
|
match item {
|
|
|
|
AssocItemId::FunctionId(it) => db.function_data(it).name.clone(),
|
|
|
|
AssocItemId::ConstId(it) => {
|
2023-11-16 14:27:21 +00:00
|
|
|
db.const_data(it).name.as_ref()?.clone()
|
2023-11-14 20:54:36 +00:00
|
|
|
}
|
|
|
|
AssocItemId::TypeAliasId(it) => db.type_alias_data(it).name.clone(),
|
|
|
|
},
|
2023-11-16 14:27:21 +00:00
|
|
|
))
|
2023-11-14 20:54:36 +00:00
|
|
|
},
|
|
|
|
));
|
|
|
|
|
2023-12-01 11:09:42 +00:00
|
|
|
let redundant = impl_assoc_items_scratch
|
|
|
|
.iter()
|
|
|
|
.filter(|(id, name)| {
|
|
|
|
!items.iter().any(|(impl_name, impl_item)| {
|
|
|
|
discriminant(impl_item) == discriminant(id) && impl_name == name
|
|
|
|
})
|
2023-11-28 13:15:45 +00:00
|
|
|
})
|
2023-12-01 11:09:42 +00:00
|
|
|
.map(|(item, name)| (name.clone(), AssocItem::from(*item)));
|
|
|
|
for (name, assoc_item) in redundant {
|
2023-11-28 13:15:45 +00:00
|
|
|
acc.push(
|
2023-12-01 11:09:42 +00:00
|
|
|
TraitImplRedundantAssocItems {
|
|
|
|
trait_,
|
2023-11-28 13:15:45 +00:00
|
|
|
file_id,
|
2023-12-07 12:45:42 +00:00
|
|
|
impl_: ast_id_map.get(node.ast_id()),
|
2023-12-01 11:09:42 +00:00
|
|
|
assoc_item: (name, assoc_item),
|
2023-11-28 13:15:45 +00:00
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-11-14 20:54:36 +00:00
|
|
|
let missing: Vec<_> = required_items
|
|
|
|
.filter(|(name, id)| {
|
|
|
|
!impl_assoc_items_scratch.iter().any(|(impl_item, impl_name)| {
|
|
|
|
discriminant(impl_item) == discriminant(id) && impl_name == name
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.map(|(name, item)| (name.clone(), AssocItem::from(*item)))
|
|
|
|
.collect();
|
|
|
|
if !missing.is_empty() {
|
|
|
|
acc.push(
|
|
|
|
TraitImplMissingAssocItems {
|
|
|
|
impl_: ast_id_map.get(node.ast_id()),
|
|
|
|
file_id,
|
|
|
|
missing,
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
impl_assoc_items_scratch.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
for &item in &db.impl_data(impl_def.id).items {
|
2024-03-05 10:41:46 +00:00
|
|
|
AssocItem::from(item).diagnostics(db, acc, style_lints);
|
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)
|
2024-03-08 10:36:37 +00:00
|
|
|
.chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id))))
|
2021-09-24 18:41:24 +00:00
|
|
|
.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;
|
2023-01-09 18:36:22 +00:00
|
|
|
scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| it.into()).collect()
|
2022-03-18 10:55:53 +00:00
|
|
|
}
|
|
|
|
|
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.
|
2022-09-20 14:39:17 +00:00
|
|
|
pub fn find_use_path(
|
|
|
|
self,
|
|
|
|
db: &dyn DefDatabase,
|
|
|
|
item: impl Into<ItemInNs>,
|
|
|
|
prefer_no_std: bool,
|
2023-11-11 13:52:11 +00:00
|
|
|
prefer_prelude: bool,
|
2022-09-20 14:39:17 +00:00
|
|
|
) -> Option<ModPath> {
|
2023-11-11 13:52:11 +00:00
|
|
|
hir_def::find_path::find_path(
|
|
|
|
db,
|
|
|
|
item.into().into(),
|
|
|
|
self.into(),
|
|
|
|
prefer_no_std,
|
|
|
|
prefer_prelude,
|
|
|
|
)
|
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,
|
2022-09-20 14:39:17 +00:00
|
|
|
prefer_no_std: bool,
|
2023-11-11 13:52:11 +00:00
|
|
|
prefer_prelude: bool,
|
2021-03-08 19:08:30 +00:00
|
|
|
) -> Option<ModPath> {
|
2022-09-20 14:39:17 +00:00
|
|
|
hir_def::find_path::find_path_prefixed(
|
|
|
|
db,
|
|
|
|
item.into().into(),
|
|
|
|
self.into(),
|
|
|
|
prefix_kind,
|
|
|
|
prefer_no_std,
|
2023-11-11 13:52:11 +00:00
|
|
|
prefer_prelude,
|
2022-09-20 14:39:17 +00:00
|
|
|
)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-11 13:34:25 +00:00
|
|
|
fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
|
2023-12-21 08:18:06 +00:00
|
|
|
let id = db.macro_def(m.id);
|
2023-07-17 13:49:15 +00:00
|
|
|
if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) {
|
|
|
|
if let Some(e) = expander.mac.err() {
|
|
|
|
let Some(ast) = id.ast_id().left() else {
|
|
|
|
never!("declarative expander for non decl-macro: {:?}", e);
|
2023-06-05 09:04:23 +00:00
|
|
|
return;
|
|
|
|
};
|
2023-07-17 13:49:15 +00:00
|
|
|
emit_def_diagnostic_(
|
|
|
|
db,
|
|
|
|
acc,
|
|
|
|
&DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
|
|
|
|
);
|
|
|
|
}
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-11 13:34:25 +00:00
|
|
|
fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag: &DefDiagnostic) {
|
|
|
|
emit_def_diagnostic_(db, acc, &diag.kind)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2022-01-11 13:34:25 +00:00
|
|
|
fn emit_def_diagnostic_(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
acc: &mut Vec<AnyDiagnostic>,
|
|
|
|
diag: &DefDiagnosticKind,
|
2023-06-05 09:04:23 +00:00
|
|
|
) {
|
2022-01-11 13:34:25 +00:00
|
|
|
match diag {
|
2022-03-11 15:49:41 +00:00
|
|
|
DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
|
2023-08-21 09:44:09 +00:00
|
|
|
let decl = declaration.to_ptr(db.upcast());
|
2022-01-11 13:34:25 +00:00
|
|
|
acc.push(
|
|
|
|
UnresolvedModule {
|
2023-08-21 09:44:09 +00:00
|
|
|
decl: InFile::new(declaration.file_id, decl),
|
2022-03-11 15:49:41 +00:00
|
|
|
candidates: candidates.clone(),
|
2022-01-11 13:34:25 +00:00
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
DefDiagnosticKind::UnresolvedExternCrate { ast } => {
|
2023-08-21 09:44:09 +00:00
|
|
|
let item = ast.to_ptr(db.upcast());
|
|
|
|
acc.push(UnresolvedExternCrate { decl: InFile::new(ast.file_id, item) }.into());
|
2022-01-11 13:34:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 } => {
|
2023-08-21 09:44:09 +00:00
|
|
|
let item = ast.to_ptr(db.upcast());
|
2022-01-11 13:34:25 +00:00
|
|
|
acc.push(
|
2023-08-21 09:44:09 +00:00
|
|
|
InactiveCode { node: ast.with_value(item), cfg: cfg.clone(), opts: opts.clone() }
|
|
|
|
.into(),
|
2022-01-11 13:34:25 +00:00
|
|
|
);
|
|
|
|
}
|
2022-06-15 16:04:39 +00:00
|
|
|
DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
|
2022-06-24 11:03:13 +00:00
|
|
|
let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db);
|
2022-06-15 15:33:55 +00:00
|
|
|
acc.push(
|
2022-06-15 16:04:39 +00:00
|
|
|
UnresolvedProcMacro { node, precise_location, macro_name, kind, krate: *krate }
|
|
|
|
.into(),
|
2022-06-15 15:33:55 +00:00
|
|
|
);
|
2022-01-11 13:34:25 +00:00
|
|
|
}
|
|
|
|
DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
|
2022-06-24 11:03:13 +00:00
|
|
|
let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
|
2022-01-11 13:34:25 +00:00
|
|
|
acc.push(
|
|
|
|
UnresolvedMacroCall {
|
2022-06-24 11:03:13 +00:00
|
|
|
macro_call: node,
|
|
|
|
precise_location,
|
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 } => {
|
2022-06-24 11:03:13 +00:00
|
|
|
let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
|
|
|
|
acc.push(MacroError { node, precise_location, message: message.clone() }.into());
|
2022-01-11 13:34:25 +00:00
|
|
|
}
|
|
|
|
DefDiagnosticKind::MacroExpansionParseError { ast, errors } => {
|
2022-06-24 11:03:13 +00:00
|
|
|
let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
|
2022-01-11 13:34:25 +00:00
|
|
|
acc.push(
|
2022-06-24 11:03:13 +00:00
|
|
|
MacroExpansionParseError { node, precise_location, errors: errors.clone() }.into(),
|
2023-06-05 09:04:23 +00:00
|
|
|
);
|
|
|
|
}
|
2022-01-11 13:34:25 +00:00
|
|
|
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());
|
2024-01-22 00:00:50 +00:00
|
|
|
let derive = node.attrs().nth(*id);
|
2022-01-11 13:34:25 +00:00
|
|
|
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());
|
2024-01-22 00:00:50 +00:00
|
|
|
let derive = node.attrs().nth(*id);
|
2022-01-11 13:34:25 +00:00
|
|
|
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"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DefDiagnosticKind::MacroDefError { ast, message } => {
|
|
|
|
let node = ast.to_node(db.upcast());
|
|
|
|
acc.push(
|
2022-06-24 11:03:13 +00:00
|
|
|
MacroDefError {
|
2022-01-11 13:34:25 +00:00
|
|
|
node: InFile::new(ast.file_id, AstPtr::new(&node)),
|
2022-06-24 11:03:13 +00:00
|
|
|
name: node.name().map(|it| it.syntax().text_range()),
|
|
|
|
message: message.clone(),
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
}
|
2022-01-11 13:34:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-24 11:03:13 +00:00
|
|
|
fn precise_macro_call_location(
|
|
|
|
ast: &MacroCallKind,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
) -> (InFile<SyntaxNodePtr>, Option<TextRange>, Option<String>, MacroKind) {
|
|
|
|
// FIXME: maybe we actually want slightly different ranges for the different macro diagnostics
|
|
|
|
// - e.g. the full attribute for macro errors, but only the name for name resolution
|
|
|
|
match ast {
|
|
|
|
MacroCallKind::FnLike { ast_id, .. } => {
|
|
|
|
let node = ast_id.to_node(db.upcast());
|
|
|
|
(
|
|
|
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
|
|
|
|
node.path()
|
|
|
|
.and_then(|it| it.segment())
|
|
|
|
.and_then(|it| it.name_ref())
|
|
|
|
.map(|it| it.syntax().text_range()),
|
|
|
|
node.path().and_then(|it| it.segment()).map(|it| it.to_string()),
|
|
|
|
MacroKind::ProcMacro,
|
|
|
|
)
|
|
|
|
}
|
2024-03-18 11:10:02 +00:00
|
|
|
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
|
2022-06-24 11:03:13 +00:00
|
|
|
let node = ast_id.to_node(db.upcast());
|
|
|
|
// Compute the precise location of the macro name's token in the derive
|
|
|
|
// list.
|
|
|
|
let token = (|| {
|
2023-12-09 20:02:51 +00:00
|
|
|
let derive_attr = collect_attrs(&node)
|
2023-02-13 11:55:14 +00:00
|
|
|
.nth(derive_attr_index.ast_index())
|
2023-12-09 20:02:51 +00:00
|
|
|
.and_then(|x| Either::left(x.1))?;
|
2022-06-24 11:03:13 +00:00
|
|
|
let token_tree = derive_attr.meta()?.token_tree()?;
|
|
|
|
let group_by = token_tree
|
|
|
|
.syntax()
|
|
|
|
.children_with_tokens()
|
|
|
|
.filter_map(|elem| match elem {
|
|
|
|
syntax::NodeOrToken::Token(tok) => Some(tok),
|
|
|
|
_ => None,
|
|
|
|
})
|
|
|
|
.group_by(|t| t.kind() == T![,]);
|
|
|
|
let (_, mut group) = group_by
|
|
|
|
.into_iter()
|
|
|
|
.filter(|&(comma, _)| !comma)
|
|
|
|
.nth(*derive_index as usize)?;
|
|
|
|
group.find(|t| t.kind() == T![ident])
|
|
|
|
})();
|
|
|
|
(
|
|
|
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
|
|
|
|
token.as_ref().map(|tok| tok.text_range()),
|
|
|
|
token.as_ref().map(ToString::to_string),
|
|
|
|
MacroKind::Derive,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
|
|
|
|
let node = ast_id.to_node(db.upcast());
|
2023-12-09 20:02:51 +00:00
|
|
|
let attr = collect_attrs(&node)
|
2023-02-13 11:55:14 +00:00
|
|
|
.nth(invoc_attr_index.ast_index())
|
2023-12-09 20:02:51 +00:00
|
|
|
.and_then(|x| Either::left(x.1))
|
2023-02-13 11:55:14 +00:00
|
|
|
.unwrap_or_else(|| {
|
|
|
|
panic!("cannot find attribute #{}", invoc_attr_index.ast_index())
|
|
|
|
});
|
2022-06-24 11:03:13 +00:00
|
|
|
|
|
|
|
(
|
|
|
|
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
|
|
|
|
Some(attr.syntax().text_range()),
|
|
|
|
attr.path()
|
|
|
|
.and_then(|path| path.segment())
|
|
|
|
.and_then(|seg| seg.name_ref())
|
|
|
|
.as_ref()
|
|
|
|
.map(ToString::to_string),
|
|
|
|
MacroKind::Attr,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
2024-01-06 14:04:58 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
|
|
|
|
pub struct TupleField {
|
|
|
|
pub owner: DefWithBodyId,
|
|
|
|
pub tuple: TupleId,
|
|
|
|
pub index: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TupleField {
|
|
|
|
pub fn name(&self) -> Name {
|
|
|
|
Name::new_tuple_field(self.index as usize)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ty(&self, db: &dyn HirDatabase) -> Type {
|
|
|
|
let ty = db.infer(self.owner).tuple_field_access_types[&self.tuple]
|
|
|
|
.as_slice(Interner)
|
|
|
|
.get(self.index as usize)
|
|
|
|
.and_then(|arg| arg.ty(Interner))
|
|
|
|
.cloned()
|
|
|
|
.unwrap_or_else(|| TyKind::Error.intern(Interner));
|
|
|
|
Type { env: db.trait_environment_for_body(self.owner), ty }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[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()
|
|
|
|
}
|
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
pub fn index(&self) -> usize {
|
|
|
|
u32::from(self.id.into_raw()) as usize
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
/// 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(),
|
2024-01-15 09:24:14 +00:00
|
|
|
VariantDef::Variant(it) => it.id.into(),
|
2021-03-08 19:08:30 +00:00
|
|
|
};
|
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
|
|
|
}
|
|
|
|
|
2024-02-01 09:02:19 +00:00
|
|
|
// FIXME: Find better API to also handle const generics
|
2024-01-06 13:17:16 +00:00
|
|
|
pub fn ty_with_args(&self, db: &dyn HirDatabase, generics: impl Iterator<Item = Type>) -> Type {
|
2023-12-11 15:04:20 +00:00
|
|
|
let var_id = self.parent.into();
|
|
|
|
let def_id: AdtId = match self.parent {
|
|
|
|
VariantDef::Struct(it) => it.id.into(),
|
|
|
|
VariantDef::Union(it) => it.id.into(),
|
|
|
|
VariantDef::Variant(it) => it.parent_enum(db).id.into(),
|
|
|
|
};
|
2024-03-17 11:50:22 +00:00
|
|
|
let mut generics = generics.map(|it| it.ty);
|
2023-12-11 15:04:20 +00:00
|
|
|
let substs = TyBuilder::subst_for_def(db, def_id, None)
|
2024-02-01 09:02:19 +00:00
|
|
|
.fill(|x| match x {
|
|
|
|
ParamKind::Type => {
|
|
|
|
generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
|
2024-01-06 13:17:16 +00:00
|
|
|
}
|
2024-02-01 09:02:19 +00:00
|
|
|
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
|
2024-03-08 12:35:44 +00:00
|
|
|
ParamKind::Lifetime => error_lifetime().cast(Interner),
|
2023-12-11 15:04:20 +00:00
|
|
|
})
|
|
|
|
.build();
|
|
|
|
let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
|
|
|
|
Type::new(db, var_id, ty)
|
|
|
|
}
|
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
2023-07-24 09:21:34 +00:00
|
|
|
db.layout_of_ty(
|
2024-01-06 23:17:48 +00:00
|
|
|
self.ty(db).ty,
|
2023-07-24 09:21:34 +00:00
|
|
|
db.trait_environment(match hir_def::VariantId::from(self.parent) {
|
|
|
|
hir_def::VariantId::EnumVariantId(id) => GenericDefId::EnumVariantId(id),
|
|
|
|
hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()),
|
|
|
|
hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()),
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
.map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-12-29 13:35:59 +00:00
|
|
|
pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::from_value_def(db, self.id)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
|
2023-02-13 11:55:14 +00:00
|
|
|
db.struct_data(self.id).repr
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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()
|
|
|
|
}
|
2023-12-16 14:29:23 +00:00
|
|
|
|
|
|
|
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.attrs(self.id.into()).is_unstable()
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-12-29 13:35:59 +00:00
|
|
|
pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::from_value_def(db, self.id)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
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()
|
|
|
|
}
|
2023-12-16 14:29:23 +00:00
|
|
|
|
|
|
|
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.attrs(self.id.into()).is_unstable()
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
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> {
|
2024-01-15 09:24:14 +00:00
|
|
|
db.enum_data(self.id).variants.iter().map(|&(id, _)| Variant { id }).collect()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
|
2021-03-15 16:05:03 +00:00
|
|
|
db.enum_data(self.id).repr
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
2022-10-11 07:37:35 +00:00
|
|
|
|
|
|
|
/// The type of the enum variant bodies.
|
|
|
|
pub fn variant_body_ty(self, db: &dyn HirDatabase) -> Type {
|
|
|
|
Type::new_for_crate(
|
|
|
|
self.id.lookup(db.upcast()).container.krate(),
|
|
|
|
TyBuilder::builtin(match db.enum_data(self.id).variant_body_type() {
|
2023-01-09 18:36:22 +00:00
|
|
|
layout::IntegerType::Pointer(sign) => match sign {
|
|
|
|
true => hir_def::builtin_type::BuiltinType::Int(
|
|
|
|
hir_def::builtin_type::BuiltinInt::Isize,
|
|
|
|
),
|
|
|
|
false => hir_def::builtin_type::BuiltinType::Uint(
|
|
|
|
hir_def::builtin_type::BuiltinUint::Usize,
|
|
|
|
),
|
|
|
|
},
|
|
|
|
layout::IntegerType::Fixed(i, sign) => match sign {
|
|
|
|
true => hir_def::builtin_type::BuiltinType::Int(match i {
|
|
|
|
layout::Integer::I8 => hir_def::builtin_type::BuiltinInt::I8,
|
|
|
|
layout::Integer::I16 => hir_def::builtin_type::BuiltinInt::I16,
|
|
|
|
layout::Integer::I32 => hir_def::builtin_type::BuiltinInt::I32,
|
|
|
|
layout::Integer::I64 => hir_def::builtin_type::BuiltinInt::I64,
|
|
|
|
layout::Integer::I128 => hir_def::builtin_type::BuiltinInt::I128,
|
|
|
|
}),
|
|
|
|
false => hir_def::builtin_type::BuiltinType::Uint(match i {
|
|
|
|
layout::Integer::I8 => hir_def::builtin_type::BuiltinUint::U8,
|
|
|
|
layout::Integer::I16 => hir_def::builtin_type::BuiltinUint::U16,
|
|
|
|
layout::Integer::I32 => hir_def::builtin_type::BuiltinUint::U32,
|
|
|
|
layout::Integer::I64 => hir_def::builtin_type::BuiltinUint::U64,
|
|
|
|
layout::Integer::I128 => hir_def::builtin_type::BuiltinUint::U128,
|
|
|
|
}),
|
|
|
|
},
|
2022-10-11 07:37:35 +00:00
|
|
|
}),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-02-13 11:55:14 +00:00
|
|
|
/// Returns true if at least one variant of this enum is a non-unit variant.
|
2022-10-11 07:37:35 +00:00
|
|
|
pub fn is_data_carrying(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
|
|
|
|
}
|
2023-06-05 09:04:23 +00:00
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
|
|
|
Adt::from(self).layout(db)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
2023-12-16 14:29:23 +00:00
|
|
|
|
|
|
|
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.attrs(self.id.into()).is_unstable()
|
|
|
|
}
|
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()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-11 07:37:35 +00:00
|
|
|
impl From<&Variant> for DefWithBodyId {
|
|
|
|
fn from(&v: &Variant) -> Self {
|
|
|
|
DefWithBodyId::VariantId(v.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Variant {
|
2024-01-15 09:24:14 +00:00
|
|
|
pub(crate) id: EnumVariantId,
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Variant {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
2024-01-15 11:03:31 +00:00
|
|
|
Module { id: self.id.module(db.upcast()) }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-05-23 13:45:26 +00:00
|
|
|
|
2024-01-15 09:24:14 +00:00
|
|
|
pub fn parent_enum(self, db: &dyn HirDatabase) -> Enum {
|
|
|
|
self.id.lookup(db.upcast()).parent.into()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-12-29 13:35:59 +00:00
|
|
|
pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
|
2024-01-15 09:24:14 +00:00
|
|
|
Type::from_value_def(db, self.id)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
2024-01-15 09:24:14 +00:00
|
|
|
db.enum_variant_data(self.id).name.clone()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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> {
|
2024-01-15 09:24:14 +00:00
|
|
|
db.enum_variant_data(self.id).variant_data.clone()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2022-10-11 07:37:35 +00:00
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
|
2022-10-11 07:37:35 +00:00
|
|
|
self.source(db)?.value.expr()
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
pub fn eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError> {
|
|
|
|
db.const_eval_discriminant(self.into())
|
2022-10-11 07:37:35 +00:00
|
|
|
}
|
2023-06-05 09:04:23 +00:00
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
2021-03-08 19:08:30 +00:00
|
|
|
let parent_enum = self.parent_enum(db);
|
|
|
|
let parent_layout = parent_enum.layout(db)?;
|
2022-10-11 07:37:35 +00:00
|
|
|
Ok(match &parent_layout.0.variants {
|
2022-05-19 16:53:08 +00:00
|
|
|
layout::Variants::Multiple { variants, .. } => Layout(
|
2024-01-15 09:24:14 +00:00
|
|
|
{
|
|
|
|
let lookup = self.id.lookup(db.upcast());
|
2024-01-15 11:03:31 +00:00
|
|
|
let rustc_enum_variant_idx = RustcEnumVariantIdx(lookup.index as usize);
|
2024-01-15 09:24:14 +00:00
|
|
|
Arc::new(variants[rustc_enum_variant_idx].clone())
|
|
|
|
},
|
2022-03-09 18:50:24 +00:00
|
|
|
db.target_data_layout(parent_enum.krate(db).into()).unwrap(),
|
2023-06-05 09:04:23 +00:00
|
|
|
),
|
2023-01-09 18:36:22 +00:00
|
|
|
_ => parent_layout,
|
2023-06-05 09:04:23 +00:00
|
|
|
})
|
|
|
|
}
|
2023-12-16 14:29:23 +00:00
|
|
|
|
|
|
|
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.attrs(self.id.into()).is_unstable()
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
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) {
|
2023-07-17 13:49:15 +00:00
|
|
|
GenericArgData::Ty(it) => it.is_unknown(),
|
2022-03-09 18:50:24 +00:00
|
|
|
_ => false,
|
|
|
|
})
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
2023-07-24 09:21:34 +00:00
|
|
|
db.layout_of_adt(
|
|
|
|
self.into(),
|
2024-04-03 06:57:48 +00:00
|
|
|
TyBuilder::adt(db, self.into())
|
|
|
|
.fill_with_defaults(db, || TyKind::Error.intern(Interner))
|
|
|
|
.build_into_subst(),
|
2023-07-24 09:21:34 +00:00
|
|
|
db.trait_environment(self.into()),
|
|
|
|
)
|
2024-04-03 06:57:48 +00:00
|
|
|
.map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap()))
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
|
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.
|
2024-02-01 09:02:19 +00:00
|
|
|
pub fn ty_with_args(self, db: &dyn HirDatabase, args: impl Iterator<Item = Type>) -> Type {
|
2022-03-20 18:20:16 +00:00
|
|
|
let id = AdtId::from(self);
|
2024-03-17 11:50:22 +00:00
|
|
|
let mut it = args.map(|t| t.ty);
|
2022-10-11 07:37:35 +00:00
|
|
|
let ty = TyBuilder::def_ty(db, id.into(), None)
|
2022-03-20 18:20:16 +00:00
|
|
|
.fill(|x| {
|
|
|
|
let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
|
|
|
|
match x {
|
2023-08-21 09:44:09 +00:00
|
|
|
ParamKind::Type => r.cast(Interner),
|
2022-03-20 23:08:12 +00:00
|
|
|
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
|
2024-03-08 12:35:44 +00:00
|
|
|
ParamKind::Lifetime => error_lifetime().cast(Interner),
|
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
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
/// Returns the lifetime of the DataType
|
|
|
|
pub fn lifetime(&self, db: &dyn HirDatabase) -> Option<LifetimeParamData> {
|
|
|
|
let resolver = match self {
|
|
|
|
Adt::Struct(s) => s.id.resolver(db.upcast()),
|
|
|
|
Adt::Union(u) => u.id.resolver(db.upcast()),
|
|
|
|
Adt::Enum(e) => e.id.resolver(db.upcast()),
|
|
|
|
};
|
|
|
|
resolver
|
|
|
|
.generic_params()
|
|
|
|
.and_then(|gp| {
|
2024-01-19 14:25:51 +00:00
|
|
|
gp.lifetimes
|
2023-03-13 08:42:24 +00:00
|
|
|
.iter()
|
|
|
|
// there should only be a single lifetime
|
|
|
|
// but `Arena` requires to use an iterator
|
|
|
|
.nth(0)
|
|
|
|
})
|
|
|
|
.map(|arena| arena.1.clone())
|
|
|
|
}
|
|
|
|
|
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),
|
2022-10-11 07:37:35 +00:00
|
|
|
Variant(Variant),
|
2023-06-19 06:14:04 +00:00
|
|
|
InTypeConst(InTypeConst),
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2023-06-19 06:14:04 +00:00
|
|
|
impl_from!(Function, Const, Static, Variant, InTypeConst for DefWithBody);
|
2021-03-08 19:08:30 +00:00
|
|
|
|
|
|
|
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),
|
2022-10-11 07:37:35 +00:00
|
|
|
DefWithBody::Variant(v) => v.module(db),
|
2023-06-19 06:14:04 +00:00
|
|
|
DefWithBody::InTypeConst(c) => c.module(db),
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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),
|
2022-10-11 07:37:35 +00:00
|
|
|
DefWithBody::Variant(v) => Some(v.name(db)),
|
2023-06-19 06:14:04 +00:00
|
|
|
DefWithBody::InTypeConst(_) => None,
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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),
|
2024-01-15 09:24:14 +00:00
|
|
|
DefWithBody::Variant(it) => it.parent_enum(db).variant_body_ty(db),
|
2023-06-19 06:14:04 +00:00
|
|
|
DefWithBody::InTypeConst(it) => Type::new_with_resolver_inner(
|
|
|
|
db,
|
|
|
|
&DefWithBodyId::from(it.id).resolver(db.upcast()),
|
|
|
|
TyKind::Error.intern(Interner),
|
|
|
|
),
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2021-05-14 02:36:12 +00:00
|
|
|
}
|
|
|
|
|
2022-08-23 07:05:52 +00:00
|
|
|
fn id(&self) -> DefWithBodyId {
|
|
|
|
match self {
|
|
|
|
DefWithBody::Function(it) => it.id.into(),
|
|
|
|
DefWithBody::Static(it) => it.id.into(),
|
|
|
|
DefWithBody::Const(it) => it.id.into(),
|
2022-10-11 07:37:35 +00:00
|
|
|
DefWithBody::Variant(it) => it.into(),
|
2023-06-19 06:14:04 +00:00
|
|
|
DefWithBody::InTypeConst(it) => it.id.into(),
|
2022-08-23 07:05:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A textual representation of the HIR of this def's body for debugging purposes.
|
|
|
|
pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
|
|
|
|
let body = db.body(self.id());
|
|
|
|
body.pretty_print(db.upcast(), self.id())
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
/// A textual representation of the MIR of this def's body for debugging purposes.
|
|
|
|
pub fn debug_mir(self, db: &dyn HirDatabase) -> String {
|
|
|
|
let body = db.mir_body(self.id());
|
|
|
|
match body {
|
|
|
|
Ok(body) => body.pretty_print(db),
|
|
|
|
Err(e) => format!("error:\n{e:?}"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-05 10:41:46 +00:00
|
|
|
pub fn diagnostics(
|
|
|
|
self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
acc: &mut Vec<AnyDiagnostic>,
|
|
|
|
style_lints: bool,
|
|
|
|
) {
|
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()) {
|
2024-03-05 10:41:46 +00:00
|
|
|
Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints);
|
2022-01-11 13:34:25 +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
|
|
|
for diag in source_map.diagnostics() {
|
2024-01-26 09:43:25 +00:00
|
|
|
acc.push(match diag {
|
|
|
|
BodyDiagnostic::InactiveCode { node, cfg, opts } => {
|
|
|
|
InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into()
|
|
|
|
}
|
|
|
|
BodyDiagnostic::MacroError { node, message } => MacroError {
|
|
|
|
node: (*node).map(|it| it.into()),
|
|
|
|
precise_location: None,
|
|
|
|
message: message.to_string(),
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
BodyDiagnostic::UnresolvedProcMacro { node, krate } => UnresolvedProcMacro {
|
|
|
|
node: (*node).map(|it| it.into()),
|
|
|
|
precise_location: None,
|
|
|
|
macro_name: None,
|
|
|
|
kind: MacroKind::ProcMacro,
|
|
|
|
krate: *krate,
|
|
|
|
}
|
|
|
|
.into(),
|
|
|
|
BodyDiagnostic::UnresolvedMacroCall { node, path } => UnresolvedMacroCall {
|
|
|
|
macro_call: (*node).map(|ast_ptr| ast_ptr.into()),
|
|
|
|
precise_location: None,
|
|
|
|
path: path.clone(),
|
|
|
|
is_bang: true,
|
|
|
|
}
|
|
|
|
.into(),
|
2021-06-13 14:06:36 +00:00
|
|
|
BodyDiagnostic::UnreachableLabel { node, name } => {
|
2024-01-26 09:43:25 +00:00
|
|
|
UnreachableLabel { node: *node, name: name.clone() }.into()
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
2021-06-13 14:06:36 +00:00
|
|
|
BodyDiagnostic::UndeclaredLabel { node, name } => {
|
2024-01-26 09:43:25 +00:00
|
|
|
UndeclaredLabel { node: *node, name: name.clone() }.into()
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
2024-01-26 09:43:25 +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());
|
2021-06-12 14:17:23 +00:00
|
|
|
for d in &infer.diagnostics {
|
2024-01-30 08:51:28 +00:00
|
|
|
acc.extend(AnyDiagnostic::inference_diagnostic(db, self.into(), d, &source_map));
|
2021-06-12 14:17:23 +00:00
|
|
|
}
|
2024-03-29 05:13:31 +00:00
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
for (pat_or_expr, mismatch) in infer.type_mismatches() {
|
|
|
|
let expr_or_pat = match pat_or_expr {
|
|
|
|
ExprOrPatId::ExprId(expr) => source_map.expr_syntax(expr).map(Either::Left),
|
|
|
|
ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right),
|
2022-03-21 16:00:03 +00:00
|
|
|
};
|
2023-03-13 08:42:24 +00:00
|
|
|
let expr_or_pat = match expr_or_pat {
|
2023-11-08 06:15:03 +00:00
|
|
|
Ok(Either::Left(expr)) => expr.map(AstPtr::wrap_left),
|
|
|
|
Ok(Either::Right(InFile { file_id, value: pat })) => {
|
|
|
|
// cast from Either<Pat, SelfParam> -> Either<_, Pat>
|
|
|
|
let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else {
|
|
|
|
continue;
|
|
|
|
};
|
|
|
|
InFile { file_id, value: ptr }
|
2023-03-13 08:42:24 +00:00
|
|
|
}
|
2023-11-08 06:15:03 +00:00
|
|
|
Err(SyntheticSyntax) => continue,
|
2023-03-13 08:42:24 +00:00
|
|
|
};
|
|
|
|
|
2022-03-20 15:26:48 +00:00
|
|
|
acc.push(
|
|
|
|
TypeMismatch {
|
2023-03-13 08:42:24 +00:00
|
|
|
expr_or_pat,
|
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 elsewhere in this file, the `expr` was
|
|
|
|
// desugared, report or assert that this doesn't happen.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
if let Ok(borrowck_results) = db.borrowck(self.into()) {
|
2022-04-14 12:44:17 +00:00
|
|
|
for borrowck_result in borrowck_results.iter() {
|
2023-03-13 08:42:24 +00:00
|
|
|
let mir_body = &borrowck_result.mir_body;
|
|
|
|
for moof in &borrowck_result.moved_out_of_ref {
|
|
|
|
let span: InFile<SyntaxNodePtr> = match moof.span {
|
|
|
|
mir::MirSpan::ExprId(e) => match source_map.expr_syntax(e) {
|
2023-07-17 13:49:15 +00:00
|
|
|
Ok(s) => s.map(|it| it.into()),
|
2023-03-13 08:42:24 +00:00
|
|
|
Err(_) => continue,
|
2023-06-05 09:04:23 +00:00
|
|
|
},
|
2021-06-13 12:48:54 +00:00
|
|
|
mir::MirSpan::PatId(p) => match source_map.pat_syntax(p) {
|
2023-11-08 06:15:03 +00:00
|
|
|
Ok(s) => s.map(|it| it.into()),
|
2023-03-13 08:42:24 +00:00
|
|
|
Err(_) => continue,
|
2023-06-05 09:04:23 +00:00
|
|
|
},
|
2024-03-06 14:57:05 +00:00
|
|
|
mir::MirSpan::SelfParam => match source_map.self_param_syntax() {
|
|
|
|
Some(s) => s.map(|it| it.into()),
|
|
|
|
None => continue,
|
|
|
|
},
|
2023-03-13 08:42:24 +00:00
|
|
|
mir::MirSpan::Unknown => continue,
|
2023-06-05 09:04:23 +00:00
|
|
|
};
|
2021-06-13 18:44:31 +00:00
|
|
|
acc.push(
|
2022-03-26 20:22:35 +00:00
|
|
|
MovedOutOfRef { ty: Type::new_for_crate(krate, moof.ty.clone()), span }
|
2023-06-05 09:04:23 +00:00
|
|
|
.into(),
|
|
|
|
)
|
|
|
|
}
|
2023-03-13 08:42:24 +00:00
|
|
|
let mol = &borrowck_result.mutability_of_locals;
|
2024-01-26 09:43:25 +00:00
|
|
|
for (binding_id, binding_data) in body.bindings.iter() {
|
2021-03-14 12:03:39 +00:00
|
|
|
if binding_data.problems.is_some() {
|
2023-03-13 08:42:24 +00:00
|
|
|
// We should report specific diagnostics for these problems, not `need-mut` and `unused-mut`.
|
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
|
|
|
continue;
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
2023-03-13 08:42:24 +00:00
|
|
|
let Some(&local) = mir_body.binding_locals.get(binding_id) else {
|
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
|
|
|
continue;
|
2023-06-05 09:04:23 +00:00
|
|
|
};
|
2023-07-17 13:49:15 +00:00
|
|
|
if body[binding_id]
|
|
|
|
.definitions
|
|
|
|
.iter()
|
|
|
|
.any(|&pat| source_map.pat_syntax(pat).is_err())
|
|
|
|
{
|
|
|
|
// Skip synthetic bindings
|
|
|
|
continue;
|
|
|
|
}
|
2023-11-08 06:15:03 +00:00
|
|
|
let mut need_mut = &mol[local];
|
|
|
|
if body[binding_id].name.as_str() == Some("self")
|
|
|
|
&& need_mut == &mir::MutabilityReason::Unused
|
|
|
|
{
|
|
|
|
need_mut = &mir::MutabilityReason::Not;
|
|
|
|
}
|
2023-03-13 08:42:24 +00:00
|
|
|
let local = Local { parent: self.into(), binding_id };
|
2024-04-15 18:38:54 +00:00
|
|
|
let is_mut = body[binding_id].mode == BindingAnnotation::Mutable;
|
|
|
|
|
|
|
|
match (need_mut, is_mut) {
|
2023-11-08 06:15:03 +00:00
|
|
|
(mir::MutabilityReason::Unused, _) => {
|
2024-01-07 00:20:20 +00:00
|
|
|
let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_'));
|
2023-11-08 06:15:03 +00:00
|
|
|
if !should_ignore {
|
|
|
|
acc.push(UnusedVariable { local }.into())
|
|
|
|
}
|
|
|
|
}
|
2023-03-13 08:42:24 +00:00
|
|
|
(mir::MutabilityReason::Mut { .. }, true)
|
|
|
|
| (mir::MutabilityReason::Not, false) => (),
|
|
|
|
(mir::MutabilityReason::Mut { spans }, false) => {
|
|
|
|
for span in spans {
|
2022-06-24 11:03:13 +00:00
|
|
|
let span: InFile<SyntaxNodePtr> = match span {
|
2023-03-13 08:42:24 +00:00
|
|
|
mir::MirSpan::ExprId(e) => match source_map.expr_syntax(*e) {
|
2023-07-17 13:49:15 +00:00
|
|
|
Ok(s) => s.map(|it| it.into()),
|
2023-03-13 08:42:24 +00:00
|
|
|
Err(_) => continue,
|
|
|
|
},
|
|
|
|
mir::MirSpan::PatId(p) => match source_map.pat_syntax(*p) {
|
2023-11-08 06:15:03 +00:00
|
|
|
Ok(s) => s.map(|it| it.into()),
|
2023-03-13 08:42:24 +00:00
|
|
|
Err(_) => continue,
|
|
|
|
},
|
2024-03-06 14:57:05 +00:00
|
|
|
mir::MirSpan::SelfParam => match source_map.self_param_syntax()
|
|
|
|
{
|
|
|
|
Some(s) => s.map(|it| it.into()),
|
|
|
|
None => continue,
|
|
|
|
},
|
2023-03-13 08:42:24 +00:00
|
|
|
mir::MirSpan::Unknown => continue,
|
|
|
|
};
|
|
|
|
acc.push(NeedMut { local, span }.into());
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
2023-03-13 08:42:24 +00:00
|
|
|
(mir::MutabilityReason::Not, true) => {
|
|
|
|
if !infer.mutated_bindings_in_closure.contains(&binding_id) {
|
2024-01-07 00:20:20 +00:00
|
|
|
let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_'));
|
2021-03-08 19:08:30 +00:00
|
|
|
if !should_ignore {
|
2023-03-13 08:42:24 +00:00
|
|
|
acc.push(UnusedMut { local }.into())
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
2023-03-13 08:42:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-05 10:41:46 +00:00
|
|
|
for diagnostic in BodyValidationDiagnostic::collect(db, self.into(), style_lints) {
|
2024-01-30 08:51:28 +00:00
|
|
|
acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, &source_map));
|
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(),
|
2022-10-11 07:37:35 +00:00
|
|
|
DefWithBody::Variant(it) => it.into(),
|
2023-06-19 06:14:04 +00:00
|
|
|
// FIXME: don't ignore diagnostics for in type const
|
|
|
|
DefWithBody::InTypeConst(_) => return,
|
2021-08-27 21:21:21 +00:00
|
|
|
};
|
2023-07-24 09:21:34 +00:00
|
|
|
for diag in hir_ty::diagnostics::incorrect_case(db, 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 {
|
2024-02-10 10:37:59 +00:00
|
|
|
self.id.module(db.upcast()).into()
|
2021-08-27 21:21:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
db.function_data(self.id).name.clone()
|
|
|
|
}
|
|
|
|
|
2021-08-03 18:47:51 +00:00
|
|
|
pub fn ty(self, db: &dyn HirDatabase) -> Type {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::from_value_def(db, self.id)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2021-08-27 21:21:21 +00:00
|
|
|
/// 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
|
|
|
}
|
|
|
|
|
2024-02-01 09:02:19 +00:00
|
|
|
// FIXME: Find better API to also handle const generics
|
2024-01-06 13:17:16 +00:00
|
|
|
pub fn ret_type_with_args(
|
2023-12-11 15:04:20 +00:00
|
|
|
self,
|
|
|
|
db: &dyn HirDatabase,
|
2024-01-06 13:17:16 +00:00
|
|
|
generics: impl Iterator<Item = Type>,
|
2023-12-11 15:04:20 +00:00
|
|
|
) -> Type {
|
|
|
|
let resolver = self.id.resolver(db.upcast());
|
|
|
|
let parent_id: Option<GenericDefId> = match self.id.lookup(db.upcast()).container {
|
|
|
|
ItemContainerId::ImplId(it) => Some(it.into()),
|
|
|
|
ItemContainerId::TraitId(it) => Some(it.into()),
|
|
|
|
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
|
|
|
|
};
|
2024-03-17 11:50:22 +00:00
|
|
|
let mut generics = generics.map(|it| it.ty);
|
2024-02-01 09:02:19 +00:00
|
|
|
let mut filler = |x: &_| match x {
|
|
|
|
ParamKind::Type => {
|
|
|
|
generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
|
2024-01-06 13:17:16 +00:00
|
|
|
}
|
2024-02-01 09:02:19 +00:00
|
|
|
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
|
2024-03-08 12:35:44 +00:00
|
|
|
ParamKind::Lifetime => error_lifetime().cast(Interner),
|
2024-01-06 13:17:16 +00:00
|
|
|
};
|
2023-12-11 15:04:20 +00:00
|
|
|
|
2024-01-06 13:17:16 +00:00
|
|
|
let parent_substs =
|
|
|
|
parent_id.map(|id| TyBuilder::subst_for_def(db, id, None).fill(&mut filler).build());
|
|
|
|
let substs = TyBuilder::subst_for_def(db, self.id, parent_substs).fill(&mut filler).build();
|
2023-12-11 15:04:20 +00:00
|
|
|
|
|
|
|
let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
|
|
|
|
let ty = callable_sig.ret().clone();
|
|
|
|
Type::new_with_resolver_inner(db, &resolver, ty)
|
|
|
|
}
|
|
|
|
|
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> {
|
2023-01-09 18:36:22 +00:00
|
|
|
self.has_self_param(db).then_some(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()
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
pub fn num_params(self, db: &dyn HirDatabase) -> usize {
|
|
|
|
db.function_data(self.id).params.len()
|
|
|
|
}
|
|
|
|
|
2021-08-27 21:21:21 +00:00
|
|
|
pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
|
2024-01-19 15:29:07 +00:00
|
|
|
self.self_param(db)?;
|
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
|
|
|
}
|
|
|
|
|
2024-02-01 09:02:19 +00:00
|
|
|
// FIXME: Find better API to also handle const generics
|
|
|
|
pub fn params_without_self_with_args(
|
2023-12-11 15:04:20 +00:00
|
|
|
self,
|
|
|
|
db: &dyn HirDatabase,
|
2024-02-01 09:02:19 +00:00
|
|
|
generics: impl Iterator<Item = Type>,
|
2023-12-11 15:04:20 +00:00
|
|
|
) -> Vec<Param> {
|
|
|
|
let environment = db.trait_environment(self.id.into());
|
|
|
|
let parent_id: Option<GenericDefId> = match self.id.lookup(db.upcast()).container {
|
|
|
|
ItemContainerId::ImplId(it) => Some(it.into()),
|
|
|
|
ItemContainerId::TraitId(it) => Some(it.into()),
|
|
|
|
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
|
|
|
|
};
|
2024-03-17 11:50:22 +00:00
|
|
|
let mut generics = generics.map(|it| it.ty);
|
2023-12-11 15:04:20 +00:00
|
|
|
let parent_substs = parent_id.map(|id| {
|
|
|
|
TyBuilder::subst_for_def(db, id, None)
|
2024-02-01 09:02:19 +00:00
|
|
|
.fill(|x| match x {
|
|
|
|
ParamKind::Type => generics
|
|
|
|
.next()
|
|
|
|
.unwrap_or_else(|| TyKind::Error.intern(Interner))
|
|
|
|
.cast(Interner),
|
|
|
|
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
|
2024-03-08 12:35:44 +00:00
|
|
|
ParamKind::Lifetime => error_lifetime().cast(Interner),
|
2023-12-11 15:04:20 +00:00
|
|
|
})
|
|
|
|
.build()
|
|
|
|
});
|
|
|
|
|
|
|
|
let substs = TyBuilder::subst_for_def(db, self.id, parent_substs)
|
|
|
|
.fill(|_| {
|
2024-02-01 09:02:19 +00:00
|
|
|
let ty = generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
|
|
|
|
GenericArg::new(Interner, GenericArgData::Ty(ty))
|
2023-12-11 15:04:20 +00:00
|
|
|
})
|
|
|
|
.build();
|
|
|
|
let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
|
|
|
|
let skip = if db.function_data(self.id).has_self_param() { 1 } else { 0 };
|
|
|
|
callable_sig
|
|
|
|
.params()
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.skip(skip)
|
|
|
|
.map(|(idx, ty)| {
|
|
|
|
let ty = Type { env: environment.clone(), ty: ty.clone() };
|
|
|
|
Param { func: self, ty, idx }
|
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2023-07-17 13:49:15 +00:00
|
|
|
/// Does this function have `#[test]` attribute?
|
|
|
|
pub fn is_test(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.function_data(self.id).attrs.is_test()
|
|
|
|
}
|
|
|
|
|
2023-11-08 06:15:03 +00:00
|
|
|
/// is this a `fn main` or a function with an `export_name` of `main`?
|
|
|
|
pub fn is_main(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
let data = db.function_data(self.id);
|
2024-04-04 12:51:10 +00:00
|
|
|
data.attrs.export_name() == Some("main")
|
|
|
|
|| self.module(db).is_crate_root() && data.name.to_smol_str() == "main"
|
|
|
|
}
|
2023-11-08 06:15:03 +00:00
|
|
|
|
2024-04-04 12:51:10 +00:00
|
|
|
/// Is this a function with an `export_name` of `main`?
|
|
|
|
pub fn exported_main(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
let data = db.function_data(self.id);
|
|
|
|
data.attrs.export_name() == Some("main")
|
2023-11-08 06:15:03 +00:00
|
|
|
}
|
|
|
|
|
2023-07-17 13:49:15 +00:00
|
|
|
/// Does this function have the ignore attribute?
|
|
|
|
pub fn is_ignore(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.function_data(self.id).attrs.is_ignore()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Does this function have `#[bench]` attribute?
|
|
|
|
pub fn is_bench(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.function_data(self.id).attrs.is_bench()
|
|
|
|
}
|
|
|
|
|
2023-12-11 15:04:20 +00:00
|
|
|
/// Is this function marked as unstable with `#[feature]` attribute?
|
|
|
|
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.function_data(self.id).attrs.is_unstable()
|
|
|
|
}
|
|
|
|
|
2022-04-07 16:33:03 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-02-10 10:37:59 +00:00
|
|
|
let def_map = db.crate_def_map(HasModule::krate(&self.id, db.upcast()));
|
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
|
|
|
}
|
2023-03-13 08:42:24 +00:00
|
|
|
|
|
|
|
pub fn eval(
|
|
|
|
self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
span_formatter: impl Fn(FileId, TextRange) -> String,
|
|
|
|
) -> String {
|
|
|
|
let body = match db.monomorphized_mir_body(
|
|
|
|
self.id.into(),
|
|
|
|
Substitution::empty(Interner),
|
|
|
|
db.trait_environment(self.id.into()),
|
2023-06-05 09:04:23 +00:00
|
|
|
) {
|
2023-03-13 08:42:24 +00:00
|
|
|
Ok(body) => body,
|
|
|
|
Err(e) => {
|
|
|
|
let mut r = String::new();
|
|
|
|
_ = e.pretty_print(&mut r, db, &span_formatter);
|
|
|
|
return r;
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
};
|
2024-01-06 18:20:13 +00:00
|
|
|
let (result, output) = interpret_mir(db, body, false, None);
|
2022-04-15 18:14:35 +00:00
|
|
|
let mut text = match result {
|
2024-02-09 15:33:00 +00:00
|
|
|
Ok(_) => "pass".to_owned(),
|
2021-06-12 14:39:46 +00:00
|
|
|
Err(e) => {
|
2021-03-15 09:11:48 +00:00
|
|
|
let mut r = String::new();
|
2022-04-16 14:18:42 +00:00
|
|
|
_ = e.pretty_print(&mut r, db, &span_formatter);
|
2023-06-05 09:04:23 +00:00
|
|
|
r
|
|
|
|
}
|
|
|
|
};
|
2024-01-06 18:20:13 +00:00
|
|
|
let stdout = output.stdout().into_owned();
|
2021-03-08 19:08:30 +00:00
|
|
|
if !stdout.is_empty() {
|
2023-06-05 09:04:23 +00:00
|
|
|
text += "\n--------- stdout ---------\n";
|
|
|
|
text += &stdout;
|
|
|
|
}
|
2024-01-06 18:20:13 +00:00
|
|
|
let stderr = output.stdout().into_owned();
|
2021-03-08 19:08:30 +00:00
|
|
|
if !stderr.is_empty() {
|
2022-03-20 18:20:16 +00:00
|
|
|
text += "\n--------- stderr ---------\n";
|
2023-06-05 09:04:23 +00:00
|
|
|
text += &stderr;
|
|
|
|
}
|
|
|
|
text
|
2023-03-13 08:42:24 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Note: logically, this belongs to `hir_ty`, but we are not using it there yet.
|
2022-05-16 17:10:38 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
2021-03-08 19:08:30 +00:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-27 19:53:29 +00:00
|
|
|
#[derive(Clone, PartialEq, Eq, Hash, 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 {
|
2024-03-05 15:01:01 +00:00
|
|
|
pub fn parent_fn(&self) -> Function {
|
|
|
|
self.func
|
|
|
|
}
|
|
|
|
|
2024-03-05 15:02:22 +00:00
|
|
|
pub fn index(&self) -> usize {
|
|
|
|
self.idx
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
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> {
|
|
|
|
Some(self.as_local(db)?.name(db))
|
|
|
|
}
|
|
|
|
|
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);
|
2024-03-06 14:57:05 +00:00
|
|
|
if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
|
|
|
|
Some(Local { parent, binding_id: self_param })
|
|
|
|
} else if let Pat::Bind { id, .. } =
|
|
|
|
&body[body.params[self.idx - body.self_param.is_some() as usize]]
|
|
|
|
{
|
2023-03-13 08:42:24 +00:00
|
|
|
Some(Local { parent, binding_id: *id })
|
2022-04-08 22:55:45 +00:00
|
|
|
} 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() {
|
2024-03-06 14:57:05 +00:00
|
|
|
params.params().nth(self.idx.checked_sub(params.self_param().is_some() as usize)?)
|
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
|
|
|
|
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
|
|
|
|
2024-03-05 15:01:01 +00:00
|
|
|
pub fn parent_fn(&self) -> Function {
|
|
|
|
Function::from(self.func)
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
2023-12-11 15:04:20 +00:00
|
|
|
|
2024-02-01 09:02:19 +00:00
|
|
|
// FIXME: Find better API to also handle const generics
|
2024-01-06 13:17:16 +00:00
|
|
|
pub fn ty_with_args(&self, db: &dyn HirDatabase, generics: impl Iterator<Item = Type>) -> Type {
|
2023-12-11 15:04:20 +00:00
|
|
|
let parent_id: GenericDefId = match self.func.lookup(db.upcast()).container {
|
|
|
|
ItemContainerId::ImplId(it) => it.into(),
|
|
|
|
ItemContainerId::TraitId(it) => it.into(),
|
|
|
|
ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
|
|
|
|
panic!("Never get here")
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-03-17 11:50:22 +00:00
|
|
|
let mut generics = generics.map(|it| it.ty);
|
2024-02-01 09:02:19 +00:00
|
|
|
let mut filler = |x: &_| match x {
|
|
|
|
ParamKind::Type => {
|
|
|
|
generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
|
2024-01-06 13:17:16 +00:00
|
|
|
}
|
2024-02-01 09:02:19 +00:00
|
|
|
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
|
2024-03-08 12:35:44 +00:00
|
|
|
ParamKind::Lifetime => error_lifetime().cast(Interner),
|
2024-01-06 13:17:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let parent_substs = TyBuilder::subst_for_def(db, parent_id, None).fill(&mut filler).build();
|
|
|
|
let substs =
|
|
|
|
TyBuilder::subst_for_def(db, self.func, Some(parent_substs)).fill(&mut filler).build();
|
2023-12-11 15:04:20 +00:00
|
|
|
let callable_sig =
|
|
|
|
db.callable_item_signature(self.func.into()).substitute(Interner, &substs);
|
|
|
|
let environment = db.trait_environment(self.func.into());
|
|
|
|
let ty = callable_sig.params()[0].clone();
|
|
|
|
Type { env: environment, ty }
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-07 09:03:15 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct ExternCrateDecl {
|
|
|
|
pub(crate) id: ExternCrateId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ExternCrateDecl {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
self.id.module(db.upcast()).into()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn resolved_crate(self, db: &dyn HirDatabase) -> Option<Crate> {
|
|
|
|
db.extern_crate_decl_data(self.id).crate_id.map(Into::into)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
db.extern_crate_decl_data(self.id).name.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> {
|
|
|
|
db.extern_crate_decl_data(self.id).alias.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the name under which this crate is made accessible, taking `_` into account.
|
|
|
|
pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> {
|
|
|
|
let extern_crate_decl_data = db.extern_crate_decl_data(self.id);
|
|
|
|
match &extern_crate_decl_data.alias {
|
|
|
|
Some(ImportAlias::Underscore) => None,
|
|
|
|
Some(ImportAlias::Alias(alias)) => Some(alias.clone()),
|
|
|
|
None => Some(extern_crate_decl_data.name.clone()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasVisibility for ExternCrateDecl {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
db.extern_crate_decl_data(self.id)
|
|
|
|
.visibility
|
|
|
|
.resolve(db.upcast(), &self.id.resolver(db.upcast()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-19 06:14:04 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct InTypeConst {
|
|
|
|
pub(crate) id: InTypeConstId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl InTypeConst {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
Module { id: self.id.lookup(db.upcast()).owner.module(db.upcast()) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 {
|
2024-02-10 10:37:59 +00:00
|
|
|
Module { id: self.id.module(db.upcast()) }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::from_value_def(db, self.id)
|
2021-03-15 16:05:03 +00:00
|
|
|
}
|
2021-12-04 22:21:36 +00:00
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
|
2023-07-24 09:21:34 +00:00
|
|
|
let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?;
|
2023-07-17 13:49:15 +00:00
|
|
|
let data = &c.data(Interner);
|
|
|
|
if let TyKind::Scalar(s) = data.ty.kind(Interner) {
|
|
|
|
if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) {
|
|
|
|
if let hir_ty::ConstValue::Concrete(c) = &data.value {
|
|
|
|
if let hir_ty::ConstScalar::Bytes(b, _) = &c.interned {
|
|
|
|
let value = u128::from_le_bytes(mir::pad16(b, false));
|
|
|
|
let value_signed =
|
|
|
|
i128::from_le_bytes(mir::pad16(b, matches!(s, Scalar::Int(_))));
|
|
|
|
if value >= 10 {
|
|
|
|
return Ok(format!("{} ({:#X})", value_signed, value));
|
|
|
|
} else {
|
|
|
|
return Ok(format!("{}", value_signed));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Ok(s) = mir::render_const_using_debug_impl(db, self.id, &c) {
|
2024-01-19 14:41:23 +00:00
|
|
|
Ok(s)
|
|
|
|
} else {
|
|
|
|
Ok(format!("{}", c.display(db)))
|
2023-07-17 13:49:15 +00:00
|
|
|
}
|
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 {
|
2024-02-10 10:37:59 +00:00
|
|
|
Module { id: self.id.module(db.upcast()) }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
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 {
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::from_value_def(db, self.id)
|
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> {
|
2023-02-13 11:55:14 +00:00
|
|
|
db.lang_item(krate.into(), LangItem::from_name(name)?)
|
2022-01-06 12:31:36 +00:00
|
|
|
.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()
|
|
|
|
}
|
|
|
|
|
2022-05-09 15:30:49 +00:00
|
|
|
pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
|
|
|
|
let traits = all_super_traits(db.upcast(), self.into());
|
|
|
|
traits.iter().flat_map(|tr| Trait::from(*tr).items(db)).collect()
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
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
|
|
|
|
}
|
2022-07-06 14:58:27 +00:00
|
|
|
|
2022-07-06 16:43:59 +00:00
|
|
|
pub fn type_or_const_param_count(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
count_required_only: bool,
|
|
|
|
) -> usize {
|
2022-07-06 14:58:27 +00:00
|
|
|
db.generic_params(GenericDefId::from(self.id))
|
|
|
|
.type_or_consts
|
|
|
|
.iter()
|
2024-01-19 14:14:29 +00:00
|
|
|
.filter(|(_, ty)| !matches!(ty, TypeOrConstParamData::TypeParamData(ty) if ty.provenance != TypeParamProvenance::TypeParamList))
|
2022-07-06 16:43:59 +00:00
|
|
|
.filter(|(_, ty)| !count_required_only || !ty.has_default())
|
|
|
|
.count()
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct TraitAlias {
|
|
|
|
pub(crate) id: TraitAliasId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TraitAlias {
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
Module { id: self.id.lookup(db.upcast()).container }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
db.trait_alias_data(self.id).name.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasVisibility for TraitAlias {
|
|
|
|
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
|
|
|
|
db.trait_alias_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) {
|
2023-07-17 13:49:15 +00:00
|
|
|
GenericArgData::Ty(it) => it.is_unknown(),
|
2022-03-09 18:50:24 +00:00
|
|
|
_ => false,
|
|
|
|
})
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
2024-02-10 10:37:59 +00:00
|
|
|
Module { id: self.id.module(db.upcast()) }
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2024-03-21 08:33:17 +00:00
|
|
|
ProcMacroKind::Bang => MacroKind::ProcMacro,
|
2022-03-09 10:26:06 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2024-03-14 11:02:23 +00:00
|
|
|
pub fn is_env_or_option_env(&self, db: &dyn HirDatabase) -> bool {
|
|
|
|
match self.id {
|
|
|
|
MacroId::Macro2Id(it) => {
|
|
|
|
matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
|
|
|
|
}
|
|
|
|
MacroId::MacroRulesId(_) | MacroId::ProcMacroId(_) => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2024-02-19 17:14:48 +00:00
|
|
|
/// Invariant: `inner.as_extern_assoc_item(db).is_some()`
|
|
|
|
/// We do not actively enforce this invariant.
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
|
|
|
pub enum ExternAssocItem {
|
|
|
|
Function(Function),
|
|
|
|
Static(Static),
|
|
|
|
TypeAlias(TypeAlias),
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait AsExternAssocItem {
|
|
|
|
fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AsExternAssocItem for Function {
|
|
|
|
fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
|
|
|
|
as_extern_assoc_item(db, ExternAssocItem::Function, self.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AsExternAssocItem for Static {
|
|
|
|
fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
|
|
|
|
as_extern_assoc_item(db, ExternAssocItem::Static, self.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AsExternAssocItem for TypeAlias {
|
|
|
|
fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
|
|
|
|
as_extern_assoc_item(db, ExternAssocItem::TypeAlias, self.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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),
|
|
|
|
}
|
2024-02-10 00:48:41 +00:00
|
|
|
|
2023-02-13 11:55:14 +00:00
|
|
|
#[derive(Debug, Clone)]
|
2021-03-08 19:08:30 +00:00
|
|
|
pub enum AssocItemContainer {
|
|
|
|
Trait(Trait),
|
|
|
|
Impl(Impl),
|
|
|
|
}
|
2024-02-10 00:48:41 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
2024-02-10 00:48:41 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
impl AsAssocItem for Const {
|
|
|
|
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
|
|
|
|
as_assoc_item(db, AssocItem::Const, self.id)
|
|
|
|
}
|
|
|
|
}
|
2024-02-10 00:48:41 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
impl AsAssocItem for TypeAlias {
|
|
|
|
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
|
|
|
|
as_assoc_item(db, AssocItem::TypeAlias, self.id)
|
|
|
|
}
|
|
|
|
}
|
2024-02-10 00:48:41 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-02-10 00:48:41 +00:00
|
|
|
|
2023-02-13 11:55:14 +00:00
|
|
|
impl AsAssocItem for DefWithBody {
|
|
|
|
fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
|
|
|
|
match self {
|
|
|
|
DefWithBody::Function(it) => it.as_assoc_item(db),
|
|
|
|
DefWithBody::Const(it) => it.as_assoc_item(db),
|
2023-06-19 06:14:04 +00:00
|
|
|
DefWithBody::Static(_) | DefWithBody::Variant(_) | DefWithBody::InTypeConst(_) => None,
|
2023-02-13 11:55:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-10 10:37:59 +00:00
|
|
|
fn as_assoc_item<'db, ID, DEF, LOC>(
|
2023-12-20 20:24:20 +00:00
|
|
|
db: &(dyn HirDatabase + 'db),
|
2024-02-10 00:48:41 +00:00
|
|
|
ctor: impl FnOnce(DEF) -> AssocItem,
|
2023-12-20 20:24:20 +00:00
|
|
|
id: ID,
|
|
|
|
) -> Option<AssocItem>
|
2021-03-08 19:08:30 +00:00
|
|
|
where
|
2024-02-10 10:37:59 +00:00
|
|
|
ID: Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<LOC>>,
|
2021-03-08 19:08:30 +00:00
|
|
|
DEF: From<ID>,
|
2024-02-10 10:37:59 +00:00
|
|
|
LOC: ItemTreeNode,
|
2021-03-08 19:08:30 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-19 17:14:48 +00:00
|
|
|
fn as_extern_assoc_item<'db, ID, DEF, LOC>(
|
|
|
|
db: &(dyn HirDatabase + 'db),
|
|
|
|
ctor: impl FnOnce(DEF) -> ExternAssocItem,
|
|
|
|
id: ID,
|
|
|
|
) -> Option<ExternAssocItem>
|
|
|
|
where
|
|
|
|
ID: Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<LOC>>,
|
|
|
|
DEF: From<ID>,
|
|
|
|
LOC: ItemTreeNode,
|
|
|
|
{
|
|
|
|
match id.lookup(db.upcast()).container {
|
|
|
|
ItemContainerId::ExternBlockId(_) => Some(ctor(DEF::from(id))),
|
|
|
|
ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) | ItemContainerId::ModuleId(_) => {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ExternAssocItem {
|
|
|
|
pub fn name(self, db: &dyn HirDatabase) -> Name {
|
|
|
|
match self {
|
|
|
|
Self::Function(it) => it.name(db),
|
|
|
|
Self::Static(it) => it.name(db),
|
|
|
|
Self::TypeAlias(it) => it.name(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
|
|
|
match self {
|
|
|
|
Self::Function(f) => f.module(db),
|
|
|
|
Self::Static(c) => c.module(db),
|
|
|
|
Self::TypeAlias(t) => t.module(db),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_function(self) -> Option<Function> {
|
|
|
|
match self {
|
|
|
|
Self::Function(v) => Some(v),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_static(self) -> Option<Static> {
|
|
|
|
match self {
|
|
|
|
Self::Static(v) => Some(v),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_type_alias(self) -> Option<TypeAlias> {
|
|
|
|
match self {
|
|
|
|
Self::TypeAlias(v) => Some(v),
|
|
|
|
_ => 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)),
|
|
|
|
}
|
|
|
|
}
|
2024-01-16 15:15:56 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
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),
|
|
|
|
}
|
|
|
|
}
|
2024-01-16 15:15:56 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-10 00:48:41 +00:00
|
|
|
pub fn container_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
|
2021-03-08 19:08:30 +00:00
|
|
|
match self.container(db) {
|
|
|
|
AssocItemContainer::Trait(t) => Some(t),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2021-06-11 17:23:59 +00:00
|
|
|
|
2024-02-10 00:48:41 +00:00
|
|
|
pub fn implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
|
2021-06-11 17:23:59 +00:00
|
|
|
match self.container(db) {
|
|
|
|
AssocItemContainer::Impl(i) => i.trait_(db),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-10 00:48:41 +00:00
|
|
|
pub fn container_or_implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
|
2021-06-11 17:23:59 +00:00
|
|
|
match self.container(db) {
|
|
|
|
AssocItemContainer::Trait(t) => Some(t),
|
|
|
|
AssocItemContainer::Impl(i) => i.trait_(db),
|
|
|
|
}
|
|
|
|
}
|
2024-01-16 15:15:56 +00:00
|
|
|
|
2024-02-10 00:48:41 +00:00
|
|
|
pub fn implementing_ty(self, db: &dyn HirDatabase) -> Option<Type> {
|
|
|
|
match self.container(db) {
|
|
|
|
AssocItemContainer::Impl(i) => Some(i.self_ty(db)),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-16 15:15:56 +00:00
|
|
|
pub fn as_function(self) -> Option<Function> {
|
|
|
|
match self {
|
|
|
|
Self::Function(v) => Some(v),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_const(self) -> Option<Const> {
|
|
|
|
match self {
|
|
|
|
Self::Const(v) => Some(v),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_type_alias(self) -> Option<TypeAlias> {
|
|
|
|
match self {
|
|
|
|
Self::TypeAlias(v) => Some(v),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2024-02-02 10:16:49 +00:00
|
|
|
|
2024-03-05 10:41:46 +00:00
|
|
|
pub fn diagnostics(
|
|
|
|
self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
acc: &mut Vec<AnyDiagnostic>,
|
|
|
|
style_lints: bool,
|
|
|
|
) {
|
2024-02-02 10:16:49 +00:00
|
|
|
match self {
|
|
|
|
AssocItem::Function(func) => {
|
2024-03-05 10:41:46 +00:00
|
|
|
DefWithBody::from(func).diagnostics(db, acc, style_lints);
|
2024-02-02 10:16:49 +00:00
|
|
|
}
|
|
|
|
AssocItem::Const(const_) => {
|
2024-03-05 10:41:46 +00:00
|
|
|
DefWithBody::from(const_).diagnostics(db, acc, style_lints);
|
2024-02-02 10:16:49 +00:00
|
|
|
}
|
|
|
|
AssocItem::TypeAlias(type_alias) => {
|
|
|
|
for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) {
|
|
|
|
acc.push(diag.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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),
|
2023-03-13 08:42:24 +00:00
|
|
|
TraitAlias(TraitAlias),
|
2021-03-08 19:08:30 +00:00
|
|
|
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,
|
2023-03-13 08:42:24 +00:00
|
|
|
TraitAlias,
|
2021-03-08 19:08:30 +00:00
|
|
|
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) {
|
2023-07-17 13:49:15 +00:00
|
|
|
Either::Left(it) => GenericParam::ConstParam(it),
|
|
|
|
Either::Right(it) => GenericParam::TypeParam(it),
|
2021-12-29 13:35:59 +00:00
|
|
|
}
|
|
|
|
});
|
2023-06-19 06:14:04 +00:00
|
|
|
self.lifetime_params(db)
|
|
|
|
.into_iter()
|
|
|
|
.map(GenericParam::LifetimeParam)
|
|
|
|
.chain(ty_params)
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn lifetime_params(self, db: &dyn HirDatabase) -> Vec<LifetimeParam> {
|
|
|
|
let generics = db.generic_params(self.into());
|
|
|
|
generics
|
2021-03-08 19:08:30 +00:00
|
|
|
.lifetimes
|
|
|
|
.iter()
|
|
|
|
.map(|(local_id, _)| LifetimeParam {
|
|
|
|
id: LifetimeParamId { parent: self.into(), local_id },
|
|
|
|
})
|
2023-06-19 06:14:04 +00:00
|
|
|
.collect()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2023-12-16 14:29:23 +00:00
|
|
|
pub fn type_or_const_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.
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct Local {
|
|
|
|
pub(crate) parent: DefWithBodyId,
|
2023-03-13 08:42:24 +00:00
|
|
|
pub(crate) binding_id: BindingId,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct LocalSource {
|
|
|
|
pub local: Local,
|
|
|
|
pub source: InFile<Either<ast::IdentPat, ast::SelfParam>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LocalSource {
|
|
|
|
pub fn as_ident_pat(&self) -> Option<&ast::IdentPat> {
|
|
|
|
match &self.source.value {
|
2023-07-17 13:49:15 +00:00
|
|
|
Either::Left(it) => Some(it),
|
2023-03-13 08:42:24 +00:00
|
|
|
Either::Right(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_ident_pat(self) -> Option<ast::IdentPat> {
|
|
|
|
match self.source.value {
|
2023-07-17 13:49:15 +00:00
|
|
|
Either::Left(it) => Some(it),
|
2023-03-13 08:42:24 +00:00
|
|
|
Either::Right(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn original_file(&self, db: &dyn HirDatabase) -> FileId {
|
|
|
|
self.source.file_id.original_file(db.upcast())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn file(&self) -> HirFileId {
|
|
|
|
self.source.file_id
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
pub fn name(&self) -> Option<InFile<ast::Name>> {
|
|
|
|
self.source.as_ref().map(|it| it.name()).transpose()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn syntax(&self) -> &SyntaxNode {
|
|
|
|
self.source.value.syntax()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn syntax_ptr(self) -> InFile<SyntaxNodePtr> {
|
2023-07-17 13:49:15 +00:00
|
|
|
self.source.map(|it| SyntaxNodePtr::new(it.syntax()))
|
2023-03-13 08:42:24 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Local {
|
|
|
|
pub fn is_param(self, db: &dyn HirDatabase) -> bool {
|
2024-01-16 15:15:56 +00:00
|
|
|
// FIXME: This parses!
|
2023-03-13 08:42:24 +00:00
|
|
|
let src = self.primary_source(db);
|
|
|
|
match src.source.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);
|
2023-03-13 08:42:24 +00:00
|
|
|
body[self.binding_id].name.clone()
|
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);
|
2023-03-13 08:42:24 +00:00
|
|
|
body[self.binding_id].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);
|
2023-03-13 08:42:24 +00:00
|
|
|
matches!(body[self.binding_id].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);
|
2023-03-13 08:42:24 +00:00
|
|
|
let ty = infer[self.binding_id].clone();
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new(db, def, ty)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2023-07-17 13:49:15 +00:00
|
|
|
/// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = it;`
|
2023-03-13 08:42:24 +00:00
|
|
|
pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource> {
|
|
|
|
let (body, source_map) = db.body_with_source_map(self.parent);
|
2024-03-06 14:57:05 +00:00
|
|
|
match body.self_param.zip(source_map.self_param_syntax()) {
|
|
|
|
Some((param, source)) if param == self.binding_id => {
|
|
|
|
let root = source.file_syntax(db.upcast());
|
|
|
|
vec![LocalSource {
|
|
|
|
local: self,
|
|
|
|
source: source.map(|ast| Either::Right(ast.to_node(&root))),
|
|
|
|
}]
|
|
|
|
}
|
|
|
|
_ => body[self.binding_id]
|
|
|
|
.definitions
|
|
|
|
.iter()
|
|
|
|
.map(|&definition| {
|
|
|
|
let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
|
|
|
|
let root = src.file_syntax(db.upcast());
|
|
|
|
LocalSource {
|
|
|
|
local: self,
|
|
|
|
source: src.map(|ast| match ast.to_node(&root) {
|
|
|
|
ast::Pat::IdentPat(it) => Either::Left(it),
|
|
|
|
_ => unreachable!("local with non ident-pattern"),
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
}
|
2023-06-19 06:14:04 +00:00
|
|
|
}
|
|
|
|
|
2023-07-17 13:49:15 +00:00
|
|
|
/// The leftmost definition for this local. Example: `let (a$0, _) | (_, a) = it;`
|
2023-06-19 06:14:04 +00:00
|
|
|
pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource {
|
|
|
|
let (body, source_map) = db.body_with_source_map(self.parent);
|
2024-03-06 14:57:05 +00:00
|
|
|
match body.self_param.zip(source_map.self_param_syntax()) {
|
|
|
|
Some((param, source)) if param == self.binding_id => {
|
|
|
|
let root = source.file_syntax(db.upcast());
|
|
|
|
LocalSource {
|
|
|
|
local: self,
|
|
|
|
source: source.map(|ast| Either::Right(ast.to_node(&root))),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => body[self.binding_id]
|
|
|
|
.definitions
|
|
|
|
.first()
|
|
|
|
.map(|&definition| {
|
|
|
|
let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
|
|
|
|
let root = src.file_syntax(db.upcast());
|
|
|
|
LocalSource {
|
|
|
|
local: self,
|
|
|
|
source: src.map(|ast| match ast.to_node(&root) {
|
|
|
|
ast::Pat::IdentPat(it) => Either::Left(it),
|
|
|
|
_ => unreachable!("local with non ident-pattern"),
|
|
|
|
}),
|
|
|
|
}
|
2023-03-13 08:42:24 +00:00
|
|
|
})
|
2024-03-06 14:57:05 +00:00
|
|
|
.unwrap(),
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-26 09:53:50 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct DeriveHelper {
|
|
|
|
pub(crate) derive: MacroId,
|
2023-02-13 11:55:14 +00:00
|
|
|
pub(crate) idx: u32,
|
2022-07-26 09:53:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl DeriveHelper {
|
|
|
|
pub fn derive(&self) -> Macro {
|
2023-01-09 18:36:22 +00:00
|
|
|
Macro { id: self.derive }
|
2022-07-26 09:53:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn name(&self, db: &dyn HirDatabase) -> Name {
|
|
|
|
match self.derive {
|
2023-02-13 11:55:14 +00:00
|
|
|
MacroId::Macro2Id(it) => db
|
|
|
|
.macro2_data(it)
|
|
|
|
.helpers
|
|
|
|
.as_deref()
|
|
|
|
.and_then(|it| it.get(self.idx as usize))
|
|
|
|
.cloned(),
|
2022-07-26 09:53:50 +00:00
|
|
|
MacroId::MacroRulesId(_) => None,
|
|
|
|
MacroId::ProcMacroId(proc_macro) => db
|
|
|
|
.proc_macro_data(proc_macro)
|
|
|
|
.helpers
|
2023-01-09 18:36:22 +00:00
|
|
|
.as_deref()
|
2023-02-13 11:55:14 +00:00
|
|
|
.and_then(|it| it.get(self.idx as usize))
|
2022-07-26 09:53:50 +00:00
|
|
|
.cloned(),
|
|
|
|
}
|
2024-01-19 15:37:08 +00:00
|
|
|
.unwrap_or_else(Name::missing)
|
2022-07-26 09:53:50 +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>,
|
2023-02-13 11:55:14 +00:00
|
|
|
idx: u32,
|
2022-01-06 13:56:50 +00:00
|
|
|
}
|
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;
|
|
|
|
}
|
2023-02-13 11:55:14 +00:00
|
|
|
let idx =
|
|
|
|
db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)? as u32;
|
2022-01-06 13:56:50 +00:00
|
|
|
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::attr::builtin::find_builtin_attr_idx(name)
|
2023-02-13 11:55:14 +00:00
|
|
|
.map(|idx| BuiltinAttr { krate: None, idx: idx as u32 })
|
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 {
|
2023-02-13 11:55:14 +00:00
|
|
|
Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx as usize].clone(),
|
|
|
|
None => SmolStr::new(hir_def::attr::builtin::INERT_ATTRIBUTES[self.idx as usize].name),
|
2022-01-06 13:56:50 +00:00
|
|
|
}
|
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,
|
2023-02-13 11:55:14 +00:00
|
|
|
None => Some(hir_def::attr::builtin::INERT_ATTRIBUTES[self.idx as usize].template),
|
2022-01-06 13:56:50 +00:00
|
|
|
}
|
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>,
|
2023-02-13 11:55:14 +00:00
|
|
|
idx: u32,
|
2022-01-06 13:56:50 +00:00
|
|
|
}
|
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;
|
|
|
|
}
|
2023-02-13 11:55:14 +00:00
|
|
|
let idx =
|
|
|
|
db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)? as u32;
|
2022-01-06 13:56:50 +00:00
|
|
|
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::attr::builtin::TOOL_MODULES
|
|
|
|
.iter()
|
|
|
|
.position(|&tool| tool == name)
|
2023-02-13 11:55:14 +00:00
|
|
|
.map(|idx| ToolModule { krate: None, idx: idx as u32 })
|
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 {
|
2023-02-13 11:55:14 +00:00
|
|
|
Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx as usize].clone(),
|
|
|
|
None => SmolStr::new(hir_def::attr::builtin::TOOL_MODULES[self.idx as usize]),
|
2022-01-06 13:56:50 +00:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
}
|
2023-02-13 11:55:14 +00:00
|
|
|
|
|
|
|
pub fn parent(self) -> GenericDef {
|
|
|
|
match self {
|
|
|
|
GenericParam::TypeParam(it) => it.id.parent().into(),
|
|
|
|
GenericParam::ConstParam(it) => it.id.parent().into(),
|
|
|
|
GenericParam::LifetimeParam(it) => it.id.parent.into(),
|
|
|
|
}
|
|
|
|
}
|
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> {
|
2023-08-21 09:44:09 +00:00
|
|
|
let ty = generic_arg_from_param(db, self.id.into())?;
|
2021-12-29 13:35:59 +00:00
|
|
|
let resolver = self.id.parent().resolver(db.upcast());
|
2022-03-09 18:50:24 +00:00
|
|
|
match ty.data(Interner) {
|
2023-12-16 14:29:23 +00:00
|
|
|
GenericArgData::Ty(it) if *it.kind(Interner) != TyKind::Error => {
|
2023-07-17 13:49:15 +00:00
|
|
|
Some(Type::new_with_resolver_inner(db, &resolver, it.clone()))
|
|
|
|
}
|
2022-03-09 18:50:24 +00:00
|
|
|
_ => None,
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2023-12-16 14:29:23 +00:00
|
|
|
|
|
|
|
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.attrs(GenericParamId::from(self.id).into()).is_unstable()
|
|
|
|
}
|
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() {
|
2023-07-17 13:49:15 +00:00
|
|
|
Some(it) => it.clone(),
|
2021-12-29 13:35:59 +00:00
|
|
|
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
|
|
|
}
|
2023-08-21 09:44:09 +00:00
|
|
|
|
|
|
|
pub fn default(self, db: &dyn HirDatabase) -> Option<ast::ConstArg> {
|
|
|
|
let arg = generic_arg_from_param(db, self.id.into())?;
|
|
|
|
known_const_to_ast(arg.constant(Interner)?, db)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg> {
|
|
|
|
let params = db.generic_defaults(id.parent);
|
|
|
|
let local_idx = hir_ty::param_idx(db, id)?;
|
|
|
|
let ty = params.get(local_idx)?.clone();
|
|
|
|
let subst = TyBuilder::placeholder_subst(db, id.parent);
|
|
|
|
Some(ty.substitute(Interner, &subst))
|
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) {
|
2023-07-17 13:49:15 +00:00
|
|
|
Either::Left(it) => it.ty(db),
|
|
|
|
Either::Right(it) => it.ty(db),
|
2021-12-29 13:35:59 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2024-02-01 09:02:19 +00:00
|
|
|
|
|
|
|
pub fn as_type_param(self, db: &dyn HirDatabase) -> Option<TypeParam> {
|
|
|
|
let params = db.generic_params(self.id.parent);
|
|
|
|
match ¶ms.type_or_consts[self.id.local_id] {
|
|
|
|
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
|
|
|
|
Some(TypeParam { id: TypeParamId::from_unchecked(self.id) })
|
|
|
|
}
|
|
|
|
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_const_param(self, db: &dyn HirDatabase) -> Option<ConstParam> {
|
|
|
|
let params = db.generic_params(self.id.parent);
|
|
|
|
match ¶ms.type_or_consts[self.id.local_id] {
|
|
|
|
hir_def::generics::TypeOrConstParamData::TypeParamData(_) => None,
|
|
|
|
hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
|
|
|
|
Some(ConstParam { id: ConstParamId::from_unchecked(self.id) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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
|
|
|
});
|
2023-12-11 15:04:20 +00:00
|
|
|
|
2024-02-01 09:02:19 +00:00
|
|
|
for id in def_crates
|
|
|
|
.iter()
|
|
|
|
.flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
|
|
|
|
.map(|Crate { id }| id)
|
|
|
|
{
|
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
|
|
|
}
|
2024-03-11 16:13:13 +00:00
|
|
|
|
|
|
|
if let Some(block) =
|
|
|
|
ty.adt_id(Interner).and_then(|def| def.0.module(db.upcast()).containing_block())
|
|
|
|
{
|
|
|
|
if let Some(inherent_impls) = db.inherent_impls_in_block(block) {
|
|
|
|
all.extend(
|
|
|
|
inherent_impls.for_self_ty(&ty).iter().cloned().map(Self::from).filter(filter),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if let Some(trait_impls) = db.trait_impls_in_block(block) {
|
|
|
|
all.extend(
|
|
|
|
trait_impls
|
|
|
|
.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> {
|
2024-03-11 16:13:13 +00:00
|
|
|
let module = trait_.module(db);
|
|
|
|
let krate = module.krate();
|
2021-03-15 09:11:48 +00:00
|
|
|
let mut all = Vec::new();
|
2023-01-09 18:36:22 +00:00
|
|
|
for Crate { id } in krate.transitive_reverse_dependencies(db) {
|
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))
|
|
|
|
}
|
2024-03-11 16:13:13 +00:00
|
|
|
if let Some(block) = module.id.containing_block() {
|
|
|
|
if let Some(trait_impls) = db.trait_impls_in_block(block) {
|
|
|
|
all.extend(trait_impls.for_trait(trait_.id).map(Self::from));
|
|
|
|
}
|
|
|
|
}
|
2021-03-15 09:11:48 +00:00
|
|
|
all
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2021-06-01 23:16:59 +00:00
|
|
|
pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
|
2023-02-13 11:55:14 +00:00
|
|
|
let trait_ref = db.impl_trait(self.id)?;
|
|
|
|
let id = trait_ref.skip_binders().hir_trait_id();
|
2021-06-01 23:16:59 +00:00
|
|
|
Some(Trait { id })
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2023-02-13 11:55:14 +00:00
|
|
|
pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef> {
|
|
|
|
let substs = TyBuilder::placeholder_subst(db, self.id);
|
|
|
|
let trait_ref = db.impl_trait(self.id)?.substitute(Interner, &substs);
|
|
|
|
let resolver = self.id.resolver(db.upcast());
|
|
|
|
Some(TraitRef::new_with_resolver(db, &resolver, trait_ref))
|
|
|
|
}
|
|
|
|
|
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> {
|
2024-02-10 00:48:41 +00:00
|
|
|
db.impl_data(self.id).items.iter().map(|&it| it.into()).collect()
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
db.impl_data(self.id).is_negative
|
|
|
|
}
|
|
|
|
|
2023-11-14 17:53:17 +00:00
|
|
|
pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
|
2023-11-14 19:02:23 +00:00
|
|
|
db.impl_data(self.id).is_unsafe
|
2023-11-14 17:53:17 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-11-24 15:38:48 +00:00
|
|
|
pub fn as_builtin_derive_path(self, db: &dyn HirDatabase) -> Option<InMacroFile<ast::Path>> {
|
2021-03-08 19:08:30 +00:00
|
|
|
let src = self.source(db)?;
|
2023-11-24 15:38:48 +00:00
|
|
|
|
|
|
|
let macro_file = src.file_id.macro_file()?;
|
2023-12-20 20:24:20 +00:00
|
|
|
let loc = macro_file.macro_call_id.lookup(db.upcast());
|
2023-11-24 15:38:48 +00:00
|
|
|
let (derive_attr, derive_index) = match loc.kind {
|
2024-03-18 11:10:02 +00:00
|
|
|
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
|
2023-11-24 15:38:48 +00:00
|
|
|
let module_id = self.id.lookup(db.upcast()).container;
|
|
|
|
(
|
|
|
|
db.crate_def_map(module_id.krate())[module_id.local_id]
|
|
|
|
.scope
|
|
|
|
.derive_macro_invoc(ast_id, derive_attr_index)?,
|
|
|
|
derive_index,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
_ => return None,
|
|
|
|
};
|
2023-11-25 13:39:55 +00:00
|
|
|
let file_id = MacroFileId { macro_call_id: derive_attr };
|
2023-11-24 15:38:48 +00:00
|
|
|
let path = db
|
|
|
|
.parse_macro_expansion(file_id)
|
|
|
|
.value
|
|
|
|
.0
|
|
|
|
.syntax_node()
|
|
|
|
.children()
|
|
|
|
.nth(derive_index as usize)
|
|
|
|
.and_then(<ast::Attr as AstNode>::cast)
|
|
|
|
.and_then(|it| it.path())?;
|
|
|
|
Some(InMacroFile { file_id, value: path })
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
2023-11-14 17:09:28 +00:00
|
|
|
|
|
|
|
pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
|
|
|
|
check_orphan_rules(db, self.id)
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2023-02-13 11:55:14 +00:00
|
|
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
|
|
|
pub struct TraitRef {
|
|
|
|
env: Arc<TraitEnvironment>,
|
|
|
|
trait_ref: hir_ty::TraitRef,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TraitRef {
|
|
|
|
pub(crate) fn new_with_resolver(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
resolver: &Resolver,
|
|
|
|
trait_ref: hir_ty::TraitRef,
|
|
|
|
) -> TraitRef {
|
2023-12-08 09:47:36 +00:00
|
|
|
let env = resolver
|
|
|
|
.generic_def()
|
|
|
|
.map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
|
2023-02-13 11:55:14 +00:00
|
|
|
TraitRef { env, trait_ref }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn trait_(&self) -> Trait {
|
|
|
|
let id = self.trait_ref.hir_trait_id();
|
|
|
|
Trait { id }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn self_ty(&self) -> Type {
|
|
|
|
let ty = self.trait_ref.self_type_parameter(Interner);
|
|
|
|
Type { env: self.env.clone(), ty }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the
|
|
|
|
/// first argument is the `Self` type.
|
|
|
|
pub fn get_type_argument(&self, idx: usize) -> Option<Type> {
|
|
|
|
self.trait_ref
|
|
|
|
.substitution
|
|
|
|
.as_slice(Interner)
|
|
|
|
.get(idx)
|
|
|
|
.and_then(|arg| arg.ty(Interner))
|
|
|
|
.cloned()
|
|
|
|
.map(|ty| Type { env: self.env.clone(), ty })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
2023-03-13 08:42:24 +00:00
|
|
|
pub struct Closure {
|
2022-05-19 16:53:08 +00:00
|
|
|
id: ClosureId,
|
2021-03-15 20:02:34 +00:00
|
|
|
subst: Substitution,
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2022-05-19 16:53:08 +00:00
|
|
|
impl From<Closure> for ClosureId {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn from(value: Closure) -> Self {
|
2023-06-05 09:04:23 +00:00
|
|
|
value.id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
impl Closure {
|
2021-03-29 15:46:33 +00:00
|
|
|
fn as_ty(self) -> Ty {
|
2021-12-29 13:35:59 +00:00
|
|
|
TyKind::Closure(self.id, self.subst).intern(Interner)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2021-03-07 00:56:07 +00:00
|
|
|
pub fn display_with_id(&self, db: &dyn HirDatabase) -> String {
|
2021-05-23 10:52:41 +00:00
|
|
|
self.clone().as_ty().display(db).with_closure_style(ClosureStyle::ClosureWithId).to_string()
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2021-03-07 00:56:07 +00:00
|
|
|
pub fn display_with_impl(&self, db: &dyn HirDatabase) -> String {
|
2022-03-20 15:19:02 +00:00
|
|
|
self.clone().as_ty().display(db).with_closure_style(ClosureStyle::ImplFn).to_string()
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
pub fn captured_items(&self, db: &dyn HirDatabase) -> Vec<ClosureCapture> {
|
2022-05-19 16:53:08 +00:00
|
|
|
let owner = db.lookup_intern_closure((self.id).into()).0;
|
2021-03-08 19:08:30 +00:00
|
|
|
let infer = &db.infer(owner);
|
2022-04-16 14:18:42 +00:00
|
|
|
let info = infer.closure_info(&self.id);
|
2023-06-05 09:04:23 +00:00
|
|
|
info.0
|
|
|
|
.iter()
|
2023-02-13 11:55:14 +00:00
|
|
|
.cloned()
|
2022-05-19 16:53:08 +00:00
|
|
|
.map(|capture| ClosureCapture { owner, closure: self.id, capture })
|
2021-03-08 19:08:30 +00:00
|
|
|
.collect()
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn capture_types(&self, db: &dyn HirDatabase) -> Vec<Type> {
|
2022-05-19 16:53:08 +00:00
|
|
|
let owner = db.lookup_intern_closure((self.id).into()).0;
|
2021-03-08 19:08:30 +00:00
|
|
|
let infer = &db.infer(owner);
|
2022-05-19 16:53:08 +00:00
|
|
|
let (captures, _) = infer.closure_info(&self.id);
|
2023-06-05 09:04:23 +00:00
|
|
|
captures
|
|
|
|
.iter()
|
2023-02-13 11:55:14 +00:00
|
|
|
.map(|capture| Type {
|
2021-12-19 16:58:39 +00:00
|
|
|
env: db.trait_environment_for_body(owner),
|
2022-04-16 14:18:42 +00:00
|
|
|
ty: capture.ty(&self.subst),
|
2023-06-05 09:04:23 +00:00
|
|
|
})
|
2021-03-08 19:08:30 +00:00
|
|
|
.collect()
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait {
|
2022-05-19 16:53:08 +00:00
|
|
|
let owner = db.lookup_intern_closure((self.id).into()).0;
|
2021-03-08 19:08:30 +00:00
|
|
|
let infer = &db.infer(owner);
|
2022-04-16 14:18:42 +00:00
|
|
|
let info = infer.closure_info(&self.id);
|
2023-06-05 09:04:23 +00:00
|
|
|
info.1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-14 12:26:08 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
2023-03-13 08:42:24 +00:00
|
|
|
pub struct ClosureCapture {
|
|
|
|
owner: DefWithBodyId,
|
2022-05-19 16:53:08 +00:00
|
|
|
closure: ClosureId,
|
2021-12-19 16:58:39 +00:00
|
|
|
capture: hir_ty::CapturedItem,
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2022-08-23 07:05:52 +00:00
|
|
|
impl ClosureCapture {
|
2022-04-08 22:55:45 +00:00
|
|
|
pub fn local(&self) -> Local {
|
2023-03-13 08:42:24 +00:00
|
|
|
Local { parent: self.owner, binding_id: self.capture.local() }
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn kind(&self) -> CaptureKind {
|
2022-05-19 16:53:08 +00:00
|
|
|
match self.capture.kind() {
|
2021-12-19 16:58:39 +00:00
|
|
|
hir_ty::CaptureKind::ByRef(
|
2021-03-08 19:08:30 +00:00
|
|
|
hir_ty::mir::BorrowKind::Shallow | hir_ty::mir::BorrowKind::Shared,
|
2022-05-19 16:53:08 +00:00
|
|
|
) => CaptureKind::SharedRef,
|
2024-02-25 16:57:03 +00:00
|
|
|
hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut {
|
|
|
|
kind: MutBorrowKind::ClosureCapture,
|
|
|
|
}) => CaptureKind::UniqueSharedRef,
|
|
|
|
hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut {
|
|
|
|
kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow,
|
|
|
|
}) => CaptureKind::MutableRef,
|
2021-06-08 15:31:47 +00:00
|
|
|
hir_ty::CaptureKind::ByValue => CaptureKind::Move,
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn display_place(&self, db: &dyn HirDatabase) -> String {
|
2021-12-29 13:35:59 +00:00
|
|
|
self.capture.display_place(self.owner, db)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub enum CaptureKind {
|
2023-06-05 09:04:23 +00:00
|
|
|
SharedRef,
|
|
|
|
UniqueSharedRef,
|
|
|
|
MutableRef,
|
|
|
|
Move,
|
|
|
|
}
|
|
|
|
|
2023-12-11 15:04:20 +00:00
|
|
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
2021-03-08 19:08:30 +00:00
|
|
|
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 {
|
2023-12-08 09:47:36 +00:00
|
|
|
let environment = resolver
|
|
|
|
.generic_def()
|
|
|
|
.map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
|
2022-04-15 18:14:35 +00:00
|
|
|
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 {
|
2023-12-08 09:47:36 +00:00
|
|
|
Type { env: 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 },
|
2024-04-02 12:03:49 +00:00
|
|
|
hir_ty::error_lifetime(),
|
2022-03-20 23:08:12 +00:00
|
|
|
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());
|
2023-12-08 09:47:36 +00:00
|
|
|
let environment = resolver
|
|
|
|
.generic_def()
|
|
|
|
.map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
|
2022-04-15 18:14:35 +00:00
|
|
|
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 Into<TyDefId> + HasResolver) -> Type {
|
2022-10-11 07:37:35 +00:00
|
|
|
let ty = db.ty(def.into());
|
|
|
|
let substs = TyBuilder::unknown_subst(
|
|
|
|
db,
|
|
|
|
match def.into() {
|
2022-05-19 16:53:08 +00:00
|
|
|
TyDefId::AdtId(it) => GenericDefId::AdtId(it),
|
2022-10-11 07:37:35 +00:00
|
|
|
TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it),
|
|
|
|
TyDefId::BuiltinType(_) => return Type::new(db, def, ty.skip_binders().clone()),
|
|
|
|
},
|
|
|
|
);
|
|
|
|
Type::new(db, def, ty.substitute(Interner, &substs))
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2022-10-11 07:37:35 +00:00
|
|
|
fn from_value_def(db: &dyn HirDatabase, def: impl Into<ValueTyDefId> + HasResolver) -> Type {
|
2024-01-16 11:09:40 +00:00
|
|
|
let Some(ty) = db.value_ty(def.into()) else {
|
|
|
|
return Type::new(db, def, TyKind::Error.intern(Interner));
|
|
|
|
};
|
2022-10-11 07:37:35 +00:00
|
|
|
let substs = TyBuilder::unknown_subst(
|
2023-06-05 09:04:23 +00:00
|
|
|
db,
|
2022-10-11 07:37:35 +00:00
|
|
|
match def.into() {
|
2021-12-07 16:31:26 +00:00
|
|
|
ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it),
|
2022-05-19 16:53:08 +00:00
|
|
|
ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it),
|
|
|
|
ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)),
|
|
|
|
ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)),
|
2022-10-11 07:37:35 +00:00
|
|
|
ValueTyDefId::EnumVariantId(it) => GenericDefId::EnumVariantId(it),
|
|
|
|
ValueTyDefId::StaticId(_) => return Type::new(db, def, ty.skip_binders().clone()),
|
2023-06-05 09:04:23 +00:00
|
|
|
},
|
|
|
|
);
|
2022-04-15 18:14:35 +00:00
|
|
|
Type::new(db, def, ty.substitute(Interner, &substs))
|
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
|
|
|
}
|
|
|
|
|
2024-02-25 14:50:34 +00:00
|
|
|
pub fn new_tuple(krate: CrateId, tys: &[Type]) -> Type {
|
|
|
|
let tys = tys.iter().map(|it| it.ty.clone());
|
|
|
|
Type { env: TraitEnvironment::empty(krate), ty: TyBuilder::tuple_with(tys) }
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-12-16 14:29:23 +00:00
|
|
|
pub fn contains_reference(&self, db: &dyn HirDatabase) -> bool {
|
|
|
|
return go(db, self.env.krate, &self.ty);
|
|
|
|
|
|
|
|
fn go(db: &dyn HirDatabase, krate: CrateId, ty: &Ty) -> bool {
|
|
|
|
match ty.kind(Interner) {
|
|
|
|
// Reference itself
|
|
|
|
TyKind::Ref(_, _, _) => true,
|
|
|
|
|
|
|
|
// For non-phantom_data adts we check variants/fields as well as generic parameters
|
|
|
|
TyKind::Adt(adt_id, substitution)
|
2022-08-23 12:56:56 +00:00
|
|
|
if !db.adt_datum(krate, *adt_id).flags.phantom_data =>
|
2023-12-16 14:29:23 +00:00
|
|
|
{
|
2022-08-23 12:56:56 +00:00
|
|
|
let adt_datum = &db.adt_datum(krate, *adt_id);
|
2023-12-16 14:29:23 +00:00
|
|
|
let adt_datum_bound =
|
|
|
|
adt_datum.binders.clone().substitute(Interner, substitution);
|
|
|
|
adt_datum_bound
|
|
|
|
.variants
|
|
|
|
.into_iter()
|
|
|
|
.flat_map(|variant| variant.fields.into_iter())
|
|
|
|
.any(|ty| go(db, krate, &ty))
|
|
|
|
|| substitution
|
|
|
|
.iter(Interner)
|
|
|
|
.filter_map(|x| x.ty(Interner))
|
|
|
|
.any(|ty| go(db, krate, ty))
|
|
|
|
}
|
|
|
|
// And for `PhantomData<T>`, we check `T`.
|
|
|
|
TyKind::Adt(_, substitution)
|
|
|
|
| TyKind::Tuple(_, substitution)
|
|
|
|
| TyKind::OpaqueType(_, substitution)
|
|
|
|
| TyKind::AssociatedType(_, substitution)
|
|
|
|
| TyKind::FnDef(_, substitution) => substitution
|
|
|
|
.iter(Interner)
|
|
|
|
.filter_map(|x| x.ty(Interner))
|
|
|
|
.any(|ty| go(db, krate, ty)),
|
|
|
|
|
|
|
|
// For `[T]` or `*T` we check `T`
|
|
|
|
TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) => go(db, krate, ty),
|
|
|
|
|
|
|
|
// Consider everything else as not reference
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-03-20 06:31:01 +00:00
|
|
|
pub fn is_float(&self) -> bool {
|
|
|
|
matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Float(_)))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_char(&self) -> bool {
|
|
|
|
matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Char))
|
|
|
|
}
|
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
pub fn is_int_or_uint(&self) -> bool {
|
2024-01-19 14:14:29 +00:00
|
|
|
matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)))
|
2023-01-09 18:36:22 +00:00
|
|
|
}
|
|
|
|
|
2023-06-19 06:14:04 +00:00
|
|
|
pub fn is_scalar(&self) -> bool {
|
|
|
|
matches!(self.ty.kind(Interner), TyKind::Scalar(_))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_tuple(&self) -> bool {
|
|
|
|
matches!(self.ty.kind(Interner), TyKind::Tuple(..))
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-20 06:31:01 +00:00
|
|
|
pub fn as_slice(&self) -> Option<Type> {
|
|
|
|
match &self.ty.kind(Interner) {
|
|
|
|
TyKind::Slice(ty) => Some(self.derived(ty.clone())),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-05 20:55:12 +00:00
|
|
|
pub fn strip_references(&self) -> Type {
|
|
|
|
self.derived(self.ty.strip_references().clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn strip_reference(&self) -> Type {
|
|
|
|
self.derived(self.ty.strip_reference().clone())
|
2022-08-02 06:05:16 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2022-08-23 07:05:52 +00:00
|
|
|
/// Checks that particular type `ty` implements `std::future::IntoFuture` or
|
|
|
|
/// `std::future::Future`.
|
2021-03-08 19:08:30 +00:00
|
|
|
/// This function is used in `.await` syntax completion.
|
2022-08-23 07:05:52 +00:00
|
|
|
pub fn impls_into_future(&self, db: &dyn HirDatabase) -> bool {
|
|
|
|
let trait_ = db
|
2023-02-13 11:55:14 +00:00
|
|
|
.lang_item(self.env.krate, LangItem::IntoFutureIntoFuture)
|
2022-08-23 07:05:52 +00:00
|
|
|
.and_then(|it| {
|
|
|
|
let into_future_fn = it.as_function()?;
|
|
|
|
let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
|
2024-02-10 00:48:41 +00:00
|
|
|
let into_future_trait = assoc_item.container_or_implemented_trait(db)?;
|
2022-08-23 07:05:52 +00:00
|
|
|
Some(into_future_trait.id)
|
|
|
|
})
|
|
|
|
.or_else(|| {
|
2023-02-13 11:55:14 +00:00
|
|
|
let future_trait = db.lang_item(self.env.krate, LangItem::Future)?;
|
2022-08-23 07:05:52 +00:00
|
|
|
future_trait.as_trait()
|
|
|
|
});
|
|
|
|
|
|
|
|
let trait_ = match trait_ {
|
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) };
|
2024-03-04 15:04:19 +00:00
|
|
|
method_resolution::implements_trait(&canonical_ty, db, &self.env, 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) };
|
2024-03-04 15:04:19 +00:00
|
|
|
method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, fnonce_trait)
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2024-02-01 09:02:19 +00:00
|
|
|
// FIXME: Find better API that also handles const generics
|
2021-03-08 19:08:30 +00:00
|
|
|
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| {
|
|
|
|
match x {
|
2024-02-01 09:02:19 +00:00
|
|
|
ParamKind::Type => {
|
|
|
|
it.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
|
|
|
|
}
|
2022-03-09 18:50:24 +00:00
|
|
|
ParamKind::Const(ty) => {
|
|
|
|
// FIXME: this code is not covered in tests.
|
|
|
|
unknown_const_as_generic(ty.clone())
|
|
|
|
}
|
2024-03-08 12:35:44 +00:00
|
|
|
ParamKind::Lifetime => error_lifetime().cast(Interner),
|
2022-03-09 18:50:24 +00:00
|
|
|
}
|
|
|
|
})
|
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, self.env.block, 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();
|
2022-10-11 07:37:35 +00:00
|
|
|
let trait_id = match alias.id.lookup(db.upcast()).container {
|
|
|
|
ItemContainerId::TraitId(id) => id,
|
|
|
|
_ => unreachable!("non assoc type alias reached in normalize_trait_assoc_type()"),
|
|
|
|
};
|
|
|
|
let parent_subst = TyBuilder::subst_for_def(db, trait_id, None)
|
2021-03-21 19:19:07 +00:00
|
|
|
.push(self.ty.clone())
|
2023-07-17 13:49:15 +00:00
|
|
|
.fill(|it| {
|
2022-03-09 18:50:24 +00:00
|
|
|
// FIXME: this code is not covered in tests.
|
2023-07-17 13:49:15 +00:00
|
|
|
match it {
|
2023-08-21 09:44:09 +00:00
|
|
|
ParamKind::Type => args.next().unwrap().ty.clone().cast(Interner),
|
2022-03-09 18:50:24 +00:00
|
|
|
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
|
2024-03-08 12:35:44 +00:00
|
|
|
ParamKind::Lifetime => error_lifetime().cast(Interner),
|
2022-03-09 18:50:24 +00:00
|
|
|
}
|
|
|
|
})
|
2021-03-08 19:08:30 +00:00
|
|
|
.build();
|
2022-10-11 07:37:35 +00:00
|
|
|
// FIXME: We don't handle GATs yet.
|
|
|
|
let projection = TyBuilder::assoc_type_projection(db, alias.id, Some(parent_subst)).build();
|
2021-03-08 19:08:30 +00:00
|
|
|
|
2022-09-20 14:39:17 +00:00
|
|
|
let ty = db.normalize_projection(projection, self.env.clone());
|
|
|
|
if ty.is_unknown() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(self.derived(ty))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
|
2023-02-13 11:55:14 +00:00
|
|
|
let lang_item = db.lang_item(self.env.krate, LangItem::Copy);
|
2021-03-08 19:08:30 +00:00
|
|
|
let copy_trait = match lang_item {
|
2023-02-13 11:55:14 +00:00
|
|
|
Some(LangItemTarget::Trait(it)) => it,
|
2021-03-08 19:08:30 +00:00
|
|
|
_ => return false,
|
|
|
|
};
|
|
|
|
self.impls_trait(db, copy_trait.into(), &[])
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
|
2021-05-23 10:52:41 +00:00
|
|
|
let mut the_ty = &self.ty;
|
2022-05-19 16:53:08 +00:00
|
|
|
let callee = match self.ty.kind(Interner) {
|
2021-03-14 16:40:55 +00:00
|
|
|
TyKind::Ref(_, _, ty) if ty.as_closure().is_some() => {
|
2021-05-23 10:52:41 +00:00
|
|
|
the_ty = ty;
|
2022-05-19 16:53:08 +00:00
|
|
|
Callee::Closure(ty.as_closure().unwrap())
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
2022-05-19 16:53:08 +00:00
|
|
|
TyKind::Closure(id, _) => Callee::Closure(*id),
|
|
|
|
TyKind::Function(_) => Callee::FnPtr,
|
2022-11-09 19:49:10 +00:00
|
|
|
TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
|
|
|
|
_ => {
|
2022-11-23 15:24:03 +00:00
|
|
|
let sig = hir_ty::callable_sig_from_fnonce(&self.ty, self.env.clone(), db)?;
|
2022-11-09 19:49:10 +00:00
|
|
|
return Some(Callable {
|
|
|
|
ty: self.clone(),
|
|
|
|
sig,
|
|
|
|
callee: Callee::Other,
|
|
|
|
is_bound_method: false,
|
|
|
|
});
|
|
|
|
}
|
2022-05-19 16:53:08 +00:00
|
|
|
};
|
2021-03-08 19:08:30 +00:00
|
|
|
|
2021-03-21 19:19:07 +00:00
|
|
|
let sig = the_ty.callable_sig(db)?;
|
2022-05-19 16:53:08 +00:00
|
|
|
Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_closure(&self) -> bool {
|
2023-02-13 11:55:14 +00:00
|
|
|
matches!(self.ty.kind(Interner), TyKind::Closure { .. })
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn as_closure(&self) -> Option<Closure> {
|
2021-12-19 16:58:39 +00:00
|
|
|
match self.ty.kind(Interner) {
|
2022-05-19 16:53:08 +00:00
|
|
|
TyKind::Closure(id, subst) => Some(Closure { id: *id, subst: subst.clone() }),
|
2021-12-10 18:18:21 +00:00
|
|
|
_ => None,
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn is_fn(&self) -> bool {
|
2023-02-13 11:55:14 +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 {
|
2023-02-13 11:55:14 +00:00
|
|
|
matches!(self.ty.kind(Interner), TyKind::Array(..))
|
2022-01-04 14:59:00 +00:00
|
|
|
}
|
|
|
|
|
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 {
|
2023-01-09 18:36:22 +00:00
|
|
|
Adt::Struct(s) => s.repr(db).unwrap_or_default().pack.is_some(),
|
2021-03-08 19:08:30 +00:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_raw_ptr(&self) -> bool {
|
2023-02-13 11:55:14 +00:00
|
|
|
matches!(self.ty.kind(Interner), TyKind::Raw(..))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
pub fn remove_raw_ptr(&self) -> Option<Type> {
|
|
|
|
if let TyKind::Raw(_, ty) = self.ty.kind(Interner) {
|
|
|
|
Some(self.derived(ty.clone()))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn contains_unknown(&self) -> bool {
|
2023-02-13 11:55:14 +00:00
|
|
|
// FIXME: When we get rid of `ConstScalar::Unknown`, we can just look at precomputed
|
|
|
|
// `TypeFlags` in `TyData`.
|
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(_)
|
2023-12-25 22:42:38 +00:00
|
|
|
| TyKind::Coroutine(..)
|
|
|
|
| TyKind::CoroutineWitness(..) => 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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-13 11:55:14 +00:00
|
|
|
pub fn as_array(&self, db: &dyn HirDatabase) -> Option<(Type, usize)> {
|
|
|
|
if let TyKind::Array(ty, len) = &self.ty.kind(Interner) {
|
2023-07-17 13:49:15 +00:00
|
|
|
try_const_usize(db, len).map(|it| (self.derived(ty.clone()), it as usize))
|
2023-02-13 11:55:14 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-13 18:25:03 +00:00
|
|
|
pub fn fingerprint_for_trait_impl(&self) -> Option<TyFingerprint> {
|
|
|
|
TyFingerprint::for_trait_impl(&self.ty)
|
|
|
|
}
|
|
|
|
|
2023-11-19 08:23:08 +00:00
|
|
|
pub(crate) fn canonical(&self) -> Canonical<Ty> {
|
|
|
|
hir_ty::replace_errors_with_variables(&self.ty)
|
|
|
|
}
|
|
|
|
|
2023-06-19 06:14:04 +00:00
|
|
|
/// Returns types that this type dereferences to (including this type itself). The returned
|
|
|
|
/// iterator won't yield the same type more than once even if the deref chain contains a cycle.
|
|
|
|
pub fn autoderef(&self, db: &dyn HirDatabase) -> impl Iterator<Item = Type> + '_ {
|
2021-12-10 18:18:21 +00:00
|
|
|
self.autoderef_(db).map(move |ty| self.derived(ty))
|
|
|
|
}
|
|
|
|
|
2023-06-19 06:14:04 +00:00
|
|
|
fn autoderef_(&self, db: &dyn HirDatabase) -> impl Iterator<Item = Ty> {
|
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);
|
2023-06-19 06:14:04 +00:00
|
|
|
autoderef(db, self.env.clone(), canonical)
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
/// Iterates its type arguments
|
|
|
|
///
|
|
|
|
/// It iterates the actual type arguments when concrete types are used
|
|
|
|
/// and otherwise the generic names.
|
|
|
|
/// It does not include `const` arguments.
|
|
|
|
///
|
|
|
|
/// For code, such as:
|
|
|
|
/// ```text
|
|
|
|
/// struct Foo<T, U>
|
|
|
|
///
|
|
|
|
/// impl<U> Foo<String, U>
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// It iterates:
|
|
|
|
/// ```text
|
|
|
|
/// - "String"
|
|
|
|
/// - "U"
|
|
|
|
/// ```
|
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()
|
2024-02-25 15:24:07 +00:00
|
|
|
.map(|(_, substs)| substs)
|
|
|
|
.or_else(|| self.ty.strip_references().as_tuple())
|
2021-03-08 19:08:30 +00:00
|
|
|
.into_iter()
|
2024-02-25 15:24:07 +00:00
|
|
|
.flat_map(|substs| substs.iter(Interner))
|
2021-12-19 16:58:39 +00:00
|
|
|
.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
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
/// Iterates its type and const arguments
|
|
|
|
///
|
|
|
|
/// It iterates the actual type and const arguments when concrete types
|
|
|
|
/// are used and otherwise the generic names.
|
|
|
|
///
|
|
|
|
/// For code, such as:
|
|
|
|
/// ```text
|
|
|
|
/// struct Foo<T, const U: usize, const X: usize>
|
|
|
|
///
|
|
|
|
/// impl<U> Foo<String, U, 12>
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// It iterates:
|
|
|
|
/// ```text
|
|
|
|
/// - "String"
|
|
|
|
/// - "U"
|
|
|
|
/// - "12"
|
|
|
|
/// ```
|
|
|
|
pub fn type_and_const_arguments<'a>(
|
|
|
|
&'a self,
|
|
|
|
db: &'a dyn HirDatabase,
|
|
|
|
) -> impl Iterator<Item = SmolStr> + 'a {
|
|
|
|
self.ty
|
|
|
|
.strip_references()
|
|
|
|
.as_adt()
|
|
|
|
.into_iter()
|
|
|
|
.flat_map(|(_, substs)| substs.iter(Interner))
|
|
|
|
.filter_map(|arg| {
|
|
|
|
// arg can be either a `Ty` or `constant`
|
|
|
|
if let Some(ty) = arg.ty(Interner) {
|
2024-01-17 12:43:18 +00:00
|
|
|
Some(format_smolstr!("{}", ty.display(db)))
|
2023-03-13 08:42:24 +00:00
|
|
|
} else {
|
2024-01-19 13:06:12 +00:00
|
|
|
arg.constant(Interner).map(|const_| format_smolstr!("{}", const_.display(db)))
|
2023-03-13 08:42:24 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Combines lifetime indicators, type and constant parameters into a single `Iterator`
|
|
|
|
pub fn generic_parameters<'a>(
|
|
|
|
&'a self,
|
|
|
|
db: &'a dyn HirDatabase,
|
|
|
|
) -> impl Iterator<Item = SmolStr> + 'a {
|
|
|
|
// iterate the lifetime
|
|
|
|
self.as_adt()
|
2024-01-19 14:25:51 +00:00
|
|
|
.and_then(|a| a.lifetime(db).map(|lt| lt.name.to_smol_str()))
|
2023-03-13 08:42:24 +00:00
|
|
|
.into_iter()
|
|
|
|
// add the type and const parameters
|
|
|
|
.chain(self.type_and_const_arguments(db))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn iterate_method_candidates_with_traits<T>(
|
2021-03-08 19:08:30 +00:00
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
2022-07-20 13:02:08 +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(Function) -> Option<T>,
|
2021-03-08 19:08:30 +00:00
|
|
|
) -> Option<T> {
|
2024-04-17 00:07:56 +00:00
|
|
|
let _p = tracing::span!(tracing::Level::INFO, "iterate_method_candidates").entered();
|
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
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
pub fn iterate_method_candidates<T>(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
scope: &SemanticsScope<'_>,
|
|
|
|
with_local_impls: Option<Module>,
|
|
|
|
name: Option<&Name>,
|
|
|
|
callback: impl FnMut(Function) -> Option<T>,
|
|
|
|
) -> Option<T> {
|
|
|
|
self.iterate_method_candidates_with_traits(
|
|
|
|
db,
|
|
|
|
scope,
|
|
|
|
&scope.visible_traits().0,
|
|
|
|
with_local_impls,
|
|
|
|
name,
|
|
|
|
callback,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
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
|
|
|
fn iterate_method_candidates_dyn(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
2022-07-20 13:02:08 +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
|
|
|
) {
|
2024-02-01 21:10:32 +00:00
|
|
|
let _p = tracing::span!(
|
|
|
|
tracing::Level::INFO,
|
|
|
|
"iterate_method_candidates_dyn",
|
|
|
|
with_local_impls = traits_in_scope.len(),
|
|
|
|
traits_in_scope = traits_in_scope.len(),
|
|
|
|
?name,
|
|
|
|
)
|
|
|
|
.entered();
|
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();
|
2023-12-08 09:47:36 +00:00
|
|
|
let environment = scope
|
|
|
|
.resolver()
|
|
|
|
.generic_def()
|
|
|
|
.map_or_else(|| 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,
|
2023-01-09 18:36:22 +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
|
|
|
}
|
|
|
|
|
2024-02-01 21:10:32 +00:00
|
|
|
#[tracing::instrument(skip_all, fields(name = ?name))]
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn iterate_path_candidates<T>(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
2022-07-20 13:02:08 +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> {
|
2024-04-17 00:07:56 +00:00
|
|
|
let _p = tracing::span!(tracing::Level::INFO, "iterate_path_candidates").entered();
|
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
|
|
|
|
}
|
|
|
|
|
2024-02-01 21:10:32 +00:00
|
|
|
#[tracing::instrument(skip_all, fields(name = ?name))]
|
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
|
|
|
fn iterate_path_candidates_dyn(
|
|
|
|
&self,
|
|
|
|
db: &dyn HirDatabase,
|
2022-07-20 13:02:08 +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();
|
2023-12-08 09:47:36 +00:00
|
|
|
let environment = scope
|
|
|
|
.resolver()
|
|
|
|
.generic_def()
|
|
|
|
.map_or_else(|| 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,
|
2024-01-19 15:37:08 +00:00
|
|
|
callback,
|
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 {
|
2024-04-17 00:07:56 +00:00
|
|
|
let _p = tracing::span!(tracing::Level::INFO, "applicable_inherent_traits").entered();
|
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 {
|
2024-04-17 00:07:56 +00:00
|
|
|
let _p = tracing::span!(tracing::Level::INFO, "env_traits").entered();
|
2021-12-10 18:18:21 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2023-02-13 11:55:14 +00:00
|
|
|
/// Visits every type, including generic arguments, in this type. `cb` is called with type
|
|
|
|
/// itself first, and then with its generic arguments.
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
|
|
|
|
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
|
2024-03-18 15:33:13 +00:00
|
|
|
if let [self_ty, params @ ..] = trait_ref.substitution.as_slice(Interner) {
|
|
|
|
for ty in
|
|
|
|
params.iter().filter(|&ty| ty != self_ty).filter_map(|a| a.ty(Interner))
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2024-02-01 09:02:19 +00:00
|
|
|
/// Check if type unifies with another type.
|
|
|
|
///
|
|
|
|
/// Note that we consider placeholder types to unify with everything.
|
|
|
|
/// For example `Option<T>` and `Option<U>` unify although there is unresolved goal `T = U`.
|
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)
|
|
|
|
}
|
|
|
|
|
2024-02-01 09:02:19 +00:00
|
|
|
/// Check if type unifies with another type eagerly making sure there are no unresolved goals.
|
|
|
|
///
|
|
|
|
/// This means that placeholder types are not considered to unify if there are any bounds set on
|
|
|
|
/// them. For example `Option<T>` and `Option<U>` do not unify as we cannot show that `T = U`
|
2023-12-11 15:04:20 +00:00
|
|
|
pub fn could_unify_with_deeply(&self, db: &dyn HirDatabase, other: &Type) -> bool {
|
|
|
|
let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone()));
|
|
|
|
hir_ty::could_unify_deeply(db, self.env.clone(), &tys)
|
|
|
|
}
|
|
|
|
|
2022-03-20 15:19:02 +00:00
|
|
|
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
|
|
|
}
|
2022-04-30 17:29:55 +00:00
|
|
|
|
|
|
|
pub fn as_type_param(&self, db: &dyn HirDatabase) -> Option<TypeParam> {
|
|
|
|
match self.ty.kind(Interner) {
|
|
|
|
TyKind::Placeholder(p) => Some(TypeParam {
|
|
|
|
id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)),
|
|
|
|
}),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2023-02-13 11:55:14 +00:00
|
|
|
|
|
|
|
/// Returns unique `GenericParam`s contained in this type.
|
|
|
|
pub fn generic_params(&self, db: &dyn HirDatabase) -> FxHashSet<GenericParam> {
|
|
|
|
hir_ty::collect_placeholders(&self.ty, db)
|
|
|
|
.into_iter()
|
|
|
|
.map(|id| TypeOrConstParam { id }.split(db).either_into())
|
|
|
|
.collect()
|
|
|
|
}
|
2023-06-05 09:04:23 +00:00
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
|
2023-07-24 09:21:34 +00:00
|
|
|
db.layout_of_ty(self.ty.clone(), self.env.clone())
|
2023-01-09 18:36:22 +00:00
|
|
|
.map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
// FIXME: Document this
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Callable {
|
|
|
|
ty: Type,
|
|
|
|
sig: CallableSig,
|
2022-05-19 16:53:08 +00:00
|
|
|
callee: Callee,
|
2023-03-13 08:42:24 +00:00
|
|
|
/// Whether this is a method that was called with method call syntax.
|
2021-03-08 19:08:30 +00:00
|
|
|
pub(crate) is_bound_method: bool,
|
|
|
|
}
|
|
|
|
|
2022-05-19 16:53:08 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
enum Callee {
|
|
|
|
Def(CallableDefId),
|
|
|
|
Closure(ClosureId),
|
|
|
|
FnPtr,
|
2022-11-09 19:49:10 +00:00
|
|
|
Other,
|
2022-05-19 16:53:08 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub enum CallableKind {
|
|
|
|
Function(Function),
|
|
|
|
TupleStruct(Struct),
|
|
|
|
TupleEnumVariant(Variant),
|
|
|
|
Closure,
|
2022-05-19 16:53:08 +00:00
|
|
|
FnPtr,
|
2022-11-09 19:49:10 +00:00
|
|
|
/// Some other type that implements `FnOnce`.
|
|
|
|
Other,
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Callable {
|
|
|
|
pub fn kind(&self) -> CallableKind {
|
2022-05-19 16:53:08 +00:00
|
|
|
use Callee::*;
|
|
|
|
match self.callee {
|
|
|
|
Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
|
|
|
|
Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
|
|
|
|
Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
|
|
|
|
Closure(_) => CallableKind::Closure,
|
|
|
|
FnPtr => CallableKind::FnPtr,
|
2022-11-09 19:49:10 +00:00
|
|
|
Other => CallableKind::Other,
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
}
|
2023-08-21 09:44:09 +00:00
|
|
|
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
|
2022-05-19 16:53:08 +00:00
|
|
|
let func = match self.callee {
|
|
|
|
Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
|
2021-03-08 19:08:30 +00:00
|
|
|
_ => return None,
|
|
|
|
};
|
2023-08-21 09:44:09 +00:00
|
|
|
let func = Function { id: func };
|
|
|
|
Some((func.self_param(db)?, self.ty.derived(self.sig.params()[0].clone())))
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
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()));
|
2022-05-19 16:53:08 +00:00
|
|
|
let map_param = |it: ast::Param| it.pat().map(Either::Right);
|
|
|
|
let patterns = match self.callee {
|
|
|
|
Callee::Def(CallableDefId::FunctionId(func)) => {
|
2021-03-08 19:08:30 +00:00
|
|
|
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()
|
2022-05-19 16:53:08 +00:00
|
|
|
.chain(param_list.params().map(map_param))
|
2021-03-08 19:08:30 +00:00
|
|
|
})
|
|
|
|
}
|
2022-05-19 16:53:08 +00:00
|
|
|
Callee::Closure(closure_id) => match closure_source(db, closure_id) {
|
|
|
|
Some(src) => src.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(map_param))
|
|
|
|
}),
|
|
|
|
None => None,
|
|
|
|
},
|
2021-03-08 19:08:30 +00:00
|
|
|
_ => 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())
|
|
|
|
}
|
2023-12-16 14:49:26 +00:00
|
|
|
pub fn sig(&self) -> &CallableSig {
|
|
|
|
&self.sig
|
|
|
|
}
|
2021-03-08 19:08:30 +00:00
|
|
|
}
|
|
|
|
|
2022-05-19 16:53:08 +00:00
|
|
|
fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::ClosureExpr> {
|
2024-02-10 14:36:26 +00:00
|
|
|
let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
|
2022-05-19 16:53:08 +00:00
|
|
|
let (_, source_map) = db.body_with_source_map(owner);
|
|
|
|
let ast = source_map.expr_syntax(expr_id).ok()?;
|
|
|
|
let root = ast.file_syntax(db.upcast());
|
|
|
|
let expr = ast.value.to_node(&root);
|
|
|
|
match expr {
|
|
|
|
ast::Expr::ClosureExpr(it) => Some(it),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
|
|
pub struct Layout(Arc<TyLayout>, Arc<TargetDataLayout>);
|
2023-06-05 09:04:23 +00:00
|
|
|
|
|
|
|
impl Layout {
|
2021-03-08 19:08:30 +00:00
|
|
|
pub fn size(&self) -> u64 {
|
2023-02-13 11:55:14 +00:00
|
|
|
self.0.size.bytes()
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2021-05-08 20:34:55 +00:00
|
|
|
pub fn align(&self) -> u64 {
|
2022-10-11 07:37:35 +00:00
|
|
|
self.0.align.abi.bytes()
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2023-03-20 06:31:01 +00:00
|
|
|
pub fn niches(&self) -> Option<u128> {
|
2023-03-13 08:42:24 +00:00
|
|
|
Some(self.0.largest_niche?.available(&*self.1))
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2023-11-08 06:15:03 +00:00
|
|
|
pub fn field_offset(&self, field: Field) -> Option<u64> {
|
2022-05-19 16:53:08 +00:00
|
|
|
match self.0.fields {
|
2022-01-11 13:34:25 +00:00
|
|
|
layout::FieldsShape::Primitive => None,
|
2022-05-19 16:53:08 +00:00
|
|
|
layout::FieldsShape::Union(_) => Some(0),
|
2023-03-13 08:42:24 +00:00
|
|
|
layout::FieldsShape::Array { stride, count } => {
|
2023-11-08 06:15:03 +00:00
|
|
|
let i = u64::try_from(field.index()).ok()?;
|
2023-03-13 08:42:24 +00:00
|
|
|
(i < count).then_some((stride * i).bytes())
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
2023-11-08 06:15:03 +00:00
|
|
|
layout::FieldsShape::Arbitrary { ref offsets, .. } => {
|
|
|
|
Some(offsets.get(RustcFieldIdx(field.id))?.bytes())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn tuple_field_offset(&self, field: usize) -> Option<u64> {
|
|
|
|
match self.0.fields {
|
|
|
|
layout::FieldsShape::Primitive => None,
|
|
|
|
layout::FieldsShape::Union(_) => Some(0),
|
|
|
|
layout::FieldsShape::Array { stride, count } => {
|
|
|
|
let i = u64::try_from(field).ok()?;
|
|
|
|
(i < count).then_some((stride * i).bytes())
|
|
|
|
}
|
|
|
|
layout::FieldsShape::Arbitrary { ref offsets, .. } => {
|
|
|
|
Some(offsets.get(RustcFieldIdx::new(field))?.bytes())
|
|
|
|
}
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-13 11:55:14 +00:00
|
|
|
pub fn enum_tag_size(&self) -> Option<usize> {
|
2022-01-11 13:34:25 +00:00
|
|
|
let tag_size =
|
2021-03-08 19:08:30 +00:00
|
|
|
if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants {
|
2022-06-20 10:48:09 +00:00
|
|
|
match tag_encoding {
|
2021-11-20 16:19:19 +00:00
|
|
|
TagEncoding::Direct => tag.size(&*self.1).bytes_usize(),
|
2022-06-20 10:48:09 +00:00
|
|
|
TagEncoding::Niche { .. } => 0,
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
} else {
|
2022-03-09 00:13:38 +00:00
|
|
|
return None;
|
2023-06-05 09:04:23 +00:00
|
|
|
};
|
2023-02-13 11:55:14 +00:00
|
|
|
Some(tag_size)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-14 12:26:08 +00:00
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
|
|
pub enum BindingMode {
|
|
|
|
Move,
|
|
|
|
Ref(Mutability),
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
/// 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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-09 18:36:22 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
|
|
pub struct Adjustment {
|
|
|
|
pub source: Type,
|
|
|
|
pub target: Type,
|
|
|
|
pub kind: Adjust,
|
|
|
|
}
|
|
|
|
|
2022-11-23 15:24:03 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub enum Adjust {
|
|
|
|
/// Go from ! to any type.
|
|
|
|
NeverToAny,
|
|
|
|
/// Dereference once, producing a place.
|
|
|
|
Deref(Option<OverloadedDeref>),
|
|
|
|
/// Take the address and produce either a `&` or `*` pointer.
|
|
|
|
Borrow(AutoBorrow),
|
|
|
|
Pointer(PointerCast),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub enum AutoBorrow {
|
|
|
|
/// Converts from T to &T.
|
|
|
|
Ref(Mutability),
|
|
|
|
/// Converts from T to *T.
|
|
|
|
RawPtr(Mutability),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct OverloadedDeref(pub Mutability);
|
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-23 15:00:51 +00:00
|
|
|
impl HasCrate for Struct {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasCrate for Union {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-23 13:36:43 +00:00
|
|
|
impl HasCrate for Enum {
|
2022-07-14 21:22:54 +00:00
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-23 13:36:43 +00:00
|
|
|
impl HasCrate for Field {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.parent_def(db).module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-23 15:00:51 +00:00
|
|
|
impl HasCrate for Variant {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-23 13:36:43 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|
2022-07-14 21:22:54 +00:00
|
|
|
|
|
|
|
impl HasCrate for Trait {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
impl HasCrate for TraitAlias {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-14 21:22:54 +00:00
|
|
|
impl HasCrate for Static {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasCrate for Adt {
|
|
|
|
fn krate(&self, db: &dyn HirDatabase) -> Crate {
|
|
|
|
self.module(db).krate()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HasCrate for Module {
|
|
|
|
fn krate(&self, _: &dyn HirDatabase) -> Crate {
|
|
|
|
Module::krate(*self)
|
|
|
|
}
|
|
|
|
}
|
2023-06-05 09:04:23 +00:00
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
pub trait HasContainer {
|
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
|
2023-08-07 09:03:15 +00:00
|
|
|
impl HasContainer for ExternCrateDecl {
|
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
|
|
|
container_id_to_hir(self.id.lookup(db.upcast()).container.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-14 21:22:54 +00:00
|
|
|
impl HasContainer for Module {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
|
|
|
// FIXME: handle block expressions as modules (their parent is in a different DefMap)
|
2021-07-20 14:11:09 +00:00
|
|
|
let def_map = self.id.def_map(db.upcast());
|
2021-03-08 19:08:30 +00:00
|
|
|
match def_map[self.id.local_id].parent {
|
|
|
|
Some(parent_id) => ItemContainer::Module(Module { id: def_map.module_id(parent_id) }),
|
2021-12-07 16:31:26 +00:00
|
|
|
None => ItemContainer::Crate(def_map.krate()),
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-23 13:36:43 +00:00
|
|
|
impl HasContainer for Function {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
2021-03-09 18:09:02 +00:00
|
|
|
container_id_to_hir(self.id.lookup(db.upcast()).container)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-23 15:00:51 +00:00
|
|
|
impl HasContainer for Struct {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
2023-03-13 08:42:24 +00:00
|
|
|
ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-23 15:00:51 +00:00
|
|
|
impl HasContainer for Union {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
2023-03-13 08:42:24 +00:00
|
|
|
ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-11 07:37:35 +00:00
|
|
|
impl HasContainer for Enum {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
2023-03-13 08:42:24 +00:00
|
|
|
ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-16 12:25:23 +00:00
|
|
|
impl HasContainer for TypeAlias {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
2021-03-09 18:09:02 +00:00
|
|
|
container_id_to_hir(self.id.lookup(db.upcast()).container)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-16 12:25:23 +00:00
|
|
|
impl HasContainer for Const {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
2021-03-09 18:09:02 +00:00
|
|
|
container_id_to_hir(self.id.lookup(db.upcast()).container)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-14 21:22:54 +00:00
|
|
|
impl HasContainer for Static {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
2021-03-09 18:09:02 +00:00
|
|
|
container_id_to_hir(self.id.lookup(db.upcast()).container)
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
impl HasContainer for Trait {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
2023-03-13 08:42:24 +00:00
|
|
|
ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 08:42:24 +00:00
|
|
|
impl HasContainer for TraitAlias {
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
|
2023-03-13 08:42:24 +00:00
|
|
|
ItemContainer::Module(Module { id: self.id.lookup(db.upcast()).container })
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
fn container_id_to_hir(c: ItemContainerId) -> ItemContainer {
|
2023-06-05 09:04:23 +00:00
|
|
|
match c {
|
2021-12-07 16:31:26 +00:00
|
|
|
ItemContainerId::ExternBlockId(_id) => ItemContainer::ExternBlock(),
|
|
|
|
ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }),
|
|
|
|
ItemContainerId::ImplId(id) => ItemContainer::Impl(Impl { id }),
|
|
|
|
ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }),
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 19:08:30 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub enum ItemContainer {
|
|
|
|
Trait(Trait),
|
|
|
|
Impl(Impl),
|
|
|
|
Module(Module),
|
2021-12-07 16:31:26 +00:00
|
|
|
ExternBlock(),
|
2022-03-26 20:22:35 +00:00
|
|
|
Crate(CrateId),
|
2023-06-05 09:04:23 +00:00
|
|
|
}
|
2023-09-18 09:32:37 +00:00
|
|
|
|
|
|
|
/// Subset of `ide_db::Definition` that doc links can resolve to.
|
|
|
|
pub enum DocLinkDef {
|
|
|
|
ModuleDef(ModuleDef),
|
|
|
|
Field(Field),
|
|
|
|
SelfType(Trait),
|
|
|
|
}
|