From 9170a7dffc05ab9f6ff389cf3605197eba93d3fd Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 12 Oct 2025 09:45:18 +0300 Subject: [PATCH] Migrate `hir` types to next solver --- .../crates/hir-ty/src/autoderef.rs | 23 +- .../crates/hir-ty/src/chalk_ext.rs | 327 +--- .../crates/hir-ty/src/consteval_chalk.rs | 91 +- .../crates/hir-ty/src/infer/coerce.rs | 19 +- .../crates/hir-ty/src/infer/path.rs | 16 +- .../crates/hir-ty/src/infer/unify.rs | 71 +- .../rust-analyzer/crates/hir-ty/src/lib.rs | 404 ++--- .../rust-analyzer/crates/hir-ty/src/lower.rs | 44 +- .../crates/hir-ty/src/lower/path.rs | 30 +- .../crates/hir-ty/src/lower_nextsolver.rs | 23 +- .../hir-ty/src/lower_nextsolver/path.rs | 43 +- .../crates/hir-ty/src/method_resolution.rs | 54 +- .../crates/hir-ty/src/next_solver/consts.rs | 12 +- .../crates/hir-ty/src/next_solver/def_id.rs | 9 + .../hir-ty/src/next_solver/generic_arg.rs | 15 + .../crates/hir-ty/src/next_solver/interner.rs | 2 +- .../crates/hir-ty/src/next_solver/region.rs | 11 +- .../crates/hir-ty/src/next_solver/ty.rs | 209 ++- .../rust-analyzer/crates/hir-ty/src/traits.rs | 64 +- .../rust-analyzer/crates/hir/src/attrs.rs | 14 +- .../crates/hir/src/diagnostics.rs | 24 +- .../rust-analyzer/crates/hir/src/display.rs | 6 +- .../crates/hir/src/has_source.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 1429 +++++++---------- .../rust-analyzer/crates/hir/src/semantics.rs | 18 +- .../crates/hir/src/source_analyzer.rs | 227 ++- .../crates/hir/src/term_search/tactics.rs | 22 +- .../crates/ide/src/hover/render.rs | 8 +- 28 files changed, 1284 insertions(+), 1933 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs index 0be00afe7bf4..abd1b8b155d2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs @@ -5,23 +5,21 @@ use std::fmt; -use hir_def::TraitId; -use hir_def::{TypeAliasId, lang_item::LangItem}; +use hir_def::{TraitId, TypeAliasId, lang_item::LangItem}; use rustc_type_ir::inherent::{IntoKind, Ty as _}; use tracing::debug; use triomphe::Arc; -use crate::next_solver::TraitRef; -use crate::next_solver::infer::InferOk; -use crate::next_solver::infer::traits::Obligation; use crate::{ TraitEnvironment, db::HirDatabase, infer::unify::InferenceTable, next_solver::{ - Ty, TyKind, - infer::traits::{ObligationCause, PredicateObligations}, - mapping::{ChalkToNextSolver, NextSolverToChalk}, + Canonical, TraitRef, Ty, TyKind, + infer::{ + InferOk, + traits::{Obligation, ObligationCause, PredicateObligations}, + }, obligation_ctxt::ObligationCtxt, }, }; @@ -38,17 +36,16 @@ const AUTODEREF_RECURSION_LIMIT: usize = 20; pub fn autoderef<'db>( db: &'db dyn HirDatabase, env: Arc>, - ty: crate::Canonical, -) -> impl Iterator + use<> { + ty: Canonical<'db, Ty<'db>>, +) -> impl Iterator> + use<'db> { let mut table = InferenceTable::new(db, env); - let interner = table.interner(); - let ty = table.instantiate_canonical(ty.to_nextsolver(interner)); + let ty = table.instantiate_canonical(ty); let mut autoderef = Autoderef::new_no_tracking(&mut table, ty); let mut v = Vec::new(); while let Some((ty, _steps)) = autoderef.next() { // `ty` may contain unresolved inference variables. Since there's no chance they would be // resolved, just replace with fallback type. - let resolved = autoderef.table.resolve_completely(ty).to_chalk(interner); + let resolved = autoderef.table.resolve_completely(ty); // If the deref chain contains a cycle (e.g. `A` derefs to `B` and `B` derefs to `A`), we // would revisit some already visited types. Stop here to avoid duplication. diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs index 6956a0a12328..e9960374c6f5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs @@ -1,66 +1,32 @@ //! Various extensions traits for Chalk types. -use chalk_ir::{ - FloatTy, IntTy, Mutability, Scalar, TyVariableKind, TypeOutlives, UintTy, cast::Cast, -}; -use hir_def::{ - DefWithBodyId, FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId, - builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint}, - hir::generics::{TypeOrConstParamData, TypeParamProvenance}, - lang_item::LangItem, - type_ref::Rawness, -}; +use chalk_ir::Mutability; +use hir_def::{FunctionId, ItemContainerId, Lookup, TraitId}; use crate::{ - AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, - ClosureId, DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy, - QuantifiedWhereClause, Substitution, ToChalk, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, - WhereClause, - db::HirDatabase, - from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, - generics::generics, - next_solver::{DbInterner, mapping::NextSolverToChalk}, - to_chalk_trait_id, + AdtId, Binders, CallableDefId, CallableSig, DynTy, Interner, Lifetime, ProjectionTy, + Substitution, ToChalk, TraitRef, Ty, TyKind, TypeFlags, WhereClause, db::HirDatabase, + from_assoc_type_id, from_chalk_trait_id, generics::generics, to_chalk_trait_id, utils::ClosureSubst, }; -pub trait TyExt { +pub(crate) trait TyExt { fn is_unit(&self) -> bool; - fn is_integral(&self) -> bool; - fn is_scalar(&self) -> bool; - fn is_floating_point(&self) -> bool; - fn is_never(&self) -> bool; - fn is_str(&self) -> bool; fn is_unknown(&self) -> bool; fn contains_unknown(&self) -> bool; - fn is_ty_var(&self) -> bool; - fn is_union(&self) -> bool; fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>; - fn as_builtin(&self) -> Option; fn as_tuple(&self) -> Option<&Substitution>; - fn as_closure(&self) -> Option; fn as_fn_def(&self, db: &dyn HirDatabase) -> Option; fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>; - fn as_raw_ptr(&self) -> Option<(&Ty, Mutability)>; - fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>; - fn as_generic_def(&self, db: &dyn HirDatabase) -> Option; fn callable_def(&self, db: &dyn HirDatabase) -> Option; fn callable_sig(&self, db: &dyn HirDatabase) -> Option; fn strip_references(&self) -> &Ty; - fn strip_reference(&self) -> &Ty; /// If this is a `dyn Trait`, returns that trait. fn dyn_trait(&self) -> Option; - - fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option>; - fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option; - fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool; - - /// FIXME: Get rid of this, it's not a good abstraction - fn equals_ctor(&self, other: &Ty) -> bool; } impl TyExt for Ty { @@ -68,33 +34,6 @@ impl TyExt for Ty { matches!(self.kind(Interner), TyKind::Tuple(0, _)) } - fn is_integral(&self) -> bool { - matches!( - self.kind(Interner), - TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)) - | TyKind::InferenceVar(_, TyVariableKind::Integer) - ) - } - - fn is_scalar(&self) -> bool { - matches!(self.kind(Interner), TyKind::Scalar(_)) - } - - fn is_floating_point(&self) -> bool { - matches!( - self.kind(Interner), - TyKind::Scalar(Scalar::Float(_)) | TyKind::InferenceVar(_, TyVariableKind::Float) - ) - } - - fn is_never(&self) -> bool { - matches!(self.kind(Interner), TyKind::Never) - } - - fn is_str(&self) -> bool { - matches!(self.kind(Interner), TyKind::Str) - } - fn is_unknown(&self) -> bool { matches!(self.kind(Interner), TyKind::Error) } @@ -103,14 +42,6 @@ impl TyExt for Ty { self.data(Interner).flags.contains(TypeFlags::HAS_ERROR) } - fn is_ty_var(&self) -> bool { - matches!(self.kind(Interner), TyKind::InferenceVar(_, _)) - } - - fn is_union(&self) -> bool { - matches!(self.adt_id(Interner), Some(AdtId(hir_def::AdtId::UnionId(_)))) - } - fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> { match self.kind(Interner) { TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), @@ -118,37 +49,6 @@ impl TyExt for Ty { } } - fn as_builtin(&self) -> Option { - match self.kind(Interner) { - TyKind::Str => Some(BuiltinType::Str), - TyKind::Scalar(Scalar::Bool) => Some(BuiltinType::Bool), - TyKind::Scalar(Scalar::Char) => Some(BuiltinType::Char), - TyKind::Scalar(Scalar::Float(fty)) => Some(BuiltinType::Float(match fty { - FloatTy::F128 => BuiltinFloat::F128, - FloatTy::F64 => BuiltinFloat::F64, - FloatTy::F32 => BuiltinFloat::F32, - FloatTy::F16 => BuiltinFloat::F16, - })), - TyKind::Scalar(Scalar::Int(ity)) => Some(BuiltinType::Int(match ity { - IntTy::Isize => BuiltinInt::Isize, - IntTy::I8 => BuiltinInt::I8, - IntTy::I16 => BuiltinInt::I16, - IntTy::I32 => BuiltinInt::I32, - IntTy::I64 => BuiltinInt::I64, - IntTy::I128 => BuiltinInt::I128, - })), - TyKind::Scalar(Scalar::Uint(ity)) => Some(BuiltinType::Uint(match ity { - UintTy::Usize => BuiltinUint::Usize, - UintTy::U8 => BuiltinUint::U8, - UintTy::U16 => BuiltinUint::U16, - UintTy::U32 => BuiltinUint::U32, - UintTy::U64 => BuiltinUint::U64, - UintTy::U128 => BuiltinUint::U128, - })), - _ => None, - } - } - fn as_tuple(&self) -> Option<&Substitution> { match self.kind(Interner) { TyKind::Tuple(_, substs) => Some(substs), @@ -156,13 +56,6 @@ impl TyExt for Ty { } } - fn as_closure(&self) -> Option { - match self.kind(Interner) { - TyKind::Closure(id, _) => Some(*id), - _ => None, - } - } - fn as_fn_def(&self, db: &dyn HirDatabase) -> Option { match self.callable_def(db) { Some(CallableDefId::FunctionId(func)) => Some(func), @@ -177,33 +70,6 @@ impl TyExt for Ty { } } - fn as_raw_ptr(&self) -> Option<(&Ty, Mutability)> { - match self.kind(Interner) { - TyKind::Raw(mutability, ty) => Some((ty, *mutability)), - _ => None, - } - } - - fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { - match self.kind(Interner) { - TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)), - TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)), - _ => None, - } - } - - fn as_generic_def(&self, db: &dyn HirDatabase) -> Option { - match *self.kind(Interner) { - TyKind::Adt(AdtId(adt), ..) => Some(adt.into()), - TyKind::FnDef(callable, ..) => { - Some(GenericDefId::from_callable(db, ToChalk::from_chalk(db, callable))) - } - TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()), - TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()), - _ => None, - } - } - fn callable_def(&self, db: &dyn HirDatabase) -> Option { match self.kind(Interner) { &TyKind::FnDef(def, ..) => Some(ToChalk::from_chalk(db, def)), @@ -244,177 +110,6 @@ impl TyExt for Ty { } t } - - fn strip_reference(&self) -> &Ty { - self.as_reference().map_or(self, |(ty, _, _)| ty) - } - - fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option> { - let handle_async_block_type_impl_trait = |def: DefWithBodyId| { - let krate = def.module(db).krate(); - if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) { - // This is only used by type walking. - // Parameters will be walked outside, and projection predicate is not used. - // So just provide the Future trait. - let impl_bound = Binders::empty( - Interner, - WhereClause::Implemented(TraitRef { - trait_id: to_chalk_trait_id(future_trait), - substitution: Substitution::empty(Interner), - }), - ); - Some(vec![impl_bound]) - } else { - None - } - }; - - match self.kind(Interner) { - TyKind::OpaqueType(opaque_ty_id, subst) => { - match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { - ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => { - handle_async_block_type_impl_trait(def) - } - ImplTraitId::ReturnTypeImplTrait(func, idx) => { - db.return_type_impl_traits(func).map(|it| { - let data = - (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); - data.substitute(Interner, &subst).into_value_and_skipped_binders().0 - }) - } - ImplTraitId::TypeAliasImplTrait(alias, idx) => { - db.type_alias_impl_traits(alias).map(|it| { - let data = - (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); - data.substitute(Interner, &subst).into_value_and_skipped_binders().0 - }) - } - } - } - TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { - let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into()) - { - ImplTraitId::ReturnTypeImplTrait(func, idx) => { - db.return_type_impl_traits(func).map(|it| { - let data = - (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); - data.substitute(Interner, &opaque_ty.substitution) - }) - } - ImplTraitId::TypeAliasImplTrait(alias, idx) => { - db.type_alias_impl_traits(alias).map(|it| { - let data = - (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone()); - data.substitute(Interner, &opaque_ty.substitution) - }) - } - ImplTraitId::AsyncBlockTypeImplTrait(def, _) => { - return handle_async_block_type_impl_trait(def); - } - }; - - predicates.map(|it| it.into_value_and_skipped_binders().0) - } - TyKind::Placeholder(idx) => { - let id = from_placeholder_idx(db, *idx).0; - let generic_params = db.generic_params(id.parent); - let param_data = &generic_params[id.local_id]; - match param_data { - TypeOrConstParamData::TypeParamData(p) => match p.provenance { - TypeParamProvenance::ArgumentImplTrait => { - let substs = TyBuilder::placeholder_subst(db, id.parent); - let predicates = db - .generic_predicates(id.parent) - .iter() - .map(|pred| pred.clone().substitute(Interner, &substs)) - .filter(|wc| match wc.skip_binders() { - WhereClause::Implemented(tr) => { - &tr.self_type_parameter(Interner) == self - } - WhereClause::AliasEq(AliasEq { - alias: AliasTy::Projection(proj), - ty: _, - }) => &proj.self_type_parameter(db) == self, - WhereClause::TypeOutlives(TypeOutlives { ty, lifetime: _ }) => { - ty == self - } - _ => false, - }) - .collect::>(); - - Some(predicates) - } - _ => None, - }, - _ => None, - } - } - _ => None, - } - } - - fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option { - match self.kind(Interner) { - TyKind::AssociatedType(id, ..) => match from_assoc_type_id(*id).lookup(db).container { - ItemContainerId::TraitId(trait_id) => Some(trait_id), - _ => None, - }, - TyKind::Alias(AliasTy::Projection(projection_ty)) => { - match from_assoc_type_id(projection_ty.associated_ty_id).lookup(db).container { - ItemContainerId::TraitId(trait_id) => Some(trait_id), - _ => None, - } - } - _ => None, - } - } - - fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool { - let crate_id = owner.module(db).krate(); - let Some(copy_trait) = LangItem::Copy.resolve_trait(db, crate_id) else { - return false; - }; - let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(self).build(); - let env = db.trait_environment_for_body(owner); - let goal = Canonical { - value: InEnvironment::new( - &env.env.to_chalk(DbInterner::new_with(db, Some(env.krate), env.block)), - trait_ref.cast(Interner), - ), - binders: CanonicalVarKinds::empty(Interner), - }; - !db.trait_solve(crate_id, None, goal).no_solution() - } - - fn equals_ctor(&self, other: &Ty) -> bool { - match (self.kind(Interner), other.kind(Interner)) { - (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2, - (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => { - true - } - (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2, - (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2, - (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => { - ty_id == ty_id2 - } - (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2, - (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2, - (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..)) - | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => { - mutability == mutability2 - } - ( - TyKind::Function(FnPointer { num_binders, sig, .. }), - TyKind::Function(FnPointer { num_binders: num_binders2, sig: sig2, .. }), - ) => num_binders == num_binders2 && sig == sig2, - (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => { - cardinality == cardinality2 - } - (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true, - (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2, - _ => false, - } - } } pub trait ProjectionTyExt { @@ -445,9 +140,8 @@ impl ProjectionTyExt for ProjectionTy { } } -pub trait DynTyExt { +pub(crate) trait DynTyExt { fn principal(&self) -> Option>>; - fn principal_id(&self) -> Option>; } impl DynTyExt for DynTy { @@ -461,13 +155,6 @@ impl DynTyExt for DynTy { }) }) } - - fn principal_id(&self) -> Option> { - self.bounds.skip_binders().interned().first().and_then(|b| match b.skip_binders() { - crate::WhereClause::Implemented(trait_ref) => Some(trait_ref.trait_id), - _ => None, - }) - } } pub trait TraitRefExt { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval_chalk.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval_chalk.rs index 458974384dca..07b783ea9292 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval_chalk.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval_chalk.rs @@ -11,48 +11,15 @@ use stdx::never; use crate::{ Const, ConstData, ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, - TraitEnvironment, Ty, TyBuilder, + TraitEnvironment, Ty, db::HirDatabase, generics::Generics, lower::ParamLoweringMode, - next_solver::{ - DbInterner, - mapping::{ChalkToNextSolver, NextSolverToChalk}, - }, + next_solver::{DbInterner, mapping::ChalkToNextSolver}, to_placeholder_idx, }; -use super::mir::pad16; - -/// Extension trait for [`Const`] -pub trait ConstExt { - /// Is a [`Const`] unknown? - fn is_unknown(&self) -> bool; -} - -impl ConstExt for Const { - fn is_unknown(&self) -> bool { - match self.data(Interner).value { - // interned Unknown - chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { - interned: ConstScalar::Unknown, - }) => true, - - // interned concrete anything else - chalk_ir::ConstValue::Concrete(..) => false, - - _ => { - tracing::error!( - "is_unknown was called on a non-concrete constant value! {:?}", - self - ); - true - } - } - } -} - -pub fn path_to_const<'g>( +pub(crate) fn path_to_const<'g>( db: &dyn HirDatabase, resolver: &Resolver<'_>, path: &Path, @@ -94,7 +61,7 @@ pub fn path_to_const<'g>( } } -pub fn unknown_const(ty: Ty) -> Const { +pub(crate) fn unknown_const(ty: Ty) -> Const { ConstData { ty, value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: ConstScalar::Unknown }), @@ -102,18 +69,18 @@ pub fn unknown_const(ty: Ty) -> Const { .intern(Interner) } -pub fn unknown_const_as_generic(ty: Ty) -> GenericArg { +pub(crate) fn unknown_const_as_generic(ty: Ty) -> GenericArg { unknown_const(ty).cast(Interner) } /// Interns a constant scalar with the given type -pub fn intern_const_scalar(value: ConstScalar, ty: Ty) -> Const { +pub(crate) fn intern_const_scalar(value: ConstScalar, ty: Ty) -> Const { ConstData { ty, value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: value }) } .intern(Interner) } /// Interns a constant scalar with the given type -pub fn intern_const_ref( +pub(crate) fn intern_const_ref( db: &dyn HirDatabase, value: &LiteralConstRef, ty: Ty, @@ -139,47 +106,3 @@ pub fn intern_const_ref( }; intern_const_scalar(bytes, ty) } - -/// Interns a possibly-unknown target usize -pub fn usize_const(db: &dyn HirDatabase, value: Option, krate: Crate) -> Const { - intern_const_ref( - db, - &value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt), - TyBuilder::usize(), - krate, - ) -} - -pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option { - let interner = DbInterner::new_with(db, None, None); - match &c.data(Interner).value { - chalk_ir::ConstValue::BoundVar(_) => None, - chalk_ir::ConstValue::InferenceVar(_) => None, - chalk_ir::ConstValue::Placeholder(_) => None, - chalk_ir::ConstValue::Concrete(c) => match &c.interned { - ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(it, false))), - ConstScalar::UnevaluatedConst(c, subst) => { - let ec = db.const_eval(*c, subst.to_nextsolver(interner), None).ok()?; - try_const_usize(db, &ec.to_chalk(interner)) - } - _ => None, - }, - } -} - -pub fn try_const_isize(db: &dyn HirDatabase, c: &Const) -> Option { - let interner = DbInterner::new_with(db, None, None); - match &c.data(Interner).value { - chalk_ir::ConstValue::BoundVar(_) => None, - chalk_ir::ConstValue::InferenceVar(_) => None, - chalk_ir::ConstValue::Placeholder(_) => None, - chalk_ir::ConstValue::Concrete(c) => match &c.interned { - ConstScalar::Bytes(it, _) => Some(i128::from_le_bytes(pad16(it, true))), - ConstScalar::UnevaluatedConst(c, subst) => { - let ec = db.const_eval(*c, subst.to_nextsolver(interner), None).ok()?; - try_const_isize(db, &ec.to_chalk(interner)) - } - _ => None, - }, - } -} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs index 10c1f9c98091..ce5c98979d4d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs @@ -46,7 +46,7 @@ use rustc_ast_ir::Mutability; use rustc_type_ir::{ BoundVar, TypeAndMut, error::TypeError, - inherent::{Const as _, GenericArg as _, IntoKind, Region as _, Safety, SliceLike, Ty as _}, + inherent::{Const as _, GenericArg as _, IntoKind, Safety, SliceLike, Ty as _}, }; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; @@ -59,15 +59,15 @@ use crate::{ infer::{AllowTwoPhase, InferenceContext, TypeMismatch, unify::InferenceTable}, next_solver::{ Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, CallableIdWrapper, - ClauseKind, CoercePredicate, Const, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, - PolyFnSig, PredicateKind, Region, RegionKind, SolverDefId, TraitRef, Ty, TyKind, + Canonical, ClauseKind, CoercePredicate, Const, ConstKind, DbInterner, ErrorGuaranteed, + GenericArgs, PolyFnSig, PredicateKind, Region, RegionKind, SolverDefId, TraitRef, Ty, + TyKind, infer::{ DefineOpaqueTypes, InferCtxt, InferOk, InferResult, relate::RelateResult, select::{ImplSource, SelectionError}, traits::{Obligation, ObligationCause, PredicateObligation, PredicateObligations}, }, - mapping::{ChalkToNextSolver, NextSolverToChalk}, obligation_ctxt::ObligationCtxt, }, utils::TargetFeatureIsSafeInTarget, @@ -1525,7 +1525,7 @@ impl<'db, 'exprs> CoerceMany<'db, 'exprs> { pub fn could_coerce<'db>( db: &'db dyn HirDatabase, env: Arc>, - tys: &crate::Canonical<(crate::Ty, crate::Ty)>, + tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, ) -> bool { coerce(db, env, tys).is_ok() } @@ -1533,12 +1533,11 @@ pub fn could_coerce<'db>( fn coerce<'db>( db: &'db dyn HirDatabase, env: Arc>, - tys: &crate::Canonical<(crate::Ty, crate::Ty)>, -) -> Result<(Vec>, crate::Ty), TypeError>> { + tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, +) -> Result<(Vec>, Ty<'db>), TypeError>> { let mut table = InferenceTable::new(db, env); let interner = table.interner(); - let tys = tys.to_nextsolver(interner); - let ((ty1_with_vars, ty2_with_vars), vars) = table.infer_ctxt.instantiate_canonical(&tys); + let ((ty1_with_vars, ty2_with_vars), vars) = table.infer_ctxt.instantiate_canonical(tys); let cause = ObligationCause::new(); // FIXME: Target features. @@ -1614,5 +1613,5 @@ fn coerce<'db>( &mut fallback_const, &mut fallback_region, ); - Ok((adjustments, ty.to_chalk(interner))) + Ok((adjustments, ty)) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs index 110f767967c1..f70ed90b953a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs @@ -1,7 +1,7 @@ //! Path expression resolution. use hir_def::{ - AdtId, AssocItemId, GenericDefId, GenericParamId, ItemContainerId, Lookup, + AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup, expr_store::path::{Path, PathSegment}, resolver::{ResolveValueResult, TypeNs, ValueNs}, }; @@ -10,7 +10,7 @@ use rustc_type_ir::inherent::{SliceLike, Ty as _}; use stdx::never; use crate::{ - InferenceDiagnostic, ValueTyDefId, consteval, + InferenceDiagnostic, ValueTyDefId, generics::generics, infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext, lower_nextsolver::LifetimeElisionKind, @@ -118,22 +118,12 @@ impl<'db> InferenceContext<'_, 'db> { self.interner(), generic_def.into(), self_subst.iter().flat_map(|it| it.iter()).chain(substs.iter().skip(parent_substs_len)), - |_, _, id, _| self.error_param(id), + |_, _, id, _| GenericArg::error_from_id(self.interner(), id), ); Some(ValuePathResolution::GenericDef(value_def, generic_def, substs)) } - fn error_param(&mut self, id: GenericParamId) -> GenericArg<'db> { - match id { - GenericParamId::TypeParamId(_) => self.types.error.into(), - GenericParamId::ConstParamId(id) => { - consteval::unknown_const_as_generic(self.db.const_param_ty_ns(id)) - } - GenericParamId::LifetimeParamId(_) => self.types.re_error.into(), - } - } - pub(super) fn resolve_value_path_inner( &mut self, path: &Path, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 89bab4e59c94..114c90c7becf 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -2,29 +2,27 @@ use std::fmt; -use chalk_ir::cast::Cast; -use hir_def::GenericParamId; -use hir_def::{AdtId, lang_item::LangItem}; +use hir_def::{AdtId, GenericParamId, lang_item::LangItem}; use hir_expand::name::Name; use intern::sym; use rustc_hash::{FxHashMap, FxHashSet}; -use rustc_type_ir::{DebruijnIndex, InferConst, InferTy, RegionVid}; use rustc_type_ir::{ - TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UpcastFrom, + DebruijnIndex, InferConst, InferTy, RegionVid, TyVid, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitableExt, UpcastFrom, inherent::{Const as _, IntoKind, Ty as _}, solve::{Certainty, GoalSource}, }; use smallvec::SmallVec; use triomphe::Arc; -use crate::next_solver::{Binder, ConstKind, GenericArgs, RegionKind, SolverDefId}; use crate::{ - Interner, TraitEnvironment, + TraitEnvironment, db::{HirDatabase, InternedOpaqueTyId}, infer::InferenceContext, next_solver::{ - self, AliasTy, ClauseKind, Const, DbInterner, ErrorGuaranteed, GenericArg, Predicate, - PredicateKind, Region, SolverDefIds, TraitRef, Ty, TyKind, TypingMode, + self, AliasTy, Binder, Canonical, ClauseKind, Const, ConstKind, DbInterner, + ErrorGuaranteed, GenericArg, GenericArgs, Predicate, PredicateKind, Region, RegionKind, + SolverDefId, SolverDefIds, TraitRef, Ty, TyKind, TypingMode, fulfill::{FulfillmentCtxt, NextSolverError}, infer::{ DbInternerInferExt, DefineOpaqueTypes, InferCtxt, InferOk, InferResult, @@ -33,7 +31,6 @@ use crate::{ traits::{Obligation, ObligationCause, PredicateObligation}, }, inspect::{InspectConfig, InspectGoal, ProofTreeVisitor}, - mapping::{ChalkToNextSolver, NextSolverToChalk}, obligation_ctxt::ObligationCtxt, }, traits::{ @@ -115,10 +112,10 @@ impl<'a, 'db> ProofTreeVisitor<'db> for NestedObligationsForSelfTy<'a, 'db> { /// This means that there may be some unresolved goals that actually set bounds for the placeholder /// type for the types to unify. For example `Option` and `Option` unify although there is /// unresolved goal `T = U`. -pub fn could_unify( - db: &dyn HirDatabase, - env: Arc>, - tys: &crate::Canonical<(crate::Ty, crate::Ty)>, +pub fn could_unify<'db>( + db: &'db dyn HirDatabase, + env: Arc>, + tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, ) -> bool { could_unify_impl(db, env, tys, |ctxt| ctxt.select_where_possible()) } @@ -127,32 +124,28 @@ pub fn could_unify( /// /// This means that placeholder types are not considered to unify if there are any bounds set on /// them. For example `Option` and `Option` do not unify as we cannot show that `T = U` -pub fn could_unify_deeply( - db: &dyn HirDatabase, - env: Arc>, - tys: &crate::Canonical<(crate::Ty, crate::Ty)>, +pub fn could_unify_deeply<'db>( + db: &'db dyn HirDatabase, + env: Arc>, + tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, ) -> bool { could_unify_impl(db, env, tys, |ctxt| ctxt.select_all_or_error()) } -fn could_unify_impl( - db: &dyn HirDatabase, - env: Arc>, - tys: &crate::Canonical<(crate::Ty, crate::Ty)>, - select: for<'a, 'db> fn(&mut ObligationCtxt<'a, 'db>) -> Vec>, +fn could_unify_impl<'db>( + db: &'db dyn HirDatabase, + env: Arc>, + tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, + select: for<'a> fn(&mut ObligationCtxt<'a, 'db>) -> Vec>, ) -> bool { let interner = DbInterner::new_with(db, Some(env.krate), env.block); // FIXME(next-solver): I believe this should use `PostAnalysis` (this is only used for IDE things), // but this causes some bug because of our incorrect impl of `type_of_opaque_hir_typeck()` for TAIT // and async blocks. - let infcx = interner.infer_ctxt().build(TypingMode::Analysis { - defining_opaque_types_and_generators: SolverDefIds::new_from_iter(interner, []), - }); + let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); let cause = ObligationCause::dummy(); let at = infcx.at(&cause, env.env); - let vars = make_substitutions(tys, &infcx); - let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner).to_nextsolver(interner); - let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner).to_nextsolver(interner); + let ((ty1_with_vars, ty2_with_vars), _) = infcx.instantiate_canonical(tys); let mut ctxt = ObligationCtxt::new(&infcx); let can_unify = at .eq(DefineOpaqueTypes::No, ty1_with_vars, ty2_with_vars) @@ -161,26 +154,6 @@ fn could_unify_impl( can_unify && select(&mut ctxt).is_empty() } -fn make_substitutions( - tys: &crate::Canonical<(crate::Ty, crate::Ty)>, - infcx: &InferCtxt<'_>, -) -> crate::Substitution { - let interner = infcx.interner; - crate::Substitution::from_iter( - Interner, - tys.binders.iter(Interner).map(|it| match &it.kind { - chalk_ir::VariableKind::Ty(_) => infcx.next_ty_var().to_chalk(interner).cast(Interner), - // FIXME: maybe wrong? - chalk_ir::VariableKind::Lifetime => { - infcx.next_ty_var().to_chalk(interner).cast(Interner) - } - chalk_ir::VariableKind::Const(_ty) => { - infcx.next_const_var().to_chalk(interner).cast(Interner) - } - }), - ) -} - #[derive(Clone)] pub(crate) struct InferenceTable<'db> { pub(crate) db: &'db dyn HirDatabase, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 76cc65277cd3..734483a823e4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -39,7 +39,7 @@ mod utils; pub mod autoderef; pub mod consteval; -pub mod consteval_chalk; +mod consteval_chalk; pub mod db; pub mod diagnostics; pub mod display; @@ -62,7 +62,7 @@ mod variance; use std::hash::Hash; use chalk_ir::{ - NoSolution, VariableKinds, + VariableKinds, fold::{Shift, TypeFoldable}, interner::HasInterner, }; @@ -74,15 +74,16 @@ use la_arena::{Arena, Idx}; use mir::{MirEvalError, VTableMap}; use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; use rustc_type_ir::{ - UpcastFrom, - inherent::{SliceLike, Ty as _}, + TypeSuperVisitable, TypeVisitableExt, UpcastFrom, + inherent::{IntoKind, SliceLike, Ty as _}, }; use syntax::ast::{ConstArg, make}; use traits::FnTrait; use triomphe::Arc; +#[cfg(not(debug_assertions))] +use crate::next_solver::ErrorGuaranteed; use crate::{ - consteval::unknown_const, db::HirDatabase, display::{DisplayTarget, HirDisplay}, generics::Generics, @@ -104,11 +105,10 @@ pub use infer::{ could_coerce, could_unify, could_unify_deeply, }; pub use interner::Interner; -pub use lower::{ - ImplTraitLoweringMode, LifetimeElisionKind, ParamLoweringMode, TyDefId, TyLoweringContext, - ValueTyDefId, diagnostics::*, +pub use lower::{ImplTraitLoweringMode, ParamLoweringMode, TyDefId, ValueTyDefId, diagnostics::*}; +pub use lower_nextsolver::{ + LifetimeElisionKind, TyLoweringContext, associated_type_shorthand_candidates, }; -pub use lower_nextsolver::associated_type_shorthand_candidates; pub use mapping::{ ToChalk, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, @@ -124,20 +124,16 @@ pub use utils::{ }; pub use variance::Variance; -pub use chalk_ir::{ - AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, - cast::Cast, - visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, -}; +use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Safety, Scalar}; -pub type ForeignDefId = chalk_ir::ForeignDefId; -pub type AssocTypeId = chalk_ir::AssocTypeId; -pub type FnDefId = chalk_ir::FnDefId; -pub type ClosureId = chalk_ir::ClosureId; -pub type OpaqueTyId = chalk_ir::OpaqueTyId; -pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; +pub(crate) type ForeignDefId = chalk_ir::ForeignDefId; +pub(crate) type AssocTypeId = chalk_ir::AssocTypeId; +pub(crate) type FnDefId = chalk_ir::FnDefId; +pub(crate) type ClosureId = chalk_ir::ClosureId; +pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId; +pub(crate) type PlaceholderIndex = chalk_ir::PlaceholderIndex; -pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds; +pub(crate) type CanonicalVarKinds = chalk_ir::CanonicalVarKinds; pub(crate) type VariableKind = chalk_ir::VariableKind; /// Represents generic parameters and an item bound by them. When the item has parent, the binders @@ -148,49 +144,48 @@ pub(crate) type VariableKind = chalk_ir::VariableKind; /// parameters/arguments for an item MUST come before those for its parent. This is to facilitate /// the integration with chalk-solve, which mildly puts constraints as such. See #13335 for its /// motivation in detail. -pub type Binders = chalk_ir::Binders; +pub(crate) type Binders = chalk_ir::Binders; /// Interned list of generic arguments for an item. When an item has parent, the `Substitution` for /// it contains generic arguments for both its parent and itself. See chalk's documentation for /// details. /// /// See `Binders` for the constraint on the ordering. -pub type Substitution = chalk_ir::Substitution; -pub type GenericArg = chalk_ir::GenericArg; -pub type GenericArgData = chalk_ir::GenericArgData; +pub(crate) type Substitution = chalk_ir::Substitution; +pub(crate) type GenericArg = chalk_ir::GenericArg; +pub(crate) type GenericArgData = chalk_ir::GenericArgData; -pub type Ty = chalk_ir::Ty; +pub(crate) type Ty = chalk_ir::Ty; pub type TyKind = chalk_ir::TyKind; -pub type TypeFlags = chalk_ir::TypeFlags; +pub(crate) type TypeFlags = chalk_ir::TypeFlags; pub(crate) type DynTy = chalk_ir::DynTy; -pub type FnPointer = chalk_ir::FnPointer; +pub(crate) type FnPointer = chalk_ir::FnPointer; pub(crate) use chalk_ir::FnSubst; // a re-export so we don't lose the tuple constructor pub type AliasTy = chalk_ir::AliasTy; -pub type ProjectionTy = chalk_ir::ProjectionTy; +pub(crate) type ProjectionTy = chalk_ir::ProjectionTy; pub(crate) type OpaqueTy = chalk_ir::OpaqueTy; -pub(crate) type InferenceVar = chalk_ir::InferenceVar; pub(crate) type Lifetime = chalk_ir::Lifetime; pub(crate) type LifetimeData = chalk_ir::LifetimeData; pub(crate) type LifetimeOutlives = chalk_ir::LifetimeOutlives; -pub type ConstValue = chalk_ir::ConstValue; +pub(crate) type ConstValue = chalk_ir::ConstValue; -pub type Const = chalk_ir::Const; +pub(crate) type Const = chalk_ir::Const; pub(crate) type ConstData = chalk_ir::ConstData; pub(crate) type ConcreteConst = chalk_ir::ConcreteConst; -pub type TraitRef = chalk_ir::TraitRef; -pub type QuantifiedWhereClause = Binders; -pub type Canonical = chalk_ir::Canonical; +pub(crate) type TraitRef = chalk_ir::TraitRef; +pub(crate) type QuantifiedWhereClause = Binders; +pub(crate) type Canonical = chalk_ir::Canonical; pub(crate) type ChalkTraitId = chalk_ir::TraitId; pub(crate) type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses; pub(crate) type FnSig = chalk_ir::FnSig; -pub type InEnvironment = chalk_ir::InEnvironment; +pub(crate) type InEnvironment = chalk_ir::InEnvironment; pub type AliasEq = chalk_ir::AliasEq; pub type WhereClause = chalk_ir::WhereClause; @@ -717,130 +712,167 @@ pub(crate) fn fold_free_vars + TypeFoldable< /// 'Canonicalizes' the `t` by replacing any errors with new variables. Also /// ensures there are no unbound variables or inference variables anywhere in /// the `t`. -pub fn replace_errors_with_variables(t: &T) -> Canonical +pub fn replace_errors_with_variables<'db, T>( + interner: DbInterner<'db>, + t: &T, +) -> crate::next_solver::Canonical<'db, T> where - T: HasInterner + TypeFoldable + Clone, + T: rustc_type_ir::TypeFoldable> + Clone, { - use chalk_ir::{ - Fallible, - fold::{FallibleTypeFolder, TypeSuperFoldable}, - }; - struct ErrorReplacer { - vars: usize, + use rustc_type_ir::{FallibleTypeFolder, TypeSuperFoldable}; + struct ErrorReplacer<'db> { + interner: DbInterner<'db>, + vars: Vec>, + binder: rustc_type_ir::DebruijnIndex, } - impl FallibleTypeFolder for ErrorReplacer { - type Error = NoSolution; + impl<'db> FallibleTypeFolder> for ErrorReplacer<'db> { + #[cfg(debug_assertions)] + type Error = (); + #[cfg(not(debug_assertions))] + type Error = std::convert::Infallible; - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { - self + fn cx(&self) -> DbInterner<'db> { + self.interner } - fn interner(&self) -> Interner { - Interner + fn try_fold_binder( + &mut self, + t: crate::next_solver::Binder<'db, T>, + ) -> Result, Self::Error> + where + T: rustc_type_ir::TypeFoldable>, + { + self.binder.shift_in(1); + let result = t.try_super_fold_with(self); + self.binder.shift_out(1); + result } - fn try_fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible { - if let TyKind::Error = ty.kind(Interner) { - let index = self.vars; - self.vars += 1; - Ok(TyKind::BoundVar(BoundVar::new(outer_binder, index)).intern(Interner)) - } else { - ty.try_super_fold_with(self.as_dyn(), outer_binder) + fn try_fold_ty( + &mut self, + t: crate::next_solver::Ty<'db>, + ) -> Result, Self::Error> { + if !t.has_type_flags( + rustc_type_ir::TypeFlags::HAS_ERROR + | rustc_type_ir::TypeFlags::HAS_TY_INFER + | rustc_type_ir::TypeFlags::HAS_CT_INFER + | rustc_type_ir::TypeFlags::HAS_RE_INFER, + ) { + return Ok(t); + } + + #[cfg(debug_assertions)] + let error = || Err(()); + #[cfg(not(debug_assertions))] + let error = || Ok(crate::next_solver::Ty::new_error(self.interner, ErrorGuaranteed)); + + match t.kind() { + crate::next_solver::TyKind::Error(_) => { + let var = rustc_type_ir::BoundVar::from_usize(self.vars.len()); + self.vars.push(crate::next_solver::CanonicalVarKind::Ty { + ui: rustc_type_ir::UniverseIndex::ZERO, + sub_root: var, + }); + Ok(crate::next_solver::Ty::new_bound( + self.interner, + self.binder, + crate::next_solver::BoundTy { + var, + kind: crate::next_solver::BoundTyKind::Anon, + }, + )) + } + crate::next_solver::TyKind::Infer(_) => error(), + crate::next_solver::TyKind::Bound(index, _) if index > self.binder => error(), + _ => t.try_super_fold_with(self), } } - fn try_fold_inference_ty( + fn try_fold_const( &mut self, - _var: InferenceVar, - _kind: TyVariableKind, - _outer_binder: DebruijnIndex, - ) -> Fallible { - if cfg!(debug_assertions) { - // we don't want to just panic here, because then the error message - // won't contain the whole thing, which would not be very helpful - Err(NoSolution) - } else { - Ok(TyKind::Error.intern(Interner)) + ct: crate::next_solver::Const<'db>, + ) -> Result, Self::Error> { + if !ct.has_type_flags( + rustc_type_ir::TypeFlags::HAS_ERROR + | rustc_type_ir::TypeFlags::HAS_TY_INFER + | rustc_type_ir::TypeFlags::HAS_CT_INFER + | rustc_type_ir::TypeFlags::HAS_RE_INFER, + ) { + return Ok(ct); + } + + #[cfg(debug_assertions)] + let error = || Err(()); + #[cfg(not(debug_assertions))] + let error = || Ok(crate::next_solver::Const::error(self.interner)); + + match ct.kind() { + crate::next_solver::ConstKind::Error(_) => { + let var = rustc_type_ir::BoundVar::from_usize(self.vars.len()); + self.vars.push(crate::next_solver::CanonicalVarKind::Const( + rustc_type_ir::UniverseIndex::ZERO, + )); + Ok(crate::next_solver::Const::new_bound( + self.interner, + self.binder, + crate::next_solver::BoundConst { var }, + )) + } + crate::next_solver::ConstKind::Infer(_) => error(), + crate::next_solver::ConstKind::Bound(index, _) if index > self.binder => error(), + _ => ct.try_super_fold_with(self), } } - fn try_fold_free_var_ty( + fn try_fold_region( &mut self, - _bound_var: BoundVar, - _outer_binder: DebruijnIndex, - ) -> Fallible { - if cfg!(debug_assertions) { - // we don't want to just panic here, because then the error message - // won't contain the whole thing, which would not be very helpful - Err(NoSolution) - } else { - Ok(TyKind::Error.intern(Interner)) + region: crate::next_solver::Region<'db>, + ) -> Result, Self::Error> { + #[cfg(debug_assertions)] + let error = || Err(()); + #[cfg(not(debug_assertions))] + let error = || Ok(crate::next_solver::Region::error(self.interner)); + + match region.kind() { + crate::next_solver::RegionKind::ReError(_) => { + let var = rustc_type_ir::BoundVar::from_usize(self.vars.len()); + self.vars.push(crate::next_solver::CanonicalVarKind::Region( + rustc_type_ir::UniverseIndex::ZERO, + )); + Ok(crate::next_solver::Region::new_bound( + self.interner, + self.binder, + crate::next_solver::BoundRegion { + var, + kind: crate::next_solver::BoundRegionKind::Anon, + }, + )) + } + crate::next_solver::RegionKind::ReVar(_) => error(), + crate::next_solver::RegionKind::ReBound(index, _) if index > self.binder => error(), + _ => Ok(region), } } - - fn try_fold_inference_const( - &mut self, - ty: Ty, - _var: InferenceVar, - _outer_binder: DebruijnIndex, - ) -> Fallible { - if cfg!(debug_assertions) { - Err(NoSolution) - } else { - let interner = DbInterner::conjure(); - Ok(unknown_const(ty.to_nextsolver(interner)).to_chalk(interner)) - } - } - - fn try_fold_free_var_const( - &mut self, - ty: Ty, - _bound_var: BoundVar, - _outer_binder: DebruijnIndex, - ) -> Fallible { - if cfg!(debug_assertions) { - Err(NoSolution) - } else { - let interner = DbInterner::conjure(); - Ok(unknown_const(ty.to_nextsolver(interner)).to_chalk(interner)) - } - } - - fn try_fold_inference_lifetime( - &mut self, - _var: InferenceVar, - _outer_binder: DebruijnIndex, - ) -> Fallible { - if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(error_lifetime()) } - } - - fn try_fold_free_var_lifetime( - &mut self, - _bound_var: BoundVar, - _outer_binder: DebruijnIndex, - ) -> Fallible { - if cfg!(debug_assertions) { Err(NoSolution) } else { Ok(error_lifetime()) } - } } - let mut error_replacer = ErrorReplacer { vars: 0 }; - let value = match t.clone().try_fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) { + + let mut error_replacer = + ErrorReplacer { vars: Vec::new(), binder: rustc_type_ir::DebruijnIndex::ZERO, interner }; + let value = match t.clone().try_fold_with(&mut error_replacer) { Ok(t) => t, Err(_) => panic!("Encountered unbound or inference vars in {t:?}"), }; - let kinds = (0..error_replacer.vars).map(|_| { - chalk_ir::CanonicalVarKind::new( - chalk_ir::VariableKind::Ty(TyVariableKind::General), - chalk_ir::UniverseIndex::ROOT, - ) - }); - Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) } + crate::next_solver::Canonical { + value, + max_universe: rustc_type_ir::UniverseIndex::ZERO, + variables: crate::next_solver::CanonicalVars::new_from_iter(interner, error_replacer.vars), + } } pub fn callable_sig_from_fn_trait<'db>( - self_ty: &Ty, + self_ty: crate::next_solver::Ty<'db>, trait_env: Arc>, db: &'db dyn HirDatabase, -) -> Option<(FnTrait, CallableSig)> { +) -> Option<(FnTrait, crate::next_solver::PolyFnSig<'db>)> { let krate = trait_env.krate; let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?; let output_assoc_type = fn_once_trait @@ -857,7 +889,7 @@ pub fn callable_sig_from_fn_trait<'db>( // - Self: FnOnce // - >::Output == ?ret_ty let args_ty = table.next_ty_var(); - let args = [self_ty.to_nextsolver(table.interner()), args_ty]; + let args = [self_ty, args_ty]; let trait_ref = crate::next_solver::TraitRef::new(table.interner(), fn_once_trait.into(), args); let projection = crate::next_solver::Ty::new_alias( table.interner(), @@ -880,23 +912,24 @@ pub fn callable_sig_from_fn_trait<'db>( )) .no_solution() { - let ret_ty = table.resolve_completely(return_ty).to_chalk(table.interner()); - let args_ty = table.resolve_completely(args_ty).to_chalk(table.interner()); - let params = args_ty - .as_tuple()? - .iter(Interner) - .map(|it| it.assert_ty_ref(Interner)) - .cloned(); + let ret_ty = table.resolve_completely(return_ty); + let args_ty = table.resolve_completely(args_ty); + let crate::next_solver::TyKind::Tuple(params) = args_ty.kind() else { + return None; + }; + let inputs_and_output = crate::next_solver::Tys::new_from_iter( + table.interner(), + params.iter().chain(std::iter::once(ret_ty)), + ); return Some(( fn_x, - CallableSig::from_params_and_return( - params, - ret_ty, - false, - Safety::Safe, - FnAbi::RustCall, - ), + crate::next_solver::Binder::dummy(crate::next_solver::FnSig { + inputs_and_output, + c_variadic: false, + safety: crate::next_solver::abi::Safety::Safe, + abi: FnAbi::RustCall, + }), )); } } @@ -906,74 +939,43 @@ pub fn callable_sig_from_fn_trait<'db>( } } -struct PlaceholderCollector<'db> { - db: &'db dyn HirDatabase, - placeholders: FxHashSet, +struct ParamCollector { + params: FxHashSet, } -impl PlaceholderCollector<'_> { - fn collect(&mut self, idx: PlaceholderIndex) { - let id = from_placeholder_idx(self.db, idx).0; - self.placeholders.insert(id); - } -} +impl<'db> rustc_type_ir::TypeVisitor> for ParamCollector { + type Result = (); -impl TypeVisitor for PlaceholderCollector<'_> { - type BreakTy = (); - - fn as_dyn(&mut self) -> &mut dyn TypeVisitor { - self - } - - fn interner(&self) -> Interner { - Interner - } - - fn visit_ty( - &mut self, - ty: &Ty, - outer_binder: DebruijnIndex, - ) -> std::ops::ControlFlow { - let has_placeholder_bits = TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER; - let chalk_ir::TyData { kind, flags } = ty.data(Interner); - - if let TyKind::Placeholder(idx) = kind { - self.collect(*idx); - } else if flags.intersects(has_placeholder_bits) { - return ty.super_visit_with(self, outer_binder); - } else { - // Fast path: don't visit inner types (e.g. generic arguments) when `flags` indicate - // that there are no placeholders. + fn visit_ty(&mut self, ty: crate::next_solver::Ty<'db>) -> Self::Result { + if let crate::next_solver::TyKind::Param(param) = ty.kind() { + self.params.insert(param.id.into()); } - std::ops::ControlFlow::Continue(()) + ty.super_visit_with(self); } - fn visit_const( - &mut self, - constant: &chalk_ir::Const, - _outer_binder: DebruijnIndex, - ) -> std::ops::ControlFlow { - if let chalk_ir::ConstValue::Placeholder(idx) = constant.data(Interner).value { - self.collect(idx); + fn visit_const(&mut self, konst: crate::next_solver::Const<'db>) -> Self::Result { + if let crate::next_solver::ConstKind::Param(param) = konst.kind() { + self.params.insert(param.id.into()); } - std::ops::ControlFlow::Continue(()) + + konst.super_visit_with(self); } } -/// Returns unique placeholders for types and consts contained in `value`. -pub fn collect_placeholders(value: &T, db: &dyn HirDatabase) -> Vec +/// Returns unique params for types and consts contained in `value`. +pub fn collect_params<'db, T>(value: &T) -> Vec where - T: ?Sized + TypeVisitable, + T: ?Sized + rustc_type_ir::TypeVisitable>, { - let mut collector = PlaceholderCollector { db, placeholders: FxHashSet::default() }; - _ = value.visit_with(&mut collector, DebruijnIndex::INNERMOST); - collector.placeholders.into_iter().collect() + let mut collector = ParamCollector { params: FxHashSet::default() }; + value.visit_with(&mut collector); + Vec::from_iter(collector.params) } -pub fn known_const_to_ast( - konst: &Const, - db: &dyn HirDatabase, +pub fn known_const_to_ast<'db>( + konst: crate::next_solver::Const<'db>, + db: &'db dyn HirDatabase, display_target: DisplayTarget, ) -> Option { Some(make::expr_const_value(konst.display(db, display_target).to_string().as_str())) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index ee7b0cdd1fe3..b18d713c411e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -86,7 +86,7 @@ impl ImplTraitLoweringState { pub(crate) struct PathDiagnosticCallbackData(pub(crate) TypeRefId); #[derive(Debug, Clone)] -pub enum LifetimeElisionKind { +pub(crate) enum LifetimeElisionKind { /// Create a new anonymous lifetime parameter and reference it. /// /// If `report_in_path`, report an error when encountering lifetime elision in a path: @@ -111,14 +111,6 @@ pub enum LifetimeElisionKind { /// error on default object bounds (e.g., `Box`). AnonymousReportError, - /// Resolves elided lifetimes to `'static` if there are no other lifetimes in scope, - /// otherwise give a warning that the previous behavior of introducing a new early-bound - /// lifetime is a bug and will be removed (if `only_lint` is enabled). - StaticIfNoLifetimeInScope { only_lint: bool }, - - /// Signal we cannot find which should be the anonymous lifetime. - ElisionFailure, - /// Infer all elided lifetimes. Infer, } @@ -132,7 +124,7 @@ impl LifetimeElisionKind { } #[derive(Debug)] -pub struct TyLoweringContext<'db> { +pub(crate) struct TyLoweringContext<'db> { pub db: &'db dyn HirDatabase, resolver: &'db Resolver<'db>, store: &'db ExpressionStore, @@ -152,7 +144,7 @@ pub struct TyLoweringContext<'db> { } impl<'db> TyLoweringContext<'db> { - pub fn new( + pub(crate) fn new( db: &'db dyn HirDatabase, resolver: &'db Resolver<'db>, store: &'db ExpressionStore, @@ -177,7 +169,7 @@ impl<'db> TyLoweringContext<'db> { } } - pub fn with_debruijn( + pub(crate) fn with_debruijn( &mut self, debruijn: DebruijnIndex, f: impl FnOnce(&mut TyLoweringContext<'_>) -> T, @@ -188,7 +180,7 @@ impl<'db> TyLoweringContext<'db> { result } - pub fn with_shifted_in( + pub(crate) fn with_shifted_in( &mut self, debruijn: DebruijnIndex, f: impl FnOnce(&mut TyLoweringContext<'_>) -> T, @@ -207,25 +199,15 @@ impl<'db> TyLoweringContext<'db> { result } - pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { + pub(crate) fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self } } - pub fn with_type_param_mode(self, type_param_mode: ParamLoweringMode) -> Self { + pub(crate) fn with_type_param_mode(self, type_param_mode: ParamLoweringMode) -> Self { Self { type_param_mode, ..self } } - pub fn impl_trait_mode(&mut self, impl_trait_mode: ImplTraitLoweringMode) -> &mut Self { - self.impl_trait_mode = ImplTraitLoweringState::new(impl_trait_mode); - self - } - - pub fn type_param_mode(&mut self, type_param_mode: ParamLoweringMode) -> &mut Self { - self.type_param_mode = type_param_mode; - self - } - - pub fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { + pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind }); } } @@ -249,11 +231,11 @@ pub enum ParamLoweringMode { } impl<'db> TyLoweringContext<'db> { - pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty { + pub(crate) fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty { self.lower_ty_ext(type_ref).0 } - pub fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty) -> Const { + pub(crate) fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty) -> Const { let const_ref = &self.store[const_ref.expr]; match const_ref { hir_def::hir::Expr::Path(path) => path_to_const( @@ -308,7 +290,7 @@ impl<'db> TyLoweringContext<'db> { } } - pub fn lower_path_as_const(&mut self, path: &Path, const_type: Ty) -> Const { + pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty) -> Const { path_to_const( self.db, self.resolver, @@ -325,7 +307,7 @@ impl<'db> TyLoweringContext<'db> { self.generics.get_or_init(|| generics(self.db, self.def)) } - pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty, Option) { + pub(crate) fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty, Option) { let mut res = None; let type_ref = &self.store[type_ref_id]; let ty = match type_ref { @@ -774,7 +756,7 @@ impl<'db> TyLoweringContext<'db> { ImplTrait { bounds: crate::make_single_type_binders(predicates) } } - pub fn lower_lifetime(&self, lifetime: LifetimeRefId) -> Lifetime { + pub(crate) fn lower_lifetime(&self, lifetime: LifetimeRefId) -> Lifetime { match self.resolver.resolve_lifetime(&self.store[lifetime]) { Some(resolution) => match resolution { LifetimeNs::Static => static_lifetime(), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs index f988b6160ba5..09a256a86dcc 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs @@ -21,18 +21,17 @@ use stdx::never; use crate::{ AliasEq, AliasTy, GenericArgsProhibitedReason, ImplTraitLoweringMode, IncorrectGenericsLenKind, Interner, ParamLoweringMode, PathGenericsSource, PathLoweringDiagnostic, ProjectionTy, - QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyDefId, TyKind, - TyLoweringContext, WhereClause, + QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyDefId, TyKind, WhereClause, consteval_chalk::{unknown_const, unknown_const_as_generic}, db::HirDatabase, error_lifetime, generics::{Generics, generics}, - lower::{LifetimeElisionKind, named_associated_type_shorthand_candidates}, + lower::{LifetimeElisionKind, TyLoweringContext, named_associated_type_shorthand_candidates}, next_solver::{ DbInterner, mapping::{ChalkToNextSolver, NextSolverToChalk}, }, - static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, + to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, utils::associated_type_by_name_including_super_traits, }; @@ -650,14 +649,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { }); } - fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32) { - self.ctx.on_diagnostic(PathLoweringDiagnostic::ElisionFailure { - generics_source: self.generics_source, - def, - expected_count, - }); - } - fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32) { self.ctx.on_diagnostic(PathLoweringDiagnostic::MissingLifetime { generics_source: self.generics_source, @@ -810,8 +801,6 @@ pub(crate) trait GenericArgsLowerer { hard_error: bool, ); - fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32); - fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32); fn report_len_mismatch( @@ -884,13 +873,6 @@ fn check_generic_args_len( ctx.report_missing_lifetime(def, lifetime_args_len as u32); had_error = true } - LifetimeElisionKind::ElisionFailure => { - ctx.report_elision_failure(def, lifetime_args_len as u32); - had_error = true; - } - LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => { - // FIXME: Check there are other lifetimes in scope, and error/lint. - } LifetimeElisionKind::Elided(_) => { ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, false); } @@ -1099,15 +1081,11 @@ pub(crate) fn substs_from_args_and_bindings( // If there are fewer arguments than parameters, it means we're inferring the remaining arguments. let param = if let GenericParamId::LifetimeParamId(_) = param_id { match &lifetime_elision { - LifetimeElisionKind::ElisionFailure - | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true } + LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true } | LifetimeElisionKind::AnonymousReportError => { assert!(had_count_error); ctx.inferred_kind(def, param_id, param, infer_args, &substs) } - LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => { - static_lifetime().cast(Interner) - } LifetimeElisionKind::Elided(lifetime) => lifetime.clone().cast(Interner), LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false } | LifetimeElisionKind::Infer => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs index 5a0bccea5f9c..abca6b6bb9e5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs @@ -40,7 +40,7 @@ use hir_def::{ConstId, LifetimeParamId, StaticId, TypeParamId}; use hir_expand::name::Name; use intern::{Symbol, sym}; use la_arena::{Arena, ArenaMap, Idx}; -use path::{PathDiagnosticCallback, PathLoweringContext, builtin}; +use path::{PathDiagnosticCallback, PathLoweringContext}; use rustc_ast_ir::Mutability; use rustc_hash::FxHashSet; use rustc_pattern_analysis::Captures; @@ -105,7 +105,7 @@ impl<'db> ImplTraitLoweringState<'db> { } #[derive(Debug, Clone)] -pub(crate) enum LifetimeElisionKind<'db> { +pub enum LifetimeElisionKind<'db> { /// Create a new anonymous lifetime parameter and reference it. /// /// If `report_in_path`, report an error when encountering lifetime elision in a path: @@ -174,7 +174,7 @@ impl<'db> LifetimeElisionKind<'db> { } #[derive(Debug)] -pub(crate) struct TyLoweringContext<'db, 'a> { +pub struct TyLoweringContext<'db, 'a> { pub db: &'db dyn HirDatabase, interner: DbInterner<'db>, resolver: &'a Resolver<'db>, @@ -192,7 +192,7 @@ pub(crate) struct TyLoweringContext<'db, 'a> { } impl<'db, 'a> TyLoweringContext<'db, 'a> { - pub(crate) fn new( + pub fn new( db: &'db dyn HirDatabase, resolver: &'a Resolver<'db>, store: &'a ExpressionStore, @@ -271,7 +271,7 @@ pub(crate) enum ImplTraitLoweringMode { } impl<'db, 'a> TyLoweringContext<'db, 'a> { - pub(crate) fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> { + pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> { self.lower_ty_ext(type_ref).0 } @@ -361,7 +361,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { } #[tracing::instrument(skip(self), ret)] - pub(crate) fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option) { + pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option) { let interner = self.interner; let mut res = None; let type_ref = &self.store[type_ref_id]; @@ -1013,7 +1013,7 @@ pub(crate) fn type_alias_impl_traits<'db>( pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBinder<'db, Ty<'db>> { let interner = DbInterner::new_with(db, None, None); match def { - TyDefId::BuiltinType(it) => EarlyBinder::bind(builtin(interner, it)), + TyDefId::BuiltinType(it) => EarlyBinder::bind(Ty::from_builtin_type(interner, it)), TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt( interner, it, @@ -1401,6 +1401,7 @@ pub(crate) fn generic_predicates_for_param_cycle_result( pub struct GenericPredicates<'db>(Option]>>); impl<'db> GenericPredicates<'db> { + #[inline] pub fn instantiate( &self, interner: DbInterner<'db>, @@ -1410,6 +1411,11 @@ impl<'db> GenericPredicates<'db> { .as_ref() .map(|it| EarlyBinder::bind(it.iter().copied()).iter_instantiated(interner, args)) } + + #[inline] + pub fn instantiate_identity(&self) -> Option>> { + self.0.as_ref().map(|it| it.iter().copied()) + } } impl<'db> ops::Deref for GenericPredicates<'db> { @@ -1458,8 +1464,7 @@ pub(crate) fn trait_environment_query<'db>( for pred in maybe_parent_generics.where_predicates() { for pred in ctx.lower_where_predicate(pred, false, &generics, PredicateFilter::All) { if let rustc_type_ir::ClauseKind::Trait(tr) = pred.kind().skip_binder() { - traits_in_scope - .push((convert_ty_for_result(interner, tr.self_ty()), tr.def_id().0)); + traits_in_scope.push((tr.self_ty(), tr.def_id().0)); } clauses.push(pred); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs index b003cc574d5b..ef2c392f0861 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs @@ -550,7 +550,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> { let generic_def = match typeable { - TyDefId::BuiltinType(builtinty) => return builtin(self.ctx.interner, builtinty), + TyDefId::BuiltinType(builtinty) => { + return Ty::from_builtin_type(self.ctx.interner, builtinty); + } TyDefId::AdtId(it) => it.into(), TyDefId::TypeAliasId(it) => it.into(), }; @@ -1350,42 +1352,3 @@ fn unknown_subst<'db>( }), ) } - -pub(crate) fn builtin<'db>(interner: DbInterner<'db>, builtin: BuiltinType) -> Ty<'db> { - match builtin { - BuiltinType::Char => Ty::new(interner, rustc_type_ir::TyKind::Char), - BuiltinType::Bool => Ty::new_bool(interner), - BuiltinType::Str => Ty::new(interner, rustc_type_ir::TyKind::Str), - BuiltinType::Int(t) => { - let int_ty = match primitive::int_ty_from_builtin(t) { - chalk_ir::IntTy::Isize => rustc_type_ir::IntTy::Isize, - chalk_ir::IntTy::I8 => rustc_type_ir::IntTy::I8, - chalk_ir::IntTy::I16 => rustc_type_ir::IntTy::I16, - chalk_ir::IntTy::I32 => rustc_type_ir::IntTy::I32, - chalk_ir::IntTy::I64 => rustc_type_ir::IntTy::I64, - chalk_ir::IntTy::I128 => rustc_type_ir::IntTy::I128, - }; - Ty::new_int(interner, int_ty) - } - BuiltinType::Uint(t) => { - let uint_ty = match primitive::uint_ty_from_builtin(t) { - chalk_ir::UintTy::Usize => rustc_type_ir::UintTy::Usize, - chalk_ir::UintTy::U8 => rustc_type_ir::UintTy::U8, - chalk_ir::UintTy::U16 => rustc_type_ir::UintTy::U16, - chalk_ir::UintTy::U32 => rustc_type_ir::UintTy::U32, - chalk_ir::UintTy::U64 => rustc_type_ir::UintTy::U64, - chalk_ir::UintTy::U128 => rustc_type_ir::UintTy::U128, - }; - Ty::new_uint(interner, uint_ty) - } - BuiltinType::Float(t) => { - let float_ty = match primitive::float_ty_from_builtin(t) { - chalk_ir::FloatTy::F16 => rustc_type_ir::FloatTy::F16, - chalk_ir::FloatTy::F32 => rustc_type_ir::FloatTy::F32, - chalk_ir::FloatTy::F64 => rustc_type_ir::FloatTy::F64, - chalk_ir::FloatTy::F128 => rustc_type_ir::FloatTy::F128, - }; - Ty::new_float(interner, float_ty) - } - } -} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index 110fee824cb2..98c8f3e89016 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -5,7 +5,6 @@ use std::ops::ControlFlow; use base_db::Crate; -use chalk_ir::{UniverseIndex, WithKind, cast::Cast}; use hir_def::{ AdtId, AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleId, TraitId, TypeAliasId, @@ -29,8 +28,7 @@ use triomphe::Arc; use crate::next_solver::infer::InferCtxt; use crate::next_solver::infer::select::ImplSource; use crate::{ - CanonicalVarKinds, DebruijnIndex, GenericArgData, InEnvironment, Interner, TraitEnvironment, - TyBuilder, VariableKind, + TraitEnvironment, TyBuilder, autoderef::{self, AutoderefKind}, db::HirDatabase, infer::{Adjust, Adjustment, OverloadedDeref, PointerCast, unify::InferenceTable}, @@ -42,7 +40,6 @@ use crate::{ DbInternerInferExt, DefineOpaqueTypes, traits::{Obligation, ObligationCause, PredicateObligation}, }, - mapping::NextSolverToChalk, obligation_ctxt::ObligationCtxt, }, traits::next_trait_solve_canonical_in_ctxt, @@ -1390,9 +1387,8 @@ fn iterate_inherent_methods<'db>( match self_ty.kind() { TyKind::Param(_) => { let env = table.trait_env.clone(); - let traits = env - .traits_in_scope_from_clauses(self_ty.to_chalk(table.interner())) - .flat_map(|t| all_super_traits(db, t)); + let traits = + env.traits_in_scope_from_clauses(self_ty).flat_map(|t| all_super_traits(db, t)); iterate_inherent_trait_methods( self_ty, table, @@ -1755,50 +1751,6 @@ fn is_valid_impl_fn_candidate<'db>( }) } -pub fn implements_trait_unique<'db>( - ty: &crate::Canonical, - db: &'db dyn HirDatabase, - env: &TraitEnvironment<'db>, - trait_: TraitId, -) -> bool { - let goal = generic_implements_goal(db, env, trait_, ty); - db.trait_solve(env.krate, env.block, goal.cast(Interner)).certain() -} - -/// This creates Substs for a trait with the given Self type and type variables -/// for all other parameters, to query next solver with it. -#[tracing::instrument(skip_all)] -fn generic_implements_goal<'db>( - db: &'db dyn HirDatabase, - env: &TraitEnvironment<'db>, - trait_: TraitId, - self_ty: &crate::Canonical, -) -> crate::Canonical> { - let binders = self_ty.binders.interned(); - let trait_ref = TyBuilder::trait_ref(db, trait_) - .push(self_ty.value.clone()) - .fill_with_bound_vars(DebruijnIndex::INNERMOST, binders.len()) - .build(); - - let kinds = - binders.iter().cloned().chain(trait_ref.substitution.iter(Interner).skip(1).map(|it| { - let vk = match it.data(Interner) { - GenericArgData::Ty(_) => VariableKind::Ty(chalk_ir::TyVariableKind::General), - GenericArgData::Lifetime(_) => VariableKind::Lifetime, - GenericArgData::Const(c) => VariableKind::Const(c.data(Interner).ty.clone()), - }; - WithKind::new(vk, UniverseIndex::ROOT) - })); - let binders = CanonicalVarKinds::from_iter(Interner, kinds); - - let obligation = trait_ref.cast(Interner); - let value = InEnvironment::new( - &env.env.to_chalk(DbInterner::new_with(db, Some(env.krate), env.block)), - obligation, - ); - crate::Canonical { binders, value } -} - /// This creates Substs for a trait with the given Self type and type variables /// for all other parameters, to query the trait solver with it. #[tracing::instrument(skip_all)] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs index da86fa3ae53c..2fc1fc4f45a5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs @@ -7,8 +7,8 @@ use intern::{Interned, Symbol}; use macros::{TypeFoldable, TypeVisitable}; use rustc_ast_ir::{try_visit, visit::VisitorResult}; use rustc_type_ir::{ - BoundVar, FlagComputation, Flags, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, WithCachedTypeInfo, + BoundVar, DebruijnIndex, FlagComputation, Flags, TypeFoldable, TypeSuperFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, WithCachedTypeInfo, inherent::{IntoKind, ParamEnv as _, PlaceholderLike, SliceLike}, relate::Relate, }; @@ -62,6 +62,10 @@ impl<'db> Const<'db> { Const::new(interner, ConstKind::Placeholder(placeholder)) } + pub fn new_bound(interner: DbInterner<'db>, index: DebruijnIndex, bound: BoundConst) -> Self { + Const::new(interner, ConstKind::Bound(index, bound)) + } + pub fn new_valtree( interner: DbInterner<'db>, ty: Ty<'db>, @@ -159,11 +163,11 @@ impl ParamConst { /// Represents a typed, fully evaluated constant. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, TypeFoldable, TypeVisitable)] pub struct ValueConst<'db> { - pub(crate) ty: Ty<'db>, + pub ty: Ty<'db>, // FIXME: Should we ignore this for TypeVisitable, TypeFoldable? #[type_visitable(ignore)] #[type_foldable(identity)] - pub(crate) value: Valtree<'db>, + pub value: Valtree<'db>, } impl<'db> ValueConst<'db> { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/def_id.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/def_id.rs index 3e4c4171bedd..789be3b731b1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/def_id.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/def_id.rs @@ -158,6 +158,15 @@ impl SolverDefId { _ => panic!("expected opaque type, found {self:?}"), } } + + #[inline] + #[track_caller] + pub fn expect_type_alias(self) -> TypeAliasId { + match self { + SolverDefId::TypeAliasId(it) => it, + _ => panic!("expected type alias, found {self:?}"), + } + } } impl<'db> inherent::DefId> for SolverDefId { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs index 79527dac2fef..38293c45422c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/generic_arg.rs @@ -69,6 +69,14 @@ impl<'db> GenericArg<'db> { _ => None, } } + + pub fn error_from_id(interner: DbInterner<'db>, id: GenericParamId) -> GenericArg<'db> { + match id { + GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(), + GenericParamId::ConstParamId(_) => Const::error(interner).into(), + GenericParamId::LifetimeParamId(_) => Region::error(interner).into(), + } + } } impl<'db> From> for GenericArg<'db> { @@ -192,6 +200,13 @@ impl<'db> GenericArgs<'db> { interner.mk_args(&args) } + /// Creates an all-error `GenericArgs`. + pub fn error_for_item(interner: DbInterner<'db>, def_id: SolverDefId) -> GenericArgs<'db> { + GenericArgs::for_item(interner, def_id, |_, _, id, _| { + GenericArg::error_from_id(interner, id) + }) + } + /// Like `for_item`, but prefers the default of a parameter if it has any. pub fn for_item_with_defaults( interner: DbInterner<'db>, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs index cd1667527ba6..3fd8e7b39dd7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs @@ -304,6 +304,7 @@ impl<'db> DbInterner<'db> { DbInterner { db, krate, block } } + #[inline] pub fn db(&self) -> &'db dyn HirDatabase { self.db } @@ -1952,7 +1953,6 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { false } - // FIXME(next-solver): Make this a query? Can this make cycles? fn impl_specializes( self, specializing_impl_def_id: Self::ImplId, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs index 13c333b9d54d..5e7eb7532bb0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs @@ -3,7 +3,8 @@ use hir_def::LifetimeParamId; use intern::{Interned, Symbol}; use rustc_type_ir::{ - BoundVar, Flags, INNERMOST, RegionVid, TypeFlags, TypeFoldable, TypeVisitable, VisitorResult, + BoundVar, DebruijnIndex, Flags, INNERMOST, RegionVid, TypeFlags, TypeFoldable, TypeVisitable, + VisitorResult, inherent::{IntoKind, PlaceholderLike, SliceLike}, relate::Relate, }; @@ -62,6 +63,14 @@ impl<'db> Region<'db> { Region::new(interner, RegionKind::ReErased) } + pub fn new_bound( + interner: DbInterner<'db>, + index: DebruijnIndex, + bound: BoundRegion, + ) -> Region<'db> { + Region::new(interner, RegionKind::ReBound(index, bound)) + } + pub fn is_placeholder(&self) -> bool { matches!(self.inner(), RegionKind::RePlaceholder(..)) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs index c5969120c966..44b85abba0ef 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs @@ -3,18 +3,22 @@ use std::iter; use std::ops::ControlFlow; -use hir_def::type_ref::Rawness; -use hir_def::{AdtId, GenericDefId, TypeOrConstParamId, TypeParamId}; +use hir_def::{ + AdtId, DefWithBodyId, GenericDefId, HasModule, TypeOrConstParamId, TypeParamId, + hir::generics::{TypeOrConstParamData, TypeParamProvenance}, + lang_item::LangItem, +}; +use hir_def::{TraitId, type_ref::Rawness}; use intern::{Interned, Symbol, sym}; use rustc_abi::{Float, Integer, Size}; use rustc_ast_ir::{Mutability, try_visit, visit::VisitorResult}; use rustc_type_ir::{ - BoundVar, ClosureKind, CollectAndApply, FlagComputation, Flags, FloatTy, FloatVid, InferTy, - IntTy, IntVid, Interner, TyVid, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, WithCachedTypeInfo, + AliasTyKind, BoundVar, ClosureKind, CollectAndApply, FlagComputation, Flags, FloatTy, FloatVid, + InferTy, IntTy, IntVid, Interner, TyVid, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, WithCachedTypeInfo, inherent::{ - Abi, AdtDef as _, BoundVarLike, Const as _, GenericArgs as _, IntoKind, ParamLike, - PlaceholderLike, Safety as _, SliceLike, Ty as _, + Abi, AdtDef as _, BoundExistentialPredicates, BoundVarLike, Const as _, GenericArgs as _, + IntoKind, ParamLike, PlaceholderLike, Safety as _, SliceLike, Ty as _, }, relate::Relate, solve::SizedTraitKind, @@ -24,13 +28,14 @@ use salsa::plumbing::{AsId, FromId}; use smallvec::SmallVec; use crate::{ - FnAbi, + FnAbi, ImplTraitId, db::HirDatabase, interner::InternedWrapperNoDebug, next_solver::{ - AdtDef, Binder, CallableIdWrapper, ClosureIdWrapper, Const, CoroutineIdWrapper, FnSig, - GenericArg, PolyFnSig, Region, TypeAliasIdWrapper, + AdtDef, Binder, CallableIdWrapper, Clause, ClauseKind, ClosureIdWrapper, Const, + CoroutineIdWrapper, FnSig, GenericArg, PolyFnSig, Region, TraitRef, TypeAliasIdWrapper, abi::Safety, + mapping::ChalkToNextSolver, util::{CoroutineArgsExt, IntegerTypeExt}, }, }; @@ -409,7 +414,7 @@ impl<'db> Ty<'db> { pub fn as_reference(self) -> Option<(Ty<'db>, Region<'db>, Mutability)> { match self.kind() { - TyKind::Ref(lifetime, ty, mutability) => Some((ty, lifetime, mutability)), + TyKind::Ref(region, ty, mutability) => Some((ty, region, mutability)), _ => None, } } @@ -422,6 +427,18 @@ impl<'db> Ty<'db> { } } + pub fn as_tuple(self) -> Option> { + match self.kind() { + TyKind::Tuple(tys) => Some(tys), + _ => None, + } + } + + pub fn dyn_trait(self) -> Option { + let TyKind::Dynamic(bounds, _) = self.kind() else { return None }; + Some(bounds.principal_def_id()?.0) + } + pub fn strip_references(self) -> Ty<'db> { let mut t = self; while let TyKind::Ref(_lifetime, ty, _mutability) = t.kind() { @@ -443,6 +460,176 @@ impl<'db> Ty<'db> { interner, )) } + + pub fn from_builtin_type( + interner: DbInterner<'db>, + ty: hir_def::builtin_type::BuiltinType, + ) -> Ty<'db> { + let kind = match ty { + hir_def::builtin_type::BuiltinType::Char => TyKind::Char, + hir_def::builtin_type::BuiltinType::Bool => TyKind::Bool, + hir_def::builtin_type::BuiltinType::Str => TyKind::Str, + hir_def::builtin_type::BuiltinType::Int(int) => TyKind::Int(match int { + hir_def::builtin_type::BuiltinInt::Isize => rustc_type_ir::IntTy::Isize, + hir_def::builtin_type::BuiltinInt::I8 => rustc_type_ir::IntTy::I8, + hir_def::builtin_type::BuiltinInt::I16 => rustc_type_ir::IntTy::I16, + hir_def::builtin_type::BuiltinInt::I32 => rustc_type_ir::IntTy::I32, + hir_def::builtin_type::BuiltinInt::I64 => rustc_type_ir::IntTy::I64, + hir_def::builtin_type::BuiltinInt::I128 => rustc_type_ir::IntTy::I128, + }), + hir_def::builtin_type::BuiltinType::Uint(uint) => TyKind::Uint(match uint { + hir_def::builtin_type::BuiltinUint::Usize => rustc_type_ir::UintTy::Usize, + hir_def::builtin_type::BuiltinUint::U8 => rustc_type_ir::UintTy::U8, + hir_def::builtin_type::BuiltinUint::U16 => rustc_type_ir::UintTy::U16, + hir_def::builtin_type::BuiltinUint::U32 => rustc_type_ir::UintTy::U32, + hir_def::builtin_type::BuiltinUint::U64 => rustc_type_ir::UintTy::U64, + hir_def::builtin_type::BuiltinUint::U128 => rustc_type_ir::UintTy::U128, + }), + hir_def::builtin_type::BuiltinType::Float(float) => TyKind::Float(match float { + hir_def::builtin_type::BuiltinFloat::F16 => rustc_type_ir::FloatTy::F16, + hir_def::builtin_type::BuiltinFloat::F32 => rustc_type_ir::FloatTy::F32, + hir_def::builtin_type::BuiltinFloat::F64 => rustc_type_ir::FloatTy::F64, + hir_def::builtin_type::BuiltinFloat::F128 => rustc_type_ir::FloatTy::F128, + }), + }; + Ty::new(interner, kind) + } + + pub fn as_builtin(self) -> Option { + let builtin = match self.kind() { + TyKind::Char => hir_def::builtin_type::BuiltinType::Char, + TyKind::Bool => hir_def::builtin_type::BuiltinType::Bool, + TyKind::Str => hir_def::builtin_type::BuiltinType::Str, + TyKind::Int(int) => hir_def::builtin_type::BuiltinType::Int(match int { + rustc_type_ir::IntTy::Isize => hir_def::builtin_type::BuiltinInt::Isize, + rustc_type_ir::IntTy::I8 => hir_def::builtin_type::BuiltinInt::I8, + rustc_type_ir::IntTy::I16 => hir_def::builtin_type::BuiltinInt::I16, + rustc_type_ir::IntTy::I32 => hir_def::builtin_type::BuiltinInt::I32, + rustc_type_ir::IntTy::I64 => hir_def::builtin_type::BuiltinInt::I64, + rustc_type_ir::IntTy::I128 => hir_def::builtin_type::BuiltinInt::I128, + }), + TyKind::Uint(uint) => hir_def::builtin_type::BuiltinType::Uint(match uint { + rustc_type_ir::UintTy::Usize => hir_def::builtin_type::BuiltinUint::Usize, + rustc_type_ir::UintTy::U8 => hir_def::builtin_type::BuiltinUint::U8, + rustc_type_ir::UintTy::U16 => hir_def::builtin_type::BuiltinUint::U16, + rustc_type_ir::UintTy::U32 => hir_def::builtin_type::BuiltinUint::U32, + rustc_type_ir::UintTy::U64 => hir_def::builtin_type::BuiltinUint::U64, + rustc_type_ir::UintTy::U128 => hir_def::builtin_type::BuiltinUint::U128, + }), + TyKind::Float(float) => hir_def::builtin_type::BuiltinType::Float(match float { + rustc_type_ir::FloatTy::F16 => hir_def::builtin_type::BuiltinFloat::F16, + rustc_type_ir::FloatTy::F32 => hir_def::builtin_type::BuiltinFloat::F32, + rustc_type_ir::FloatTy::F64 => hir_def::builtin_type::BuiltinFloat::F64, + rustc_type_ir::FloatTy::F128 => hir_def::builtin_type::BuiltinFloat::F128, + }), + _ => return None, + }; + Some(builtin) + } + + // FIXME: Should this be here? + pub fn impl_trait_bounds(self, db: &'db dyn HirDatabase) -> Option>> { + let interner = DbInterner::new_with(db, None, None); + + match self.kind() { + TyKind::Alias(AliasTyKind::Opaque, opaque_ty) => { + match db.lookup_intern_impl_trait_id(opaque_ty.def_id.expect_opaque_ty()) { + ImplTraitId::ReturnTypeImplTrait(func, idx) => { + db.return_type_impl_traits_ns(func).map(|it| { + let data = (*it).as_ref().map_bound(|rpit| { + &rpit.impl_traits[idx.to_nextsolver(interner)].predicates + }); + data.iter_instantiated_copied(interner, opaque_ty.args.as_slice()) + .collect() + }) + } + ImplTraitId::TypeAliasImplTrait(alias, idx) => { + db.type_alias_impl_traits_ns(alias).map(|it| { + let data = (*it).as_ref().map_bound(|rpit| { + &rpit.impl_traits[idx.to_nextsolver(interner)].predicates + }); + data.iter_instantiated_copied(interner, opaque_ty.args.as_slice()) + .collect() + }) + } + ImplTraitId::AsyncBlockTypeImplTrait(def, _) => { + let krate = def.module(db).krate(); + if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) { + // This is only used by type walking. + // Parameters will be walked outside, and projection predicate is not used. + // So just provide the Future trait. + let impl_bound = TraitRef::new( + interner, + future_trait.into(), + GenericArgs::new_from_iter(interner, []), + ) + .upcast(interner); + Some(vec![impl_bound]) + } else { + None + } + } + } + } + TyKind::Param(param) => { + // FIXME: We shouldn't use `param.id` here. + let generic_params = db.generic_params(param.id.parent()); + let param_data = &generic_params[param.id.local_id()]; + match param_data { + TypeOrConstParamData::TypeParamData(p) => match p.provenance { + TypeParamProvenance::ArgumentImplTrait => { + let predicates = db + .generic_predicates_ns(param.id.parent()) + .instantiate_identity() + .into_iter() + .flatten() + .filter(|wc| match wc.kind().skip_binder() { + ClauseKind::Trait(tr) => tr.self_ty() == self, + ClauseKind::Projection(pred) => pred.self_ty() == self, + ClauseKind::TypeOutlives(pred) => pred.0 == self, + _ => false, + }) + .collect::>(); + + Some(predicates) + } + _ => None, + }, + _ => None, + } + } + _ => None, + } + } + + /// FIXME: Get rid of this, it's not a good abstraction + pub fn equals_ctor(self, other: Ty<'db>) -> bool { + match (self.kind(), other.kind()) { + (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt.def_id() == adt2.def_id(), + (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => { + true + } + (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2, + (TyKind::Alias(_, alias, ..), TyKind::Alias(_, alias2)) => { + alias.def_id == alias2.def_id + } + (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2, + (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2, + (TyKind::Ref(.., mutability), TyKind::Ref(.., mutability2)) + | (TyKind::RawPtr(.., mutability), TyKind::RawPtr(.., mutability2)) => { + mutability == mutability2 + } + (TyKind::FnPtr(sig, hdr), TyKind::FnPtr(sig2, hdr2)) => sig == sig2 && hdr == hdr2, + (TyKind::Tuple(tys), TyKind::Tuple(tys2)) => tys.len() == tys2.len(), + (TyKind::Str, TyKind::Str) + | (TyKind::Never, TyKind::Never) + | (TyKind::Char, TyKind::Char) + | (TyKind::Bool, TyKind::Bool) => true, + (TyKind::Int(int), TyKind::Int(int2)) => int == int2, + (TyKind::Float(float), TyKind::Float(float2)) => float == float2, + _ => false, + } + } } pub fn references_non_lt_error<'db, T: TypeVisitableExt>>(t: &T) -> bool { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index 16ad54a2f2c0..cd125f3af864 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -12,7 +12,7 @@ use intern::sym; use rustc_next_trait_solver::solve::{HasChanged, SolverDelegateEvalExt}; use rustc_type_ir::{ InferCtxtLike, TypingMode, - inherent::{SliceLike, Span as _, Ty as _}, + inherent::{IntoKind, SliceLike, Span as _, Ty as _}, solve::Certainty, }; use span::Edition; @@ -28,6 +28,7 @@ use crate::{ DbInterner, GenericArg, ParamEnv, Predicate, SolverContext, Span, infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause}, mapping::{ChalkToNextSolver, NextSolverToChalk, convert_canonical_args_for_result}, + obligation_ctxt::ObligationCtxt, util::mini_canonicalize, }, utils::UnevaluatedConstEvaluatorFolder, @@ -43,7 +44,7 @@ pub struct TraitEnvironment<'db> { pub krate: Crate, pub block: Option, // FIXME make this a BTreeMap - traits_from_clauses: Box<[(Ty, TraitId)]>, + traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>, pub env: ParamEnv<'db>, } @@ -60,7 +61,7 @@ impl<'db> TraitEnvironment<'db> { pub fn new( krate: Crate, block: Option, - traits_from_clauses: Box<[(Ty, TraitId)]>, + traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>, env: ParamEnv<'db>, ) -> Arc { Arc::new(TraitEnvironment { krate, block, traits_from_clauses, env }) @@ -71,13 +72,28 @@ impl<'db> TraitEnvironment<'db> { Arc::make_mut(this).block = Some(block); } - pub fn traits_in_scope_from_clauses(&self, ty: Ty) -> impl Iterator + '_ { + pub fn traits_in_scope_from_clauses( + &self, + ty: crate::next_solver::Ty<'db>, + ) -> impl Iterator + '_ { self.traits_from_clauses .iter() .filter_map(move |(self_ty, trait_id)| (*self_ty == ty).then_some(*trait_id)) } } +/// This should be used in `hir` only. +pub fn structurally_normalize_ty<'db>( + infcx: &InferCtxt<'db>, + ty: crate::next_solver::Ty<'db>, + env: Arc>, +) -> crate::next_solver::Ty<'db> { + let crate::next_solver::TyKind::Alias(..) = ty.kind() else { return ty }; + let mut ocx = ObligationCtxt::new(infcx); + let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty); + ty.replace_infer_with_error(infcx.interner) +} + pub(crate) fn normalize_projection_query<'db>( db: &'db dyn HirDatabase, projection: ProjectionTy, @@ -440,3 +456,43 @@ impl FnTrait { self.lang_item().resolve_trait(db, krate) } } + +/// This should not be used in `hir-ty`, only in `hir`. +pub fn implements_trait_unique<'db>( + ty: crate::next_solver::Ty<'db>, + db: &'db dyn HirDatabase, + env: Arc>, + trait_: TraitId, +) -> bool { + implements_trait_unique_impl(db, env, trait_, &mut |infcx| { + infcx.fill_rest_fresh_args(trait_.into(), [ty.into()]) + }) +} + +/// This should not be used in `hir-ty`, only in `hir`. +pub fn implements_trait_unique_with_args<'db>( + db: &'db dyn HirDatabase, + env: Arc>, + trait_: TraitId, + args: crate::next_solver::GenericArgs<'db>, +) -> bool { + implements_trait_unique_impl(db, env, trait_, &mut |_| args) +} + +fn implements_trait_unique_impl<'db>( + db: &'db dyn HirDatabase, + env: Arc>, + trait_: TraitId, + create_args: &mut dyn FnMut(&InferCtxt<'db>) -> crate::next_solver::GenericArgs<'db>, +) -> bool { + let interner = DbInterner::new_with(db, Some(env.krate), env.block); + // FIXME(next-solver): I believe this should be `PostAnalysis`. + let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); + + let args = create_args(&infcx); + let trait_ref = rustc_type_ir::TraitRef::new_from_args(interner, trait_.into(), args); + let goal = crate::next_solver::Goal::new(interner, env.env, trait_ref); + + let result = crate::traits::next_trait_solve_in_ctxt(&infcx, goal); + matches!(result, Ok((_, Certainty::Yes))) +} diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index c230bbad0bc4..147f1b8653be 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -14,11 +14,7 @@ use hir_expand::{ mod_path::{ModPath, PathKind}, name::Name, }; -use hir_ty::{ - db::HirDatabase, - method_resolution, - next_solver::{DbInterner, mapping::ChalkToNextSolver}, -}; +use hir_ty::{db::HirDatabase, method_resolution}; use crate::{ Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, @@ -261,7 +257,7 @@ fn resolve_impl_trait_item<'db>( name: &Name, ns: Option, ) -> Option { - let canonical = ty.canonical(); + let canonical = ty.canonical(db); let krate = ty.krate(db); let environment = resolver .generic_def() @@ -275,11 +271,7 @@ fn resolve_impl_trait_item<'db>( // // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates) _ = method_resolution::iterate_path_candidates( - &canonical.to_nextsolver(DbInterner::new_with( - db, - Some(environment.krate), - environment.block, - )), + &canonical, db, environment, &traits_in_scope, diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index c094487a8709..a6d67e8fb4fb 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -19,7 +19,6 @@ use hir_ty::{ PathLoweringDiagnostic, TyLoweringDiagnostic, TyLoweringDiagnosticKind, db::HirDatabase, diagnostics::{BodyValidationDiagnostic, UnsafetyReason}, - next_solver::{DbInterner, mapping::NextSolverToChalk}, }; use syntax::{ AstNode, AstPtr, SyntaxError, SyntaxNodePtr, TextRange, @@ -641,7 +640,6 @@ impl<'db> AnyDiagnostic<'db> { ExprOrPatId::ExprId(expr) => expr_syntax(expr), ExprOrPatId::PatId(pat) => pat_syntax(pat), }; - let interner = DbInterner::new_with(db, None, None); Some(match d { &InferenceDiagnostic::NoSuchField { field: expr, private, variant } => { let expr_or_pat = match expr { @@ -668,11 +666,7 @@ impl<'db> AnyDiagnostic<'db> { } InferenceDiagnostic::ExpectedFunction { call_expr, found } => { let call_expr = expr_syntax(*call_expr)?; - ExpectedFunction { - call: call_expr, - found: Type::new(db, def, found.to_chalk(interner)), - } - .into() + ExpectedFunction { call: call_expr, found: Type::new(db, def, *found) }.into() } InferenceDiagnostic::UnresolvedField { expr, @@ -684,7 +678,7 @@ impl<'db> AnyDiagnostic<'db> { UnresolvedField { expr, name: name.clone(), - receiver: Type::new(db, def, receiver.to_chalk(interner)), + receiver: Type::new(db, def, *receiver), method_with_same_name_exists: *method_with_same_name_exists, } .into() @@ -700,9 +694,8 @@ impl<'db> AnyDiagnostic<'db> { UnresolvedMethodCall { expr, name: name.clone(), - receiver: Type::new(db, def, receiver.to_chalk(interner)), - field_with_same_name: (*field_with_same_name) - .map(|ty| Type::new(db, def, ty.to_chalk(interner))), + receiver: Type::new(db, def, *receiver), + field_with_same_name: (*field_with_same_name).map(|ty| Type::new(db, def, ty)), assoc_func_with_same_name: assoc_func_with_same_name.map(Into::into), } .into() @@ -729,7 +722,7 @@ impl<'db> AnyDiagnostic<'db> { } InferenceDiagnostic::TypedHole { expr, expected } => { let expr = expr_syntax(*expr)?; - TypedHole { expr, expected: Type::new(db, def, expected.to_chalk(interner)) }.into() + TypedHole { expr, expected: Type::new(db, def, *expected) }.into() } &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => { let expr_or_pat = match pat { @@ -746,13 +739,12 @@ impl<'db> AnyDiagnostic<'db> { } InferenceDiagnostic::CastToUnsized { expr, cast_ty } => { let expr = expr_syntax(*expr)?; - CastToUnsized { expr, cast_ty: Type::new(db, def, cast_ty.to_chalk(interner)) } - .into() + CastToUnsized { expr, cast_ty: Type::new(db, def, *cast_ty) }.into() } InferenceDiagnostic::InvalidCast { expr, error, expr_ty, cast_ty } => { let expr = expr_syntax(*expr)?; - let expr_ty = Type::new(db, def, expr_ty.to_chalk(interner)); - let cast_ty = Type::new(db, def, cast_ty.to_chalk(interner)); + let expr_ty = Type::new(db, def, *expr_ty); + let cast_ty = Type::new(db, def, *cast_ty); InvalidCast { expr, error: *error, expr_ty, cast_ty }.into() } InferenceDiagnostic::TyDiagnostic { source, diag } => { diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index 2bf9bb85e50d..49bf843367d3 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir/src/display.rs @@ -11,7 +11,7 @@ use hir_def::{ type_ref::{TypeBound, TypeRef, TypeRefId}, }; use hir_ty::{ - AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause, + AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyBuilder, TyKind, WhereClause, db::HirDatabase, display::{ HirDisplay, HirDisplayError, HirDisplayWithExpressionStore, HirFormatter, SizedByDefault, @@ -23,8 +23,8 @@ use itertools::Itertools; use crate::{ Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Crate, Enum, ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam, - Macro, Module, SelfParam, Static, Struct, StructKind, Trait, TraitRef, TupleField, TyBuilder, - Type, TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union, Variant, + Macro, Module, SelfParam, Static, Struct, StructKind, Trait, TraitRef, TupleField, Type, + TypeAlias, TypeNs, TypeOrConstParam, TypeParam, Union, Variant, }; impl HirDisplay for Function { diff --git a/src/tools/rust-analyzer/crates/hir/src/has_source.rs b/src/tools/rust-analyzer/crates/hir/src/has_source.rs index ae82275e3873..6f427d728b20 100644 --- a/src/tools/rust-analyzer/crates/hir/src/has_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/has_source.rs @@ -238,7 +238,7 @@ impl HasSource for Param<'_> { .map(|value| InFile { file_id, value }) } Callee::Closure(closure, _) => { - let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into()); + let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure); let (_, source_map) = db.body_with_source_map(owner); let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?; let root = db.parse_or_expand(file_id); diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 59038c2656c9..55da27781db1 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -71,29 +71,31 @@ use hir_expand::{ proc_macro::ProcMacroKind, }; use hir_ty::{ - AliasTy, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg, - GenericArgData, Interner, ParamKind, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, - TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyLoweringDiagnostic, - ValueTyDefId, WhereClause, all_super_traits, autoderef, check_orphan_rules, - consteval_chalk::{ConstExt, try_const_usize, unknown_const_as_generic}, + TraitEnvironment, TyDefId, TyLoweringDiagnostic, ValueTyDefId, all_super_traits, autoderef, + check_orphan_rules, + consteval::try_const_usize, + db::InternedClosureId, diagnostics::BodyValidationDiagnostic, - direct_super_traits, error_lifetime, known_const_to_ast, + direct_super_traits, known_const_to_ast, layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, method_resolution, mir::{MutBorrowKind, interpret_mir}, next_solver::{ - ClauseKind, DbInterner, GenericArgs, TypingMode, + AliasTy, Canonical, ClauseKind, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, + GenericArgs, PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode, infer::{DbInternerInferExt, InferCtxt}, - mapping::{ChalkToNextSolver, NextSolverToChalk, convert_ty_for_result}, }, - primitive::UintTy, - traits::FnTrait, + traits::{self, FnTrait, structurally_normalize_ty}, }; use itertools::Itertools; use rustc_hash::FxHashSet; +use rustc_type_ir::{ + AliasTyKind, TypeSuperVisitable, TypeVisitable, TypeVisitor, + inherent::{AdtDef, IntoKind, SliceLike, Term as _, Ty as _}, +}; use smallvec::SmallVec; use span::{AstIdNode, Edition, FileId}; -use stdx::{format_to, impl_from, never, variance::PhantomCovariantLifetime}; +use stdx::{format_to, impl_from, never}; use syntax::{ AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, T, TextRange, ToSmolStr, ast::{self, HasAttrs as _, HasName, HasVisibility as _}, @@ -112,7 +114,6 @@ pub use crate::{ VisibleTraits, }, }; -use rustc_type_ir::inherent::{IntoKind, SliceLike}; // Be careful with these re-exports. // @@ -156,6 +157,8 @@ pub use { proc_macro::{ProcMacros, ProcMacrosBuilder}, tt, }, + // FIXME: Properly encapsulate mir + hir_ty::mir, hir_ty::{ CastError, FnAbi, PointerCast, Variance, attach_db, attach_db_allow_change, consteval::ConstEvalError, @@ -168,8 +171,6 @@ pub use { mir::{MirEvalError, MirLowerError}, next_solver::abi::Safety, }, - // FIXME: Properly encapsulate mir - hir_ty::{Interner as ChalkTyInterner, mir}, intern::{Symbol, sym}, }; @@ -750,6 +751,9 @@ impl Module { let inherent_impls = db.inherent_impls_in_crate(self.id.krate()); + let interner = DbInterner::new_with(db, Some(self.id.krate()), self.id.containing_block()); + let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); + let mut impl_assoc_items_scratch = vec![]; for impl_def in self.impl_defs(db) { GenericDef::Impl(impl_def).diagnostics(db, acc); @@ -874,26 +878,15 @@ impl Module { .collect(); if !missing.is_empty() { - let interner = DbInterner::new_with(db, None, None); - let args: crate::next_solver::GenericArgs<'_> = - hir_ty::generics::generics(db, impl_def.id.into()) - .placeholder_subst(db) - .to_nextsolver(interner); - let self_ty = - db.impl_self_ty(impl_def.id).instantiate(interner, args).to_chalk(interner); - let self_ty = if let TyKind::Alias(AliasTy::Projection(projection)) = - self_ty.kind(Interner) - { - db.normalize_projection( - projection.clone(), - db.trait_environment(impl_def.id.into()), - ) - } else { - self_ty - }; + let self_ty = db.impl_self_ty(impl_def.id).instantiate_identity(); + let self_ty = structurally_normalize_ty( + &infcx, + self_ty, + db.trait_environment(impl_def.id.into()), + ); let self_ty_is_guaranteed_unsized = matches!( - self_ty.kind(Interner), - TyKind::Dyn(..) | TyKind::Slice(..) | TyKind::Str + self_ty.kind(), + TyKind::Dynamic(..) | TyKind::Slice(..) | TyKind::Str ); if self_ty_is_guaranteed_unsized { missing.retain(|(_, assoc_item)| { @@ -1300,17 +1293,11 @@ impl TupleField { let ty = db .infer(self.owner) .tuple_field_access_type(self.tuple) - .to_chalk(interner) - .as_slice(Interner) + .as_slice() .get(self.index as usize) - .and_then(|arg| arg.ty(Interner)) - .cloned() - .unwrap_or_else(|| TyKind::Error.intern(Interner)); - Type { - env: db.trait_environment_for_body(self.owner), - ty, - _pd: PhantomCovariantLifetime::new(), - } + .copied() + .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)); + Type { env: db.trait_environment_for_body(self.owner), ty } } } @@ -1378,17 +1365,9 @@ impl Field { VariantDef::Union(it) => it.id.into(), VariantDef::Variant(it) => it.parent_enum(db).id.into(), }; - let mut generics = generics.map(|it| it.ty); - let substs = TyBuilder::subst_for_def(db, def_id, None) - .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()), - ParamKind::Lifetime => error_lifetime().cast(Interner), - }) - .build(); - let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs); + 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); Type::new(db, var_id, ty) } @@ -1448,8 +1427,8 @@ impl Struct { Type::from_def(db, self.id) } - pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type<'_> { - Type::from_def_placeholders(db, self.id) + pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> { + Type::from_def_params(db, self.id) } pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> { @@ -1537,8 +1516,8 @@ impl Union { Type::from_def(db, self.id) } - pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type<'_> { - Type::from_def_placeholders(db, self.id) + pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> { + Type::from_def_params(db, self.id) } pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> { @@ -1604,40 +1583,43 @@ impl Enum { Type::from_def(db, self.id) } - pub fn ty_placeholders<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { - Type::from_def_placeholders(db, self.id) + pub fn ty_params<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { + Type::from_def_params(db, self.id) } /// The type of the enum variant bodies. pub fn variant_body_ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { + let interner = DbInterner::new_with(db, None, None); Type::new_for_crate( self.id.lookup(db).container.krate(), - TyBuilder::builtin(match db.enum_signature(self.id).variant_body_type() { + match db.enum_signature(self.id).variant_body_type() { layout::IntegerType::Pointer(sign) => match sign { - true => hir_def::builtin_type::BuiltinType::Int( - hir_def::builtin_type::BuiltinInt::Isize, - ), - false => hir_def::builtin_type::BuiltinType::Uint( - hir_def::builtin_type::BuiltinUint::Usize, - ), + true => Ty::new_int(interner, rustc_type_ir::IntTy::Isize), + false => Ty::new_uint(interner, rustc_type_ir::UintTy::Usize), }, layout::IntegerType::Fixed(i, sign) => match sign { - true => hir_def::builtin_type::BuiltinType::Int(match i { - layout::Integer::I8 => hir_def::builtin_type::BuiltinInt::I8, - layout::Integer::I16 => hir_def::builtin_type::BuiltinInt::I16, - layout::Integer::I32 => hir_def::builtin_type::BuiltinInt::I32, - layout::Integer::I64 => hir_def::builtin_type::BuiltinInt::I64, - layout::Integer::I128 => hir_def::builtin_type::BuiltinInt::I128, - }), - false => hir_def::builtin_type::BuiltinType::Uint(match i { - layout::Integer::I8 => hir_def::builtin_type::BuiltinUint::U8, - layout::Integer::I16 => hir_def::builtin_type::BuiltinUint::U16, - layout::Integer::I32 => hir_def::builtin_type::BuiltinUint::U32, - layout::Integer::I64 => hir_def::builtin_type::BuiltinUint::U64, - layout::Integer::I128 => hir_def::builtin_type::BuiltinUint::U128, - }), + true => Ty::new_int( + interner, + match i { + layout::Integer::I8 => rustc_type_ir::IntTy::I8, + layout::Integer::I16 => rustc_type_ir::IntTy::I16, + layout::Integer::I32 => rustc_type_ir::IntTy::I32, + layout::Integer::I64 => rustc_type_ir::IntTy::I64, + layout::Integer::I128 => rustc_type_ir::IntTy::I128, + }, + ), + false => Ty::new_uint( + interner, + match i { + layout::Integer::I8 => rustc_type_ir::UintTy::U8, + layout::Integer::I16 => rustc_type_ir::UintTy::U16, + layout::Integer::I32 => rustc_type_ir::UintTy::U32, + layout::Integer::I64 => rustc_type_ir::UintTy::U64, + layout::Integer::I128 => rustc_type_ir::UintTy::U128, + }, + ), }, - }), + }, ) } @@ -1813,26 +1795,18 @@ impl_from!(Struct, Union, Enum for Adt); impl Adt { pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { - let subst = db.generic_defaults(self.into()); - (subst.is_empty() && db.generic_params(self.into()).len_type_or_consts() != 0) - || subst.iter().any(|ty| match ty.skip_binders().data(Interner) { - GenericArgData::Ty(it) => it.is_unknown(), - _ => false, - }) + has_non_default_type_params(db, self.into()) } pub fn layout(self, db: &dyn HirDatabase) -> Result { let env = db.trait_environment(self.into()); let interner = DbInterner::new_with(db, Some(env.krate), env.block); - db.layout_of_adt( - self.into(), - TyBuilder::adt(db, self.into()) - .fill_with_defaults(db, || TyKind::Error.intern(Interner)) - .build_into_subst() - .to_nextsolver(interner), - env, - ) - .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap())) + let adt_id = AdtId::from(self); + 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) + .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap())) } /// Turns this ADT into a type. Any type parameters of the ADT will be @@ -1851,18 +1825,12 @@ impl Adt { args: impl IntoIterator>, ) -> Type<'db> { let id = AdtId::from(self); - let mut it = args.into_iter().map(|t| t.ty); - let ty = TyBuilder::def_ty(db, id.into(), None) - .fill(|x| { - let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); - match x { - ParamKind::Type => r.cast(Interner), - ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), - ParamKind::Lifetime => error_lifetime().cast(Interner), - } - }) - .build(DbInterner::conjure()) - .to_chalk(DbInterner::conjure()); + let interner = DbInterner::new_with(db, None, None); + let ty = Ty::new_adt( + interner, + id, + generic_args_from_tys(interner, id.into(), args.into_iter().map(|ty| ty.ty)), + ); Type::new(db, id, ty) } @@ -2023,7 +1991,6 @@ impl DefWithBody { style_lints: bool, ) { let krate = self.module(db).id.krate(); - let interner = DbInterner::new_with(db, Some(krate), None); let (body, source_map) = db.body_with_source_map(self.into()); let sig_source_map = match self { @@ -2073,16 +2040,8 @@ impl DefWithBody { acc.push( TypeMismatch { expr_or_pat, - expected: Type::new( - db, - DefWithBodyId::from(self), - mismatch.expected.to_chalk(interner), - ), - actual: Type::new( - db, - DefWithBodyId::from(self), - mismatch.actual.to_chalk(interner), - ), + expected: Type::new(db, DefWithBodyId::from(self), mismatch.expected), + actual: Type::new(db, DefWithBodyId::from(self), mismatch.actual), } .into(), ); @@ -2152,13 +2111,7 @@ impl DefWithBody { } mir::MirSpan::Unknown => continue, }; - acc.push( - MovedOutOfRef { - ty: Type::new_for_crate(krate, moof.ty.to_chalk(interner)), - span, - } - .into(), - ) + acc.push(MovedOutOfRef { ty: Type::new_for_crate(krate, moof.ty), span }.into()) } let mol = &borrowck_result.mutability_of_locals; for (binding_id, binding_data) in body.bindings() { @@ -2308,30 +2261,24 @@ impl Function { pub fn fn_ptr_type(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.resolver(db); - let substs = TyBuilder::placeholder_subst(db, self.id); let interner = DbInterner::new_with(db, None, None); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - let callable_sig = db - .callable_item_signature(self.id.into()) - .instantiate(interner, args) - .skip_binder() - .to_chalk(interner); - let ty = TyKind::Function(callable_sig.to_fn_ptr()).intern(Interner); + // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. + let callable_sig = db.callable_item_signature(self.id.into()).instantiate_identity(); + let ty = Ty::new_fn_ptr(interner, callable_sig); Type::new_with_resolver_inner(db, &resolver, ty) } + // FIXME: Find a better API to express all combinations here, perhaps we should have `PreInstantiationType`? + /// Get this function's return type pub fn ret_type(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.resolver(db); - let substs = TyBuilder::placeholder_subst(db, self.id); - let interner = DbInterner::new_with(db, None, None); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); + // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. let ty = db .callable_item_signature(self.id.into()) - .instantiate(interner, args) + .instantiate_identity() .skip_binder() - .output() - .to_chalk(interner); + .output(); Type::new_with_resolver_inner(db, &resolver, ty) } @@ -2342,32 +2289,15 @@ impl Function { generics: impl Iterator>, ) -> Type<'db> { let resolver = self.id.resolver(db); - let parent_id: Option = match self.id.lookup(db).container { - ItemContainerId::ImplId(it) => Some(it.into()), - ItemContainerId::TraitId(it) => Some(it.into()), - ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None, - }; - let mut generics = generics.map(|it| it.ty); - 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()), - ParamKind::Lifetime => error_lifetime().cast(Interner), - }; - - let parent_substs = - parent_id.map(|id| TyBuilder::subst_for_def(db, id, None).fill(&mut filler).build()); - let substs = TyBuilder::subst_for_def(db, self.id, parent_substs).fill(&mut filler).build(); + let interner = DbInterner::new_with(db, None, None); + let args = generic_args_from_tys(interner, self.id.into(), generics.map(|ty| ty.ty)); let interner = DbInterner::new_with(db, None, None); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); let ty = db .callable_item_signature(self.id.into()) .instantiate(interner, args) .skip_binder() - .output() - .to_chalk(interner); + .output(); Type::new_with_resolver_inner(db, &resolver, ty) } @@ -2376,18 +2306,17 @@ impl Function { return None; } let resolver = self.id.resolver(db); - let substs = TyBuilder::placeholder_subst(db, self.id); - let interner = DbInterner::new_with(db, None, None); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); + // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. let ret_ty = db .callable_item_signature(self.id.into()) - .instantiate(interner, args) + .instantiate_identity() .skip_binder() - .output() - .to_chalk(interner); + .output(); for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() { - if let WhereClause::AliasEq(output_eq) = pred.into_value_and_skipped_binders().0 { - return Type::new_with_resolver_inner(db, &resolver, output_eq.ty).into(); + if let ClauseKind::Projection(projection) = pred.kind().skip_binder() + && let Some(output_ty) = projection.term.as_type() + { + return Type::new_with_resolver_inner(db, &resolver, output_ty).into(); } } None @@ -2403,24 +2332,15 @@ impl Function { pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec> { let environment = db.trait_environment(self.id.into()); - let substs = TyBuilder::placeholder_subst(db, self.id); - let interner = DbInterner::new_with(db, None, None); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - let callable_sig = db - .callable_item_signature(self.id.into()) - .instantiate(interner, args) - .skip_binder() - .to_chalk(interner); + // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. + let callable_sig = + db.callable_item_signature(self.id.into()).instantiate_identity().skip_binder(); callable_sig - .params() + .inputs() .iter() .enumerate() .map(|(idx, ty)| { - let ty = Type { - env: environment.clone(), - ty: ty.clone(), - _pd: PhantomCovariantLifetime::new(), - }; + let ty = Type { env: environment.clone(), ty }; Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } }) .collect() @@ -2437,26 +2357,17 @@ impl Function { pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec> { let environment = db.trait_environment(self.id.into()); - let substs = TyBuilder::placeholder_subst(db, self.id); - let interner = DbInterner::new_with(db, None, None); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - let callable_sig = db - .callable_item_signature(self.id.into()) - .instantiate(interner, args) - .skip_binder() - .to_chalk(interner); + // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. + let callable_sig = + db.callable_item_signature(self.id.into()).instantiate_identity().skip_binder(); let skip = if db.function_signature(self.id).has_self_param() { 1 } else { 0 }; callable_sig - .params() + .inputs() .iter() .enumerate() .skip(skip) .map(|(idx, ty)| { - let ty = Type { - env: environment.clone(), - ty: ty.clone(), - _pd: PhantomCovariantLifetime::new(), - }; + let ty = Type { env: environment.clone(), ty }; Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } }) .collect() @@ -2469,50 +2380,18 @@ impl Function { generics: impl Iterator>, ) -> Vec> { let environment = db.trait_environment(self.id.into()); - let parent_id: Option = match self.id.lookup(db).container { - ItemContainerId::ImplId(it) => Some(it.into()), - ItemContainerId::TraitId(it) => Some(it.into()), - ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None, - }; - let mut generics = generics.map(|it| it.ty); - let parent_substs = parent_id.map(|id| { - TyBuilder::subst_for_def(db, id, None) - .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()), - ParamKind::Lifetime => error_lifetime().cast(Interner), - }) - .build() - }); - - let substs = TyBuilder::subst_for_def(db, self.id, parent_substs) - .fill(|_| { - let ty = generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)); - GenericArg::new(Interner, GenericArgData::Ty(ty)) - }) - .build(); let interner = DbInterner::new_with(db, None, None); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - let callable_sig = db - .callable_item_signature(self.id.into()) - .instantiate(interner, args) - .skip_binder() - .to_chalk(interner); + let args = generic_args_from_tys(interner, self.id.into(), generics.map(|ty| ty.ty)); + let callable_sig = + db.callable_item_signature(self.id.into()).instantiate(interner, args).skip_binder(); let skip = if db.function_signature(self.id).has_self_param() { 1 } else { 0 }; callable_sig - .params() + .inputs() .iter() .enumerate() .skip(skip) .map(|(idx, ty)| { - let ty = Type { - env: environment.clone(), - ty: ty.clone(), - _pd: PhantomCovariantLifetime::new(), - }; + let ty = Type { env: environment.clone(), ty }; Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx } }) .collect() @@ -2694,18 +2573,18 @@ pub enum Access { Owned, } -impl From for Access { - fn from(mutability: hir_ty::Mutability) -> Access { +impl From for Access { + fn from(mutability: hir_ty::next_solver::Mutability) -> Access { match mutability { - hir_ty::Mutability::Not => Access::Shared, - hir_ty::Mutability::Mut => Access::Exclusive, + hir_ty::next_solver::Mutability::Not => Access::Shared, + hir_ty::next_solver::Mutability::Mut => Access::Exclusive, } } } #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct Param<'db> { - func: Callee, + func: Callee<'db>, /// The index in parameter list, including self parameter. idx: usize, ty: Type<'db>, @@ -2751,7 +2630,7 @@ impl<'db> Param<'db> { } } Callee::Closure(closure, _) => { - let c = db.lookup_intern_closure(closure.into()); + let c = db.lookup_intern_closure(closure); let body = db.body(c.0); if let Expr::Closure { args, .. } = &body[c.1] && let Pat::Bind { id, .. } = &body[args[self.idx]] @@ -2795,17 +2674,12 @@ impl SelfParam { } pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> { - let substs = TyBuilder::placeholder_subst(db, self.func); - let interner = DbInterner::new_with(db, None, None); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - let callable_sig = db - .callable_item_signature(self.func.into()) - .instantiate(interner, args) - .skip_binder() - .to_chalk(interner); + // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. + let callable_sig = + db.callable_item_signature(self.func.into()).instantiate_identity().skip_binder(); let environment = db.trait_environment(self.func.into()); - let ty = callable_sig.params()[0].clone(); - Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } + let ty = callable_sig.inputs().as_slice()[0]; + Type { env: environment, ty } } // FIXME: Find better API to also handle const generics @@ -2814,36 +2688,13 @@ impl SelfParam { db: &'db dyn HirDatabase, generics: impl Iterator>, ) -> Type<'db> { - let parent_id: GenericDefId = match self.func.lookup(db).container { - ItemContainerId::ImplId(it) => it.into(), - ItemContainerId::TraitId(it) => it.into(), - ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => { - panic!("Never get here") - } - }; - - let mut generics = generics.map(|it| it.ty); - 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()), - ParamKind::Lifetime => error_lifetime().cast(Interner), - }; - - let parent_substs = TyBuilder::subst_for_def(db, parent_id, None).fill(&mut filler).build(); - let substs = - TyBuilder::subst_for_def(db, self.func, Some(parent_substs)).fill(&mut filler).build(); let interner = DbInterner::new_with(db, None, None); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - let callable_sig = db - .callable_item_signature(self.func.into()) - .instantiate(interner, args) - .skip_binder() - .to_chalk(interner); + let args = generic_args_from_tys(interner, self.func.into(), generics.map(|ty| ty.ty)); + let callable_sig = + db.callable_item_signature(self.func.into()).instantiate(interner, args).skip_binder(); let environment = db.trait_environment(self.func.into()); - let ty = callable_sig.params()[0].clone(); - Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } + let ty = callable_sig.inputs().as_slice()[0]; + Type { env: environment, ty } } } @@ -2936,11 +2787,11 @@ impl Const { } /// Evaluate the constant. - pub fn eval(self, db: &dyn HirDatabase) -> Result> { + pub fn eval(self, db: &dyn HirDatabase) -> Result, ConstEvalError<'_>> { let interner = DbInterner::new_with(db, None, None); - let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().to_chalk(interner); + let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity(); db.const_eval(self.id.into(), GenericArgs::new_from_iter(interner, []), None) - .map(|it| EvaluatedConst { const_: it.to_chalk(interner), def: self.id.into(), ty }) + .map(|it| EvaluatedConst { const_: it, def: self.id.into(), ty }) } } @@ -2950,29 +2801,28 @@ impl HasVisibility for Const { } } -pub struct EvaluatedConst { +pub struct EvaluatedConst<'db> { def: DefWithBodyId, - const_: hir_ty::Const, - ty: hir_ty::Ty, + const_: hir_ty::next_solver::Const<'db>, + ty: Ty<'db>, } -impl EvaluatedConst { +impl<'db> EvaluatedConst<'db> { pub fn render(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { format!("{}", self.const_.display(db, display_target)) } - pub fn render_debug<'db>(&self, db: &'db dyn HirDatabase) -> Result> { - let interner = DbInterner::new_with(db, None, None); - let data = self.const_.data(Interner); - if let TyKind::Scalar(s) = data.ty.kind(Interner) - && matches!(s, Scalar::Int(_) | Scalar::Uint(_)) - && let hir_ty::ConstValue::Concrete(c) = &data.value - && let hir_ty::ConstScalar::Bytes(b, _) = &c.interned + pub fn render_debug(&self, db: &'db dyn HirDatabase) -> Result> { + let kind = self.const_.kind(); + if let ConstKind::Value(c) = kind + && let ty = c.ty.kind() + && let TyKind::Int(_) | TyKind::Uint(_) = ty { + let b = &c.value.inner().memory; let value = u128::from_le_bytes(mir::pad16(b, false)); - let value_signed = i128::from_le_bytes(mir::pad16(b, matches!(s, Scalar::Int(_)))); + let value_signed = i128::from_le_bytes(mir::pad16(b, matches!(ty, TyKind::Int(_)))); let mut result = - if let Scalar::Int(_) = s { value_signed.to_string() } else { value.to_string() }; + if let TyKind::Int(_) = ty { value_signed.to_string() } else { value.to_string() }; if value >= 10 { format_to!(result, " ({value:#X})"); return Ok(result); @@ -2980,12 +2830,7 @@ impl EvaluatedConst { return Ok(result); } } - mir::render_const_using_debug_impl( - db, - self.def, - self.const_.to_nextsolver(interner), - self.ty.to_nextsolver(interner), - ) + mir::render_const_using_debug_impl(db, self.def, self.const_, self.ty) } } @@ -3023,11 +2868,11 @@ impl Static { } /// Evaluate the static initializer. - pub fn eval(self, db: &dyn HirDatabase) -> Result> { + pub fn eval(self, db: &dyn HirDatabase) -> Result, ConstEvalError<'_>> { let interner = DbInterner::new_with(db, None, None); - let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().to_chalk(interner); + let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity(); db.const_eval(self.id.into(), GenericArgs::new_from_iter(interner, []), None) - .map(|it| EvaluatedConst { const_: it.to_chalk(interner), def: self.id.into(), ty }) + .map(|it| EvaluatedConst { const_: it, def: self.id.into(), ty }) } } @@ -3148,12 +2993,7 @@ pub struct TypeAlias { impl TypeAlias { pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { - let subst = db.generic_defaults(self.id.into()); - (subst.is_empty() && db.generic_params(self.id.into()).len_type_or_consts() != 0) - || subst.iter().any(|ty| match ty.skip_binders().data(Interner) { - GenericArgData::Ty(it) => it.is_unknown(), - _ => false, - }) + has_non_default_type_params(db, self.id.into()) } pub fn module(self, db: &dyn HirDatabase) -> Module { @@ -3164,8 +3004,8 @@ impl TypeAlias { Type::from_def(db, self.id) } - pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type<'_> { - Type::from_def_placeholders(db, self.id) + pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> { + Type::from_def_params(db, self.id) } pub fn name(self, db: &dyn HirDatabase) -> Name { @@ -3218,7 +3058,8 @@ impl BuiltinType { pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]); - Type::new_for_crate(core, TyBuilder::builtin(self.inner)) + let interner = DbInterner::new_with(db, None, None); + Type::new_for_crate(core, Ty::from_builtin_type(interner, self.inner)) } pub fn name(self) -> Name { @@ -3894,14 +3735,13 @@ impl GenericDef { #[derive(Debug)] pub struct GenericSubstitution<'db> { def: GenericDefId, - subst: Substitution, + subst: GenericArgs<'db>, env: Arc>, - _pd: PhantomCovariantLifetime<'db>, } impl<'db> GenericSubstitution<'db> { - fn new(def: GenericDefId, subst: Substitution, env: Arc>) -> Self { - Self { def, subst, env, _pd: PhantomCovariantLifetime::new() } + fn new(def: GenericDefId, subst: GenericArgs<'db>, env: Arc>) -> Self { + Self { def, subst, env } } pub fn types(&self, db: &'db dyn HirDatabase) -> Vec<(Symbol, Type<'db>)> { @@ -3931,26 +3771,23 @@ impl<'db> GenericSubstitution<'db> { TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()), TypeOrConstParamData::ConstParamData(_) => None, }); - let parent_len = self.subst.len(Interner) + let parent_len = self.subst.len() - generics .iter_type_or_consts() .filter(|g| matches!(g.1, TypeOrConstParamData::TypeParamData(..))) .count(); - let container_params = self.subst.as_slice(Interner)[..parent_len] + let container_params = self.subst.as_slice()[..parent_len] .iter() - .filter_map(|param| param.ty(Interner).cloned()) + .filter_map(|param| param.ty()) .zip(container_type_params.into_iter().flatten()); - let self_params = self.subst.as_slice(Interner)[parent_len..] + let self_params = self.subst.as_slice()[parent_len..] .iter() - .filter_map(|param| param.ty(Interner).cloned()) + .filter_map(|param| param.ty()) .zip(type_params); container_params .chain(self_params) .filter_map(|(ty, name)| { - Some(( - name?.symbol().clone(), - Type { ty, env: self.env.clone(), _pd: PhantomCovariantLifetime::new() }, - )) + Some((name?.symbol().clone(), Type { ty, env: self.env.clone() })) }) .collect() } @@ -4057,8 +3894,7 @@ impl Local { let def = self.parent; let infer = db.infer(def); let ty = infer[self.binding_id]; - let interner = DbInterner::new_with(db, None, None); - Type::new(db, def, ty.to_chalk(interner)) + Type::new(db, def, ty) } /// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = it;` @@ -4313,8 +4149,10 @@ impl TypeParam { pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.parent().resolver(db); - let ty = TyKind::Placeholder(hir_ty::to_placeholder_idx_no_index(db, self.id.into())) - .intern(Interner); + 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); Type::new_with_resolver_inner(db, &resolver, ty) } @@ -4334,9 +4172,9 @@ impl TypeParam { pub fn default(self, db: &dyn HirDatabase) -> Option> { let ty = generic_arg_from_param(db, self.id.into())?; let resolver = self.id.parent().resolver(db); - match ty.data(Interner) { - GenericArgData::Ty(it) if *it.kind(Interner) != TyKind::Error => { - Some(Type::new_with_resolver_inner(db, &resolver, it.clone())) + match ty { + GenericArg::Ty(it) if !it.is_ty_error() => { + Some(Type::new_with_resolver_inner(db, &resolver, it)) } _ => None, } @@ -4397,7 +4235,7 @@ impl ConstParam { } pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { - Type::new(db, self.id.parent(), db.const_param_ty(self.id)) + Type::new(db, self.id.parent(), db.const_param_ty_ns(self.id)) } pub fn default( @@ -4406,17 +4244,16 @@ impl ConstParam { display_target: DisplayTarget, ) -> Option { let arg = generic_arg_from_param(db, self.id.into())?; - known_const_to_ast(arg.constant(Interner)?, db, display_target) + known_const_to_ast(arg.konst()?, db, display_target) } } -fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option { +fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option> { let local_idx = hir_ty::param_idx(db, id)?; - let defaults = db.generic_defaults(id.parent); - let ty = defaults.get(local_idx)?.clone(); - let full_subst = TyBuilder::placeholder_subst(db, id.parent); - let subst = &full_subst.as_slice(Interner)[..local_idx]; - Some(ty.substitute(Interner, &subst)) + let defaults = db.generic_defaults_ns(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()) } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -4498,13 +4335,8 @@ impl Impl { module.id.def_map(db)[module.id.local_id].scope.impls().map(Into::into).collect() } - pub fn all_for_type<'db>( - db: &'db dyn HirDatabase, - Type { ty, env, _pd: _ }: Type<'db>, - ) -> Vec { - let interner = DbInterner::new_with(db, None, None); - let ty_ns = ty.to_nextsolver(interner); - let def_crates = match method_resolution::def_crates(db, ty_ns, env.krate) { + pub fn all_for_type<'db>(db: &'db dyn HirDatabase, Type { ty, env }: Type<'db>) -> Vec { + let def_crates = match method_resolution::def_crates(db, ty, env.krate) { Some(def_crates) => def_crates, None => return Vec::new(), }; @@ -4512,10 +4344,10 @@ impl Impl { let filter = |impl_def: &Impl| { 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)) + ty.equals_ctor(rref.as_ref().map_or(self_ty.ty, |it| it.ty)) }; - let fp = TyFingerprint::for_inherent_impl(ty_ns); + let fp = TyFingerprint::for_inherent_impl(ty); let fp = match fp { Some(fp) => fp, None => return Vec::new(), @@ -4525,7 +4357,7 @@ impl Impl { def_crates.iter().for_each(|&id| { all.extend( db.inherent_impls_in_crate(id) - .for_self_ty(ty_ns) + .for_self_ty(ty) .iter() .cloned() .map(Self::from) @@ -4546,16 +4378,10 @@ impl Impl { ); } - if let Some(block) = ty.adt_id(Interner).and_then(|def| def.0.module(db).containing_block()) - { + if let Some(block) = ty.as_adt().and_then(|(def, _)| def.module(db).containing_block()) { if let Some(inherent_impls) = db.inherent_impls_in_block(block) { all.extend( - inherent_impls - .for_self_ty(ty_ns) - .iter() - .cloned() - .map(Self::from) - .filter(filter), + inherent_impls.for_self_ty(ty).iter().cloned().map(Self::from).filter(filter), ); } if let Some(trait_impls) = db.trait_impls_in_block(block) { @@ -4601,10 +4427,8 @@ impl Impl { pub fn self_ty(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - let substs = TyBuilder::placeholder_subst(db, self.id); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - let ty = db.impl_self_ty(self.id).instantiate(interner, args).to_chalk(interner); + // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. + let ty = db.impl_self_ty(self.id).instantiate_identity(); Type::new_with_resolver_inner(db, &resolver, ty) } @@ -4666,7 +4490,6 @@ impl Impl { pub struct TraitRef<'db> { env: Arc>, trait_ref: hir_ty::next_solver::TraitRef<'db>, - _pd: PhantomCovariantLifetime<'db>, } impl<'db> TraitRef<'db> { @@ -4678,7 +4501,7 @@ impl<'db> TraitRef<'db> { let env = resolver .generic_def() .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); - TraitRef { env, trait_ref, _pd: PhantomCovariantLifetime::new() } + TraitRef { env, trait_ref } } pub fn trait_(&self) -> Trait { @@ -4687,57 +4510,51 @@ impl<'db> TraitRef<'db> { pub fn self_ty(&self) -> TypeNs<'_> { let ty = self.trait_ref.self_ty(); - TypeNs { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() } + TypeNs { env: self.env.clone(), ty } } /// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the /// first argument is the `Self` type. pub fn get_type_argument(&self, idx: usize) -> Option> { - self.trait_ref.args.as_slice().get(idx).and_then(|arg| arg.ty()).map(|ty| TypeNs { - env: self.env.clone(), - ty, - _pd: PhantomCovariantLifetime::new(), - }) + self.trait_ref + .args + .as_slice() + .get(idx) + .and_then(|arg| arg.ty()) + .map(|ty| TypeNs { env: self.env.clone(), ty }) } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Closure { - id: ClosureId, - subst: Substitution, +pub struct Closure<'db> { + id: InternedClosureId, + subst: GenericArgs<'db>, } -impl From for ClosureId { - fn from(value: Closure) -> Self { - value.id - } -} - -impl Closure { - fn as_ty(self) -> Ty { - TyKind::Closure(self.id, self.subst).intern(Interner) +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) } pub fn display_with_id(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { - self.clone() - .as_ty() + self.as_ty(db) .display(db, display_target) .with_closure_style(ClosureStyle::ClosureWithId) .to_string() } pub fn display_with_impl(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String { - self.clone() - .as_ty() + self.as_ty(db) .display(db, display_target) .with_closure_style(ClosureStyle::ImplFn) .to_string() } - pub fn captured_items<'db>(&self, db: &'db dyn HirDatabase) -> Vec> { - let owner = db.lookup_intern_closure((self.id).into()).0; - let infer = &db.infer(owner); - let info = infer.closure_info(self.id.into()); + pub fn captured_items(&self, db: &'db dyn HirDatabase) -> Vec> { + let owner = db.lookup_intern_closure(self.id).0; + let infer = db.infer(owner); + let info = infer.closure_info(self.id); info.0 .iter() .cloned() @@ -4745,25 +4562,21 @@ impl Closure { .collect() } - pub fn capture_types<'db>(&self, db: &'db dyn HirDatabase) -> Vec> { - let owner = db.lookup_intern_closure((self.id).into()).0; - let infer = &db.infer(owner); - let (captures, _) = infer.closure_info(self.id.into()); - let interner = DbInterner::new_with(db, None, None); + pub fn capture_types(&self, db: &'db dyn HirDatabase) -> Vec> { + let owner = db.lookup_intern_closure(self.id).0; + let infer = db.infer(owner); + let (captures, _) = infer.closure_info(self.id); + let env = db.trait_environment_for_body(owner); captures .iter() - .map(|capture| Type { - env: db.trait_environment_for_body(owner), - ty: capture.ty(db, self.subst.to_nextsolver(interner)).to_chalk(interner), - _pd: PhantomCovariantLifetime::new(), - }) + .map(|capture| Type { env: env.clone(), ty: capture.ty(db, self.subst) }) .collect() } pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait { - let owner = db.lookup_intern_closure((self.id).into()).0; - let infer = &db.infer(owner); - let info = infer.closure_info(self.id.into()); + let owner = db.lookup_intern_closure(self.id).0; + let infer = db.infer(owner); + let info = infer.closure_info(self.id); info.1 } } @@ -4771,7 +4584,7 @@ impl Closure { #[derive(Clone, Debug, PartialEq, Eq)] pub struct ClosureCapture<'db> { owner: DefWithBodyId, - closure: ClosureId, + closure: InternedClosureId, capture: hir_ty::CapturedItem<'db>, } @@ -4889,15 +4702,14 @@ impl CaptureUsageSource { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct Type<'db> { env: Arc>, - ty: Ty, - _pd: PhantomCovariantLifetime<'db>, + ty: Ty<'db>, } impl<'db> Type<'db> { pub(crate) fn new_with_resolver( db: &'db dyn HirDatabase, resolver: &Resolver<'_>, - ty: Ty, + ty: Ty<'db>, ) -> Self { Type::new_with_resolver_inner(db, resolver, ty) } @@ -4905,275 +4717,252 @@ impl<'db> Type<'db> { pub(crate) fn new_with_resolver_inner( db: &'db dyn HirDatabase, resolver: &Resolver<'_>, - ty: Ty, + ty: Ty<'db>, ) -> Self { let environment = resolver .generic_def() .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); - Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } + Type { env: environment, ty } } - pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty) -> Self { - Type { env: TraitEnvironment::empty(krate), ty, _pd: PhantomCovariantLifetime::new() } + pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty<'db>) -> Self { + Type { env: TraitEnvironment::empty(krate), ty } } - fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty) -> Self { + fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self { let resolver = lexical_env.resolver(db); let environment = resolver .generic_def() .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); - Type { env: environment, ty, _pd: PhantomCovariantLifetime::new() } + Type { env: environment, ty } } fn from_def(db: &'db dyn HirDatabase, def: impl Into + HasResolver) -> Self { let interner = DbInterner::new_with(db, None, None); let ty = db.ty(def.into()); - let substs = TyBuilder::unknown_subst( - db, - match def.into() { - TyDefId::AdtId(it) => GenericDefId::AdtId(it), - TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it), - TyDefId::BuiltinType(_) => { - return Type::new(db, def, ty.skip_binder().to_chalk(interner)); - } - }, - ); - let args: hir_ty::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - Type::new(db, def, ty.instantiate(interner, args).to_chalk(interner)) + let def = match def.into() { + TyDefId::AdtId(it) => GenericDefId::AdtId(it), + TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it), + TyDefId::BuiltinType(_) => { + return Type::new(db, def, ty.skip_binder()); + } + }; + let args = GenericArgs::error_for_item(interner, def.into()); + Type::new(db, def, ty.instantiate(interner, args)) } - fn from_def_placeholders( - db: &'db dyn HirDatabase, - def: impl Into + HasResolver, - ) -> Self { - let interner = DbInterner::new_with(db, None, None); + // FIXME: We shouldn't leak `TyKind::Param`s. + fn from_def_params(db: &'db dyn HirDatabase, def: impl Into + HasResolver) -> Self { let ty = db.ty(def.into()); - let substs = TyBuilder::placeholder_subst( - db, - match def.into() { - TyDefId::AdtId(it) => GenericDefId::AdtId(it), - TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it), - TyDefId::BuiltinType(_) => { - return Type::new(db, def, ty.skip_binder().to_chalk(interner)); - } - }, - ); - let args: hir_ty::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - Type::new(db, def, ty.instantiate(interner, args).to_chalk(interner)) + Type::new(db, def, ty.instantiate_identity()) } fn from_value_def( db: &'db dyn HirDatabase, def: impl Into + HasResolver, ) -> Self { - let Some(ty) = db.value_ty(def.into()) else { - return Type::new(db, def, TyKind::Error.intern(Interner)); - }; let interner = DbInterner::new_with(db, None, None); - let substs = TyBuilder::unknown_subst( - db, - match def.into() { - ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it), - ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it), - ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)), - ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)), - ValueTyDefId::EnumVariantId(it) => { - GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent)) - } - ValueTyDefId::StaticId(_) => { - return Type::new(db, def, ty.skip_binder().to_chalk(interner)); - } - }, - ); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - Type::new(db, def, ty.instantiate(interner, args).to_chalk(interner)) + let Some(ty) = db.value_ty(def.into()) else { + return Type::new(db, def, Ty::new_error(interner, ErrorGuaranteed)); + }; + let def = match def.into() { + ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it), + ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it), + ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)), + ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)), + ValueTyDefId::EnumVariantId(it) => { + GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent)) + } + ValueTyDefId::StaticId(_) => { + return Type::new(db, def, ty.skip_binder()); + } + }; + let args = GenericArgs::error_for_item(interner, def.into()); + Type::new(db, def, ty.instantiate(interner, args)) } pub fn new_slice(ty: Self) -> Self { - Type { env: ty.env, ty: TyBuilder::slice(ty.ty), _pd: PhantomCovariantLifetime::new() } + let interner = DbInterner::conjure(); + Type { env: ty.env, ty: Ty::new_slice(interner, ty.ty) } } pub fn new_tuple(krate: base_db::Crate, tys: &[Self]) -> Self { - let tys = tys.iter().map(|it| it.ty.clone()); - Type { - env: TraitEnvironment::empty(krate), - ty: TyBuilder::tuple_with(tys), - _pd: PhantomCovariantLifetime::new(), - } + let tys = tys.iter().map(|it| it.ty); + let interner = DbInterner::conjure(); + Type { env: TraitEnvironment::empty(krate), ty: Ty::new_tup_from_iter(interner, tys) } } pub fn is_unit(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Tuple(0, ..)) + self.ty.is_unit() } pub fn is_bool(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool)) + matches!(self.ty.kind(), TyKind::Bool) } pub fn is_str(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Str) + matches!(self.ty.kind(), TyKind::Str) } pub fn is_never(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Never) + matches!(self.ty.kind(), TyKind::Never) } pub fn is_mutable_reference(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) + matches!(self.ty.kind(), TyKind::Ref(.., hir_ty::next_solver::Mutability::Mut)) } pub fn is_reference(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Ref(..)) + matches!(self.ty.kind(), TyKind::Ref(..)) } pub fn contains_reference(&self, db: &'db dyn HirDatabase) -> bool { - return go(db, &self.ty); + let interner = DbInterner::new_with(db, None, None); + return self.ty.visit_with(&mut Visitor { interner }).is_break(); fn is_phantom_data(db: &dyn HirDatabase, adt_id: AdtId) -> bool { match adt_id { - hir_def::AdtId::StructId(s) => { + AdtId::StructId(s) => { let flags = db.struct_signature(s).flags; flags.contains(StructFlags::IS_PHANTOM_DATA) } - hir_def::AdtId::UnionId(_) => false, - hir_def::AdtId::EnumId(_) => false, + AdtId::UnionId(_) | AdtId::EnumId(_) => false, } } - fn go(db: &dyn HirDatabase, ty: &Ty) -> bool { - match ty.kind(Interner) { - // Reference itself - TyKind::Ref(_, _, _) => true, + struct Visitor<'db> { + interner: DbInterner<'db>, + } - // For non-phantom_data adts we check variants/fields as well as generic parameters - TyKind::Adt(adt_id, substitution) if !is_phantom_data(db, adt_id.0) => { - let _variant_id_to_fields = |id: VariantId| { - let variant_data = &id.fields(db); - if variant_data.fields().is_empty() { - vec![] - } else { - let field_types = db.field_types(id); - variant_data - .fields() + impl<'db> TypeVisitor> for Visitor<'db> { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result { + match ty.kind() { + // Reference itself + TyKind::Ref(..) => ControlFlow::Break(()), + + // For non-phantom_data adts we check variants/fields as well as generic parameters + TyKind::Adt(adt_def, args) + if !is_phantom_data(self.interner.db(), adt_def.def_id().0) => + { + let _variant_id_to_fields = |id: VariantId| { + let variant_data = &id.fields(self.interner.db()); + if variant_data.fields().is_empty() { + vec![] + } else { + let field_types = self.interner.db().field_types_ns(id); + variant_data + .fields() + .iter() + .map(|(idx, _)| { + field_types[idx].instantiate(self.interner, args) + }) + .filter(|it| !it.references_non_lt_error()) + .collect() + } + }; + let variant_id_to_fields = |_: VariantId| vec![]; + + let variants: Vec>> = match adt_def.def_id().0 { + AdtId::StructId(id) => { + vec![variant_id_to_fields(id.into())] + } + AdtId::EnumId(id) => id + .enum_variants(self.interner.db()) + .variants .iter() - .map(|(idx, _)| { - field_types[idx].clone().substitute(Interner, substitution) - }) - .filter(|it| !it.contains_unknown()) - .collect() - } - }; - let variant_id_to_fields = |_: VariantId| vec![]; + .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into())) + .collect(), + AdtId::UnionId(id) => { + vec![variant_id_to_fields(id.into())] + } + }; - let variants = match adt_id.0 { - hir_def::AdtId::StructId(id) => { - vec![variant_id_to_fields(id.into())] - } - hir_def::AdtId::EnumId(id) => id - .enum_variants(db) - .variants - .iter() - .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into())) - .collect(), - hir_def::AdtId::UnionId(id) => { - vec![variant_id_to_fields(id.into())] - } - }; - - variants - .into_iter() - .flat_map(|variant| variant.into_iter()) - .any(|ty| go(db, &ty)) - || substitution - .iter(Interner) - .filter_map(|x| x.ty(Interner)) - .any(|ty| go(db, ty)) + variants + .into_iter() + .flat_map(|variant| variant.into_iter()) + .try_for_each(|ty| ty.visit_with(self))?; + args.visit_with(self) + } + // And for `PhantomData`, we check `T`. + _ => ty.super_visit_with(self), } - // And for `PhantomData`, we check `T`. - TyKind::Adt(_, substitution) - | TyKind::Tuple(_, substitution) - | TyKind::OpaqueType(_, substitution) - | TyKind::AssociatedType(_, substitution) - | TyKind::Alias(AliasTy::Projection(ProjectionTy { substitution, .. })) - | TyKind::FnDef(_, substitution) => { - substitution.iter(Interner).filter_map(|x| x.ty(Interner)).any(|ty| go(db, ty)) - } - - // For `[T]` or `*T` we check `T` - TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) => go(db, ty), - - // Consider everything else as not reference - _ => false, } } } pub fn as_reference(&self) -> Option<(Type<'db>, Mutability)> { - let (ty, _lt, m) = self.ty.as_reference()?; - let m = Mutability::from_mutable(matches!(m, hir_ty::Mutability::Mut)); - Some((self.derived(ty.clone()), m)) + let TyKind::Ref(_lt, ty, m) = self.ty.kind() else { return None }; + let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut)); + Some((self.derived(ty), m)) } pub fn add_reference(&self, mutability: Mutability) -> Self { + let interner = DbInterner::conjure(); let ty_mutability = match mutability { - Mutability::Shared => hir_ty::Mutability::Not, - Mutability::Mut => hir_ty::Mutability::Mut, + Mutability::Shared => hir_ty::next_solver::Mutability::Not, + Mutability::Mut => hir_ty::next_solver::Mutability::Mut, }; - self.derived(TyKind::Ref(ty_mutability, error_lifetime(), self.ty.clone()).intern(Interner)) + self.derived(Ty::new_ref(interner, Region::error(interner), self.ty, ty_mutability)) } pub fn is_slice(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Slice(..)) + matches!(self.ty.kind(), TyKind::Slice(..)) } pub fn is_usize(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) + matches!(self.ty.kind(), TyKind::Uint(rustc_type_ir::UintTy::Usize)) } pub fn is_float(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Float(_))) + matches!(self.ty.kind(), TyKind::Float(_)) } pub fn is_char(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Char)) + matches!(self.ty.kind(), TyKind::Char) } pub fn is_int_or_uint(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))) + matches!(self.ty.kind(), TyKind::Int(_) | TyKind::Uint(_)) } pub fn is_scalar(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Scalar(_)) + matches!( + self.ty.kind(), + TyKind::Bool | TyKind::Char | TyKind::Int(_) | TyKind::Uint(_) | TyKind::Float(_) + ) } pub fn is_tuple(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Tuple(..)) + matches!(self.ty.kind(), TyKind::Tuple(..)) } pub fn remove_ref(&self) -> Option> { - match &self.ty.kind(Interner) { - TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), + match self.ty.kind() { + TyKind::Ref(_, ty, _) => Some(self.derived(ty)), _ => None, } } pub fn as_slice(&self) -> Option> { - match &self.ty.kind(Interner) { - TyKind::Slice(ty) => Some(self.derived(ty.clone())), + match self.ty.kind() { + TyKind::Slice(ty) => Some(self.derived(ty)), _ => None, } } pub fn strip_references(&self) -> Self { - self.derived(self.ty.strip_references().clone()) + self.derived(self.ty.strip_references()) } + // FIXME: This is the same as `remove_ref()`, remove one of these methods. pub fn strip_reference(&self) -> Self { - self.derived(self.ty.strip_reference().clone()) + self.derived(self.ty.strip_reference()) } pub fn is_unknown(&self) -> bool { - self.ty.is_unknown() + self.ty.is_ty_error() } /// Checks that particular type `ty` implements `std::future::IntoFuture` or @@ -5189,9 +4978,7 @@ impl<'db> Type<'db> { }) .or_else(|| LangItem::Future.resolve_trait(db, self.env.krate))?; - let canonical_ty = - Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; - if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) { + if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) { return None; } @@ -5219,9 +5006,7 @@ impl<'db> Type<'db> { let Some(iterator_trait) = LangItem::Iterator.resolve_trait(db, self.env.krate) else { return false; }; - let canonical_ty = - Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; - method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, iterator_trait) + traits::implements_trait_unique(self.ty, db, self.env.clone(), iterator_trait) } /// Resolves the projection `::IntoIter` and returns the resulting type @@ -5234,9 +5019,7 @@ impl<'db> Type<'db> { }, )?; - let canonical_ty = - Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; - if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) { + if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) { return None; } @@ -5256,43 +5039,18 @@ impl<'db> Type<'db> { None => return false, }; - let canonical_ty = - Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; - method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, fnonce_trait) + traits::implements_trait_unique(self.ty, db, self.env.clone(), fnonce_trait) } // FIXME: Find better API that also handles const generics pub fn impls_trait(&self, db: &'db dyn HirDatabase, trait_: Trait, args: &[Type<'db>]) -> 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| { - match x { - 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()) - } - ParamKind::Lifetime => error_lifetime().cast(Interner), - } - }) - .build(); - - let goal = Canonical { - value: hir_ty::InEnvironment::new( - &self.env.env.to_chalk(DbInterner::new_with( - db, - Some(self.env.krate), - self.env.block, - )), - trait_ref.cast(Interner), - ), - binders: CanonicalVarKinds::empty(Interner), - }; - - !db.trait_solve(self.env.krate, self.env.block, goal).no_solution() + let interner = DbInterner::new_with(db, None, None); + let args = generic_args_from_tys( + interner, + trait_.id.into(), + std::iter::once(self.ty).chain(args.iter().map(|ty| ty.ty)), + ); + traits::implements_trait_unique_with_args(db, self.env.clone(), trait_.id, args) } pub fn normalize_trait_assoc_type( @@ -5301,27 +5059,25 @@ impl<'db> Type<'db> { args: &[Type<'db>], alias: TypeAlias, ) -> Option> { - let mut args = args.iter(); - let trait_id = match alias.id.lookup(db).container { - ItemContainerId::TraitId(id) => id, - _ => unreachable!("non assoc type alias reached in normalize_trait_assoc_type()"), - }; - let parent_subst = TyBuilder::subst_for_def(db, trait_id, None) - .push(self.ty.clone()) - .fill(|it| { - // FIXME: this code is not covered in tests. - match it { - ParamKind::Type => args.next().unwrap().ty.clone().cast(Interner), - ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()), - ParamKind::Lifetime => error_lifetime().cast(Interner), - } - }) - .build(); + let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block); + let args = generic_args_from_tys( + interner, + alias.id.into(), + std::iter::once(self.ty).chain(args.iter().map(|ty| ty.ty)), + ); // FIXME: We don't handle GATs yet. - let projection = TyBuilder::assoc_type_projection(db, alias.id, Some(parent_subst)).build(); + let projection = Ty::new_alias( + interner, + AliasTyKind::Projection, + AliasTy::new(interner, alias.id.into(), args), + ); - let ty = db.normalize_projection(projection, self.env.clone()); - if ty.is_unknown() { None } else { Some(self.derived(ty)) } + // FIXME(next-solver): This needs to be `PostAnalysis`, but this currently causes errors due to our incorrect + // handling of opaques. `non_body_analysis()` will also cause errors (from not revealing opaques inside their + // defining places), so we choose between two bad options. + let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); + let ty = structurally_normalize_ty(&infcx, projection, self.env.clone()); + if ty.is_ty_error() { None } else { Some(self.derived(ty)) } } pub fn is_copy(&self, db: &'db dyn HirDatabase) -> bool { @@ -5332,23 +5088,27 @@ impl<'db> Type<'db> { } pub fn as_callable(&self, db: &'db dyn HirDatabase) -> Option> { - let callee = match self.ty.kind(Interner) { - TyKind::Closure(id, subst) => Callee::Closure(*id, subst.clone()), - TyKind::Function(_) => Callee::FnPtr, - TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(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::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(Interner)) + let (ty, kind) = if let TyKind::Ref(_, ty, _) = kind { + (ty, ty.kind()) } else { - (&self.ty, kind) + (self.ty, kind) }; if let TyKind::Closure(closure, subst) = kind { - let sig = ty.callable_sig(db)?; + 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, subst.clone()), + callee: Callee::Closure(closure.0, subst), is_bound_method: false, }); } @@ -5362,32 +5122,32 @@ impl<'db> Type<'db> { } }; - let sig = self.ty.callable_sig(db)?; + let sig = self.ty.callable_sig(interner)?; Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false }) } pub fn is_closure(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Closure { .. }) + matches!(self.ty.kind(), TyKind::Closure { .. }) } - pub fn as_closure(&self) -> Option { - match self.ty.kind(Interner) { - TyKind::Closure(id, subst) => Some(Closure { id: *id, subst: subst.clone() }), + pub fn as_closure(&self) -> Option> { + match self.ty.kind() { + TyKind::Closure(id, subst) => Some(Closure { id: id.0, subst }), _ => None, } } pub fn is_fn(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::FnDef(..) | TyKind::Function { .. }) + matches!(self.ty.kind(), TyKind::FnDef(..) | TyKind::FnPtr { .. }) } pub fn is_array(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Array(..)) + matches!(self.ty.kind(), TyKind::Array(..)) } pub fn is_packed(&self, db: &'db dyn HirDatabase) -> bool { - let adt_id = match *self.ty.kind(Interner) { - TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, + let adt_id = match self.ty.kind() { + TyKind::Adt(adt_def, ..) => adt_def.def_id().0, _ => return false, }; @@ -5399,100 +5159,64 @@ impl<'db> Type<'db> { } pub fn is_raw_ptr(&self) -> bool { - matches!(self.ty.kind(Interner), TyKind::Raw(..)) + matches!(self.ty.kind(), TyKind::RawPtr(..)) } pub fn remove_raw_ptr(&self) -> Option> { - if let TyKind::Raw(_, ty) = self.ty.kind(Interner) { - Some(self.derived(ty.clone())) - } else { - None - } + if let TyKind::RawPtr(ty, _) = self.ty.kind() { Some(self.derived(ty)) } else { None } } pub fn contains_unknown(&self) -> bool { - // FIXME: When we get rid of `ConstScalar::Unknown`, we can just look at precomputed - // `TypeFlags` in `TyData`. - return go(&self.ty); - - fn go(ty: &Ty) -> bool { - 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(Interner).filter_map(|a| a.ty(Interner)).any(go) - } - - TyKind::Array(_ty, len) if len.is_unknown() => true, - 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::Foreign(_) - | TyKind::Coroutine(..) - | TyKind::CoroutineWitness(..) => false, - } - } + self.ty.references_non_lt_error() } pub fn fields(&self, db: &'db dyn HirDatabase) -> Vec<(Field, Self)> { - let (variant_id, substs) = match self.ty.kind(Interner) { - TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), substs) => ((*s).into(), substs), - TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), substs) => ((*u).into(), substs), + let interner = DbInterner::new_with(db, None, None); + let (variant_id, substs) = match self.ty.kind() { + TyKind::Adt(adt_def, substs) => { + let id = match adt_def.def_id().0 { + AdtId::StructId(id) => id.into(), + AdtId::UnionId(id) => id.into(), + AdtId::EnumId(_) => return Vec::new(), + }; + (id, substs) + } _ => return Vec::new(), }; - db.field_types(variant_id) + db.field_types_ns(variant_id) .iter() .map(|(local_id, ty)| { let def = Field { parent: variant_id.into(), id: local_id }; - let ty = ty.clone().substitute(Interner, substs); + let ty = ty.instantiate(interner, substs); (def, self.derived(ty)) }) .collect() } pub fn tuple_fields(&self, _db: &'db dyn HirDatabase) -> Vec { - if let TyKind::Tuple(_, substs) = &self.ty.kind(Interner) { - substs - .iter(Interner) - .map(|ty| self.derived(ty.assert_ty_ref(Interner).clone())) - .collect() + if let TyKind::Tuple(substs) = self.ty.kind() { + substs.iter().map(|ty| self.derived(ty)).collect() } else { Vec::new() } } pub fn as_array(&self, db: &'db dyn HirDatabase) -> Option<(Self, usize)> { - if let TyKind::Array(ty, len) = &self.ty.kind(Interner) { - try_const_usize(db, len).map(|it| (self.derived(ty.clone()), it as usize)) + if let TyKind::Array(ty, len) = self.ty.kind() { + try_const_usize(db, len).map(|it| (self.derived(ty), it as usize)) } else { None } } pub fn fingerprint_for_trait_impl(&self) -> Option { - let interner = DbInterner::conjure(); - TyFingerprint::for_trait_impl(self.ty.to_nextsolver(interner)) + TyFingerprint::for_trait_impl(self.ty) } - pub(crate) fn canonical(&self) -> Canonical { - hir_ty::replace_errors_with_variables(&self.ty) + pub(crate) fn canonical(&self, db: &'db dyn HirDatabase) -> Canonical<'db, Ty<'db>> { + let interner = DbInterner::new_with(db, None, None); + hir_ty::replace_errors_with_variables(interner, &self.ty) } /// Returns types that this type dereferences to (including this type itself). The returned @@ -5504,9 +5228,10 @@ impl<'db> Type<'db> { self.autoderef_(db).map(move |ty| self.derived(ty)) } - fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator { + fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator> { + let interner = DbInterner::new_with(db, None, None); // There should be no inference vars in types passed here - let canonical = hir_ty::replace_errors_with_variables(&self.ty); + let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty); autoderef(db, self.env.clone(), canonical) } @@ -5532,8 +5257,7 @@ impl<'db> Type<'db> { krate: Crate, callback: &mut dyn FnMut(AssocItemId) -> bool, ) { - let interner = DbInterner::new_with(db, None, None); - let ty_ns = self.ty.to_nextsolver(interner); + let ty_ns = self.ty; let def_crates = match method_resolution::def_crates(db, ty_ns, krate.id) { Some(it) => it, None => return, @@ -5570,15 +5294,13 @@ impl<'db> Type<'db> { /// - "U" /// ``` pub fn type_arguments(&self) -> impl Iterator> + '_ { - self.ty - .strip_references() - .as_adt() - .map(|(_, substs)| substs) - .or_else(|| self.ty.strip_references().as_tuple()) - .into_iter() - .flat_map(|substs| substs.iter(Interner)) - .filter_map(|arg| arg.ty(Interner).cloned()) - .map(move |ty| self.derived(ty)) + match self.ty.strip_references().kind() { + TyKind::Adt(_, substs) => Either::Left(substs.types().map(move |ty| self.derived(ty))), + TyKind::Tuple(substs) => { + Either::Right(Either::Left(substs.iter().map(move |ty| self.derived(ty)))) + } + _ => Either::Right(Either::Right(std::iter::empty())), + } } /// Iterates its type and const arguments @@ -5608,15 +5330,13 @@ impl<'db> Type<'db> { .strip_references() .as_adt() .into_iter() - .flat_map(|(_, substs)| substs.iter(Interner)) - .filter_map(move |arg| { - // arg can be either a `Ty` or `constant` - if let Some(ty) = arg.ty(Interner) { - Some(format_smolstr!("{}", ty.display(db, display_target))) - } else { - arg.constant(Interner) - .map(|const_| format_smolstr!("{}", const_.display(db, display_target))) + .flat_map(|(_, substs)| substs.iter()) + .filter_map(move |arg| match arg { + GenericArg::Ty(ty) => Some(format_smolstr!("{}", ty.display(db, display_target))), + GenericArg::Const(const_) => { + Some(format_smolstr!("{}", const_.display(db, display_target))) } + GenericArg::Lifetime(_) => None, }) } @@ -5733,8 +5453,9 @@ impl<'db> Type<'db> { ?name, ) .entered(); + let interner = DbInterner::new_with(db, None, None); // There should be no inference vars in types passed here - let canonical = hir_ty::replace_errors_with_variables(&self.ty); + let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty); let krate = scope.krate(); let environment = scope @@ -5743,11 +5464,7 @@ impl<'db> Type<'db> { .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); _ = method_resolution::iterate_method_candidates_dyn( - &canonical.to_nextsolver(DbInterner::new_with( - db, - Some(environment.krate), - environment.block, - )), + &canonical, db, environment, traits_in_scope, @@ -5825,7 +5542,8 @@ impl<'db> Type<'db> { } } - let canonical = hir_ty::replace_errors_with_variables(&self.ty); + let interner = DbInterner::new_with(db, None, None); + let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty); let krate = scope.krate(); let environment = scope @@ -5834,11 +5552,7 @@ impl<'db> Type<'db> { .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); _ = method_resolution::iterate_path_candidates( - &canonical.to_nextsolver(DbInterner::new_with( - db, - Some(environment.krate), - environment.block, - )), + &canonical, db, environment, traits_in_scope, @@ -5877,7 +5591,7 @@ impl<'db> Type<'db> { pub fn env_traits(&self, db: &'db dyn HirDatabase) -> impl Iterator { let _p = tracing::info_span!("env_traits").entered(); self.autoderef_(db) - .filter(|ty| matches!(ty.kind(Interner), TyKind::Placeholder(_))) + .filter(|ty| matches!(ty.kind(), TyKind::Param(_))) .flat_map(|ty| { self.env .traits_in_scope_from_clauses(ty) @@ -5888,136 +5602,66 @@ impl<'db> Type<'db> { pub fn as_impl_traits(&self, db: &'db dyn HirDatabase) -> Option> { self.ty.impl_trait_bounds(db).map(|it| { - it.into_iter().filter_map(|pred| match pred.skip_binders() { - hir_ty::WhereClause::Implemented(trait_ref) => { - Some(Trait::from(trait_ref.hir_trait_id())) - } + it.into_iter().filter_map(|pred| match pred.kind().skip_binder() { + ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)), _ => None, }) }) } pub fn as_associated_type_parent_trait(&self, db: &'db dyn HirDatabase) -> Option { - self.ty.associated_type_parent_trait(db).map(Into::into) + let TyKind::Alias(AliasTyKind::Projection, alias) = self.ty.kind() else { return None }; + match alias.def_id.expect_type_alias().loc(db).container { + ItemContainerId::TraitId(id) => Some(Trait { id }), + _ => None, + } } - fn derived(&self, ty: Ty) -> Self { - Type { env: self.env.clone(), ty, _pd: PhantomCovariantLifetime::new() } + fn derived(&self, ty: Ty<'db>) -> Self { + Type { env: self.env.clone(), ty } } - /// Visits every type, including generic arguments, in this type. `cb` is called with type + /// Visits every type, including generic arguments, in this type. `callback` is called with type /// itself first, and then with its generic arguments. - pub fn walk(&self, db: &'db dyn HirDatabase, mut cb: impl FnMut(Type<'db>)) { - fn walk_substs<'db>( + pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) { + struct Visitor<'db, F> { db: &'db dyn HirDatabase, - type_: &Type<'db>, - substs: &Substitution, - cb: &mut impl FnMut(Type<'db>), - ) { - for ty in substs.iter(Interner).filter_map(|a| a.ty(Interner)) { - walk_type(db, &type_.derived(ty.clone()), cb); + env: Arc>, + callback: F, + visited: FxHashSet>, + } + impl<'db, F> TypeVisitor> for Visitor<'db, F> + where + F: FnMut(Type<'db>), + { + type Result = (); + + fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result { + if !self.visited.insert(ty) { + return; + } + + (self.callback)(Type { env: self.env.clone(), ty }); + + if let Some(bounds) = ty.impl_trait_bounds(self.db) { + bounds.visit_with(self); + } + + ty.super_visit_with(self); } } - fn walk_bounds<'db>( - db: &'db dyn HirDatabase, - type_: &Type<'db>, - bounds: &[QuantifiedWhereClause], - cb: &mut impl FnMut(Type<'db>), - ) { - for pred in bounds { - if let WhereClause::Implemented(trait_ref) = pred.skip_binders() { - cb(type_.clone()); - // skip the self type. it's likely the type we just got the bounds from - if let [self_ty, params @ ..] = trait_ref.substitution.as_slice(Interner) { - for ty in - params.iter().filter(|&ty| ty != self_ty).filter_map(|a| a.ty(Interner)) - { - walk_type(db, &type_.derived(ty.clone()), cb); - } - } - } - } - } - - fn walk_type<'db>( - db: &'db dyn HirDatabase, - type_: &Type<'db>, - cb: &mut impl FnMut(Type<'db>), - ) { - let ty = type_.ty.strip_references(); - match ty.kind(Interner) { - TyKind::Adt(_, substs) => { - cb(type_.derived(ty.clone())); - walk_substs(db, type_, substs, cb); - } - TyKind::AssociatedType(_, substs) - | TyKind::Alias(AliasTy::Projection(hir_ty::ProjectionTy { - substitution: substs, - .. - })) => { - if ty.associated_type_parent_trait(db).is_some() { - cb(type_.derived(ty.clone())); - } - walk_substs(db, type_, substs, cb); - } - TyKind::OpaqueType(_, subst) => { - if let Some(bounds) = ty.impl_trait_bounds(db) { - walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); - } - - walk_substs(db, type_, subst, cb); - } - 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.substitution, cb); - } - TyKind::Placeholder(_) => { - cb(type_.derived(ty.clone())); - if let Some(bounds) = ty.impl_trait_bounds(db) { - walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); - } - } - TyKind::Dyn(bounds) => { - walk_bounds( - db, - &type_.derived(ty.clone()), - bounds.bounds.skip_binders().interned(), - cb, - ); - } - - TyKind::Ref(_, _, ty) - | TyKind::Raw(_, ty) - | TyKind::Array(ty, _) - | TyKind::Slice(ty) => { - walk_type(db, &type_.derived(ty.clone()), cb); - } - - TyKind::FnDef(_, substs) - | TyKind::Tuple(_, substs) - | TyKind::Closure(.., substs) => { - walk_substs(db, type_, substs, cb); - } - TyKind::Function(hir_ty::FnPointer { substitution, .. }) => { - walk_substs(db, type_, &substitution.0, cb); - } - - _ => {} - } - } - - walk_type(db, self, &mut cb); + let mut visitor = + Visitor { db, env: self.env.clone(), callback, visited: FxHashSet::default() }; + self.ty.visit_with(&mut visitor); } /// Check if type unifies with another type. /// /// Note that we consider placeholder types to unify with everything. /// For example `Option` and `Option` unify although there is unresolved goal `T = U`. pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool { - let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone())); + let interner = DbInterner::new_with(db, None, None); + let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty)); hir_ty::could_unify(db, self.env.clone(), &tys) } @@ -6026,35 +5670,34 @@ impl<'db> Type<'db> { /// This means that placeholder types are not considered to unify if there are any bounds set on /// them. For example `Option` and `Option` do not unify as we cannot show that `T = U` pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool { - let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone())); + let interner = DbInterner::new_with(db, None, None); + let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty)); hir_ty::could_unify_deeply(db, self.env.clone(), &tys) } pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool { - let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone())); + let interner = DbInterner::new_with(db, None, None); + let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, to.ty)); hir_ty::could_coerce(db, self.env.clone(), &tys) } - pub fn as_type_param(&self, db: &'db dyn HirDatabase) -> Option { - match self.ty.kind(Interner) { - TyKind::Placeholder(p) => Some(TypeParam { - id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p).0), - }), + pub fn as_type_param(&self, _db: &'db dyn HirDatabase) -> Option { + match self.ty.kind() { + TyKind::Param(param) => Some(TypeParam { id: param.id }), _ => None, } } /// Returns unique `GenericParam`s contained in this type. pub fn generic_params(&self, db: &'db dyn HirDatabase) -> FxHashSet { - hir_ty::collect_placeholders(&self.ty, db) + hir_ty::collect_params(&self.ty) .into_iter() .map(|id| TypeOrConstParam { id }.split(db).either_into()) .collect() } pub fn layout(&self, db: &'db dyn HirDatabase) -> Result { - let interner = DbInterner::new_with(db, None, None); - db.layout_of_ty(self.ty.to_nextsolver(interner), self.env.clone()) + db.layout_of_ty(self.ty, self.env.clone()) .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap())) } @@ -6062,33 +5705,27 @@ impl<'db> Type<'db> { let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block); // FIXME: This should be `PostAnalysis` I believe. let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); - hir_ty::drop::has_drop_glue(&infcx, self.ty.to_nextsolver(interner), self.env.clone()) + hir_ty::drop::has_drop_glue(&infcx, self.ty, self.env.clone()) } } #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct TypeNs<'db> { env: Arc>, - ty: hir_ty::next_solver::Ty<'db>, - _pd: PhantomCovariantLifetime<'db>, + ty: Ty<'db>, } impl<'db> TypeNs<'db> { - fn new( - db: &'db dyn HirDatabase, - lexical_env: impl HasResolver, - ty: hir_ty::next_solver::Ty<'db>, - ) -> Self { + fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self { let resolver = lexical_env.resolver(db); let environment = resolver .generic_def() .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d)); - TypeNs { env: environment, ty, _pd: PhantomCovariantLifetime::new() } + TypeNs { env: environment, ty } } - pub fn to_type(&self, db: &'db dyn HirDatabase) -> Type<'db> { - let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block); - Type { env: self.env.clone(), ty: convert_ty_for_result(interner, self.ty), _pd: self._pd } + pub fn to_type(&self, _db: &'db dyn HirDatabase) -> Type<'db> { + Type { env: self.env.clone(), ty: self.ty } } // FIXME: Find better API that also handles const generics @@ -6144,40 +5781,38 @@ impl InlineAsmOperand { #[derive(Debug)] pub struct Callable<'db> { ty: Type<'db>, - sig: CallableSig, - callee: Callee, + sig: PolyFnSig<'db>, + callee: Callee<'db>, /// Whether this is a method that was called with method call syntax. is_bound_method: bool, } #[derive(Clone, PartialEq, Eq, Hash, Debug)] -enum Callee { +enum Callee<'db> { Def(CallableDefId), - Closure(ClosureId, Substitution), + Closure(InternedClosureId, GenericArgs<'db>), FnPtr, FnImpl(FnTrait), } -pub enum CallableKind { +pub enum CallableKind<'db> { Function(Function), TupleStruct(Struct), TupleEnumVariant(Variant), - Closure(Closure), + Closure(Closure<'db>), FnPtr, FnImpl(FnTrait), } impl<'db> Callable<'db> { - pub fn kind(&self) -> CallableKind { + pub fn kind(&self) -> CallableKind<'db> { match self.callee { Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()), Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()), Callee::Def(CallableDefId::EnumVariantId(it)) => { CallableKind::TupleEnumVariant(it.into()) } - Callee::Closure(id, ref subst) => { - CallableKind::Closure(Closure { id, subst: subst.clone() }) - } + Callee::Closure(id, ref subst) => CallableKind::Closure(Closure { id, subst: *subst }), Callee::FnPtr => CallableKind::FnPtr, Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_), } @@ -6188,25 +5823,31 @@ impl<'db> Callable<'db> { _ => return None, }; let func = Function { id: func }; - Some((func.self_param(db)?, self.ty.derived(self.sig.params()[0].clone()))) + Some(( + func.self_param(db)?, + self.ty.derived(self.sig.skip_binder().inputs_and_output.inputs()[0]), + )) } pub fn n_params(&self) -> usize { - self.sig.params().len() - if self.is_bound_method { 1 } else { 0 } + self.sig.skip_binder().inputs_and_output.inputs().len() + - if self.is_bound_method { 1 } else { 0 } } pub fn params(&self) -> Vec> { self.sig - .params() + .skip_binder() + .inputs_and_output + .inputs() .iter() .enumerate() .skip(if self.is_bound_method { 1 } else { 0 }) - .map(|(idx, ty)| (idx, self.ty.derived(ty.clone()))) + .map(|(idx, ty)| (idx, self.ty.derived(*ty))) .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty }) .collect() } pub fn return_type(&self) -> Type<'db> { - self.ty.derived(self.sig.ret().clone()) + self.ty.derived(self.sig.skip_binder().output()) } - pub fn sig(&self) -> &CallableSig { + pub fn sig(&self) -> impl Eq { &self.sig } @@ -6758,5 +6399,37 @@ fn as_name_opt(name: Option) -> Name { name.map_or_else(Name::missing, |name| name.as_name()) } +fn generic_args_from_tys<'db>( + interner: DbInterner<'db>, + def_id: SolverDefId, + args: impl IntoIterator>, +) -> GenericArgs<'db> { + let mut args = args.into_iter(); + GenericArgs::for_item(interner, def_id, |_, _, id, _| { + if matches!(id, GenericParamId::TypeParamId(_)) + && let Some(arg) = args.next() + { + arg.into() + } else { + next_solver::GenericArg::error_from_id(interner, id) + } + }) +} + +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); + params + .iter_type_or_consts() + .filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_))) + .map(|(local_id, _)| TypeOrConstParamId { parent: generic_def, local_id }) + .any(|param| { + let Some(param) = hir_ty::param_idx(db, param) else { + return false; + }; + defaults.get(param).is_none() + }) +} + pub use hir_ty::next_solver; pub use hir_ty::setup_tracing; diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 45c2020bc8ce..eecca0244091 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -28,9 +28,10 @@ use hir_expand::{ mod_path::{ModPath, PathKind}, name::AsName, }; -use hir_ty::diagnostics::{unsafe_operations, unsafe_operations_for_body}; -use hir_ty::next_solver::DbInterner; -use hir_ty::next_solver::mapping::{ChalkToNextSolver, NextSolverToChalk}; +use hir_ty::{ + diagnostics::{unsafe_operations, unsafe_operations_for_body}, + next_solver::DbInterner, +}; use intern::{Interned, Symbol, sym}; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; @@ -1563,16 +1564,11 @@ impl<'db> SemanticsImpl<'db> { let (mut source_ty, _) = analyzer.type_of_expr(self.db, expr)?; - let interner = DbInterner::new_with(self.db, None, None); - analyzer.expr_adjustments(expr).map(|it| { it.iter() .map(|adjust| { - let target = Type::new_with_resolver( - self.db, - &analyzer.resolver, - adjust.target.to_chalk(interner), - ); + let target = + Type::new_with_resolver(self.db, &analyzer.resolver, adjust.target); let kind = match adjust.kind { hir_ty::Adjust::NeverToAny => Adjust::NeverToAny, hir_ty::Adjust::Deref(Some(hir_ty::OverloadedDeref(m))) => { @@ -1666,7 +1662,7 @@ impl<'db> SemanticsImpl<'db> { trait_.id.into(), |_, _, id, _| { assert!(matches!(id, hir_def::GenericParamId::TypeParamId(_)), "expected a type"); - subst.next().expect("too few subst").ty.to_nextsolver(interner).into() + subst.next().expect("too few subst").ty.into() }, ); assert!(subst.next().is_none(), "too many subst"); diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index a4bc3e8f1a13..8d2ba7e604e7 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -7,13 +7,6 @@ //! purely for "IDE needs". use std::iter::{self, once}; -use crate::{ - Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field, - Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct, ToolModule, Trait, - TupleField, Type, TypeAlias, Variant, - db::HirDatabase, - semantics::{PathResolution, PathResolutionPerNs}, -}; use either::Either; use hir_def::{ AdtId, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId, @@ -36,23 +29,24 @@ use hir_expand::{ name::{AsName, Name}, }; use hir_ty::{ - Adjustment, AliasTy, InferenceResult, Interner, LifetimeElisionKind, ProjectionTy, - Substitution, ToChalk, TraitEnvironment, Ty, TyKind, TyLoweringContext, + Adjustment, InferenceResult, LifetimeElisionKind, TraitEnvironment, TyLoweringContext, diagnostics::{ InsideUnsafeBlock, record_literal_missing_fields, record_pattern_missing_fields, unsafe_operations, }, - from_assoc_type_id, lang_items::lang_items_for_bin_op, method_resolution, next_solver::{ - DbInterner, GenericArgs, TypingMode, - infer::DbInternerInferExt, - mapping::{ChalkToNextSolver, NextSolverToChalk}, + DbInterner, ErrorGuaranteed, GenericArgs, Ty, TyKind, TypingMode, infer::DbInternerInferExt, }, + traits::structurally_normalize_ty, }; use intern::sym; use itertools::Itertools; +use rustc_type_ir::{ + AliasTyKind, + inherent::{AdtDef, IntoKind, Ty as _}, +}; use smallvec::SmallVec; use stdx::never; use syntax::{ @@ -61,6 +55,14 @@ use syntax::{ }; use triomphe::Arc; +use crate::{ + Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field, + Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct, ToolModule, Trait, + TupleField, Type, TypeAlias, Variant, + db::HirDatabase, + semantics::{PathResolution, PathResolutionPerNs}, +}; + /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of /// original source files. It should not be used inside the HIR itself. #[derive(Debug)] @@ -292,9 +294,7 @@ impl<'db> SourceAnalyzer<'db> { .and_then(|expr_id| infer.expr_adjustment(expr_id)) .and_then(|adjusts| adjusts.last().map(|adjust| adjust.target)); let ty = infer[expr_id]; - let mk_ty = |ty: hir_ty::next_solver::Ty<'_>| { - Type::new_with_resolver(db, &self.resolver, ty.to_chalk(DbInterner::conjure())) - }; + let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); Some((mk_ty(ty), coerced.map(mk_ty))) } @@ -316,9 +316,7 @@ impl<'db> SourceAnalyzer<'db> { }; let ty = infer[expr_or_pat_id]; - let mk_ty = |ty: hir_ty::next_solver::Ty<'db>| { - Type::new_with_resolver(db, &self.resolver, ty.to_chalk(DbInterner::conjure())) - }; + let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); Some((mk_ty(ty), coerced.map(mk_ty))) } @@ -330,9 +328,7 @@ impl<'db> SourceAnalyzer<'db> { let binding_id = self.binding_id_of_pat(pat)?; let infer = self.infer()?; let ty = infer[binding_id]; - let mk_ty = |ty: hir_ty::next_solver::Ty<'db>| { - Type::new_with_resolver(db, &self.resolver, ty.to_chalk(DbInterner::conjure())) - }; + let mk_ty = |ty: Ty<'db>| Type::new_with_resolver(db, &self.resolver, ty); Some(mk_ty(ty)) } @@ -343,7 +339,7 @@ impl<'db> SourceAnalyzer<'db> { ) -> Option> { let binding = self.body()?.self_param?; let ty = self.infer()?[binding]; - Some(Type::new_with_resolver(db, &self.resolver, ty.to_chalk(DbInterner::conjure()))) + Some(Type::new_with_resolver(db, &self.resolver, ty)) } pub(crate) fn binding_mode_of_pat( @@ -374,9 +370,7 @@ impl<'db> SourceAnalyzer<'db> { infer .pat_adjustment(pat_id.as_pat()?)? .iter() - .map(|ty| { - Type::new_with_resolver(db, &self.resolver, ty.to_chalk(DbInterner::conjure())) - }) + .map(|ty| Type::new_with_resolver(db, &self.resolver, *ty)) .collect(), ) } @@ -390,7 +384,7 @@ impl<'db> SourceAnalyzer<'db> { let (func, args) = self.infer()?.method_resolution(expr_id)?; let interner = DbInterner::new_with(db, None, None); let ty = db.value_ty(func.into())?.instantiate(interner, args); - let ty = Type::new_with_resolver(db, &self.resolver, ty.to_chalk(interner)); + let ty = Type::new_with_resolver(db, &self.resolver, ty); let mut res = ty.as_callable(db)?; res.is_bound_method = true; Some(res) @@ -414,18 +408,13 @@ impl<'db> SourceAnalyzer<'db> { ) -> Option<(Either, Option>)> { let expr_id = self.expr_id(call.clone().into())?.as_expr()?; let inference_result = self.infer()?; - let interner = DbInterner::new_with(db, None, None); match inference_result.method_resolution(expr_id) { Some((f_in_trait, substs)) => { let (fn_, subst) = self.resolve_impl_method_or_trait_def_with_subst(db, f_in_trait, substs); Some(( Either::Left(fn_.into()), - Some(GenericSubstitution::new( - fn_.into(), - subst.to_chalk(interner), - self.trait_environment(db), - )), + Some(GenericSubstitution::new(fn_.into(), subst, self.trait_environment(db))), )) } None => { @@ -465,11 +454,7 @@ impl<'db> SourceAnalyzer<'db> { let body = self.store()?; if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] { let (adt, subst) = infer.type_of_expr_with_adjust(object_expr)?.as_adt()?; - return Some(GenericSubstitution::new( - adt.into(), - subst.to_chalk(DbInterner::conjure()), - self.trait_environment(db), - )); + return Some(GenericSubstitution::new(adt.into(), subst, self.trait_environment(db))); } None } @@ -483,7 +468,6 @@ impl<'db> SourceAnalyzer<'db> { let (def, ..) = self.body_()?; let expr_id = self.expr_id(field.clone().into())?.as_expr()?; let inference_result = self.infer()?; - let interner = DbInterner::new_with(db, None, None); match inference_result.field_resolution(expr_id) { Some(field) => match field { Either::Left(field) => Some(( @@ -503,11 +487,7 @@ impl<'db> SourceAnalyzer<'db> { let (f, subst) = self.resolve_impl_method_or_trait_def_with_subst(db, f, substs); ( Either::Right(f.into()), - Some(GenericSubstitution::new( - f.into(), - subst.to_chalk(interner), - self.trait_environment(db), - )), + Some(GenericSubstitution::new(f.into(), subst, self.trait_environment(db))), ) }), } @@ -557,7 +537,7 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, await_expr: &ast::AwaitExpr, ) -> Option { - let mut ty = self.ty_of_expr(await_expr.expr()?)?.clone(); + let mut ty = self.ty_of_expr(await_expr.expr()?)?; let into_future_trait = self .resolver @@ -565,7 +545,7 @@ impl<'db> SourceAnalyzer<'db> { .map(Trait::from); if let Some(into_future_trait) = into_future_trait { - let type_ = Type::new_with_resolver(db, &self.resolver, ty.clone()); + let type_ = Type::new_with_resolver(db, &self.resolver, ty); if type_.impls_trait(db, into_future_trait, &[]) { let items = into_future_trait.items(db); let into_future_type = items.into_iter().find_map(|item| match item { @@ -585,7 +565,7 @@ impl<'db> SourceAnalyzer<'db> { // HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself // doesn't have any generic parameters, so we skip building another subst for `poll()`. let interner = DbInterner::new_with(db, None, None); - let substs = GenericArgs::new_from_iter(interner, [ty.to_nextsolver(interner).into()]); + let substs = GenericArgs::new_from_iter(interner, [ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, poll_fn, substs)) } @@ -627,7 +607,7 @@ impl<'db> SourceAnalyzer<'db> { let interner = DbInterner::new_with(db, None, None); // HACK: subst for all methods coincides with that for their trait because the methods // don't have any generic parameters, so we skip building another subst for the methods. - let substs = GenericArgs::new_from_iter(interner, [ty.to_nextsolver(interner).into()]); + let substs = GenericArgs::new_from_iter(interner, [ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -658,10 +638,7 @@ impl<'db> SourceAnalyzer<'db> { // HACK: subst for all methods coincides with that for their trait because the methods // don't have any generic parameters, so we skip building another subst for the methods. let interner = DbInterner::new_with(db, None, None); - let substs = GenericArgs::new_from_iter( - interner, - [base_ty.to_nextsolver(interner).into(), index_ty.to_nextsolver(interner).into()], - ); + let substs = GenericArgs::new_from_iter(interner, [base_ty.into(), index_ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -679,10 +656,7 @@ impl<'db> SourceAnalyzer<'db> { // HACK: subst for `index()` coincides with that for `Index` because `index()` itself // doesn't have any generic parameters, so we skip building another subst for `index()`. let interner = DbInterner::new_with(db, None, None); - let substs = GenericArgs::new_from_iter( - interner, - [lhs.to_nextsolver(interner).into(), rhs.to_nextsolver(interner).into()], - ); + let substs = GenericArgs::new_from_iter(interner, [lhs.into(), rhs.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -698,7 +672,7 @@ impl<'db> SourceAnalyzer<'db> { // HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself // doesn't have any generic parameters, so we skip building another subst for `branch()`. let interner = DbInterner::new_with(db, None, None); - let substs = GenericArgs::new_from_iter(interner, [ty.to_nextsolver(interner).into()]); + let substs = GenericArgs::new_from_iter(interner, [ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -735,12 +709,11 @@ impl<'db> SourceAnalyzer<'db> { } }; let (adt, subst) = self.infer()?.type_of_expr_or_pat(expr_id)?.as_adt()?; - let subst = subst.to_chalk(interner); let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?; let variant_data = variant.fields(db); let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; let field_ty = - db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, &subst); + (*db.field_types_ns(variant).get(field.local_id)?).instantiate(interner, subst); Some(( field.into(), local, @@ -762,9 +735,8 @@ impl<'db> SourceAnalyzer<'db> { let variant_data = variant.fields(db); let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? }; let (adt, subst) = self.infer()?[pat_id.as_pat()?].as_adt()?; - let subst = subst.to_chalk(interner); let field_ty = - db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, &subst); + (*db.field_types_ns(variant).get(field.local_id)?).instantiate(interner, subst); Some(( field.into(), Type::new_with_resolver(db, &self.resolver, field_ty), @@ -817,43 +789,40 @@ impl<'db> SourceAnalyzer<'db> { let container = self.type_of_type(db, &container)?; let trait_env = container.env; + + let interner = DbInterner::new_with(db, Some(trait_env.krate), trait_env.block); + let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); + let mut container = Either::Right(container.ty); for field_name in offset_of_expr.fields() { - if let Some( - TyKind::Alias(AliasTy::Projection(ProjectionTy { associated_ty_id, substitution })) - | TyKind::AssociatedType(associated_ty_id, substitution), - ) = container.as_ref().right().map(|it| it.kind(Interner)) - { - let projection = ProjectionTy { - associated_ty_id: *associated_ty_id, - substitution: substitution.clone(), - }; - container = Either::Right(db.normalize_projection(projection, trait_env.clone())); + if let Either::Right(container) = &mut container { + *container = structurally_normalize_ty(&infcx, *container, trait_env.clone()); } - let handle_variants = |variant: VariantId, subst: &Substitution, container: &mut _| { - let fields = variant.fields(db); - let field = fields.field(&field_name.as_name())?; - let field_types = db.field_types(variant); - *container = Either::Right(field_types[field].clone().substitute(Interner, subst)); - let generic_def = match variant { - VariantId::EnumVariantId(it) => it.loc(db).parent.into(), - VariantId::StructId(it) => it.into(), - VariantId::UnionId(it) => it.into(), + let handle_variants = + |variant: VariantId, subst: GenericArgs<'db>, container: &mut _| { + let fields = variant.fields(db); + let field = fields.field(&field_name.as_name())?; + let field_types = db.field_types_ns(variant); + *container = Either::Right(field_types[field].instantiate(interner, subst)); + let generic_def = match variant { + VariantId::EnumVariantId(it) => it.loc(db).parent.into(), + VariantId::StructId(it) => it.into(), + VariantId::UnionId(it) => it.into(), + }; + Some(( + Either::Right(Field { parent: variant.into(), id: field }), + generic_def, + subst, + )) }; - Some(( - Either::Right(Field { parent: variant.into(), id: field }), - generic_def, - subst.clone(), - )) - }; - let temp_ty = TyKind::Error.intern(Interner); + let temp_ty = Ty::new_error(interner, ErrorGuaranteed); let (field_def, generic_def, subst) = - match std::mem::replace(&mut container, Either::Right(temp_ty.clone())) { + match std::mem::replace(&mut container, Either::Right(temp_ty)) { Either::Left((variant_id, subst)) => { - handle_variants(VariantId::from(variant_id), &subst, &mut container)? + handle_variants(VariantId::from(variant_id), subst, &mut container)? } - Either::Right(container_ty) => match container_ty.kind(Interner) { - TyKind::Adt(adt_id, subst) => match adt_id.0 { + Either::Right(container_ty) => match container_ty.kind() { + TyKind::Adt(adt_def, subst) => match adt_def.def_id().0 { AdtId::StructId(id) => { handle_variants(id.into(), subst, &mut container)? } @@ -863,8 +832,8 @@ impl<'db> SourceAnalyzer<'db> { AdtId::EnumId(id) => { let variants = id.enum_variants(db); let variant = variants.variant(&field_name.as_name())?; - container = Either::Left((variant, subst.clone())); - (Either::Left(Variant { id: variant }), id.into(), subst.clone()) + container = Either::Left((variant, subst)); + (Either::Left(Variant { id: variant }), id.into(), subst) } }, _ => return None, @@ -884,7 +853,6 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, path: &ast::Path, ) -> Option<(PathResolution, Option>)> { - let interner = DbInterner::new_with(db, None, None); let parent = path.syntax().parent(); let parent = || parent.clone(); @@ -900,31 +868,27 @@ impl<'db> SourceAnalyzer<'db> { None => { let subst = GenericSubstitution::new( f_in_trait.into(), - subs.to_chalk(interner), + subs, self.trait_environment(db), ); (assoc, subst) } Some(func_ty) => { - if let TyKind::FnDef(_fn_def, subs) = - func_ty.to_chalk(interner).kind(Interner) - { + if let TyKind::FnDef(_fn_def, subs) = func_ty.kind() { let (fn_, subst) = self .resolve_impl_method_or_trait_def_with_subst( - db, - f_in_trait, - subs.to_nextsolver(interner), + db, f_in_trait, subs, ); let subst = GenericSubstitution::new( fn_.into(), - subst.to_chalk(interner), + subst, self.trait_environment(db), ); (fn_.into(), subst) } else { let subst = GenericSubstitution::new( f_in_trait.into(), - subs.to_chalk(interner), + subs, self.trait_environment(db), ); (assoc, subst) @@ -937,7 +901,7 @@ impl<'db> SourceAnalyzer<'db> { self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs); let subst = GenericSubstitution::new( konst.into(), - subst.to_chalk(interner), + subst, self.trait_environment(db), ); (konst.into(), subst) @@ -946,7 +910,7 @@ impl<'db> SourceAnalyzer<'db> { assoc, GenericSubstitution::new( type_alias.into(), - subs.to_chalk(interner), + subs, self.trait_environment(db), ), ), @@ -970,7 +934,7 @@ impl<'db> SourceAnalyzer<'db> { self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs); let subst = GenericSubstitution::new( konst.into(), - subst.to_chalk(interner), + subst, self.trait_environment(db), ); (konst.into(), subst) @@ -979,7 +943,7 @@ impl<'db> SourceAnalyzer<'db> { assoc, GenericSubstitution::new( assoc.into(), - subs.to_chalk(interner), + subs, self.trait_environment(db), ), ), @@ -1177,36 +1141,38 @@ impl<'db> SourceAnalyzer<'db> { let parent = parent()?; let ty = if let Some(expr) = ast::Expr::cast(parent.clone()) { let expr_id = self.expr_id(expr)?; - self.infer()?.type_of_expr_or_pat(expr_id)?.to_chalk(interner) + self.infer()?.type_of_expr_or_pat(expr_id)? } else if let Some(pat) = ast::Pat::cast(parent) { let pat_id = self.pat_id(&pat)?; - self.infer()?[pat_id].to_chalk(interner) + self.infer()?[pat_id] } else { return None; }; let env = self.trait_environment(db); - let (subst, expected_resolution) = match ty.kind(Interner) { - TyKind::Adt(adt_id, subst) => ( - GenericSubstitution::new(adt_id.0.into(), subst.clone(), env), - PathResolution::Def(ModuleDef::Adt(adt_id.0.into())), - ), - TyKind::AssociatedType(assoc_id, subst) => { - let assoc_id = from_assoc_type_id(*assoc_id); + let (subst, expected_resolution) = match ty.kind() { + TyKind::Adt(adt_def, subst) => { + let adt_id = adt_def.def_id().0; ( - GenericSubstitution::new(assoc_id.into(), subst.clone(), env), + GenericSubstitution::new(adt_id.into(), subst, env), + PathResolution::Def(ModuleDef::Adt(adt_id.into())), + ) + } + TyKind::Alias(AliasTyKind::Projection, alias) => { + let assoc_id = alias.def_id.expect_type_alias(); + ( + GenericSubstitution::new(assoc_id.into(), alias.args, env), PathResolution::Def(ModuleDef::TypeAlias(assoc_id.into())), ) } TyKind::FnDef(fn_id, subst) => { - let fn_id = ToChalk::from_chalk(db, *fn_id); - let generic_def_id = match fn_id { + let generic_def_id = match fn_id.0 { CallableDefId::StructId(id) => id.into(), CallableDefId::FunctionId(id) => id.into(), CallableDefId::EnumVariantId(_) => return None, }; ( - GenericSubstitution::new(generic_def_id, subst.clone(), env), - PathResolution::Def(ModuleDefId::from(fn_id).into()), + GenericSubstitution::new(generic_def_id, subst, env), + PathResolution::Def(ModuleDefId::from(fn_id.0).into()), ) } _ => return None, @@ -1260,8 +1226,7 @@ impl<'db> SourceAnalyzer<'db> { record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])? } }; - let interner = DbInterner::new_with(db, None, None); - let res = self.missing_fields(db, &substs.to_chalk(interner), variant, missing_fields); + let res = self.missing_fields(db, substs, variant, missing_fields); Some(res) } @@ -1278,25 +1243,25 @@ impl<'db> SourceAnalyzer<'db> { let (variant, missing_fields, _exhaustive) = record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; - let interner = DbInterner::new_with(db, None, None); - let res = self.missing_fields(db, &substs.to_chalk(interner), variant, missing_fields); + let res = self.missing_fields(db, substs, variant, missing_fields); Some(res) } fn missing_fields( &self, db: &'db dyn HirDatabase, - substs: &Substitution, + substs: GenericArgs<'db>, variant: VariantId, missing_fields: Vec, ) -> Vec<(Field, Type<'db>)> { - let field_types = db.field_types(variant); + let interner = DbInterner::new_with(db, None, None); + let field_types = db.field_types_ns(variant); missing_fields .into_iter() .map(|local_id| { let field = FieldId { parent: variant, local_id }; - let ty = field_types[local_id].clone().substitute(Interner, substs); + let ty = field_types[local_id].instantiate(interner, substs); (field.into(), Type::new_with_resolver_inner(db, &self.resolver, ty)) }) .collect() @@ -1455,10 +1420,8 @@ impl<'db> SourceAnalyzer<'db> { Some((trait_id, fn_id)) } - fn ty_of_expr(&self, expr: ast::Expr) -> Option { - self.infer()? - .type_of_expr_or_pat(self.expr_id(expr)?) - .map(|ty| ty.to_chalk(DbInterner::conjure())) + fn ty_of_expr(&self, expr: ast::Expr) -> Option> { + self.infer()?.type_of_expr_or_pat(self.expr_id(expr)?) } } diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs index 9df131f90e40..dddc03585a28 100644 --- a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs @@ -10,20 +10,21 @@ use std::iter; -use hir_ty::TyBuilder; -use hir_ty::db::HirDatabase; -use hir_ty::mir::BorrowKind; +use hir_ty::{ + db::HirDatabase, + mir::BorrowKind, + next_solver::{DbInterner, Ty}, +}; use itertools::Itertools; use rustc_hash::FxHashSet; +use rustc_type_ir::inherent::Ty as _; use span::Edition; use crate::{ Adt, AssocItem, GenericDef, GenericParam, HasAttrs, HasVisibility, Impl, ModuleDef, ScopeDef, - Type, TypeParam, + Type, TypeParam, term_search::Expr, }; -use crate::term_search::Expr; - use super::{LookupTable, NewTypesKey, TermSearchCtx}; /// # Trivial tactic @@ -596,10 +597,13 @@ pub(super) fn famous_types<'a, 'lt, 'db, DB: HirDatabase>( ) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; let module = ctx.scope.module(); + let interner = DbInterner::new_with(db, None, None); + let bool_ty = Ty::new_bool(interner); + let unit_ty = Ty::new_unit(interner); [ - Expr::FamousType { ty: Type::new(db, module.id, TyBuilder::bool()), value: "true" }, - Expr::FamousType { ty: Type::new(db, module.id, TyBuilder::bool()), value: "false" }, - Expr::FamousType { ty: Type::new(db, module.id, TyBuilder::unit()), value: "()" }, + Expr::FamousType { ty: Type::new(db, module.id, bool_ty), value: "true" }, + Expr::FamousType { ty: Type::new(db, module.id, bool_ty), value: "false" }, + Expr::FamousType { ty: Type::new(db, module.id, unit_ty), value: "()" }, ] .into_iter() .inspect(|exprs| { diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index c5d695ccec3a..f29ccc985c18 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -695,7 +695,7 @@ pub(super) fn definition( DropInfo { drop_glue: field.ty(db).to_type(db).drop_glue(db), has_dtor: None } } Definition::Adt(Adt::Struct(strukt)) => { - let struct_drop_glue = strukt.ty_placeholders(db).drop_glue(db); + let struct_drop_glue = strukt.ty_params(db).drop_glue(db); let mut fields_drop_glue = strukt .fields(db) .iter() @@ -716,10 +716,10 @@ pub(super) fn definition( // Unions cannot have fields with drop glue. Definition::Adt(Adt::Union(union)) => DropInfo { drop_glue: DropGlue::None, - has_dtor: Some(union.ty_placeholders(db).drop_glue(db) != DropGlue::None), + has_dtor: Some(union.ty_params(db).drop_glue(db) != DropGlue::None), }, Definition::Adt(Adt::Enum(enum_)) => { - let enum_drop_glue = enum_.ty_placeholders(db).drop_glue(db); + let enum_drop_glue = enum_.ty_params(db).drop_glue(db); let fields_drop_glue = enum_ .variants(db) .iter() @@ -748,7 +748,7 @@ pub(super) fn definition( DropInfo { drop_glue: fields_drop_glue, has_dtor: None } } Definition::TypeAlias(type_alias) => { - DropInfo { drop_glue: type_alias.ty_placeholders(db).drop_glue(db), has_dtor: None } + DropInfo { drop_glue: type_alias.ty_params(db).drop_glue(db), has_dtor: None } } Definition::Local(local) => { DropInfo { drop_glue: local.ty(db).drop_glue(db), has_dtor: None }