]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir/src/lib.rs
Rename TyKind::ForeignType to Foreign
[rust.git] / crates / hir / src / lib.rs
index 30b96d7e2ed7c62676e9de340dfa85a28ac3031a..b14c9a67509c04cfdc252918d68f8cf69e0fbc05 100644 (file)
@@ -44,6 +44,7 @@
     per_ns::PerNs,
     resolver::{HasResolver, Resolver},
     src::HasSource as _,
+    type_ref::TraitRef,
     AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
     DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
     LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
 };
 use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind};
 use hir_ty::{
-    autoderef,
+    autoderef, could_unify,
     method_resolution::{self, TyFingerprint},
     primitive::UintTy,
-    to_assoc_type_id,
-    traits::{FnTrait, Solution, SolutionVariables},
+    traits::FnTrait,
     AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
-    DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar,
-    Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause,
+    DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution,
+    SolutionVariables, Substitution, TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind,
+    TyVariableKind, WhereClause,
 };
 use itertools::Itertools;
 use rustc_hash::FxHashSet;
@@ -154,11 +155,7 @@ pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
     }
 
     pub fn transitive_reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
-        db.crate_graph()
-            .transitive_reverse_dependencies(self.id)
-            .into_iter()
-            .map(|id| Crate { id })
-            .collect()
+        db.crate_graph().transitive_rev_deps(self.id).into_iter().map(|id| Crate { id }).collect()
     }
 
     pub fn root_module(self, db: &dyn HirDatabase) -> Module {
@@ -518,7 +515,7 @@ pub fn signature_ty(&self, db: &dyn HirDatabase) -> Type {
             VariantDef::Union(it) => it.id.into(),
             VariantDef::Variant(it) => it.parent.id.into(),
         };
-        let substs = Substitution::type_params(db, generic_def_id);
+        let substs = TyBuilder::type_params_subst(db, generic_def_id);
         let ty = db.field_types(var_id)[self.id].clone().subst(&substs);
         Type::new(db, self.parent.module(db).id.krate(), var_id, ty)
     }
@@ -835,7 +832,7 @@ pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
     }
 
     pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
-        if !db.function_data(self.id).has_self_param {
+        if !db.function_data(self.id).has_self_param() {
             return None;
         }
         Some(SelfParam { func: self.id })
@@ -856,6 +853,7 @@ pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> {
             })
             .collect()
     }
+
     pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
         if self.self_param(db).is_none() {
             return None;
@@ -866,7 +864,7 @@ pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
     }
 
     pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
-        db.function_data(self.id).qualifier.is_unsafe
+        db.function_data(self.id).is_unsafe()
     }
 
     pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
@@ -880,7 +878,7 @@ pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
     ///
     /// This is false in the case of required (not provided) trait methods.
     pub fn has_body(self, db: &dyn HirDatabase) -> bool {
-        db.function_data(self.id).has_body
+        db.function_data(self.id).has_body()
     }
 
     /// A textual representation of the HIR of this function for debugging purposes.
@@ -913,7 +911,7 @@ fn from(mutability: hir_ty::Mutability) -> Access {
     }
 }
 
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 pub struct Param {
     func: Function,
     /// The index in parameter list, including self parameter.
@@ -926,13 +924,25 @@ pub fn ty(&self) -> &Type {
         &self.ty
     }
 
+    pub fn as_local(&self, db: &dyn HirDatabase) -> Local {
+        let parent = DefWithBodyId::FunctionId(self.func.into());
+        let body = db.body(parent);
+        Local { parent, pat_id: body.params[self.idx] }
+    }
+
     pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
-        let params = self.func.source(db)?.value.param_list()?;
+        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()?;
         if params.self_param().is_some() {
-            params.params().nth(self.idx.checked_sub(1)?)?.pat()
+            params.params().nth(self.idx.checked_sub(1)?)
         } else {
-            params.params().nth(self.idx)?.pat()
+            params.params().nth(self.idx)
         }
+        .map(|value| InFile { file_id, value })
     }
 }
 
