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 | 160 |
1 files changed, 66 insertions, 94 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 283461f219..08f7bb14ca 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1085,6 +1085,7 @@ impl Field { Type::new(db, var_id, ty) } + // FIXME: Find better API to also handle const generics pub fn ty_with_args(&self, db: &dyn HirDatabase, generics: impl Iterator<Item = Type>) -> Type { let var_id = self.parent.into(); let def_id: AdtId = match self.parent { @@ -1094,12 +1095,11 @@ impl Field { }; let mut generics = generics.map(|it| it.ty.clone()); let substs = TyBuilder::subst_for_def(db, def_id, None) - .fill(|x| { - let ty = generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); - match x { - ParamKind::Type => ty.cast(Interner), - ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), + .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()), }) .build(); let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs); @@ -1159,21 +1159,6 @@ impl Struct { Type::from_def(db, self.id) } - pub fn ty_with_args(self, db: &dyn HirDatabase, generics: impl Iterator<Item = Type>) -> Type { - let mut generics = generics.map(|it| it.ty.clone()); - let substs = TyBuilder::subst_for_def(db, self.id, None) - .fill(|x| { - let ty = generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); - match x { - ParamKind::Type => ty.cast(Interner), - ParamKind::Const(ty) => unknown_const_as_generic(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) } @@ -1273,22 +1258,6 @@ impl Enum { Type::from_def(db, self.id) } - pub fn ty_with_args(&self, db: &dyn HirDatabase, generics: impl Iterator<Item = Type>) -> Type { - let mut generics = generics.map(|it| it.ty.clone()); - let substs = TyBuilder::subst_for_def(db, self.id, None) - .fill(|x| { - let ty = generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); - match x { - ParamKind::Type => ty.cast(Interner), - ParamKind::Const(ty) => unknown_const_as_generic(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( @@ -1463,9 +1432,9 @@ impl Adt { /// Turns this ADT into a type with the given type parameters. This isn't /// the greatest API, FIXME find a better one. - pub fn ty_with_args(self, db: &dyn HirDatabase, args: &[Type]) -> Type { + pub fn ty_with_args(self, db: &dyn HirDatabase, args: impl Iterator<Item = Type>) -> Type { let id = AdtId::from(self); - let mut it = args.iter().map(|t| t.ty.clone()); + let mut it = args.map(|t| t.ty.clone()); let ty = TyBuilder::def_ty(db, id.into(), None) .fill(|x| { let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); @@ -1858,6 +1827,7 @@ impl Function { Type::new_with_resolver_inner(db, &resolver, ty) } + // FIXME: Find better API to also handle const generics pub fn ret_type_with_args( self, db: &dyn HirDatabase, @@ -1870,12 +1840,11 @@ impl Function { ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None, }; let mut generics = generics.map(|it| it.ty.clone()); - let mut filler = |x: &_| { - let ty = generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); - match x { - ParamKind::Type => ty.cast(Interner), - ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), + let mut filler = |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()), }; let parent_substs = @@ -1953,10 +1922,11 @@ impl Function { .collect() } - pub fn params_without_self_with_generics( + // FIXME: Find better API to also handle const generics + pub fn params_without_self_with_args( self, db: &dyn HirDatabase, - mut generics: impl Iterator<Item = Type>, + 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 { @@ -1964,20 +1934,23 @@ impl Function { ItemContainerId::TraitId(it) => Some(it.into()), ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None, }; + let mut generics = generics.map(|it| it.ty.clone()); 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()), - ) + .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()), }) .build() }); let substs = TyBuilder::subst_for_def(db, self.id, parent_substs) .fill(|_| { - GenericArg::new(Interner, GenericArgData::Ty(generics.next().unwrap().ty.clone())) + let ty = generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); + GenericArg::new(Interner, GenericArgData::Ty(ty)) }) .build(); let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs); @@ -2197,6 +2170,7 @@ impl SelfParam { Type { env: environment, ty } } + // FIXME: Find better API to also handle const generics pub fn ty_with_args(&self, db: &dyn HirDatabase, generics: impl Iterator<Item = Type>) -> Type { let parent_id: GenericDefId = match self.func.lookup(db.upcast()).container { ItemContainerId::ImplId(it) => it.into(), @@ -2207,12 +2181,11 @@ impl SelfParam { }; let mut generics = generics.map(|it| it.ty.clone()); - let mut filler = |x: &_| { - let ty = generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); - match x { - ParamKind::Type => ty.cast(Interner), - ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), + let mut filler = |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()), }; let parent_substs = TyBuilder::subst_for_def(db, parent_id, None).fill(&mut filler).build(); @@ -2936,40 +2909,6 @@ impl GenericDef { }) .collect() } - - pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeParam> { - let generics = db.generic_params(self.into()); - generics - .type_or_consts - .iter() - .filter_map(|(local_id, data)| match data { - hir_def::generics::TypeOrConstParamData::TypeParamData(_) => Some(TypeParam { - id: TypeParamId::from_unchecked(TypeOrConstParamId { - parent: self.into(), - local_id, - }), - }), - hir_def::generics::TypeOrConstParamData::ConstParamData(_) => None, - }) - .collect() - } - - pub fn const_params(self, db: &dyn HirDatabase) -> Vec<ConstParam> { - let generics = db.generic_params(self.into()); - generics - .type_or_consts - .iter() - .filter_map(|(local_id, data)| match data { - hir_def::generics::TypeOrConstParamData::TypeParamData(_) => None, - hir_def::generics::TypeOrConstParamData::ConstParamData(_) => Some(ConstParam { - id: ConstParamId::from_unchecked(TypeOrConstParamId { - parent: self.into(), - local_id, - }), - }), - }) - .collect() - } } /// A single local definition. @@ -3451,6 +3390,26 @@ impl TypeOrConstParam { Either::Right(it) => it.ty(db), } } + + 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) }) + } + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -3496,7 +3455,11 @@ impl Impl { ) }); - for Crate { id } in Crate::all(db) { + for id in def_crates + .iter() + .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) + .map(|Crate { id }| id) + { all.extend( db.trait_impls_in_crate(id) .for_self_ty_without_blanket_impls(fp) @@ -3976,14 +3939,16 @@ impl Type { ) } + // FIXME: Find better API that also handles const generics pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { let mut it = args.iter().map(|t| t.ty.clone()); let trait_ref = TyBuilder::trait_ref(db, trait_.id) .push(self.ty.clone()) .fill(|x| { - let r = it.next().unwrap(); match x { - ParamKind::Type => r.cast(Interner), + ParamKind::Type => { + it.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner) + } ParamKind::Const(ty) => { // FIXME: this code is not covered in tests. unknown_const_as_generic(ty.clone()) @@ -4617,12 +4582,19 @@ impl Type { walk_type(db, self, &mut cb); } - + /// 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`. pub fn could_unify_with(&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(db, self.env.clone(), &tys) } + /// 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` 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) |