Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
| -rw-r--r-- | crates/hir/src/lib.rs | 174 |
1 files changed, 166 insertions, 8 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 32abbc80c6..24323284e9 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -31,6 +31,7 @@ mod has_source; pub mod db; pub mod diagnostics; pub mod symbols; +pub mod term_search; mod display; @@ -1084,6 +1085,26 @@ impl Field { Type::new(db, var_id, ty) } + pub fn ty_with_generics( + &self, + db: &dyn HirDatabase, + mut generics: impl Iterator<Item = Type>, + ) -> Type { + 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(), + }; + let substs = TyBuilder::subst_for_def(db, def_id, None) + .fill(|_| { + GenericArg::new(Interner, GenericArgData::Ty(generics.next().unwrap().ty.clone())) + }) + .build(); + let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs); + Type::new(db, var_id, ty) + } + pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> { db.layout_of_ty( self.ty(db).ty, @@ -1137,6 +1158,20 @@ impl Struct { Type::from_def(db, self.id) } + pub fn ty_with_generics( + self, + db: &dyn HirDatabase, + mut generics: impl Iterator<Item = Type>, + ) -> Type { + let substs = TyBuilder::subst_for_def(db, self.id, None) + .fill(|_| { + GenericArg::new(Interner, GenericArgData::Ty(generics.next().unwrap().ty.clone())) + }) + .build(); + let ty = db.ty(self.id.into()).substitute(Interner, &substs); + Type::new(db, self.id, ty) + } + pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type { Type::from_value_def(db, self.id) } @@ -1228,6 +1263,20 @@ impl Enum { Type::from_def(db, self.id) } + pub fn ty_with_generics( + &self, + db: &dyn HirDatabase, + mut generics: impl Iterator<Item = Type>, + ) -> Type { + let substs = TyBuilder::subst_for_def(db, self.id, None) + .fill(|_| { + GenericArg::new(Interner, GenericArgData::Ty(generics.next().unwrap().ty.clone())) + }) + .build(); + let ty = db.ty(self.id.into()).substitute(Interner, &substs); + Type::new(db, self.id, ty) + } + /// The type of the enum variant bodies. pub fn variant_body_ty(self, db: &dyn HirDatabase) -> Type { Type::new_for_crate( @@ -1789,6 +1838,39 @@ impl Function { Type::new_with_resolver_inner(db, &resolver, ty) } + pub fn ret_type_with_generics( + self, + db: &dyn HirDatabase, + mut generics: impl Iterator<Item = Type>, + ) -> 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, + }; + let parent_substs = parent_id.map(|id| { + TyBuilder::subst_for_def(db, id, None) + .fill(|_| { + GenericArg::new( + Interner, + GenericArgData::Ty(generics.next().unwrap().ty.clone()), + ) + }) + .build() + }); + + let substs = TyBuilder::subst_for_def(db, self.id, parent_substs) + .fill(|_| { + GenericArg::new(Interner, GenericArgData::Ty(generics.next().unwrap().ty.clone())) + }) + .build(); + + 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) + } + pub fn async_ret_type(self, db: &dyn HirDatabase) -> Option<Type> { if !self.is_async(db) { return None; @@ -1855,6 +1937,47 @@ impl Function { .collect() } + pub fn params_without_self_with_generics( + self, + db: &dyn HirDatabase, + mut generics: impl Iterator<Item = Type>, + ) -> 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, + }; + let parent_substs = parent_id.map(|id| { + TyBuilder::subst_for_def(db, id, None) + .fill(|_| { + GenericArg::new( + Interner, + GenericArgData::Ty(generics.next().unwrap().ty.clone()), + ) + }) + .build() + }); + + let substs = TyBuilder::subst_for_def(db, self.id, parent_substs) + .fill(|_| { + GenericArg::new(Interner, GenericArgData::Ty(generics.next().unwrap().ty.clone())) + }) + .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() + } + pub fn is_const(self, db: &dyn HirDatabase) -> bool { db.function_data(self.id).has_const_kw() } @@ -1889,6 +2012,11 @@ impl Function { db.function_data(self.id).attrs.is_bench() } + /// 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() + } + pub fn is_unsafe_to_call(self, db: &dyn HirDatabase) -> bool { hir_ty::is_fn_unsafe_to_call(db, self.id) } @@ -2052,6 +2180,36 @@ impl SelfParam { let ty = callable_sig.params()[0].clone(); Type { env: environment, ty } } + + pub fn ty_with_generics( + &self, + db: &dyn HirDatabase, + mut generics: impl Iterator<Item = Type>, + ) -> Type { + 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") + } + }; + + let parent_substs = TyBuilder::subst_for_def(db, parent_id, None) + .fill(|_| { + GenericArg::new(Interner, GenericArgData::Ty(generics.next().unwrap().ty.clone())) + }) + .build(); + let substs = TyBuilder::subst_for_def(db, self.func, Some(parent_substs)) + .fill(|_| { + GenericArg::new(Interner, GenericArgData::Ty(generics.next().unwrap().ty.clone())) + }) + .build(); + 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 } + } } impl HasVisibility for Function { @@ -3285,13 +3443,8 @@ impl Impl { .filter(filter), ) }); - for id in def_crates - .iter() - .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) - .map(|Crate { id }| id) - .chain(def_crates.iter().copied()) - .unique() - { + + for Crate { id } in Crate::all(db) { all.extend( db.trait_impls_in_crate(id) .for_self_ty_without_blanket_impls(fp) @@ -3520,7 +3673,7 @@ pub enum CaptureKind { Move, } -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct Type { env: Arc<TraitEnvironment>, ty: Ty, @@ -4374,6 +4527,11 @@ impl Type { hir_ty::could_unify(db, self.env.clone(), &tys) } + 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) + } + 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) |