@@ -947,7 +957,7 @@ pub fn access(self, db: &dyn HirDatabase) -> Access {
         func_data
             .params
             .first()
-            .map(|param| match *param {
+            .map(|param| match &**param {
                 TypeRef::Reference(.., mutability) => match mutability {
                     hir_def::type_ref::Mutability::Shared => Access::Shared,
                     hir_def::type_ref::Mutability::Mut => Access::Exclusive,
@@ -964,6 +974,14 @@ pub fn display(self, db: &dyn HirDatabase) -> &'static str {
             Access::Owned => "self",
         }
     }
+
+    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 })
+    }
 }
 
 impl HasVisibility for Function {
@@ -993,7 +1011,7 @@ pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
     }
 
     pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef {
-        db.const_data(self.id).type_ref.clone()
+        db.const_data(self.id).type_ref.as_ref().clone()
     }
 }
 
@@ -1083,7 +1101,7 @@ pub fn krate(self, db: &dyn HirDatabase) -> Crate {
     }
 
     pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
-        db.type_alias_data(self.id).type_ref.clone()
+        db.type_alias_data(self.id).type_ref.as_deref().cloned()
     }
 
     pub fn ty(self, db: &dyn HirDatabase) -> Type {
@@ -1111,7 +1129,7 @@ pub struct BuiltinType {
 impl BuiltinType {
     pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type {
         let resolver = module.id.resolver(db.upcast());
-        Type::new_with_resolver(db, &resolver, Ty::builtin(self.inner))
+        Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner))
             .expect("crate not present in resolver")
     }
 
@@ -1120,6 +1138,14 @@ pub fn name(self) -> Name {
     }
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum MacroKind {
+    Declarative,
+    ProcMacro,
+    Derive,
+    BuiltIn,
+}
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct MacroDef {
     pub(crate) id: MacroDefId,
@@ -1144,15 +1170,15 @@ pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
         }
     }
 
-    /// Indicate it is a proc-macro
-    pub fn is_proc_macro(&self) -> bool {
-        matches!(self.id.kind, MacroDefKind::ProcMacro(..))
-    }
-
-    /// Indicate it is a derive macro
-    pub fn is_derive_macro(&self) -> bool {
-        // FIXME: wrong for `ProcMacro`
-        matches!(self.id.kind, MacroDefKind::ProcMacro(..) | MacroDefKind::BuiltInDerive(..))
+    pub fn kind(&self) -> MacroKind {
+        match self.id.kind {
+            MacroDefKind::Declarative(_) => MacroKind::Declarative,
+            MacroDefKind::BuiltIn(_, _) => MacroKind::BuiltIn,
+            MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive,
+            MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn,
+            // FIXME might be a derive
+            MacroDefKind::ProcMacro(_, _) => MacroKind::ProcMacro,
+        }
     }
 }
 
@@ -1331,6 +1357,13 @@ pub fn is_param(self, db: &dyn HirDatabase) -> bool {
         }
     }
 
+    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,
+        }
+    }
+
     // FIXME: why is this an option? It shouldn't be?
     pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
         let body = db.body(self.parent);
@@ -1469,7 +1502,7 @@ pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
         let resolver = self.id.parent.resolver(db.upcast());
         let krate = self.id.parent.module(db.upcast()).krate();
         let ty = params.get(local_idx)?.clone();
-        let subst = Substitution::type_params(db, self.id.parent);
+        let subst = TyBuilder::type_params_subst(db, self.id.parent);
         let ty = ty.subst(&subst.prefix(local_idx));
         Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
     }
@@ -1541,9 +1574,9 @@ pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<I
         };
 
         let filter = |impl_def: &Impl| {
-            let target_ty = impl_def.target_ty(db);
-            let rref = target_ty.remove_ref();
-            ty.equals_ctor(rref.as_ref().map_or(&target_ty.ty, |it| &it.ty))
+            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))
         };
 
         let mut all = Vec::new();
@@ -1572,8 +1605,7 @@ pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<I
     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.transitive_reverse_dependencies(db).into_iter().chain(Some(krate))
