pub mod diagnostics;
pub mod db;
+mod display;
+
use std::{iter, sync::Arc};
use arrayvec::ArrayVec;
use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind};
use hir_ty::{
autoderef,
- display::{write_bounds_like_dyn_trait_with_prefix, HirDisplayError, HirFormatter},
- method_resolution,
+ method_resolution::{self, TyFingerprint},
+ to_assoc_type_id,
traits::{FnTrait, Solution, SolutionVariables},
AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
- InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment,
- Ty, TyDefId, TyVariableKind,
+ InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty,
+ TyDefId, TyKind, TyVariableKind,
};
use rustc_hash::FxHashSet;
use stdx::{format_to, impl_from};
}
pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> {
- let mut segments = Vec::new();
- segments.push(self.name(db)?.to_string());
+ let mut segments = vec![self.name(db)?.to_string()];
for m in self.module(db)?.path_to_root(db) {
segments.extend(m.name(db).map(|it| it.to_string()))
}
ModuleDef::Module(it) => it.name(db),
ModuleDef::Const(it) => it.name(db),
ModuleDef::Static(it) => it.name(db),
-
ModuleDef::BuiltinType(it) => Some(it.name()),
}
}
impl Struct {
pub fn module(self, db: &dyn HirDatabase) -> Module {
- Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) }
+ Module { id: self.id.lookup(db.upcast()).container }
}
pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
}
pub fn ty(self, db: &dyn HirDatabase) -> Type {
- Type::from_def(
- db,
- self.id.lookup(db.upcast()).container.module(db.upcast()).krate(),
- self.id,
- )
+ Type::from_def(db, self.id.lookup(db.upcast()).container.krate(), self.id)
}
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> {
}
}
+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()))
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Union {
pub(crate) id: UnionId,
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
- Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) }
+ Module { id: self.id.lookup(db.upcast()).container }
}
pub fn ty(self, db: &dyn HirDatabase) -> Type {
- Type::from_def(
- db,
- self.id.lookup(db.upcast()).container.module(db.upcast()).krate(),
- self.id,
- )
+ Type::from_def(db, self.id.lookup(db.upcast()).container.krate(), self.id)
}
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
}
}
+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()))
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Enum {
pub(crate) id: EnumId,
impl Enum {
pub fn module(self, db: &dyn HirDatabase) -> Module {
- Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) }
+ Module { id: self.id.lookup(db.upcast()).container }
}
pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
}
pub fn ty(self, db: &dyn HirDatabase) -> Type {
- Type::from_def(
- db,
- self.id.lookup(db.upcast()).container.module(db.upcast()).krate(),
- self.id,
- )
+ Type::from_def(db, self.id.lookup(db.upcast()).container.krate(), self.id)
+ }
+}
+
+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()))
}
}
impl Adt {
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
let subst = db.generic_defaults(self.into());
- subst.iter().any(|ty| &ty.value == &Ty::Unknown)
+ subst.iter().any(|ty| ty.value.is_unknown())
}
/// Turns this ADT into a type. Any type parameters of the ADT will be
}
}
- pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
- Some(self.module(db).krate())
+ pub fn krate(self, db: &dyn HirDatabase) -> Crate {
+ self.module(db).krate()
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate();
let ret_type = &db.function_data(self.id).ret_type;
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
- let ty = Ty::from_hir_ext(&ctx, ret_type).0;
+ let ty = ctx.lower_ty(ret_type);
Type::new_with_resolver_inner(db, krate, &resolver, ty)
}
let resolver = self.id.resolver(db.upcast());
let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate();
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
- let environment = TraitEnvironment::lower(db, &resolver);
+ let environment = db.trait_environment(self.id.into());
db.function_data(self.id)
.params
.iter()
- .map(|type_ref| {
+ .enumerate()
+ .map(|(idx, type_ref)| {
let ty = Type {
krate,
ty: InEnvironment {
- value: Ty::from_hir_ext(&ctx, type_ref).0,
+ value: ctx.lower_ty(type_ref),
environment: environment.clone(),
},
};
- Param { ty }
+ Param { func: self, ty, idx }
})
.collect()
}
}
pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
- db.function_data(self.id).is_unsafe
+ db.function_data(self.id).qualifier.is_unsafe
}
pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
#[derive(Debug)]
pub struct Param {
+ func: Function,
+ /// The index in parameter list, including self parameter.
+ idx: usize,
ty: Type,
}
pub fn ty(&self) -> &Type {
&self.ty
}
+
+ pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
+ let params = self.func.source(db)?.value.param_list()?;
+ if params.self_param().is_some() {
+ params.params().nth(self.idx.checked_sub(1)?)?.pat()
+ } else {
+ params.params().nth(self.idx)?.pat()
+ }
+ }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
db.const_data(self.id).name.clone()
}
+
+ pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef {
+ db.const_data(self.id).type_ref.clone()
+ }
}
impl HasVisibility for Const {
}
}
+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()))
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Trait {
pub(crate) id: TraitId,
impl Trait {
pub fn module(self, db: &dyn HirDatabase) -> Module {
- Module { id: self.id.lookup(db.upcast()).container.module(db.upcast()) }
+ Module { id: self.id.lookup(db.upcast()).container }
}
pub fn name(self, db: &dyn HirDatabase) -> Name {
}
pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
- db.trait_data(self.id).auto
+ db.trait_data(self.id).is_auto
+ }
+}
+
+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()))
}
}
impl TypeAlias {
pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
let subst = db.generic_defaults(self.id.into());
- subst.iter().any(|ty| &ty.value == &Ty::Unknown)
+ subst.iter().any(|ty| ty.value.is_unknown())
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
}
- pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> {
- Some(self.module(db).krate())
+ pub fn krate(self, db: &dyn HirDatabase) -> Crate {
+ self.module(db).krate()
}
pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
{
match id.lookup(db.upcast()).container {
AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
- AssocContainerId::ContainerId(_) => None,
+ AssocContainerId::ModuleId(_) => None,
}
}
match container {
AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
AssocContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
- AssocContainerId::ContainerId(_) => panic!("invalid AssocItem"),
+ AssocContainerId::ModuleId(_) => panic!("invalid AssocItem"),
}
}
pub fn ty(self, db: &dyn HirDatabase) -> Type {
let resolver = self.id.parent.resolver(db.upcast());
let krate = self.id.parent.module(db.upcast()).krate();
- let ty = Ty::Placeholder(self.id);
+ let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id)).intern(&Interner);
Type::new_with_resolver_inner(db, krate, &resolver, ty)
}
}
}
-impl HirDisplay for TypeParam {
- fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
- write!(f, "{}", self.name(f.db))?;
- let bounds = f.db.generic_predicates_for_param(self.id);
- let substs = Substs::type_params(f.db, self.id.parent);
- let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
- if !(predicates.is_empty() || f.omit_verbose_types()) {
- write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;
- }
- Ok(())
- }
-}
-
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct LifetimeParam {
pub(crate) id: LifetimeParamId,
inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
}
- pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<Impl> {
- let impls = db.trait_impls_in_crate(krate.id);
- impls.for_trait(trait_.id).map(Self::from).collect()
+
+ pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty }: Type) -> Vec<Impl> {
+ let def_crates = match ty.value.def_crates(db, krate) {
+ Some(def_crates) => def_crates,
+ None => return Vec::new(),
+ };
+
+ let filter = |impl_def: &Impl| {
+ let target_ty = impl_def.target_ty(db);
+ let rref = target_ty.remove_ref();
+ ty.value.equals_ctor(rref.as_ref().map_or(&target_ty.ty.value, |it| &it.ty.value))
+ };
+
+ let mut all = Vec::new();
+ def_crates.into_iter().for_each(|id| {
+ all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter))
+ });
+ let fp = TyFingerprint::for_impl(&ty.value);
+ for id in db.crate_graph().iter() {
+ match fp {
+ Some(fp) => all.extend(
+ db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter),
+ ),
+ None => all
+ .extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)),
+ }
+ }
+ all
+ }
+
+ pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
+ let krate = trait_.module(db).krate();
+ let mut all = Vec::new();
+ for Crate { id } in krate.reverse_dependencies(db).into_iter().chain(Some(krate)) {
+ let impls = db.trait_impls_in_crate(id);
+ all.extend(impls.for_trait(trait_.id).map(Self::from))
+ }
+ all
}
// FIXME: the return type is wrong. This should be a hir version of
pub fn target_ty(self, db: &dyn HirDatabase) -> Type {
let impl_data = db.impl_data(self.id);
let resolver = self.id.resolver(db.upcast());
- let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate();
+ let krate = self.id.lookup(db.upcast()).container.krate();
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
- let ty = Ty::from_hir(&ctx, &impl_data.target_type);
+ let ty = ctx.lower_ty(&impl_data.target_type);
Type::new_with_resolver_inner(db, krate, &resolver, ty)
}
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
- self.id.lookup(db.upcast()).container.module(db.upcast()).into()
+ self.id.lookup(db.upcast()).container.into()
}
pub fn krate(self, db: &dyn HirDatabase) -> Crate {
resolver: &Resolver,
ty: Ty,
) -> Type {
- let environment = TraitEnvironment::lower(db, &resolver);
+ let environment =
+ resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d));
Type { krate, ty: InEnvironment { value: ty, environment } }
}
fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type {
let resolver = lexical_env.resolver(db.upcast());
- let environment = TraitEnvironment::lower(db, &resolver);
+ let environment =
+ resolver.generic_def().map_or_else(Default::default, |d| db.trait_environment(d));
Type { krate, ty: InEnvironment { value: ty, environment } }
}
}
pub fn is_unit(&self) -> bool {
- matches!(self.ty.value, Ty::Tuple(0, ..))
+ matches!(self.ty.value.interned(&Interner), TyKind::Tuple(0, ..))
}
pub fn is_bool(&self) -> bool {
- matches!(self.ty.value, Ty::Scalar(Scalar::Bool))
+ matches!(self.ty.value.interned(&Interner), TyKind::Scalar(Scalar::Bool))
}
pub fn is_mutable_reference(&self) -> bool {
- matches!(self.ty.value, Ty::Ref(hir_ty::Mutability::Mut, ..))
+ matches!(self.ty.value.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
}
pub fn remove_ref(&self) -> Option<Type> {
- if let Ty::Ref(.., substs) = &self.ty.value {
- Some(self.derived(substs[0].clone()))
- } else {
- None
+ match &self.ty.value.interned(&Interner) {
+ TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
+ _ => None,
}
}
pub fn is_unknown(&self) -> bool {
- matches!(self.ty.value, Ty::Unknown)
+ self.ty.value.is_unknown()
}
/// Checks that particular type `ty` implements `std::future::Future`.
.fill(args.iter().map(|t| t.ty.value.clone()))
.build();
let predicate = ProjectionPredicate {
- projection_ty: ProjectionTy { associated_ty: alias.id, parameters: subst },
- ty: Ty::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)),
+ projection_ty: ProjectionTy {
+ associated_ty_id: to_assoc_type_id(alias.id),
+ substitution: subst,
+ },
+ ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner),
};
let goal = Canonical {
value: InEnvironment::new(
}
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
- let def = match self.ty.value {
- Ty::FnDef(def, _) => Some(def),
- _ => None,
- };
+ let def = self.ty.value.callable_def(db);
let sig = self.ty.value.callable_sig(db)?;
Some(Callable { ty: self.clone(), sig, def, is_bound_method: false })
}
pub fn is_closure(&self) -> bool {
- matches!(&self.ty.value, Ty::Closure { .. })
+ matches!(&self.ty.value.interned(&Interner), TyKind::Closure { .. })
}
pub fn is_fn(&self) -> bool {
- matches!(&self.ty.value, Ty::FnDef(..) | Ty::Function { .. })
+ matches!(&self.ty.value.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
}
pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
- let adt_id = match self.ty.value {
- Ty::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
+ let adt_id = match self.ty.value.interned(&Interner) {
+ &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
_ => return false,
};
}
pub fn is_raw_ptr(&self) -> bool {
- matches!(&self.ty.value, Ty::Raw(..))
+ matches!(&self.ty.value.interned(&Interner), TyKind::Raw(..))
}
pub fn contains_unknown(&self) -> bool {
return go(&self.ty.value);
fn go(ty: &Ty) -> bool {
- match ty {
- Ty::Unknown => true,
- _ => ty.substs().map_or(false, |substs| substs.iter().any(go)),
+ match ty.interned(&Interner) {
+ TyKind::Unknown => true,
+
+ TyKind::Adt(_, substs)
+ | TyKind::AssociatedType(_, substs)
+ | TyKind::Tuple(_, substs)
+ | TyKind::OpaqueType(_, substs)
+ | TyKind::FnDef(_, substs)
+ | TyKind::Closure(_, substs) => substs.iter().any(go),
+
+ TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => {
+ go(ty)
+ }
+
+ TyKind::Scalar(_)
+ | TyKind::Str
+ | TyKind::Never
+ | TyKind::Placeholder(_)
+ | TyKind::BoundVar(_)
+ | TyKind::InferenceVar(_, _)
+ | TyKind::Dyn(_)
+ | TyKind::Function(_)
+ | TyKind::Alias(_)
+ | TyKind::ForeignType(_) => false,
}
}
}
pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
- let (variant_id, substs) = match self.ty.value {
- Ty::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs),
- Ty::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs),
+ let (variant_id, substs) = match self.ty.value.interned(&Interner) {
+ &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs),
+ &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs),
_ => return Vec::new(),
};
}
pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
- if let Ty::Tuple(_, substs) = &self.ty.value {
+ if let TyKind::Tuple(_, substs) = &self.ty.value.interned(&Interner) {
substs.iter().map(|ty| self.derived(ty.clone())).collect()
} else {
Vec::new()
self.ty.value.associated_type_parent_trait(db).map(Into::into)
}
- // FIXME: provide required accessors such that it becomes implementable from outside.
- pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
- let rref = other.remove_ref();
- self.ty.value.equals_ctor(rref.as_ref().map_or(&other.ty.value, |it| &it.ty.value))
- }
-
fn derived(&self, ty: Ty) -> Type {
Type {
krate: self.krate,
fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
let ty = type_.ty.value.strip_references();
- match ty {
- Ty::Adt(..) => {
+ match ty.interned(&Interner) {
+ TyKind::Adt(..) => {
cb(type_.derived(ty.clone()));
}
- Ty::AssociatedType(..) => {
+ TyKind::AssociatedType(..) => {
if let Some(_) = ty.associated_type_parent_trait(db) {
cb(type_.derived(ty.clone()));
}
}
- Ty::OpaqueType(..) => {
+ TyKind::OpaqueType(..) => {
if let Some(bounds) = ty.impl_trait_bounds(db) {
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
}
}
- Ty::Alias(AliasTy::Opaque(opaque_ty)) => {
+ TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
if let Some(bounds) = ty.impl_trait_bounds(db) {
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
}
- walk_substs(db, type_, &opaque_ty.parameters, cb);
+ walk_substs(db, type_, &opaque_ty.substitution, cb);
}
- Ty::Placeholder(_) => {
+ TyKind::Placeholder(_) => {
if let Some(bounds) = ty.impl_trait_bounds(db) {
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
}
}
- Ty::Dyn(bounds) => {
+ TyKind::Dyn(bounds) => {
walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
}
+ TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => {
+ walk_type(db, &type_.derived(ty.clone()), cb);
+ }
+
_ => {}
}
if let Some(substs) = ty.substs() {
}
}
-impl HirDisplay for Type {
- fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
- self.ty.value.hir_fmt(f)
- }
-}
-
// FIXME: closures
#[derive(Debug)]
pub struct Callable {