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 | 159 |
1 files changed, 110 insertions, 49 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 55da27781d..2bb2f80ecc 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -36,6 +36,7 @@ pub mod term_search; mod display; use std::{ + fmt, mem::discriminant, ops::{ControlFlow, Not}, }; @@ -74,7 +75,7 @@ use hir_ty::{ TraitEnvironment, TyDefId, TyLoweringDiagnostic, ValueTyDefId, all_super_traits, autoderef, check_orphan_rules, consteval::try_const_usize, - db::InternedClosureId, + db::{InternedClosureId, InternedCoroutineId}, diagnostics::BodyValidationDiagnostic, direct_super_traits, known_const_to_ast, layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, @@ -91,7 +92,7 @@ use itertools::Itertools; use rustc_hash::FxHashSet; use rustc_type_ir::{ AliasTyKind, TypeSuperVisitable, TypeVisitable, TypeVisitor, - inherent::{AdtDef, IntoKind, SliceLike, Term as _, Ty as _}, + inherent::{AdtDef, GenericArgs as _, IntoKind, SliceLike, Term as _, Ty as _}, }; use smallvec::SmallVec; use span::{AstIdNode, Edition, FileId}; @@ -160,7 +161,7 @@ pub use { // FIXME: Properly encapsulate mir hir_ty::mir, hir_ty::{ - CastError, FnAbi, PointerCast, Variance, attach_db, attach_db_allow_change, + CastError, FnAbi, PointerCast, attach_db, attach_db_allow_change, consteval::ConstEvalError, diagnostics::UnsafetyReason, display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite}, @@ -170,6 +171,7 @@ pub use { method_resolution::TyFingerprint, mir::{MirEvalError, MirLowerError}, next_solver::abi::Safety, + next_solver::clear_tls_solver_cache, }, intern::{Symbol, sym}, }; @@ -1270,7 +1272,7 @@ impl<'db> InstantiatedField<'db> { let interner = DbInterner::new_with(db, Some(krate.base()), None); let var_id = self.inner.parent.into(); - let field = db.field_types_ns(var_id)[self.inner.id]; + let field = db.field_types(var_id)[self.inner.id]; let ty = field.instantiate(interner, self.args); TypeNs::new(db, var_id, ty) } @@ -1349,7 +1351,7 @@ impl Field { /// context of the field definition. pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> TypeNs<'db> { let var_id = self.parent.into(); - let ty = db.field_types_ns(var_id)[self.id].skip_binder(); + let ty = db.field_types(var_id)[self.id].skip_binder(); TypeNs::new(db, var_id, ty) } @@ -1367,7 +1369,7 @@ impl Field { }; let interner = DbInterner::new_with(db, None, None); let args = generic_args_from_tys(interner, def_id.into(), generics.map(|ty| ty.ty)); - let ty = db.field_types_ns(var_id)[self.id].instantiate(interner, args); + let ty = db.field_types(var_id)[self.id].instantiate(interner, args); Type::new(db, var_id, ty) } @@ -1802,7 +1804,7 @@ impl Adt { let env = db.trait_environment(self.into()); let interner = DbInterner::new_with(db, Some(env.krate), env.block); let adt_id = AdtId::from(self); - let args = GenericArgs::for_item_with_defaults(interner, adt_id.into(), |_, _, id, _| { + let args = GenericArgs::for_item_with_defaults(interner, adt_id.into(), |_, id, _| { GenericArg::error_from_id(interner, id) }); db.layout_of_adt(adt_id, args, env) @@ -4110,7 +4112,39 @@ impl GenericParam { GenericParam::ConstParam(_) => return None, GenericParam::LifetimeParam(it) => generics.lifetime_idx(it.id)?, }; - db.variances_of(parent)?.get(index).copied() + db.variances_of(parent).get(index).map(Into::into) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Variance { + Bivariant, + Covariant, + Contravariant, + Invariant, +} + +impl From<rustc_type_ir::Variance> for Variance { + #[inline] + fn from(value: rustc_type_ir::Variance) -> Self { + match value { + rustc_type_ir::Variance::Covariant => Variance::Covariant, + rustc_type_ir::Variance::Invariant => Variance::Invariant, + rustc_type_ir::Variance::Contravariant => Variance::Contravariant, + rustc_type_ir::Variance::Bivariant => Variance::Bivariant, + } + } +} + +impl fmt::Display for Variance { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let description = match self { + Variance::Bivariant => "bivariant", + Variance::Covariant => "covariant", + Variance::Contravariant => "contravariant", + Variance::Invariant => "invariant", + }; + f.pad(description) } } @@ -4151,8 +4185,7 @@ impl TypeParam { let resolver = self.id.parent().resolver(db); let interner = DbInterner::new_with(db, None, None); let index = hir_ty::param_idx(db, self.id.into()).unwrap(); - let name = self.name(db).symbol().clone(); - let ty = Ty::new_param(interner, self.id, index as u32, name); + let ty = Ty::new_param(interner, self.id, index as u32); Type::new_with_resolver_inner(db, &resolver, ty) } @@ -4160,7 +4193,7 @@ impl TypeParam { /// parameter, not additional bounds that might be added e.g. by a method if /// the parameter comes from an impl! pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { - db.generic_predicates_for_param_ns(self.id.parent(), self.id.into(), None) + db.generic_predicates_for_param(self.id.parent(), self.id.into(), None) .iter() .filter_map(|pred| match &pred.kind().skip_binder() { ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)), @@ -4250,7 +4283,7 @@ impl ConstParam { fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg<'_>> { let local_idx = hir_ty::param_idx(db, id)?; - let defaults = db.generic_defaults_ns(id.parent); + let defaults = db.generic_defaults(id.parent); let ty = defaults.get(local_idx)?; // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. Some(ty.instantiate_identity()) @@ -4525,16 +4558,27 @@ impl<'db> TraitRef<'db> { } } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +enum AnyClosureId { + ClosureId(InternedClosureId), + CoroutineClosureId(InternedCoroutineId), +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Closure<'db> { - id: InternedClosureId, + id: AnyClosureId, subst: GenericArgs<'db>, } impl<'db> Closure<'db> { fn as_ty(&self, db: &'db dyn HirDatabase) -> Ty<'db> { let interner = DbInterner::new_with(db, None, None); - Ty::new_closure(interner, self.id.into(), self.subst) + match self.id { + AnyClosureId::ClosureId(id) => Ty::new_closure(interner, id.into(), self.subst), + AnyClosureId::CoroutineClosureId(id) => { + Ty::new_coroutine_closure(interner, id.into(), self.subst) + } + } } pub fn display_with_id(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { @@ -4552,20 +4596,28 @@ impl<'db> Closure<'db> { } pub fn captured_items(&self, db: &'db dyn HirDatabase) -> Vec<ClosureCapture<'db>> { - let owner = db.lookup_intern_closure(self.id).0; + let AnyClosureId::ClosureId(id) = self.id else { + // FIXME: Infer coroutine closures' captures. + return Vec::new(); + }; + let owner = db.lookup_intern_closure(id).0; let infer = db.infer(owner); - let info = infer.closure_info(self.id); + let info = infer.closure_info(id); info.0 .iter() .cloned() - .map(|capture| ClosureCapture { owner, closure: self.id, capture }) + .map(|capture| ClosureCapture { owner, closure: id, capture }) .collect() } pub fn capture_types(&self, db: &'db dyn HirDatabase) -> Vec<Type<'db>> { - let owner = db.lookup_intern_closure(self.id).0; + let AnyClosureId::ClosureId(id) = self.id else { + // FIXME: Infer coroutine closures' captures. + return Vec::new(); + }; + let owner = db.lookup_intern_closure(id).0; let infer = db.infer(owner); - let (captures, _) = infer.closure_info(self.id); + let (captures, _) = infer.closure_info(id); let env = db.trait_environment_for_body(owner); captures .iter() @@ -4574,10 +4626,22 @@ impl<'db> Closure<'db> { } pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait { - let owner = db.lookup_intern_closure(self.id).0; - let infer = db.infer(owner); - let info = infer.closure_info(self.id); - info.1 + match self.id { + AnyClosureId::ClosureId(id) => { + let owner = db.lookup_intern_closure(id).0; + let infer = db.infer(owner); + let info = infer.closure_info(id); + info.1 + } + AnyClosureId::CoroutineClosureId(_id) => { + // FIXME: Infer kind for coroutine closures. + match self.subst.as_coroutine_closure().kind() { + rustc_type_ir::ClosureKind::Fn => FnTrait::AsyncFn, + rustc_type_ir::ClosureKind::FnMut => FnTrait::AsyncFnMut, + rustc_type_ir::ClosureKind::FnOnce => FnTrait::AsyncFnOnce, + } + } + } } } @@ -4851,7 +4915,7 @@ impl<'db> Type<'db> { if variant_data.fields().is_empty() { vec![] } else { - let field_types = self.interner.db().field_types_ns(id); + let field_types = self.interner.db().field_types(id); variant_data .fields() .iter() @@ -5091,28 +5155,14 @@ impl<'db> Type<'db> { let interner = DbInterner::new_with(db, None, None); let callee = match self.ty.kind() { TyKind::Closure(id, subst) => Callee::Closure(id.0, subst), + TyKind::CoroutineClosure(id, subst) => Callee::CoroutineClosure(id.0, subst), TyKind::FnPtr(..) => Callee::FnPtr, TyKind::FnDef(id, _) => Callee::Def(id.0), - kind => { - // This will happen when it implements fn or fn mut, since we add an autoborrow adjustment - let (ty, kind) = if let TyKind::Ref(_, ty, _) = kind { - (ty, ty.kind()) - } else { - (self.ty, kind) - }; - if let TyKind::Closure(closure, subst) = kind { - let sig = subst - .split_closure_args_untupled() - .closure_sig_as_fn_ptr_ty - .callable_sig(interner)?; - return Some(Callable { - ty: self.clone(), - sig, - callee: Callee::Closure(closure.0, subst), - is_bound_method: false, - }); - } - let (fn_trait, sig) = hir_ty::callable_sig_from_fn_trait(ty, self.env.clone(), db)?; + // This will happen when it implements fn or fn mut, since we add an autoborrow adjustment + TyKind::Ref(_, inner_ty, _) => return self.derived(inner_ty).as_callable(db), + _ => { + let (fn_trait, sig) = + hir_ty::callable_sig_from_fn_trait(self.ty, self.env.clone(), db)?; return Some(Callable { ty: self.clone(), sig, @@ -5132,7 +5182,12 @@ impl<'db> Type<'db> { pub fn as_closure(&self) -> Option<Closure<'db>> { match self.ty.kind() { - TyKind::Closure(id, subst) => Some(Closure { id: id.0, subst }), + TyKind::Closure(id, subst) => { + Some(Closure { id: AnyClosureId::ClosureId(id.0), subst }) + } + TyKind::CoroutineClosure(id, subst) => { + Some(Closure { id: AnyClosureId::CoroutineClosureId(id.0), subst }) + } _ => None, } } @@ -5184,7 +5239,7 @@ impl<'db> Type<'db> { _ => return Vec::new(), }; - db.field_types_ns(variant_id) + db.field_types(variant_id) .iter() .map(|(local_id, ty)| { let def = Field { parent: variant_id.into(), id: local_id }; @@ -5791,6 +5846,7 @@ pub struct Callable<'db> { enum Callee<'db> { Def(CallableDefId), Closure(InternedClosureId, GenericArgs<'db>), + CoroutineClosure(InternedCoroutineId, GenericArgs<'db>), FnPtr, FnImpl(FnTrait), } @@ -5812,7 +5868,12 @@ impl<'db> Callable<'db> { Callee::Def(CallableDefId::EnumVariantId(it)) => { CallableKind::TupleEnumVariant(it.into()) } - Callee::Closure(id, ref subst) => CallableKind::Closure(Closure { id, subst: *subst }), + Callee::Closure(id, subst) => { + CallableKind::Closure(Closure { id: AnyClosureId::ClosureId(id), subst }) + } + Callee::CoroutineClosure(id, subst) => { + CallableKind::Closure(Closure { id: AnyClosureId::CoroutineClosureId(id), subst }) + } Callee::FnPtr => CallableKind::FnPtr, Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_), } @@ -6405,7 +6466,7 @@ fn generic_args_from_tys<'db>( args: impl IntoIterator<Item = Ty<'db>>, ) -> GenericArgs<'db> { let mut args = args.into_iter(); - GenericArgs::for_item(interner, def_id, |_, _, id, _| { + GenericArgs::for_item(interner, def_id, |_, id, _| { if matches!(id, GenericParamId::TypeParamId(_)) && let Some(arg) = args.next() { @@ -6418,7 +6479,7 @@ fn generic_args_from_tys<'db>( fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) -> bool { let params = db.generic_params(generic_def); - let defaults = db.generic_defaults_ns(generic_def); + let defaults = db.generic_defaults(generic_def); params .iter_type_or_consts() .filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_))) |