-        {
+        for Crate { id } in krate.transitive_reverse_dependencies(db).into_iter() {
             let impls = db.trait_impls_in_crate(id);
             all.extend(impls.for_trait(trait_.id).map(Self::from))
         }
@@ -1582,16 +1614,16 @@ pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
 
     // FIXME: the return type is wrong. This should be a hir version of
     // `TraitRef` (ie, resolved `TypeRef`).
-    pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> {
-        db.impl_data(self.id).target_trait.clone()
+    pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> {
+        db.impl_data(self.id).target_trait.as_deref().cloned()
     }
 
-    pub fn target_ty(self, db: &dyn HirDatabase) -> Type {
+    pub fn self_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.krate();
         let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
-        let ty = ctx.lower_ty(&impl_data.target_type);
+        let ty = ctx.lower_ty(&impl_data.self_ty);
         Type::new_with_resolver_inner(db, krate, &resolver, ty)
     }
 
@@ -1671,30 +1703,29 @@ fn new(db: &dyn HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty:
     fn from_def(
         db: &dyn HirDatabase,
         krate: CrateId,
-        def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>,
+        def: impl HasResolver + Into<TyDefId>,
     ) -> Type {
-        let substs = Substitution::build_for_def(db, def).fill_with_unknown().build();
-        let ty = db.ty(def.into()).subst(&substs);
+        let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build();
         Type::new(db, krate, def, ty)
     }
 
     pub fn is_unit(&self) -> bool {
-        matches!(self.ty.interned(&Interner), TyKind::Tuple(0, ..))
+        matches!(self.ty.kind(&Interner), TyKind::Tuple(0, ..))
     }
     pub fn is_bool(&self) -> bool {
-        matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Bool))
+        matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Bool))
     }
 
     pub fn is_mutable_reference(&self) -> bool {
-        matches!(self.ty.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
+        matches!(self.ty.kind(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
     }
 
     pub fn is_usize(&self) -> bool {
-        matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
+        matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
     }
 
     pub fn remove_ref(&self) -> Option<Type> {
-        match &self.ty.interned(&Interner) {
+        match &self.ty.kind(&Interner) {
             TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
             _ => None,
         }
@@ -1753,13 +1784,10 @@ pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool {
     }
 
     pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
-        let trait_ref = hir_ty::TraitRef {
-            trait_id: hir_ty::to_chalk_trait_id(trait_.id),
-            substitution: Substitution::build_for_def(db, trait_.id)
-                .push(self.ty.clone())
-                .fill(args.iter().map(|t| t.ty.clone()))
-                .build(),
-        };
+        let trait_ref = TyBuilder::trait_ref(db, trait_.id)
+            .push(self.ty.clone())
+            .fill(args.iter().map(|t| t.ty.clone()))
+            .build();
 
         let goal = Canonical {
             value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)),
@@ -1772,11 +1800,10 @@ pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) ->
     pub fn normalize_trait_assoc_type(
         &self,
         db: &dyn HirDatabase,
-        trait_: Trait,
         args: &[Type],
         alias: TypeAlias,
     ) -> Option<Type> {
-        let subst = Substitution::build_for_def(db, trait_.id)
+        let projection = TyBuilder::assoc_type_projection(db, alias.id)
             .push(self.ty.clone())
             .fill(args.iter().map(|t| t.ty.clone()))
             .build();
@@ -1784,10 +1811,7 @@ pub fn normalize_trait_assoc_type(
             InEnvironment::new(
                 self.env.env.clone(),
                 AliasEq {
-                    alias: AliasTy::Projection(ProjectionTy {
-                        associated_ty_id: to_assoc_type_id(alias.id),
-                        substitution: subst,
-                    }),
+                    alias: AliasTy::Projection(projection),
                     ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
                         .intern(&Interner),
                 }
@@ -1797,9 +1821,11 @@ pub fn normalize_trait_assoc_type(
         );
 
         match db.trait_solve(self.krate, goal)? {
-            Solution::Unique(SolutionVariables(subst)) => {
-                subst.value.first().map(|ty| self.derived(ty.clone()))
-            }
+            Solution::Unique(SolutionVariables(subst)) => subst
+                .value
+                .interned()
+                .first()
+                .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
             Solution::Ambig(_) => None,
         }
     }
@@ -1821,15 +1847,15 @@ pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
     }
 
     pub fn is_closure(&self) -> bool {
-        matches!(&self.ty.interned(&Interner), TyKind::Closure { .. })
+        matches!(&self.ty.kind(&Interner), TyKind::Closure { .. })
     }
 
     pub fn is_fn(&self) -> bool {
-        matches!(&self.ty.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
+        matches!(&self.ty.kind(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
     }
 
     pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
-        let adt_id = match self.ty.interned(&Interner) {
+        let adt_id = match self.ty.kind(&Interner) {
             &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
             _ => return false,
         };
@@ -1842,22 +1868,24 @@ pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
     }
 
     pub fn is_raw_ptr(&self) -> bool {
-        matches!(&self.ty.interned(&Interner), TyKind::Raw(..))
+        matches!(&self.ty.kind(&Interner), TyKind::Raw(..))
     }
 
     pub fn contains_unknown(&self) -> bool {
         return go(&self.ty);
 
         fn go(ty: &Ty) -> bool {
-            match ty.interned(&Interner) {
-                TyKind::Unknown => true,
+            match ty.kind(&Interner) {
+                TyKind::Error => true,
 
                 TyKind::Adt(_, substs)
                 | TyKind::AssociatedType(_, substs)
                 | TyKind::Tuple(_, substs)
                 | TyKind::OpaqueType(_, substs)
                 | TyKind::FnDef(_, substs)
-                | TyKind::Closure(_, substs) => substs.iter().any(go),
+                | TyKind::Closure(_, substs) => {
+                    substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go)
+                }
 
                 TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => {
                     go(ty)
@@ -1872,13 +1900,13 @@ fn go(ty: &Ty) -> bool {
                 | TyKind::Dyn(_)
                 | TyKind::Function(_)
                 | TyKind::Alias(_)
-                | TyKind::ForeignType(_) => false,
+                | TyKind::Foreign(_) => false,
             }
         }
     }
 
     pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
-        let (variant_id, substs) = match self.ty.interned(&Interner) {
+        let (variant_id, substs) = match self.ty.kind(&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(),
@@ -1895,8 +1923,11 @@ pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
     }
 
     pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
-        if let TyKind::Tuple(_, substs) = &self.ty.interned(&Interner) {
-            substs.iter().map(|ty| self.derived(ty.clone())).collect()
+        if let TyKind::Tuple(_, substs) = &self.ty.kind(&Interner) {
+            substs
+                .iter(&Interner)
+                .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone()))
+                .collect()
         } else {
             Vec::new()
         }
@@ -1941,8 +1972,9 @@ pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ {
             .strip_references()
             .substs()
             .into_iter()
-            .flat_map(|substs| substs.iter())
-            .map(move |ty| self.derived(ty.clone()))
+            .flat_map(|substs| substs.iter(&Interner))
+            .filter_map(|arg| arg.ty(&Interner).cloned())
+            .map(move |ty| self.derived(ty))
     }
 
     pub fn iterate_method_candidates<T>(
@@ -1968,6 +2000,7 @@ pub fn iterate_method_candidates<T>(
             env,
             krate,
             traits_in_scope,
+            None,
             name,
             method_resolution::LookupMode::MethodCall,
             |ty, it| match it {
@@ -2000,6 +2033,7 @@ pub fn iterate_path_candidates<T>(
             env,
             krate,
             traits_in_scope,
+            None,
             name,
             method_resolution::LookupMode::Path,
             |ty, it| callback(ty, it.into()),
@@ -2046,7 +2080,7 @@ fn walk_substs(
             substs: &Substitution,
             cb: &mut impl FnMut(Type),
         ) {
-            for ty in substs.iter() {
+            for ty in substs.iter(&Interner).filter_map(|a| a.ty(&Interner)) {
                 walk_type(db, &type_.derived(ty.clone()), cb);
             }
         }
@@ -2062,7 +2096,12 @@ fn walk_bounds(
                     WhereClause::Implemented(trait_ref) => {
                         cb(type_.clone());
                         // skip the self type. it's likely the type we just got the bounds from
-                        for ty in trait_ref.substitution.iter().skip(1) {
+                        for ty in trait_ref
+                            .substitution
+                            .iter(&Interner)
+                            .skip(1)
+                            .filter_map(|a| a.ty(&Interner))
+                        {
                             walk_type(db, &type_.derived(ty.clone()), cb);
                         }
                     }
@@ -2073,7 +2112,7 @@ fn walk_bounds(
 
         fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
             let ty = type_.ty.strip_references();
-            match ty.interned(&Interner) {
+            match ty.kind(&Interner) {
                 TyKind::Adt(..) => {
                     cb(type_.derived(ty.clone()));
                 }
@@ -2121,6 +2160,10 @@ fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
 
         walk_type(db, self, &mut cb);
     }
+
+    pub fn could_unify_with(&self, other: &Type) -> bool {
+        could_unify(&self.ty, &other.ty)
+    }
 }
 
 // FIXME: closures
@@ -2205,7 +2248,7 @@ pub enum ScopeDef {
 }
 
 impl ScopeDef {
-    pub fn all_items(def: PerNs) -> ArrayVec<[Self; 3]> {
+    pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
         let mut items = ArrayVec::new();
 
         match (def.take_types(), def.take_values()) {