diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 50ceab6c3a4a..ea8d1a781dcc 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -258,28 +258,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "chalk-derive" -version = "0.104.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea9b1e80910f66ae87c772247591432032ef3f6a67367ff17f8343db05beafa" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "chalk-ir" -version = "0.104.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7047a516de16226cd17344d41a319d0ea1064bf9e60bd612ab341ab4a34bbfa8" -dependencies = [ - "bitflags 2.9.4", - "chalk-derive", -] - [[package]] name = "clap" version = "4.5.48" @@ -777,8 +755,6 @@ dependencies = [ "arrayvec", "base-db", "bitflags 2.9.4", - "chalk-derive", - "chalk-ir", "cov-mark", "either", "ena", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index f94fd37e52a7..8a108974681a 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -37,8 +37,6 @@ debug = 2 [patch.'crates-io'] # rowan = { path = "../rowan" } -# chalk-ir = { path = "../chalk/chalk-ir" } -# chalk-derive = { path = "../chalk/chalk-derive" } # line-index = { path = "lib/line-index" } # la-arena = { path = "lib/la-arena" } # lsp-server = { path = "lib/lsp-server" } @@ -110,8 +108,6 @@ arrayvec = "0.7.6" bitflags = "2.9.1" cargo_metadata = "0.21.0" camino = "1.1.10" -chalk-ir = "0.104.0" -chalk-derive = "0.104.0" crossbeam-channel = "0.5.15" dissimilar = "1.0.10" dot = "0.1.4" diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml index ec6563315407..378a0f0382c3 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml @@ -24,8 +24,6 @@ oorandom = "11.1.5" tracing.workspace = true rustc-hash.workspace = true scoped-tls = "1.0.1" -chalk-ir.workspace = true -chalk-derive.workspace = true la-arena.workspace = true triomphe.workspace = true typed-arena = "2.0.2" diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs deleted file mode 100644 index 4cd0af28f33f..000000000000 --- a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs +++ /dev/null @@ -1,211 +0,0 @@ -//! `TyBuilder`, a helper for building instances of `Ty` and related types. - -use chalk_ir::{ - DebruijnIndex, - cast::{Cast, Caster}, -}; -use hir_def::{GenericDefId, GenericParamId, TraitId}; -use smallvec::SmallVec; - -use crate::{ - BoundVar, GenericArg, GenericArgData, Interner, Substitution, TraitRef, Ty, TyKind, - consteval::unknown_const_as_generic, - db::HirDatabase, - error_lifetime, - generics::generics, - infer::unify::InferenceTable, - next_solver::{ - DbInterner, EarlyBinder, - mapping::{ChalkToNextSolver, NextSolverToChalk}, - }, - to_chalk_trait_id, -}; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub(crate) enum ParamKind { - Type, - Lifetime, - Const(Ty), -} - -/// This is a builder for `Ty` or anything that needs a `Substitution`. -pub(crate) struct TyBuilder { - /// The `data` field is used to keep track of what we're building (e.g. an - /// ADT, a `TraitRef`, ...). - data: D, - vec: SmallVec<[GenericArg; 2]>, - param_kinds: SmallVec<[ParamKind; 2]>, - parent_subst: Substitution, -} - -impl TyBuilder { - fn with_data(self, data: B) -> TyBuilder { - TyBuilder { - data, - vec: self.vec, - param_kinds: self.param_kinds, - parent_subst: self.parent_subst, - } - } -} - -impl TyBuilder { - fn new( - data: D, - param_kinds: SmallVec<[ParamKind; 2]>, - parent_subst: Option, - ) -> Self { - let parent_subst = parent_subst.unwrap_or_else(|| Substitution::empty(Interner)); - Self { data, vec: SmallVec::with_capacity(param_kinds.len()), param_kinds, parent_subst } - } - - fn build_internal(self) -> (D, Substitution) { - assert_eq!( - self.vec.len(), - self.param_kinds.len(), - "{} args received, {} expected ({:?})", - self.vec.len(), - self.param_kinds.len(), - &self.param_kinds - ); - for (a, e) in self.vec.iter().zip(self.param_kinds.iter()) { - self.assert_match_kind(a, e); - } - let subst = Substitution::from_iter( - Interner, - self.parent_subst.iter(Interner).cloned().chain(self.vec), - ); - (self.data, subst) - } - - pub(crate) fn remaining(&self) -> usize { - self.param_kinds.len() - self.vec.len() - } - - pub(crate) fn fill_with_bound_vars( - self, - debruijn: DebruijnIndex, - starting_from: usize, - ) -> Self { - // self.fill is inlined to make borrow checker happy - let mut this = self; - let other = &this.param_kinds[this.vec.len()..]; - let filler = (starting_from..).zip(other).map(|(idx, kind)| match kind { - ParamKind::Type => BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner), - ParamKind::Const(ty) => { - BoundVar::new(debruijn, idx).to_const(Interner, ty.clone()).cast(Interner) - } - ParamKind::Lifetime => { - BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner) - } - }); - this.vec.extend(filler.take(this.remaining()).casted(Interner)); - assert_eq!(this.remaining(), 0); - this - } - - #[tracing::instrument(skip_all)] - pub(crate) fn fill_with_inference_vars(self, table: &mut InferenceTable<'_>) -> Self { - self.fill(|x| { - match x { - ParamKind::Type => crate::next_solver::GenericArg::Ty(table.next_ty_var()), - ParamKind::Const(_) => table.next_const_var().into(), - ParamKind::Lifetime => table.next_region_var().into(), - } - .to_chalk(table.interner()) - }) - } - - pub(crate) fn fill(mut self, filler: impl FnMut(&ParamKind) -> GenericArg) -> Self { - self.vec.extend(self.param_kinds[self.vec.len()..].iter().map(filler)); - assert_eq!(self.remaining(), 0); - self - } - - fn assert_match_kind(&self, a: &chalk_ir::GenericArg, e: &ParamKind) { - match (a.data(Interner), e) { - (GenericArgData::Ty(_), ParamKind::Type) - | (GenericArgData::Const(_), ParamKind::Const(_)) - | (GenericArgData::Lifetime(_), ParamKind::Lifetime) => (), - _ => panic!("Mismatched kinds: {a:?}, {:?}, {:?}", self.vec, self.param_kinds), - } - } -} - -impl TyBuilder<()> { - pub(crate) fn usize() -> Ty { - TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize)).intern(Interner) - } - - pub(crate) fn unknown_subst( - db: &dyn HirDatabase, - def: impl Into, - ) -> Substitution { - let interner = DbInterner::conjure(); - let params = generics(db, def.into()); - Substitution::from_iter( - Interner, - params.iter_id().map(|id| match id { - GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner), - GenericParamId::ConstParamId(id) => { - unknown_const_as_generic(db.const_param_ty_ns(id)) - .to_chalk(interner) - .cast(Interner) - } - GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), - }), - ) - } - - #[tracing::instrument(skip_all)] - pub(crate) fn subst_for_def( - db: &dyn HirDatabase, - def: impl Into, - parent_subst: Option, - ) -> TyBuilder<()> { - let generics = generics(db, def.into()); - assert!(generics.parent_generics().is_some() == parent_subst.is_some()); - let params = generics - .iter_self() - .map(|(id, _data)| match id { - GenericParamId::TypeParamId(_) => ParamKind::Type, - GenericParamId::ConstParamId(id) => ParamKind::Const(db.const_param_ty(id)), - GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime, - }) - .collect(); - TyBuilder::new((), params, parent_subst) - } - - pub(crate) fn build(self) -> Substitution { - let ((), subst) = self.build_internal(); - subst - } -} - -impl TyBuilder { - pub(crate) fn trait_ref(db: &dyn HirDatabase, def: TraitId) -> TyBuilder { - TyBuilder::subst_for_def(db, def, None).with_data(def) - } - - pub(crate) fn build(self) -> TraitRef { - let (trait_id, substitution) = self.build_internal(); - TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution } - } -} - -impl<'db, T: rustc_type_ir::TypeFoldable>> TyBuilder> { - pub(crate) fn build(self, interner: DbInterner<'db>) -> T { - let (b, subst) = self.build_internal(); - let args: crate::next_solver::GenericArgs<'db> = subst.to_nextsolver(interner); - b.instantiate(interner, args) - } -} - -impl<'db> TyBuilder>> { - pub(crate) fn impl_self_ty( - db: &'db dyn HirDatabase, - def: hir_def::ImplId, - ) -> TyBuilder>> { - TyBuilder::subst_for_def(db, def, None).with_data(db.impl_self_ty(def)) - } -} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs deleted file mode 100644 index a6b859b37210..000000000000 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! The implementation of `RustIrDatabase` for Chalk, which provides information -//! about the code that Chalk needs. - -use crate::Interner; - -pub(crate) type AssocTypeId = chalk_ir::AssocTypeId; -pub(crate) type TraitId = chalk_ir::TraitId; -pub(crate) type AdtId = chalk_ir::AdtId; -pub(crate) type ImplId = chalk_ir::ImplId; 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 deleted file mode 100644 index 4ea563d46e6e..000000000000 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! Various extensions traits for Chalk types. - -use hir_def::{ItemContainerId, Lookup, TraitId}; - -use crate::{ - Interner, ProjectionTy, Substitution, TraitRef, Ty, db::HirDatabase, from_assoc_type_id, - from_chalk_trait_id, generics::generics, to_chalk_trait_id, -}; - -pub(crate) trait ProjectionTyExt { - fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef; - fn trait_(&self, db: &dyn HirDatabase) -> TraitId; - fn self_type_parameter(&self, db: &dyn HirDatabase) -> Ty; -} - -impl ProjectionTyExt for ProjectionTy { - fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { - // FIXME: something like `Split` trait from chalk-solve might be nice. - let generics = generics(db, from_assoc_type_id(self.associated_ty_id).into()); - let parent_len = generics.parent_generics().map_or(0, |g| g.len_self()); - let substitution = - Substitution::from_iter(Interner, self.substitution.iter(Interner).take(parent_len)); - TraitRef { trait_id: to_chalk_trait_id(self.trait_(db)), substitution } - } - - fn trait_(&self, db: &dyn HirDatabase) -> TraitId { - match from_assoc_type_id(self.associated_ty_id).lookup(db).container { - ItemContainerId::TraitId(it) => it, - _ => panic!("projection ty without parent trait"), - } - } - - fn self_type_parameter(&self, db: &dyn HirDatabase) -> Ty { - self.trait_ref(db).self_type_parameter(Interner) - } -} - -pub(crate) trait TraitRefExt { - fn hir_trait_id(&self) -> TraitId; -} - -impl TraitRefExt for TraitRef { - fn hir_trait_id(&self) -> TraitId { - from_chalk_trait_id(self.trait_id) - } -} 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 deleted file mode 100644 index 07b783ea9292..000000000000 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval_chalk.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Constant evaluation details - -use base_db::Crate; -use chalk_ir::{BoundVar, DebruijnIndex, cast::Cast}; -use hir_def::{ - expr_store::{HygieneId, path::Path}, - resolver::{Resolver, ValueNs}, - type_ref::LiteralConstRef, -}; -use stdx::never; - -use crate::{ - Const, ConstData, ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, - TraitEnvironment, Ty, - db::HirDatabase, - generics::Generics, - lower::ParamLoweringMode, - next_solver::{DbInterner, mapping::ChalkToNextSolver}, - to_placeholder_idx, -}; - -pub(crate) fn path_to_const<'g>( - db: &dyn HirDatabase, - resolver: &Resolver<'_>, - path: &Path, - mode: ParamLoweringMode, - args: impl FnOnce() -> &'g Generics, - debruijn: DebruijnIndex, - expected_ty: Ty, -) -> Option { - match resolver.resolve_path_in_value_ns_fully(db, path, HygieneId::ROOT) { - Some(ValueNs::GenericParam(p)) => { - let ty = db.const_param_ty(p); - let args = args(); - let value = match mode { - ParamLoweringMode::Placeholder => { - let idx = args.type_or_const_param_idx(p.into()).unwrap(); - ConstValue::Placeholder(to_placeholder_idx(db, p.into(), idx as u32)) - } - ParamLoweringMode::Variable => match args.type_or_const_param_idx(p.into()) { - Some(it) => ConstValue::BoundVar(BoundVar::new(debruijn, it)), - None => { - never!( - "Generic list doesn't contain this param: {:?}, {:?}, {:?}", - args, - path, - p - ); - return None; - } - }, - }; - Some(ConstData { ty, value }.intern(Interner)) - } - Some(ValueNs::ConstId(c)) => Some(intern_const_scalar( - ConstScalar::UnevaluatedConst(c.into(), Substitution::empty(Interner)), - expected_ty, - )), - // FIXME: With feature(adt_const_params), we also need to consider other things here, e.g. struct constructors. - _ => None, - } -} - -pub(crate) fn unknown_const(ty: Ty) -> Const { - ConstData { - ty, - value: ConstValue::Concrete(chalk_ir::ConcreteConst { interned: ConstScalar::Unknown }), - } - .intern(Interner) -} - -pub(crate) fn unknown_const_as_generic(ty: Ty) -> GenericArg { - unknown_const(ty).cast(Interner) -} - -/// Interns a constant scalar with the given type -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(crate) fn intern_const_ref( - db: &dyn HirDatabase, - value: &LiteralConstRef, - ty: Ty, - krate: Crate, -) -> Const { - let interner = DbInterner::new_with(db, Some(krate), None); - let layout = || db.layout_of_ty(ty.to_nextsolver(interner), TraitEnvironment::empty(krate)); - let bytes = match value { - LiteralConstRef::Int(i) => { - // FIXME: We should handle failure of layout better. - let size = layout().map(|it| it.size.bytes_usize()).unwrap_or(16); - ConstScalar::Bytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()) - } - LiteralConstRef::UInt(i) => { - let size = layout().map(|it| it.size.bytes_usize()).unwrap_or(16); - ConstScalar::Bytes(i.to_le_bytes()[0..size].into(), MemoryMap::default()) - } - LiteralConstRef::Bool(b) => ConstScalar::Bytes(Box::new([*b as u8]), MemoryMap::default()), - LiteralConstRef::Char(c) => { - ConstScalar::Bytes((*c as u32).to_le_bytes().into(), MemoryMap::default()) - } - LiteralConstRef::Unknown => ConstScalar::Unknown, - }; - intern_const_scalar(bytes, ty) -} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index a4c19eea162e..c79ff9857898 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -1,8 +1,7 @@ //! The home of `HirDatabase`, which is the Salsa database containing all the //! type inference-related queries. -use base_db::Crate; -use base_db::target::TargetLoadError; +use base_db::{Crate, target::TargetLoadError}; use hir_def::{ AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, StaticId, TraitId, @@ -16,13 +15,14 @@ use smallvec::SmallVec; use triomphe::Arc; use crate::{ - Binders, ImplTraitId, ImplTraits, InferenceResult, TraitEnvironment, Ty, TyDefId, ValueTyDefId, + ImplTraitId, InferenceResult, TraitEnvironment, TyDefId, ValueTyDefId, consteval::ConstEvalError, dyn_compatibility::DynCompatibilityViolation, layout::{Layout, LayoutError}, - lower::{Diagnostics, GenericDefaults, GenericPredicates}, + lower::{Diagnostics, GenericDefaults, GenericPredicates, ImplTraits}, method_resolution::{InherentImpls, TraitImpls, TyFingerprint}, mir::{BorrowckResult, MirBody, MirLowerError}, + next_solver::{Const, EarlyBinder, GenericArgs, PolyFnSig, TraitRef, Ty, VariancesOf}, }; #[query_group::query_group] @@ -51,7 +51,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { fn monomorphized_mir_body<'db>( &'db self, def: DefWithBodyId, - subst: crate::next_solver::GenericArgs<'db>, + subst: GenericArgs<'db>, env: Arc>, ) -> Result>, MirLowerError<'db>>; @@ -59,7 +59,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { fn monomorphized_mir_body_for_closure<'db>( &'db self, def: InternedClosureId, - subst: crate::next_solver::GenericArgs<'db>, + subst: GenericArgs<'db>, env: Arc>, ) -> Result>, MirLowerError<'db>>; @@ -75,16 +75,13 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { fn const_eval<'db>( &'db self, def: GeneralConstId, - subst: crate::next_solver::GenericArgs<'db>, + subst: GenericArgs<'db>, trait_env: Option>>, - ) -> Result, ConstEvalError<'db>>; + ) -> Result, ConstEvalError<'db>>; #[salsa::invoke(crate::consteval::const_eval_static_query)] #[salsa::cycle(cycle_result = crate::consteval::const_eval_static_cycle_result)] - fn const_eval_static<'db>( - &'db self, - def: StaticId, - ) -> Result, ConstEvalError<'db>>; + fn const_eval_static<'db>(&'db self, def: StaticId) -> Result, ConstEvalError<'db>>; #[salsa::invoke(crate::consteval::const_eval_discriminant_variant)] #[salsa::cycle(cycle_result = crate::consteval::const_eval_discriminant_cycle_result)] @@ -99,8 +96,8 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { &'db self, env: Arc>, func: FunctionId, - fn_subst: crate::next_solver::GenericArgs<'db>, - ) -> (FunctionId, crate::next_solver::GenericArgs<'db>); + fn_subst: GenericArgs<'db>, + ) -> (FunctionId, GenericArgs<'db>); // endregion:mir @@ -109,7 +106,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { fn layout_of_adt<'db>( &'db self, def: AdtId, - args: crate::next_solver::GenericArgs<'db>, + args: GenericArgs<'db>, trait_env: Arc>, ) -> Result, LayoutError>; @@ -117,7 +114,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { #[salsa::cycle(cycle_result = crate::layout::layout_of_ty_cycle_result)] fn layout_of_ty<'db>( &'db self, - ty: crate::next_solver::Ty<'db>, + ty: Ty<'db>, env: Arc>, ) -> Result, LayoutError>; @@ -127,149 +124,130 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { #[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)] fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option; - #[salsa::invoke(crate::lower_nextsolver::ty_query)] + #[salsa::invoke(crate::lower::ty_query)] #[salsa::transparent] - fn ty<'db>( - &'db self, - def: TyDefId, - ) -> crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>; + fn ty<'db>(&'db self, def: TyDefId) -> EarlyBinder<'db, Ty<'db>>; - #[salsa::invoke(crate::lower_nextsolver::type_for_type_alias_with_diagnostics_query)] - #[salsa::cycle(cycle_result = crate::lower_nextsolver::type_for_type_alias_with_diagnostics_cycle_result)] + #[salsa::invoke(crate::lower::type_for_type_alias_with_diagnostics_query)] + #[salsa::cycle(cycle_result = crate::lower::type_for_type_alias_with_diagnostics_cycle_result)] fn type_for_type_alias_with_diagnostics<'db>( &'db self, def: TypeAliasId, - ) -> (crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>, Diagnostics); + ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics); /// Returns the type of the value of the given constant, or `None` if the `ValueTyDefId` is /// a `StructId` or `EnumVariantId` with a record constructor. - #[salsa::invoke(crate::lower_nextsolver::value_ty_query)] - fn value_ty<'db>( - &'db self, - def: ValueTyDefId, - ) -> Option>>; + #[salsa::invoke(crate::lower::value_ty_query)] + fn value_ty<'db>(&'db self, def: ValueTyDefId) -> Option>>; - #[salsa::invoke(crate::lower_nextsolver::impl_self_ty_with_diagnostics_query)] - #[salsa::cycle(cycle_result = crate::lower_nextsolver::impl_self_ty_with_diagnostics_cycle_result)] + #[salsa::invoke(crate::lower::impl_self_ty_with_diagnostics_query)] + #[salsa::cycle(cycle_result = crate::lower::impl_self_ty_with_diagnostics_cycle_result)] fn impl_self_ty_with_diagnostics<'db>( &'db self, def: ImplId, - ) -> (crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>, Diagnostics); + ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics); - #[salsa::invoke(crate::lower_nextsolver::impl_self_ty_query)] + #[salsa::invoke(crate::lower::impl_self_ty_query)] #[salsa::transparent] - fn impl_self_ty<'db>( - &'db self, - def: ImplId, - ) -> crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>; + fn impl_self_ty<'db>(&'db self, def: ImplId) -> EarlyBinder<'db, Ty<'db>>; // FIXME: Make this a non-interned query. - #[salsa::invoke_interned(crate::lower_nextsolver::const_param_ty_with_diagnostics_query)] - #[salsa::cycle(cycle_result = crate::lower_nextsolver::const_param_ty_with_diagnostics_cycle_result)] - fn const_param_ty_with_diagnostics<'db>( - &'db self, - def: ConstParamId, - ) -> (crate::next_solver::Ty<'db>, Diagnostics); + #[salsa::invoke_interned(crate::lower::const_param_ty_with_diagnostics_query)] + #[salsa::cycle(cycle_result = crate::lower::const_param_ty_with_diagnostics_cycle_result)] + fn const_param_ty_with_diagnostics<'db>(&'db self, def: ConstParamId) + -> (Ty<'db>, Diagnostics); - // FIXME: Make this a non-interned query. - #[salsa::invoke_interned(crate::lower::const_param_ty_query)] - #[salsa::cycle(cycle_result = crate::lower::const_param_ty_cycle_result)] - fn const_param_ty(&self, def: ConstParamId) -> Ty; + #[salsa::invoke(crate::lower::const_param_ty_query)] + #[salsa::transparent] + fn const_param_ty_ns<'db>(&'db self, def: ConstParamId) -> Ty<'db>; - #[salsa::invoke(crate::lower_nextsolver::impl_trait_with_diagnostics_query)] + #[salsa::invoke(crate::lower::impl_trait_with_diagnostics_query)] fn impl_trait_with_diagnostics<'db>( &'db self, def: ImplId, - ) -> Option<( - crate::next_solver::EarlyBinder<'db, crate::next_solver::TraitRef<'db>>, - Diagnostics, - )>; + ) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)>; - #[salsa::invoke(crate::lower_nextsolver::impl_trait_query)] + #[salsa::invoke(crate::lower::impl_trait_query)] #[salsa::transparent] - fn impl_trait<'db>( - &'db self, - def: ImplId, - ) -> Option>>; + fn impl_trait<'db>(&'db self, def: ImplId) -> Option>>; - #[salsa::invoke(crate::lower_nextsolver::field_types_with_diagnostics_query)] + #[salsa::invoke(crate::lower::field_types_with_diagnostics_query)] fn field_types_with_diagnostics<'db>( &'db self, var: VariantId, - ) -> ( - Arc< - ArenaMap< - LocalFieldId, - crate::next_solver::EarlyBinder<'db, crate::next_solver::Ty<'db>>, - >, - >, - Diagnostics, - ); + ) -> (Arc>>>, Diagnostics); #[salsa::invoke(crate::lower::field_types_query)] #[salsa::transparent] - fn field_types(&self, var: VariantId) -> Arc>>; + fn field_types<'db>( + &'db self, + var: VariantId, + ) -> Arc>>>; - #[salsa::invoke(crate::lower_nextsolver::callable_item_signature_query)] + #[salsa::invoke(crate::lower::callable_item_signature_query)] fn callable_item_signature<'db>( &'db self, def: CallableDefId, - ) -> crate::next_solver::EarlyBinder<'db, crate::next_solver::PolyFnSig<'db>>; + ) -> EarlyBinder<'db, PolyFnSig<'db>>; #[salsa::invoke(crate::lower::return_type_impl_traits)] - fn return_type_impl_traits(&self, def: FunctionId) -> Option>>; + fn return_type_impl_traits<'db>( + &'db self, + def: FunctionId, + ) -> Option>>>; #[salsa::invoke(crate::lower::type_alias_impl_traits)] - fn type_alias_impl_traits(&self, def: TypeAliasId) -> Option>>; + fn type_alias_impl_traits<'db>( + &'db self, + def: TypeAliasId, + ) -> Option>>>; - #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] - #[salsa::cycle(cycle_result = crate::lower::generic_predicates_for_param_cycle_result)] - fn generic_predicates_for_param( - &self, - def: GenericDefId, - param_id: TypeOrConstParamId, - assoc_name: Option, - ) -> GenericPredicates; - - #[salsa::invoke(crate::lower::generic_predicates_query)] - fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates; - - #[salsa::invoke( - crate::lower_nextsolver::generic_predicates_without_parent_with_diagnostics_query - )] + #[salsa::invoke(crate::lower::generic_predicates_without_parent_with_diagnostics_query)] fn generic_predicates_without_parent_with_diagnostics<'db>( &'db self, def: GenericDefId, - ) -> (crate::lower_nextsolver::GenericPredicates<'db>, Diagnostics); + ) -> (GenericPredicates<'db>, Diagnostics); - #[salsa::invoke(crate::lower_nextsolver::generic_predicates_without_parent_query)] + #[salsa::invoke(crate::lower::generic_predicates_without_parent_query)] #[salsa::transparent] fn generic_predicates_without_parent<'db>( &'db self, def: GenericDefId, - ) -> crate::lower_nextsolver::GenericPredicates<'db>; + ) -> GenericPredicates<'db>; - #[salsa::invoke(crate::lower_nextsolver::trait_environment_for_body_query)] + #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] + #[salsa::cycle(cycle_result = crate::lower::generic_predicates_for_param_cycle_result)] + fn generic_predicates_for_param<'db>( + &'db self, + def: GenericDefId, + param_id: TypeOrConstParamId, + assoc_name: Option, + ) -> GenericPredicates<'db>; + + #[salsa::invoke(crate::lower::generic_predicates_query)] + fn generic_predicates<'db>(&'db self, def: GenericDefId) -> GenericPredicates<'db>; + + #[salsa::invoke(crate::lower::trait_environment_for_body_query)] #[salsa::transparent] fn trait_environment_for_body<'db>(&'db self, def: DefWithBodyId) -> Arc>; - #[salsa::invoke(crate::lower_nextsolver::trait_environment_query)] + #[salsa::invoke(crate::lower::trait_environment_query)] fn trait_environment<'db>(&'db self, def: GenericDefId) -> Arc>; #[salsa::invoke(crate::lower::generic_defaults_with_diagnostics_query)] #[salsa::cycle(cycle_result = crate::lower::generic_defaults_with_diagnostics_cycle_result)] - fn generic_defaults_with_diagnostics( - &self, + fn generic_defaults_with_diagnostics<'db>( + &'db self, def: GenericDefId, - ) -> (GenericDefaults, Diagnostics); + ) -> (GenericDefaults<'db>, Diagnostics); /// This returns an empty list if no parameter has default. /// /// The binders of the returned defaults are only up to (not including) this parameter. #[salsa::invoke(crate::lower::generic_defaults_query)] #[salsa::transparent] - fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults; + fn generic_defaults<'db>(&'db self, def: GenericDefId) -> GenericDefaults<'db>; #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)] fn inherent_impls_in_crate(&self, krate: Crate) -> Arc; @@ -297,7 +275,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { #[salsa::invoke(TraitImpls::trait_impls_in_deps_query)] fn trait_impls_in_deps(&self, krate: Crate) -> Arc<[Arc]>; - // Interned IDs for Chalk integration + // Interned IDs for solver integration #[salsa::interned] fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId; @@ -313,66 +291,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug { // cycle_initial = crate::variance::variances_of_cycle_initial, cycle_result = crate::variance::variances_of_cycle_initial, )] - fn variances_of(&self, def: GenericDefId) -> crate::next_solver::VariancesOf<'_>; - - // next trait solver - - #[salsa::invoke(crate::lower_nextsolver::const_param_ty_query)] - #[salsa::transparent] - fn const_param_ty_ns<'db>(&'db self, def: ConstParamId) -> crate::next_solver::Ty<'db>; - - #[salsa::invoke(crate::lower_nextsolver::field_types_query)] - #[salsa::transparent] - fn field_types_ns<'db>( - &'db self, - var: VariantId, - ) -> Arc< - ArenaMap>>, - >; - - #[salsa::invoke(crate::lower_nextsolver::return_type_impl_traits)] - fn return_type_impl_traits_ns<'db>( - &'db self, - def: FunctionId, - ) -> Option>>>; - - #[salsa::invoke(crate::lower_nextsolver::type_alias_impl_traits)] - fn type_alias_impl_traits_ns<'db>( - &'db self, - def: TypeAliasId, - ) -> Option>>>; - - #[salsa::invoke(crate::lower_nextsolver::generic_predicates_for_param_query)] - #[salsa::cycle(cycle_result = crate::lower_nextsolver::generic_predicates_for_param_cycle_result)] - fn generic_predicates_for_param_ns<'db>( - &'db self, - def: GenericDefId, - param_id: TypeOrConstParamId, - assoc_name: Option, - ) -> crate::lower_nextsolver::GenericPredicates<'db>; - - #[salsa::invoke(crate::lower_nextsolver::generic_predicates_query)] - fn generic_predicates_ns<'db>( - &'db self, - def: GenericDefId, - ) -> crate::lower_nextsolver::GenericPredicates<'db>; - - #[salsa::invoke(crate::lower_nextsolver::generic_defaults_with_diagnostics_query)] - #[salsa::cycle(cycle_result = crate::lower_nextsolver::generic_defaults_with_diagnostics_cycle_result)] - fn generic_defaults_ns_with_diagnostics<'db>( - &'db self, - def: GenericDefId, - ) -> (crate::lower_nextsolver::GenericDefaults<'db>, Diagnostics); - - /// This returns an empty list if no parameter has default. - /// - /// The binders of the returned defaults are only up to (not including) this parameter. - #[salsa::invoke(crate::lower_nextsolver::generic_defaults_query)] - #[salsa::transparent] - fn generic_defaults_ns<'db>( - &'db self, - def: GenericDefId, - ) -> crate::lower_nextsolver::GenericDefaults<'db>; + fn variances_of(&self, def: GenericDefId) -> VariancesOf<'_>; } #[test] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index f0efadeafcea..fb942e336e65 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -150,7 +150,7 @@ impl<'a, 'db> MatchCheckCtx<'a, 'db> { ) -> impl Iterator)> { let (_, substs) = ty.as_adt().unwrap(); - let field_tys = self.db.field_types_ns(variant); + let field_tys = self.db.field_types(variant); let fields_len = variant.fields(self.db).fields().len() as u32; (0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).map(move |fid| { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 2c6cbdd03f13..2b92408f0f6b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -626,7 +626,7 @@ fn write_projection<'db>( // FIXME: We shouldn't use `param.id`, it should be removed. We should know the // `GenericDefId` from the formatted type (store it inside the `HirFormatter`). let bounds = - f.db.generic_predicates_ns(param.id.parent()) + f.db.generic_predicates(param.id.parent()) .instantiate_identity() .into_iter() .flatten() @@ -902,7 +902,7 @@ fn render_const_scalar_inner<'db>( hir_def::AdtId::StructId(s) => { let data = f.db.struct_signature(s); write!(f, "{}", data.name.display(f.db, f.edition()))?; - let field_types = f.db.field_types_ns(s.into()); + let field_types = f.db.field_types(s.into()); render_variant_after_name( s.fields(f.db), f, @@ -934,7 +934,7 @@ fn render_const_scalar_inner<'db>( .1 .display(f.db, f.edition()) )?; - let field_types = f.db.field_types_ns(var_id.into()); + let field_types = f.db.field_types(var_id.into()); render_variant_after_name( var_id.fields(f.db), f, @@ -1121,7 +1121,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> { let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id); if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id { let datas = db - .return_type_impl_traits_ns(func) + .return_type_impl_traits(func) .expect("impl trait id without data"); let data = (*datas).as_ref().map_bound(|rpit| { &rpit.impl_traits[idx.to_nextsolver(interner)].predicates @@ -1353,9 +1353,8 @@ impl<'db> HirDisplay<'db> for Ty<'db> { let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty_id); match impl_trait_id { ImplTraitId::ReturnTypeImplTrait(func, idx) => { - let datas = db - .return_type_impl_traits_ns(func) - .expect("impl trait id without data"); + let datas = + db.return_type_impl_traits(func).expect("impl trait id without data"); let data = (*datas).as_ref().map_bound(|rpit| { &rpit.impl_traits[idx.to_nextsolver(interner)].predicates }); @@ -1373,9 +1372,8 @@ impl<'db> HirDisplay<'db> for Ty<'db> { // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution } ImplTraitId::TypeAliasImplTrait(alias, idx) => { - let datas = db - .type_alias_impl_traits_ns(alias) - .expect("impl trait id without data"); + let datas = + db.type_alias_impl_traits(alias).expect("impl trait id without data"); let data = (*datas).as_ref().map_bound(|rpit| { &rpit.impl_traits[idx.to_nextsolver(interner)].predicates }); @@ -1501,7 +1499,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> { } TypeParamProvenance::ArgumentImplTrait => { let bounds = db - .generic_predicates_ns(param.id.parent()) + .generic_predicates(param.id.parent()) .instantiate_identity() .into_iter() .flatten() @@ -1621,7 +1619,7 @@ fn generic_args_sans_defaults<'ga, 'db>( parameters: &'ga [GenericArg<'db>], ) -> &'ga [GenericArg<'db>] { if f.display_kind.is_source_code() || f.omit_verbose_types() { - match generic_def.map(|generic_def_id| f.db.generic_defaults_ns(generic_def_id)) { + match generic_def.map(|generic_def_id| f.db.generic_defaults(generic_def_id)) { None => parameters, Some(default_parameters) => { let should_show = |arg: GenericArg<'db>, i: usize| match default_parameters.get(i) { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs index aaf274799c63..b09d1fb196c4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs @@ -85,7 +85,7 @@ fn has_drop_glue_impl<'db>( { return DropGlue::None; } - db.field_types_ns(id.into()) + db.field_types(id.into()) .iter() .map(|(_, field_ty)| { has_drop_glue_impl( @@ -105,7 +105,7 @@ fn has_drop_glue_impl<'db>( .variants .iter() .map(|&(variant, _, _)| { - db.field_types_ns(variant.into()) + db.field_types(variant.into()) .iter() .map(|(_, field_ty)| { has_drop_glue_impl( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index e35a79870329..437141e41db9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -18,10 +18,10 @@ use smallvec::SmallVec; use crate::{ ImplTraitId, db::{HirDatabase, InternedOpaqueTyId}, - lower_nextsolver::associated_ty_item_bounds, + lower::associated_ty_item_bounds, next_solver::{ - Clause, Clauses, DbInterner, GenericArgs, ParamEnv, SolverDefId, TraitPredicate, TraitRef, - TypingMode, infer::DbInternerInferExt, mk_param, + Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, Goal, ParamEnv, ParamTy, + SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode, infer::DbInternerInferExt, mk_param, }, traits::next_trait_solve_in_ctxt, }; @@ -136,7 +136,7 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b }; let interner = DbInterner::new_with(db, Some(krate), None); - let predicates = db.generic_predicates_ns(def); + let predicates = db.generic_predicates(def); // FIXME: We should use `explicit_predicates_of` here, which hasn't been implemented to // rust-analyzer yet // https://github.com/rust-lang/rust/blob/ddaf12390d3ffb7d5ba74491a48f3cd528e5d777/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L490 @@ -162,7 +162,7 @@ pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> b // but we don't have good way to render such locations. // So, just return single boolean value for existence of such `Self` reference fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool { - db.generic_predicates_ns(trait_.into()) + db.generic_predicates(trait_.into()) .iter() .any(|pred| predicate_references_self(db, trait_, pred, AllowSelfProjection::No)) } @@ -378,7 +378,7 @@ where }) = pred && let trait_data = db.trait_signature(pred_trait_ref.def_id.0) && trait_data.flags.contains(TraitFlags::AUTO) - && let rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0, .. }) = + && let rustc_type_ir::TyKind::Param(ParamTy { index: 0, .. }) = pred_trait_ref.self_ty().kind() { continue; @@ -397,10 +397,7 @@ fn receiver_is_dispatchable<'db>( db: &dyn HirDatabase, trait_: TraitId, func: FunctionId, - sig: &crate::next_solver::EarlyBinder< - 'db, - crate::next_solver::Binder<'db, rustc_type_ir::FnSig>>, - >, + sig: &EarlyBinder<'db, Binder<'db, rustc_type_ir::FnSig>>>, ) -> bool { let sig = sig.instantiate_identity(); @@ -409,10 +406,8 @@ fn receiver_is_dispatchable<'db>( parent: trait_.into(), local_id: LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)), }); - let self_param_ty = crate::next_solver::Ty::new( - interner, - rustc_type_ir::TyKind::Param(crate::next_solver::ParamTy { index: 0, id: self_param_id }), - ); + let self_param_ty = + Ty::new(interner, rustc_type_ir::TyKind::Param(ParamTy { index: 0, id: self_param_id })); // `self: Self` can't be dispatched on, but this is already considered dyn-compatible // See rustc's comment on https://github.com/rust-lang/rust/blob/3f121b9461cce02a703a0e7e450568849dfaa074/compiler/rustc_trait_selection/src/traits/object_safety.rs#L433-L437 @@ -440,12 +435,12 @@ fn receiver_is_dispatchable<'db>( // Type `U` // FIXME: That seems problematic to fake a generic param like that? - let unsized_self_ty = crate::next_solver::Ty::new_param(interner, self_param_id, u32::MAX); + let unsized_self_ty = Ty::new_param(interner, self_param_id, u32::MAX); // `Receiver[Self => U]` let unsized_receiver_ty = receiver_for_self_ty(interner, func, receiver_ty, unsized_self_ty); let param_env = { - let generic_predicates = &*db.generic_predicates_ns(func.into()); + let generic_predicates = &*db.generic_predicates(func.into()); // Self: Unsize let unsize_predicate = @@ -475,7 +470,7 @@ fn receiver_is_dispatchable<'db>( // Receiver: DispatchFromDyn U]> let predicate = TraitRef::new(interner, dispatch_from_dyn_did.into(), [receiver_ty, unsized_receiver_ty]); - let goal = crate::next_solver::Goal::new(interner, param_env, predicate); + let goal = Goal::new(interner, param_env, predicate); let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); // the receiver is dispatchable iff the obligation holds @@ -486,26 +481,19 @@ fn receiver_is_dispatchable<'db>( fn receiver_for_self_ty<'db>( interner: DbInterner<'db>, func: FunctionId, - receiver_ty: crate::next_solver::Ty<'db>, - self_ty: crate::next_solver::Ty<'db>, -) -> crate::next_solver::Ty<'db> { - let args = crate::next_solver::GenericArgs::for_item( - interner, - SolverDefId::FunctionId(func), - |index, kind, _| { - if index == 0 { self_ty.into() } else { mk_param(interner, index, kind) } - }, - ); + receiver_ty: Ty<'db>, + self_ty: Ty<'db>, +) -> Ty<'db> { + let args = GenericArgs::for_item(interner, SolverDefId::FunctionId(func), |index, kind, _| { + if index == 0 { self_ty.into() } else { mk_param(interner, index, kind) } + }); - crate::next_solver::EarlyBinder::bind(receiver_ty).instantiate(interner, args) + EarlyBinder::bind(receiver_ty).instantiate(interner, args) } fn contains_illegal_impl_trait_in_trait<'db>( db: &'db dyn HirDatabase, - sig: &crate::next_solver::EarlyBinder< - 'db, - crate::next_solver::Binder<'db, rustc_type_ir::FnSig>>, - >, + sig: &EarlyBinder<'db, Binder<'db, rustc_type_ir::FnSig>>>, ) -> Option { struct OpaqueTypeCollector(FxHashSet); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs index 3ca5f0dcb247..26e03aa01a1d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs @@ -9,7 +9,6 @@ //! where parent follows the same scheme. use std::ops; -use chalk_ir::{BoundVar, DebruijnIndex, cast::Cast as _}; use hir_def::{ ConstParamId, GenericDefId, GenericParamId, ItemContainerId, LifetimeParamId, Lookup, TypeOrConstParamId, TypeParamId, @@ -23,8 +22,6 @@ use hir_def::{ use itertools::chain; use triomphe::Arc; -use crate::{Interner, Substitution, db::HirDatabase, lt_to_placeholder_idx, to_placeholder_idx}; - pub fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def))); let (params, store) = db.generic_params_and_store(def); @@ -230,50 +227,6 @@ impl Generics { pub(crate) fn parent_generics(&self) -> Option<&Generics> { self.parent_generics.as_deref() } - - pub(crate) fn parent_or_self(&self) -> &Generics { - self.parent_generics.as_deref().unwrap_or(self) - } - - /// Returns a Substitution that replaces each parameter by a bound variable. - pub(crate) fn bound_vars_subst( - &self, - db: &dyn HirDatabase, - debruijn: DebruijnIndex, - ) -> Substitution { - Substitution::from_iter( - Interner, - self.iter_id().enumerate().map(|(idx, id)| match id { - GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx) - .to_const(Interner, db.const_param_ty(id)) - .cast(Interner), - GenericParamId::TypeParamId(_) => { - BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner) - } - GenericParamId::LifetimeParamId(_) => { - BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner) - } - }), - ) - } - - /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`). - pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution { - Substitution::from_iter( - Interner, - self.iter_id().enumerate().map(|(index, id)| match id { - GenericParamId::TypeParamId(id) => { - to_placeholder_idx(db, id.into(), index as u32).to_ty(Interner).cast(Interner) - } - GenericParamId::ConstParamId(id) => to_placeholder_idx(db, id.into(), index as u32) - .to_const(Interner, db.const_param_ty(id)) - .cast(Interner), - GenericParamId::LifetimeParamId(id) => { - lt_to_placeholder_idx(db, id, index as u32).to_lifetime(Interner).cast(Interner) - } - }), - ) - } } pub(crate) fn trait_self_param_idx(db: &dyn DefDatabase, def: GenericDefId) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index b2dd90a3d0df..9891f3f248bd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -63,8 +63,9 @@ use crate::{ expr::ExprIsRead, unify::InferenceTable, }, - lower::diagnostics::TyLoweringDiagnostic, - lower_nextsolver::{ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind}, + lower::{ + ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic, + }, mir::MirSpan, next_solver::{ AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Region, Ty, TyKind, @@ -1159,7 +1160,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { }, ); let return_ty = self.insert_type_vars(return_ty); - if let Some(rpits) = self.db.return_type_impl_traits_ns(func) { + if let Some(rpits) = self.db.return_type_impl_traits(func) { let mut mode = ImplTraitReplacingMode::ReturnPosition(FxHashSet::default()); let result = self.insert_inference_vars_for_impl_trait(return_ty, &mut mode); if let ImplTraitReplacingMode::ReturnPosition(taits) = mode { @@ -1234,7 +1235,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { } return ty; } - (self.db.return_type_impl_traits_ns(def), idx) + (self.db.return_type_impl_traits(def), idx) } ImplTraitId::TypeAliasImplTrait(def, idx) => { if let ImplTraitReplacingMode::ReturnPosition(taits) = mode { @@ -1243,7 +1244,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { taits.insert(ty); return ty; } - (self.db.type_alias_impl_traits_ns(def), idx) + (self.db.type_alias_impl_traits(def), idx) } _ => unreachable!(), }; @@ -1604,8 +1605,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> { match ty.kind() { TyKind::Adt(adt_def, substs) => match adt_def.def_id().0 { AdtId::StructId(struct_id) => { - match self.db.field_types_ns(struct_id.into()).values().next_back().copied() - { + match self.db.field_types(struct_id.into()).values().next_back().copied() { Some(field) => { ty = field.instantiate(self.interner(), substs); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs index 990281a7c896..c128977d7b08 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs @@ -394,7 +394,7 @@ fn pointer_kind<'db>( let struct_data = id.fields(ctx.db); if let Some((last_field, _)) = struct_data.fields().iter().last() { let last_field_ty = - ctx.db.field_types_ns(id.into())[last_field].instantiate(ctx.interner(), subst); + ctx.db.field_types(id.into())[last_field].instantiate(ctx.interner(), subst); pointer_kind(last_field_ty, ctx) } else { Ok(Some(PointerKind::Thin)) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs index 39e70c262a24..844eb02ab0d4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs @@ -15,8 +15,8 @@ use la_arena::{Idx, RawIdx}; use crate::{ InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic, db::HirDatabase, - lower_nextsolver::path::{PathDiagnosticCallback, PathLoweringContext}, - lower_nextsolver::{LifetimeElisionKind, TyLoweringContext}, + lower::path::{PathDiagnosticCallback, PathLoweringContext}, + lower::{LifetimeElisionKind, TyLoweringContext}, }; // Unfortunately, this struct needs to use interior mutability (but we encapsulate it) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index e1964608a3f0..efb7244ff637 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -37,7 +37,7 @@ use crate::{ pat::contains_explicit_ref_binding, }, lang_items::lang_items_for_bin_op, - lower_nextsolver::{ + lower::{ LifetimeElisionKind, lower_mutability, path::{GenericArgsLowerer, TypeLikeConst, substs_from_args_and_bindings}, }, @@ -564,7 +564,7 @@ impl<'db> InferenceContext<'_, 'db> { match def_id { _ if fields.is_empty() => {} Some(def) => { - let field_types = self.db.field_types_ns(def); + let field_types = self.db.field_types(def); let variant_data = def.fields(self.db); let visibilities = self.db.field_visibilities(def); for field in fields.iter() { @@ -1622,7 +1622,7 @@ impl<'db> InferenceContext<'_, 'db> { } return None; } - let ty = self.db.field_types_ns(field_id.parent)[field_id.local_id] + let ty = self.db.field_types(field_id.parent)[field_id.local_id] .instantiate(interner, parameters); Some((Either::Left(field_id), ty)) }); @@ -1637,7 +1637,7 @@ impl<'db> InferenceContext<'_, 'db> { None => { let (field_id, subst) = private_field?; let adjustments = autoderef.adjust_steps(); - let ty = self.db.field_types_ns(field_id.parent)[field_id.local_id] + let ty = self.db.field_types(field_id.parent)[field_id.local_id] .instantiate(self.interner(), subst); let ty = self.process_remote_user_written_ty(ty); @@ -2320,7 +2320,7 @@ impl<'db> InferenceContext<'_, 'db> { let callable_ty = self.table.try_structurally_resolve_type(callable_ty); if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind() { let generic_predicates = - self.db.generic_predicates_ns(GenericDefId::from_callable(self.db, fn_def.0)); + self.db.generic_predicates(GenericDefId::from_callable(self.db, fn_def.0)); if let Some(predicates) = generic_predicates.instantiate(self.interner(), parameters) { let interner = self.interner(); let param_env = self.table.trait_env.env; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index 9edbc9dda0f1..71a9c94bf5e5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -18,7 +18,7 @@ use crate::next_solver::{GenericArgs, TraitRef}; use crate::{ Adjust, Adjustment, AutoBorrow, OverloadedDeref, infer::{Expectation, InferenceContext, expr::ExprIsRead}, - lower_nextsolver::lower_mutability, + lower::lower_mutability, next_solver::TyKind, }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs index 61255d31d281..8019844b5df3 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs @@ -19,7 +19,7 @@ use crate::{ AllowTwoPhase, BindingMode, Expectation, InferenceContext, TypeMismatch, coerce::CoerceNever, expr::ExprIsRead, }, - lower_nextsolver::lower_mutability, + lower::lower_mutability, next_solver::{GenericArgs, Ty, TyKind}, }; @@ -59,7 +59,7 @@ impl<'db> InferenceContext<'_, 'db> { match def { _ if subs.is_empty() => {} Some(def) => { - let field_types = self.db.field_types_ns(def); + let field_types = self.db.field_types(def); let variant_data = def.fields(self.db); let visibilities = self.db.field_visibilities(def); @@ -128,7 +128,7 @@ impl<'db> InferenceContext<'_, 'db> { match def { _ if subs.len() == 0 => {} Some(def) => { - let field_types = self.db.field_types_ns(def); + let field_types = self.db.field_types(def); let variant_data = def.fields(self.db); let visibilities = self.db.field_visibilities(def); 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 84d17db6c663..2dae7cb04ffa 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 @@ -13,7 +13,7 @@ use crate::{ InferenceDiagnostic, ValueTyDefId, generics::generics, infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext, - lower_nextsolver::LifetimeElisionKind, + lower::LifetimeElisionKind, method_resolution::{self, VisibleFromModule}, next_solver::{ GenericArg, GenericArgs, TraitRef, Ty, @@ -221,7 +221,7 @@ impl<'db> InferenceContext<'_, 'db> { def: GenericDefId, subst: GenericArgs<'db>, ) { - let predicates = self.db.generic_predicates_ns(def); + let predicates = self.db.generic_predicates(def); let interner = self.interner(); let param_env = self.table.trait_env.env; if let Some(predicates) = predicates.instantiate(self.interner(), subst) { 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 beb26f7d6890..a18cdda559d0 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 @@ -800,7 +800,7 @@ impl<'db> InferenceTable<'db> { while let Some((AdtId::StructId(id), subst)) = ty.as_adt() { let struct_data = id.fields(self.db); if let Some((last_field, _)) = struct_data.fields().iter().next_back() { - let last_field_ty = self.db.field_types_ns(id.into())[last_field] + let last_field_ty = self.db.field_types(id.into())[last_field] .instantiate(self.interner(), subst); if structs.contains(&ty) { // A struct recursively contains itself as a tail field somewhere. diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs index 7ebc2df6f75d..8aed2608d6cd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs @@ -156,7 +156,7 @@ impl<'a, 'db> UninhabitedFrom<'a, 'db> { } let is_enum = matches!(variant, VariantId::EnumVariantId(..)); - let field_tys = self.db().field_types_ns(variant); + let field_tys = self.db().field_types(variant); let field_vis = if is_enum { None } else { Some(self.db().field_visibilities(variant)) }; for (fid, _) in fields.iter() { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs deleted file mode 100644 index 57ef5523b433..000000000000 --- a/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs +++ /dev/null @@ -1,403 +0,0 @@ -//! Implementation of the Chalk `Interner` trait, which allows customizing the -//! representation of the various objects Chalk deals with (types, goals etc.). - -use crate::{ - AliasTy, CanonicalVarKind, CanonicalVarKinds, ClosureId, Const, ConstData, ConstScalar, FnAbi, - FnDefId, GenericArg, GenericArgData, Goal, GoalData, InEnvironment, Lifetime, LifetimeData, - OpaqueTy, OpaqueTyId, ProgramClause, ProjectionTy, QuantifiedWhereClause, - QuantifiedWhereClauses, Substitution, Ty, TyKind, VariableKind, chalk_db, tls, -}; -use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variance}; -use hir_def::TypeAliasId; -use intern::{Interned, impl_internable}; -use smallvec::SmallVec; -use std::fmt; -use triomphe::Arc; - -type TyData = chalk_ir::TyData; -type VariableKinds = chalk_ir::VariableKinds; -type Goals = chalk_ir::Goals; -type ProgramClauseData = chalk_ir::ProgramClauseData; -type Constraint = chalk_ir::Constraint; -type Constraints = chalk_ir::Constraints; -type ProgramClauses = chalk_ir::ProgramClauses; - -#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] -pub struct Interner; - -#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)] -pub struct InternedWrapper(pub(crate) T); - -impl fmt::Debug for InternedWrapper { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.0, f) - } -} - -#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)] -pub struct InternedWrapperNoDebug(pub(crate) T); - -impl std::ops::Deref for InternedWrapper { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl_internable!( - InternedWrapper>, - InternedWrapper>, - InternedWrapper, - InternedWrapper, - InternedWrapper, - InternedWrapper, - InternedWrapper>, - InternedWrapper>, - InternedWrapper>, - InternedWrapper>, -); - -impl chalk_ir::interner::Interner for Interner { - type InternedType = Interned>; - type InternedLifetime = Interned>; - type InternedConst = Interned>; - type InternedConcreteConst = ConstScalar; - type InternedGenericArg = GenericArgData; - // We could do the following, but that saves "only" 20mb on self while increasing inference - // time by ~2.5% - // type InternedGoal = Interned>; - type InternedGoal = Arc; - type InternedGoals = Vec; - type InternedSubstitution = Interned>>; - type InternedProgramClauses = Interned>>; - type InternedProgramClause = ProgramClauseData; - type InternedQuantifiedWhereClauses = Interned>>; - type InternedVariableKinds = Interned>>; - type InternedCanonicalVarKinds = Interned>>; - type InternedConstraints = Vec>; - type InternedVariances = SmallVec<[Variance; 16]>; - type DefId = salsa::Id; - type InternedAdtId = hir_def::AdtId; - type Identifier = TypeAliasId; - type FnAbi = FnAbi; - - fn debug_adt_id( - type_kind_id: chalk_db::AdtId, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) - } - - fn debug_trait_id( - type_kind_id: chalk_db::TraitId, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) - } - - fn debug_assoc_type_id( - id: chalk_db::AssocTypeId, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) - } - - fn debug_opaque_ty_id( - opaque_ty_id: OpaqueTyId, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "OpaqueTy#{:?}", opaque_ty_id.0)) - } - - fn debug_fn_def_id(fn_def_id: FnDefId, fmt: &mut fmt::Formatter<'_>) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt))) - } - - fn debug_closure_id( - _fn_def_id: ClosureId, - _fmt: &mut fmt::Formatter<'_>, - ) -> Option { - None - } - - fn debug_alias(alias: &AliasTy, fmt: &mut fmt::Formatter<'_>) -> Option { - use std::fmt::Debug; - match alias { - AliasTy::Projection(projection_ty) => Interner::debug_projection_ty(projection_ty, fmt), - AliasTy::Opaque(opaque_ty) => Some(opaque_ty.fmt(fmt)), - } - } - - fn debug_projection_ty( - proj: &ProjectionTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt))) - .or_else(|| Some(fmt.write_str("ProjectionTy"))) - } - - fn debug_opaque_ty(opaque_ty: &OpaqueTy, fmt: &mut fmt::Formatter<'_>) -> Option { - Some(write!(fmt, "{:?}", opaque_ty.opaque_ty_id)) - } - - fn debug_ty(ty: &Ty, fmt: &mut fmt::Formatter<'_>) -> Option { - Some(write!(fmt, "{:?}", ty.data(Interner))) - } - - fn debug_lifetime(lifetime: &Lifetime, fmt: &mut fmt::Formatter<'_>) -> Option { - Some(write!(fmt, "{:?}", lifetime.data(Interner))) - } - - fn debug_const(constant: &Const, fmt: &mut fmt::Formatter<'_>) -> Option { - Some(write!(fmt, "{:?}", constant.data(Interner))) - } - - fn debug_generic_arg( - parameter: &GenericArg, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", parameter.data(Interner).inner_debug())) - } - - fn debug_variable_kinds( - variable_kinds: &VariableKinds, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", variable_kinds.as_slice(Interner))) - } - - fn debug_variable_kinds_with_angles( - variable_kinds: &VariableKinds, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", variable_kinds.inner_debug(Interner))) - } - - fn debug_canonical_var_kinds( - canonical_var_kinds: &CanonicalVarKinds, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", canonical_var_kinds.as_slice(Interner))) - } - fn debug_goal(goal: &Goal, fmt: &mut fmt::Formatter<'_>) -> Option { - let goal_data = goal.data(Interner); - Some(write!(fmt, "{goal_data:?}")) - } - fn debug_goals(goals: &Goals, fmt: &mut fmt::Formatter<'_>) -> Option { - Some(write!(fmt, "{:?}", goals.debug(Interner))) - } - fn debug_program_clause_implication( - pci: &ProgramClauseImplication, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", pci.debug(Interner))) - } - fn debug_program_clause( - clause: &ProgramClause, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", clause.data(Interner))) - } - fn debug_program_clauses( - clauses: &ProgramClauses, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", clauses.as_slice(Interner))) - } - fn debug_substitution( - substitution: &Substitution, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", substitution.debug(Interner))) - } - fn debug_separator_trait_ref( - separator_trait_ref: &SeparatorTraitRef<'_, Interner>, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", separator_trait_ref.debug(Interner))) - } - - fn debug_quantified_where_clauses( - clauses: &QuantifiedWhereClauses, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", clauses.as_slice(Interner))) - } - - fn debug_constraints( - _clauses: &Constraints, - _fmt: &mut fmt::Formatter<'_>, - ) -> Option { - None - } - - fn intern_ty(self, kind: TyKind) -> Self::InternedType { - let flags = kind.compute_flags(self); - Interned::new(InternedWrapper(TyData { kind, flags })) - } - - fn ty_data(self, ty: &Self::InternedType) -> &TyData { - &ty.0 - } - - fn intern_lifetime(self, lifetime: LifetimeData) -> Self::InternedLifetime { - Interned::new(InternedWrapper(lifetime)) - } - - fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &LifetimeData { - &lifetime.0 - } - - fn intern_const(self, constant: ConstData) -> Self::InternedConst { - Interned::new(InternedWrapper(constant)) - } - - fn const_data(self, constant: &Self::InternedConst) -> &ConstData { - &constant.0 - } - - fn const_eq( - self, - _ty: &Self::InternedType, - c1: &Self::InternedConcreteConst, - c2: &Self::InternedConcreteConst, - ) -> bool { - !matches!(c1, ConstScalar::Bytes(..)) || !matches!(c2, ConstScalar::Bytes(..)) || (c1 == c2) - } - - fn intern_generic_arg(self, parameter: GenericArgData) -> Self::InternedGenericArg { - parameter - } - - fn generic_arg_data(self, parameter: &Self::InternedGenericArg) -> &GenericArgData { - parameter - } - - fn intern_goal(self, goal: GoalData) -> Self::InternedGoal { - Arc::new(goal) - } - - fn goal_data(self, goal: &Self::InternedGoal) -> &GoalData { - goal - } - - fn intern_goals( - self, - data: impl IntoIterator>, - ) -> Result { - // let hash = - // std::hash::BuildHasher::hash_one(&BuildHasherDefault::::default(), &goal); - // Interned::new(InternedWrapper(PreHashedWrapper(goal, hash))) - data.into_iter().collect() - } - - fn goals_data(self, goals: &Self::InternedGoals) -> &[Goal] { - goals - } - - fn intern_substitution( - self, - data: impl IntoIterator>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn substitution_data(self, substitution: &Self::InternedSubstitution) -> &[GenericArg] { - &substitution.as_ref().0 - } - - fn intern_program_clause(self, data: ProgramClauseData) -> Self::InternedProgramClause { - data - } - - fn program_clause_data(self, clause: &Self::InternedProgramClause) -> &ProgramClauseData { - clause - } - - fn intern_program_clauses( - self, - data: impl IntoIterator>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn program_clauses_data(self, clauses: &Self::InternedProgramClauses) -> &[ProgramClause] { - clauses - } - - fn intern_quantified_where_clauses( - self, - data: impl IntoIterator>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn quantified_where_clauses_data( - self, - clauses: &Self::InternedQuantifiedWhereClauses, - ) -> &[QuantifiedWhereClause] { - clauses - } - - fn intern_generic_arg_kinds( - self, - data: impl IntoIterator>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn variable_kinds_data(self, parameter_kinds: &Self::InternedVariableKinds) -> &[VariableKind] { - ¶meter_kinds.as_ref().0 - } - - fn intern_canonical_var_kinds( - self, - data: impl IntoIterator>, - ) -> Result { - Ok(Interned::new(InternedWrapper(data.into_iter().collect::>()?))) - } - - fn canonical_var_kinds_data( - self, - canonical_var_kinds: &Self::InternedCanonicalVarKinds, - ) -> &[CanonicalVarKind] { - canonical_var_kinds - } - fn intern_constraints( - self, - data: impl IntoIterator, E>>, - ) -> Result { - data.into_iter().collect() - } - fn constraints_data( - self, - constraints: &Self::InternedConstraints, - ) -> &[InEnvironment] { - constraints - } - - fn intern_variances( - self, - data: impl IntoIterator>, - ) -> Result { - data.into_iter().collect::>() - } - - fn variances_data(self, variances: &Self::InternedVariances) -> &[Variance] { - variances - } -} - -impl chalk_ir::interner::HasInterner for Interner { - type Interner = Self; -} - -#[macro_export] -macro_rules! has_interner { - ($t:ty) => { - impl HasInterner for $t { - type Interner = $crate::Interner; - } - }; -} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index a857602fa08a..fc0b9d30b333 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -138,7 +138,7 @@ fn layout_of_simd_ty<'db>( // * #[repr(simd)] struct S([T; 4]) // // where T is a primitive scalar (integer/float/pointer). - let fields = db.field_types_ns(id.into()); + let fields = db.field_types(id.into()); let mut fields = fields.iter(); let Some(TyKind::Array(e_ty, e_len)) = fields .next() @@ -401,7 +401,7 @@ fn field_ty<'a>( fd: LocalFieldId, args: &GenericArgs<'a>, ) -> Ty<'a> { - db.field_types_ns(def)[fd].instantiate(DbInterner::new_with(db, None, None), args) + db.field_types(def)[fd].instantiate(DbInterner::new_with(db, None, None), args) } fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar { 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 b698fd9a1454..536c81ab03b2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -23,23 +23,15 @@ extern crate ra_ap_rustc_next_trait_solver as rustc_next_trait_solver; extern crate self as hir_ty; -mod builder; -mod chalk_db; -mod chalk_ext; mod infer; mod inhabitedness; -mod interner; mod lower; -mod lower_nextsolver; -mod mapping; pub mod next_solver; mod target_feature; -mod tls; mod utils; pub mod autoderef; pub mod consteval; -mod consteval_chalk; pub mod db; pub mod diagnostics; pub mod display; @@ -61,16 +53,11 @@ mod variance; use std::hash::Hash; -use chalk_ir::{ - VariableKinds, - fold::{Shift, TypeFoldable}, - interner::HasInterner, -}; -use hir_def::{CallableDefId, GeneralConstId, TypeOrConstParamId, hir::ExprId, type_ref::Rawness}; +use hir_def::{CallableDefId, TypeOrConstParamId, hir::ExprId, type_ref::Rawness}; use hir_expand::name::Name; use indexmap::{IndexMap, map::Entry}; use intern::{Symbol, sym}; -use la_arena::{Arena, Idx}; +use la_arena::Idx; use mir::{MirEvalError, VTableMap}; use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; use rustc_type_ir::{ @@ -82,13 +69,14 @@ use traits::FnTrait; use triomphe::Arc; use crate::{ - builder::TyBuilder, - chalk_ext::*, db::HirDatabase, display::{DisplayTarget, HirDisplay}, - generics::Generics, infer::unify::InferenceTable, - next_solver::DbInterner, + next_solver::{ + AliasTy, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, Canonical, + CanonicalVarKind, CanonicalVars, Const, ConstKind, DbInterner, FnSig, PolyFnSig, Predicate, + Region, RegionKind, TraitRef, Ty, TyKind, Tys, abi, + }, }; pub use autoderef::autoderef; @@ -99,15 +87,9 @@ pub use infer::{ closure::analysis::{CaptureKind, CapturedItem}, could_coerce, could_unify, could_unify_deeply, }; -pub use interner::Interner; -pub use lower::{ImplTraitLoweringMode, ParamLoweringMode, TyDefId, ValueTyDefId, diagnostics::*}; -pub use lower_nextsolver::{ - LifetimeElisionKind, TyLoweringContext, 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, - to_foreign_def_id, to_placeholder_idx, to_placeholder_idx_no_index, +pub use lower::{ + LifetimeElisionKind, TyDefId, TyLoweringContext, ValueTyDefId, + associated_type_shorthand_candidates, diagnostics::*, }; pub use method_resolution::check_orphan_rules; pub use next_solver::interner::{attach_db, attach_db_allow_change, with_attached_db}; @@ -118,76 +100,6 @@ pub use utils::{ is_fn_unsafe_to_call, target_feature_is_safe_in_target, }; -use chalk_ir::{BoundVar, DebruijnIndex, Safety, Scalar}; - -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(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 -/// also contain the generic parameters for its parent. See chalk's documentation for details. -/// -/// One thing to keep in mind when working with `Binders` (and `Substitution`s, which represent -/// generic arguments) in rust-analyzer is that the ordering within *is* significant - the generic -/// 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(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(crate) type Substitution = chalk_ir::Substitution; -pub(crate) type GenericArg = chalk_ir::GenericArg; -pub(crate) type GenericArgData = chalk_ir::GenericArgData; - -pub(crate) type Ty = chalk_ir::Ty; -pub type TyKind = chalk_ir::TyKind; -pub(crate) type DynTy = chalk_ir::DynTy; -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(crate) type ProjectionTy = chalk_ir::ProjectionTy; -pub(crate) type OpaqueTy = chalk_ir::OpaqueTy; - -pub(crate) type Lifetime = chalk_ir::Lifetime; -pub(crate) type LifetimeData = chalk_ir::LifetimeData; -pub(crate) type LifetimeOutlives = chalk_ir::LifetimeOutlives; - -pub(crate) type ConstValue = chalk_ir::ConstValue; - -pub(crate) type Const = chalk_ir::Const; -pub(crate) type ConstData = chalk_ir::ConstData; - -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(crate) type InEnvironment = chalk_ir::InEnvironment; -pub type AliasEq = chalk_ir::AliasEq; -pub type WhereClause = chalk_ir::WhereClause; - -pub(crate) type DomainGoal = chalk_ir::DomainGoal; -pub(crate) type Goal = chalk_ir::Goal; - -pub(crate) type CanonicalVarKind = chalk_ir::CanonicalVarKind; -pub(crate) type GoalData = chalk_ir::GoalData; -pub(crate) type ProgramClause = chalk_ir::ProgramClause; - /// A constant can have reference to other things. Memory map job is holding /// the necessary bits of memory of the const eval session to keep the constant /// meaningful. @@ -221,7 +133,7 @@ impl ComplexMemoryMap<'_> { } impl<'db> MemoryMap<'db> { - pub fn vtable_ty(&self, id: usize) -> Result, MirEvalError<'db>> { + pub fn vtable_ty(&self, id: usize) -> Result, MirEvalError<'db>> { match self { MemoryMap::Empty | MemoryMap::Simple(_) => Err(MirEvalError::InvalidVTableId(id)), MemoryMap::Complex(cm) => cm.vtable.ty(id), @@ -271,118 +183,11 @@ impl<'db> MemoryMap<'db> { } } -// FIXME(next-solver): add a lifetime to this -/// A concrete constant value -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ConstScalar { - Bytes(Box<[u8]>, MemoryMap<'static>), - // FIXME: this is a hack to get around chalk not being able to represent unevaluatable - // constants - UnevaluatedConst(GeneralConstId, Substitution), - /// Case of an unknown value that rustc might know but we don't - // FIXME: this is a hack to get around chalk not being able to represent unevaluatable - // constants - // https://github.com/rust-lang/rust-analyzer/pull/8813#issuecomment-840679177 - // https://rust-lang.zulipchat.com/#narrow/stream/144729-wg-traits/topic/Handling.20non.20evaluatable.20constants'.20equality/near/238386348 - Unknown, -} - -impl Hash for ConstScalar { - fn hash(&self, state: &mut H) { - core::mem::discriminant(self).hash(state); - if let ConstScalar::Bytes(b, _) = self { - b.hash(state) - } - } -} - -/// A concrete constant value -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ConstScalarNs<'db> { - Bytes(Box<[u8]>, MemoryMap<'db>), - // FIXME: this is a hack to get around chalk not being able to represent unevaluatable - // constants - UnevaluatedConst(GeneralConstId, Substitution), - /// Case of an unknown value that rustc might know but we don't - // FIXME: this is a hack to get around chalk not being able to represent unevaluatable - // constants - // https://github.com/rust-lang/rust-analyzer/pull/8813#issuecomment-840679177 - // https://rust-lang.zulipchat.com/#narrow/stream/144729-wg-traits/topic/Handling.20non.20evaluatable.20constants'.20equality/near/238386348 - Unknown, -} - -impl Hash for ConstScalarNs<'_> { - fn hash(&self, state: &mut H) { - core::mem::discriminant(self).hash(state); - if let ConstScalarNs::Bytes(b, _) = self { - b.hash(state) - } - } -} - /// Return an index of a parameter in the generic type parameter list by it's id. pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option { generics::generics(db, id.parent).type_or_const_param_idx(id) } -pub(crate) fn wrap_empty_binders(value: T) -> Binders -where - T: TypeFoldable + HasInterner, -{ - Binders::empty(Interner, value.shifted_in_from(Interner, DebruijnIndex::ONE)) -} - -pub(crate) fn make_single_type_binders>( - value: T, -) -> Binders { - Binders::new( - chalk_ir::VariableKinds::from_iter( - Interner, - std::iter::once(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)), - ), - value, - ) -} - -pub(crate) fn make_binders>( - db: &dyn HirDatabase, - generics: &Generics, - value: T, -) -> Binders { - Binders::new(variable_kinds_from_iter(db, generics.iter_id()), value) -} - -pub(crate) fn variable_kinds_from_iter( - db: &dyn HirDatabase, - iter: impl Iterator, -) -> VariableKinds { - VariableKinds::from_iter( - Interner, - iter.map(|x| match x { - hir_def::GenericParamId::ConstParamId(id) => { - chalk_ir::VariableKind::Const(db.const_param_ty(id)) - } - hir_def::GenericParamId::TypeParamId(_) => { - chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General) - } - hir_def::GenericParamId::LifetimeParamId(_) => chalk_ir::VariableKind::Lifetime, - }), - ) -} - -// FIXME: get rid of this, just replace it by FnPointer -/// A function signature as seen by type inference: Several parameter types and -/// one return type. -#[derive(Clone, PartialEq, Eq, Debug)] -pub(crate) struct CallableSig { - params_and_return: Arc<[Ty]>, - is_varargs: bool, - safety: Safety, - abi: FnAbi, -} - -has_interner!(CallableSig); - #[derive(Debug, Copy, Clone, Eq)] pub enum FnAbi { Aapcs, @@ -534,81 +339,21 @@ pub enum ImplTraitId { } #[derive(PartialEq, Eq, Debug, Hash)] -pub struct ImplTraits { - pub(crate) impl_traits: Arena, -} - -has_interner!(ImplTraits); - -#[derive(PartialEq, Eq, Debug, Hash)] -pub struct ImplTrait { - pub(crate) bounds: Binders>, -} +pub struct ImplTrait {} pub type ImplTraitIdx = Idx; -pub fn static_lifetime() -> Lifetime { - LifetimeData::Static.intern(Interner) -} - -pub fn error_lifetime() -> Lifetime { - LifetimeData::Error.intern(Interner) -} - -pub(crate) fn fold_free_vars + TypeFoldable>( - t: T, - for_ty: impl FnMut(BoundVar, DebruijnIndex) -> Ty, - for_const: impl FnMut(Ty, BoundVar, DebruijnIndex) -> Const, -) -> T { - use chalk_ir::fold::TypeFolder; - - #[derive(chalk_derive::FallibleTypeFolder)] - #[has_interner(Interner)] - struct FreeVarFolder< - F1: FnMut(BoundVar, DebruijnIndex) -> Ty, - F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const, - >(F1, F2); - impl Ty, F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const> - TypeFolder for FreeVarFolder - { - fn as_dyn(&mut self) -> &mut dyn TypeFolder { - self - } - - fn interner(&self) -> Interner { - Interner - } - - fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty { - self.0(bound_var, outer_binder) - } - - fn fold_free_var_const( - &mut self, - ty: Ty, - bound_var: BoundVar, - outer_binder: DebruijnIndex, - ) -> Const { - self.1(ty, bound_var, outer_binder) - } - } - t.fold_with(&mut FreeVarFolder(for_ty, for_const), DebruijnIndex::INNERMOST) -} - /// '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<'db, T>( - interner: DbInterner<'db>, - t: &T, -) -> crate::next_solver::Canonical<'db, T> +pub fn replace_errors_with_variables<'db, T>(interner: DbInterner<'db>, t: &T) -> Canonical<'db, T> where T: rustc_type_ir::TypeFoldable> + Clone, { use rustc_type_ir::{FallibleTypeFolder, TypeSuperFoldable}; struct ErrorReplacer<'db> { interner: DbInterner<'db>, - vars: Vec>, + vars: Vec>, binder: rustc_type_ir::DebruijnIndex, } impl<'db> FallibleTypeFolder> for ErrorReplacer<'db> { @@ -621,10 +366,7 @@ where self.interner } - fn try_fold_binder( - &mut self, - t: crate::next_solver::Binder<'db, T>, - ) -> Result, Self::Error> + fn try_fold_binder(&mut self, t: Binder<'db, T>) -> Result, Self::Error> where T: rustc_type_ir::TypeFoldable>, { @@ -634,10 +376,7 @@ where result } - fn try_fold_ty( - &mut self, - t: crate::next_solver::Ty<'db>, - ) -> Result, Self::Error> { + fn try_fold_ty(&mut self, t: Ty<'db>) -> Result, Self::Error> { if !t.has_type_flags( rustc_type_ir::TypeFlags::HAS_ERROR | rustc_type_ir::TypeFlags::HAS_TY_INFER @@ -650,39 +389,28 @@ where #[cfg(debug_assertions)] let error = || Err(()); #[cfg(not(debug_assertions))] - let error = || { - Ok(crate::next_solver::Ty::new_error( - self.interner, - crate::next_solver::ErrorGuaranteed, - )) - }; + let error = || Ok(Ty::new_error(self.interner, crate::next_solver::ErrorGuaranteed)); match t.kind() { - crate::next_solver::TyKind::Error(_) => { + TyKind::Error(_) => { let var = rustc_type_ir::BoundVar::from_usize(self.vars.len()); - self.vars.push(crate::next_solver::CanonicalVarKind::Ty { + self.vars.push(CanonicalVarKind::Ty { ui: rustc_type_ir::UniverseIndex::ZERO, sub_root: var, }); - Ok(crate::next_solver::Ty::new_bound( + Ok(Ty::new_bound( self.interner, self.binder, - crate::next_solver::BoundTy { - var, - kind: crate::next_solver::BoundTyKind::Anon, - }, + BoundTy { var, kind: BoundTyKind::Anon }, )) } - crate::next_solver::TyKind::Infer(_) => error(), - crate::next_solver::TyKind::Bound(index, _) if index > self.binder => error(), + TyKind::Infer(_) => error(), + TyKind::Bound(index, _) if index > self.binder => error(), _ => t.try_super_fold_with(self), } } - fn try_fold_const( - &mut self, - ct: crate::next_solver::Const<'db>, - ) -> Result, Self::Error> { + fn try_fold_const(&mut self, ct: Const<'db>) -> Result, Self::Error> { if !ct.has_type_flags( rustc_type_ir::TypeFlags::HAS_ERROR | rustc_type_ir::TypeFlags::HAS_TY_INFER @@ -695,52 +423,38 @@ where #[cfg(debug_assertions)] let error = || Err(()); #[cfg(not(debug_assertions))] - let error = || Ok(crate::next_solver::Const::error(self.interner)); + let error = || Ok(Const::error(self.interner)); match ct.kind() { - crate::next_solver::ConstKind::Error(_) => { + 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 }, - )) + self.vars.push(CanonicalVarKind::Const(rustc_type_ir::UniverseIndex::ZERO)); + Ok(Const::new_bound(self.interner, self.binder, BoundConst { var })) } - crate::next_solver::ConstKind::Infer(_) => error(), - crate::next_solver::ConstKind::Bound(index, _) if index > self.binder => error(), + ConstKind::Infer(_) => error(), + ConstKind::Bound(index, _) if index > self.binder => error(), _ => ct.try_super_fold_with(self), } } - fn try_fold_region( - &mut self, - region: crate::next_solver::Region<'db>, - ) -> Result, Self::Error> { + fn try_fold_region(&mut self, region: 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)); + let error = || Ok(Region::error(self.interner)); match region.kind() { - crate::next_solver::RegionKind::ReError(_) => { + 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.vars.push(CanonicalVarKind::Region(rustc_type_ir::UniverseIndex::ZERO)); + Ok(Region::new_bound( self.interner, self.binder, - crate::next_solver::BoundRegion { - var, - kind: crate::next_solver::BoundRegionKind::Anon, - }, + BoundRegion { var, kind: BoundRegionKind::Anon }, )) } - crate::next_solver::RegionKind::ReVar(_) => error(), - crate::next_solver::RegionKind::ReBound(index, _) if index > self.binder => error(), + RegionKind::ReVar(_) => error(), + RegionKind::ReBound(index, _) if index > self.binder => error(), _ => Ok(region), } } @@ -752,18 +466,18 @@ where Ok(t) => t, Err(_) => panic!("Encountered unbound or inference vars in {t:?}"), }; - crate::next_solver::Canonical { + Canonical { value, max_universe: rustc_type_ir::UniverseIndex::ZERO, - variables: crate::next_solver::CanonicalVars::new_from_iter(interner, error_replacer.vars), + variables: CanonicalVars::new_from_iter(interner, error_replacer.vars), } } pub fn callable_sig_from_fn_trait<'db>( - self_ty: crate::next_solver::Ty<'db>, + self_ty: Ty<'db>, trait_env: Arc>, db: &'db dyn HirDatabase, -) -> Option<(FnTrait, crate::next_solver::PolyFnSig<'db>)> { +) -> Option<(FnTrait, PolyFnSig<'db>)> { let krate = trait_env.krate; let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?; let output_assoc_type = fn_once_trait @@ -771,54 +485,46 @@ pub fn callable_sig_from_fn_trait<'db>( .associated_type_by_name(&Name::new_symbol_root(sym::Output))?; let mut table = InferenceTable::new(db, trait_env.clone()); - let b = TyBuilder::trait_ref(db, fn_once_trait); - if b.remaining() != 2 { - return None; - } // Register two obligations: // - Self: FnOnce // - >::Output == ?ret_ty let args_ty = table.next_ty_var(); 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( + let trait_ref = TraitRef::new(table.interner(), fn_once_trait.into(), args); + let projection = Ty::new_alias( table.interner(), rustc_type_ir::AliasTyKind::Projection, - crate::next_solver::AliasTy::new(table.interner(), output_assoc_type.into(), args), + AliasTy::new(table.interner(), output_assoc_type.into(), args), ); - let pred = crate::next_solver::Predicate::upcast_from(trait_ref, table.interner()); + let pred = Predicate::upcast_from(trait_ref, table.interner()); if !table.try_obligation(pred).no_solution() { table.register_obligation(pred); let return_ty = table.normalize_alias_ty(projection); for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] { let fn_x_trait = fn_x.get_id(db, krate)?; - let trait_ref = - crate::next_solver::TraitRef::new(table.interner(), fn_x_trait.into(), args); + let trait_ref = TraitRef::new(table.interner(), fn_x_trait.into(), args); if !table - .try_obligation(crate::next_solver::Predicate::upcast_from( - trait_ref, - table.interner(), - )) + .try_obligation(Predicate::upcast_from(trait_ref, table.interner())) .no_solution() { 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 { + let TyKind::Tuple(params) = args_ty.kind() else { return None; }; - let inputs_and_output = crate::next_solver::Tys::new_from_iter( + let inputs_and_output = Tys::new_from_iter( table.interner(), params.iter().chain(std::iter::once(ret_ty)), ); return Some(( fn_x, - crate::next_solver::Binder::dummy(crate::next_solver::FnSig { + Binder::dummy(FnSig { inputs_and_output, c_variadic: false, - safety: crate::next_solver::abi::Safety::Safe, + safety: abi::Safety::Safe, abi: FnAbi::RustCall, }), )); @@ -837,16 +543,16 @@ struct ParamCollector { impl<'db> rustc_type_ir::TypeVisitor> for ParamCollector { type Result = (); - fn visit_ty(&mut self, ty: crate::next_solver::Ty<'db>) -> Self::Result { - if let crate::next_solver::TyKind::Param(param) = ty.kind() { + fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result { + if let TyKind::Param(param) = ty.kind() { self.params.insert(param.id.into()); } ty.super_visit_with(self); } - fn visit_const(&mut self, konst: crate::next_solver::Const<'db>) -> Self::Result { - if let crate::next_solver::ConstKind::Param(param) = konst.kind() { + fn visit_const(&mut self, konst: Const<'db>) -> Self::Result { + if let ConstKind::Param(param) = konst.kind() { self.params.insert(param.id.into()); } @@ -865,7 +571,7 @@ where } pub fn known_const_to_ast<'db>( - konst: crate::next_solver::Const<'db>, + konst: Const<'db>, db: &'db dyn HirDatabase, display_target: DisplayTarget, ) -> Option { 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 b18d713c411e..42f7290962bd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -11,82 +11,93 @@ pub(crate) mod path; use std::{ cell::OnceCell, iter, mem, - ops::{self, Not as _}, + ops::{self, Deref, Not as _}, }; use base_db::Crate; -use chalk_ir::{ - Mutability, Safety, TypeOutlives, - cast::Cast, - fold::{Shift, TypeFoldable}, - interner::HasInterner, -}; - use either::Either; use hir_def::{ - AdtId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, - GenericParamId, LocalFieldId, Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, + AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, + FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, + LocalFieldId, Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId, builtin_type::BuiltinType, - expr_store::{ExpressionStore, path::Path}, - hir::generics::{GenericParamDataRef, TypeOrConstParamData, WherePredicate}, + expr_store::{ExpressionStore, HygieneId, path::Path}, + hir::generics::{ + GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate, + }, + item_tree::FieldsShape, lang_item::LangItem, - resolver::{HasResolver, LifetimeNs, Resolver, TypeNs}, - signatures::TraitFlags, + resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs}, + signatures::{FunctionSignature, TraitFlags, TypeAliasFlags}, type_ref::{ - ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier, TypeBound, TypeRef, - TypeRefId, + ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier, + TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId, }, }; use hir_expand::name::Name; -use la_arena::{Arena, ArenaMap}; +use la_arena::{Arena, ArenaMap, Idx}; +use path::{PathDiagnosticCallback, PathLoweringContext}; +use rustc_ast_ir::Mutability; use rustc_hash::FxHashSet; +use rustc_pattern_analysis::Captures; +use rustc_type_ir::{ + AliasTyKind, ConstKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection, + ExistentialTraitRef, FnSig, OutlivesPredicate, + TyKind::{self}, + TypeVisitableExt, + inherent::{GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, Ty as _}, +}; +use salsa::plumbing::AsId; +use smallvec::{SmallVec, smallvec}; use stdx::{impl_from, never}; use triomphe::{Arc, ThinArc}; use crate::{ - AliasTy, Binders, BoundVar, Const, DebruijnIndex, DynTy, FnAbi, FnPointer, FnSig, FnSubst, - ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime, LifetimeData, LifetimeOutlives, - QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, TraitRef, TraitRefExt, Ty, - TyBuilder, TyKind, WhereClause, all_super_traits, - consteval_chalk::{intern_const_ref, path_to_const, unknown_const, unknown_const_as_generic}, + FnAbi, ImplTraitId, TraitEnvironment, TyLoweringDiagnostic, TyLoweringDiagnosticKind, + consteval::intern_const_ref, db::HirDatabase, - error_lifetime, generics::{Generics, generics, trait_self_param_idx}, - lower::{ - diagnostics::*, - path::{PathDiagnosticCallback, PathLoweringContext}, - }, - make_binders, - mapping::{from_chalk_trait_id, lt_to_placeholder_idx}, next_solver::{ - DbInterner, - mapping::{ChalkToNextSolver, NextSolverToChalk}, + AliasTy, Binder, BoundExistentialPredicates, Clause, Clauses, Const, DbInterner, + EarlyBinder, EarlyParamRegion, ErrorGuaranteed, GenericArg, GenericArgs, ParamConst, + ParamEnv, PolyFnSig, Predicate, Region, SolverDefId, TraitPredicate, TraitRef, Ty, Tys, + UnevaluatedConst, abi::Safety, }, - static_lifetime, to_chalk_trait_id, to_placeholder_idx, - utils::all_super_trait_refs, - variable_kinds_from_iter, }; +pub(crate) struct PathDiagnosticCallbackData(pub(crate) TypeRefId); + +#[derive(PartialEq, Eq, Debug, Hash)] +pub struct ImplTraits<'db> { + pub(crate) impl_traits: Arena>, +} + +#[derive(PartialEq, Eq, Debug, Hash)] +pub struct ImplTrait<'db> { + pub(crate) predicates: Vec>, +} + +pub type ImplTraitIdx<'db> = Idx>; + #[derive(Debug, Default)] -struct ImplTraitLoweringState { +struct ImplTraitLoweringState<'db> { /// When turning `impl Trait` into opaque types, we have to collect the /// bounds at the same time to get the IDs correct (without becoming too /// complicated). mode: ImplTraitLoweringMode, // This is structured as a struct with fields and not as an enum because it helps with the borrow checker. - opaque_type_data: Arena, + opaque_type_data: Arena>, } -impl ImplTraitLoweringState { - fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState { + +impl<'db> ImplTraitLoweringState<'db> { + fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState<'db> { Self { mode, opaque_type_data: Arena::new() } } } -pub(crate) struct PathDiagnosticCallbackData(pub(crate) TypeRefId); - #[derive(Debug, Clone)] -pub(crate) enum LifetimeElisionKind { +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: @@ -104,75 +115,109 @@ pub(crate) enum LifetimeElisionKind { AnonymousCreateParameter { report_in_path: bool }, /// Replace all anonymous lifetimes by provided lifetime. - Elided(Lifetime), + Elided(Region<'db>), /// Give a hard error when either `&` or `'_` is written. Used to /// rule out things like `where T: Foo<'_>`. Does not imply an /// 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, } -impl LifetimeElisionKind { +impl<'db> LifetimeElisionKind<'db> { #[inline] - pub(crate) fn for_fn_ret() -> LifetimeElisionKind { + pub(crate) fn for_const( + interner: DbInterner<'db>, + const_parent: ItemContainerId, + ) -> LifetimeElisionKind<'db> { + match const_parent { + ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => { + LifetimeElisionKind::Elided(Region::new_static(interner)) + } + ItemContainerId::ImplId(_) => { + LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true } + } + ItemContainerId::TraitId(_) => { + LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false } + } + } + } + + #[inline] + pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind<'db> { + LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() } + } + + #[inline] + pub(crate) fn for_fn_ret(interner: DbInterner<'db>) -> LifetimeElisionKind<'db> { // FIXME: We should use the elided lifetime here, or `ElisionFailure`. - LifetimeElisionKind::Elided(error_lifetime()) + LifetimeElisionKind::Elided(Region::error(interner)) } } #[derive(Debug)] -pub(crate) struct TyLoweringContext<'db> { +pub struct TyLoweringContext<'db, 'a> { pub db: &'db dyn HirDatabase, - resolver: &'db Resolver<'db>, - store: &'db ExpressionStore, + interner: DbInterner<'db>, + resolver: &'a Resolver<'db>, + store: &'a ExpressionStore, def: GenericDefId, generics: OnceCell, in_binders: DebruijnIndex, - /// Note: Conceptually, it's thinkable that we could be in a location where - /// some type params should be represented as placeholders, and others - /// should be converted to variables. I think in practice, this isn't - /// possible currently, so this should be fine for now. - pub type_param_mode: ParamLoweringMode, - impl_trait_mode: ImplTraitLoweringState, + impl_trait_mode: ImplTraitLoweringState<'db>, /// Tracks types with explicit `?Sized` bounds. - pub(crate) unsized_types: FxHashSet, + pub(crate) unsized_types: FxHashSet>, pub(crate) diagnostics: Vec, - lifetime_elision: LifetimeElisionKind, + lifetime_elision: LifetimeElisionKind<'db>, + /// When lowering the defaults for generic params, this contains the index of the currently lowered param. + /// We disallow referring to later params, or to ADT's `Self`. + lowering_param_default: Option, } -impl<'db> TyLoweringContext<'db> { - pub(crate) fn new( +impl<'db, 'a> TyLoweringContext<'db, 'a> { + pub fn new( db: &'db dyn HirDatabase, - resolver: &'db Resolver<'db>, - store: &'db ExpressionStore, + resolver: &'a Resolver<'db>, + store: &'a ExpressionStore, def: GenericDefId, - lifetime_elision: LifetimeElisionKind, + lifetime_elision: LifetimeElisionKind<'db>, ) -> Self { let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed); - let type_param_mode = ParamLoweringMode::Placeholder; - let in_binders = DebruijnIndex::INNERMOST; + let in_binders = DebruijnIndex::ZERO; Self { db, + interner: DbInterner::new_with(db, Some(resolver.krate()), None), resolver, def, generics: Default::default(), store, in_binders, impl_trait_mode, - type_param_mode, unsized_types: FxHashSet::default(), diagnostics: Vec::new(), lifetime_elision, + lowering_param_default: None, } } + pub(crate) fn set_lifetime_elision(&mut self, lifetime_elision: LifetimeElisionKind<'db>) { + self.lifetime_elision = lifetime_elision; + } + pub(crate) fn with_debruijn( &mut self, debruijn: DebruijnIndex, - f: impl FnOnce(&mut TyLoweringContext<'_>) -> T, + f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T, ) -> T { let old_debruijn = mem::replace(&mut self.in_binders, debruijn); let result = f(self); @@ -183,28 +228,22 @@ impl<'db> TyLoweringContext<'db> { pub(crate) fn with_shifted_in( &mut self, debruijn: DebruijnIndex, - f: impl FnOnce(&mut TyLoweringContext<'_>) -> T, + f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T, ) -> T { - self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f) - } - - fn with_lifetime_elision( - &mut self, - lifetime_elision: LifetimeElisionKind, - f: impl FnOnce(&mut TyLoweringContext<'_>) -> T, - ) -> T { - let old_lifetime_elision = mem::replace(&mut self.lifetime_elision, lifetime_elision); - let result = f(self); - self.lifetime_elision = old_lifetime_elision; - result + self.with_debruijn(self.in_binders.shifted_in(debruijn.as_u32()), f) } pub(crate) fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self } } - pub(crate) fn with_type_param_mode(self, type_param_mode: ParamLoweringMode) -> Self { - Self { type_param_mode, ..self } + pub(crate) fn impl_trait_mode(&mut self, impl_trait_mode: ImplTraitLoweringMode) -> &mut Self { + self.impl_trait_mode = ImplTraitLoweringState::new(impl_trait_mode); + self + } + + pub(crate) fn lowering_param_default(&mut self, index: u32) { + self.lowering_param_default = Some(index); } pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { @@ -213,7 +252,7 @@ impl<'db> TyLoweringContext<'db> { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] -pub enum ImplTraitLoweringMode { +pub(crate) enum ImplTraitLoweringMode { /// `impl Trait` gets lowered into an opaque type that doesn't unify with /// anything except itself. This is used in places where values flow 'out', /// i.e. for arguments of the function we're currently checking, and return @@ -224,30 +263,17 @@ pub enum ImplTraitLoweringMode { Disallowed, } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum ParamLoweringMode { - Placeholder, - Variable, -} - -impl<'db> TyLoweringContext<'db> { - pub(crate) fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty { +impl<'db, 'a> TyLoweringContext<'db, 'a> { + pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> { self.lower_ty_ext(type_ref).0 } - pub(crate) 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<'db>) -> Const<'db> { let const_ref = &self.store[const_ref.expr]; match const_ref { - hir_def::hir::Expr::Path(path) => path_to_const( - self.db, - self.resolver, - path, - self.type_param_mode, - || self.generics(), - self.in_binders, - const_type.clone(), - ) - .unwrap_or_else(|| unknown_const(const_type)), + hir_def::hir::Expr::Path(path) => { + self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type)) + } hir_def::hir::Expr::Literal(literal) => intern_const_ref( self.db, &match *literal { @@ -290,32 +316,88 @@ impl<'db> TyLoweringContext<'db> { } } - pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty) -> Const { - path_to_const( - self.db, - self.resolver, - path, - self.type_param_mode, - || self.generics(), - self.in_binders, - const_type.clone(), - ) - .unwrap_or_else(|| unknown_const(const_type)) + pub(crate) fn path_to_const(&mut self, path: &Path) -> Option> { + match self.resolver.resolve_path_in_value_ns_fully(self.db, path, HygieneId::ROOT) { + Some(ValueNs::GenericParam(p)) => { + let args = self.generics(); + match args.type_or_const_param_idx(p.into()) { + Some(idx) => Some(self.const_param(p, idx as u32)), + None => { + never!( + "Generic list doesn't contain this param: {:?}, {:?}, {:?}", + args, + path, + p + ); + None + } + } + } + Some(ValueNs::ConstId(c)) => { + let args = GenericArgs::new_from_iter(self.interner, []); + Some(Const::new( + self.interner, + rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new( + SolverDefId::ConstId(c), + args, + )), + )) + } + _ => None, + } + } + + pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty<'db>) -> Const<'db> { + self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type)) } fn generics(&self) -> &Generics { self.generics.get_or_init(|| generics(self.db, self.def)) } - pub(crate) fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty, Option) { + fn param_index_is_disallowed(&self, index: u32) -> bool { + self.lowering_param_default + .is_some_and(|disallow_params_after| index >= disallow_params_after) + } + + fn type_param(&mut self, id: TypeParamId, index: u32) -> Ty<'db> { + if self.param_index_is_disallowed(index) { + // FIXME: Report an error. + Ty::new_error(self.interner, ErrorGuaranteed) + } else { + Ty::new_param(self.interner, id, index) + } + } + + fn const_param(&mut self, id: ConstParamId, index: u32) -> Const<'db> { + if self.param_index_is_disallowed(index) { + // FIXME: Report an error. + Const::error(self.interner) + } else { + Const::new_param(self.interner, ParamConst { id, index }) + } + } + + fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> { + if self.param_index_is_disallowed(index) { + // FIXME: Report an error. + Region::error(self.interner) + } else { + Region::new_early_param(self.interner, EarlyParamRegion { id, index }) + } + } + + #[tracing::instrument(skip(self), ret)] + 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]; + tracing::debug!(?type_ref); let ty = match type_ref { - TypeRef::Never => TyKind::Never.intern(Interner), + TypeRef::Never => Ty::new(interner, TyKind::Never), TypeRef::Tuple(inner) => { let inner_tys = inner.iter().map(|&tr| self.lower_ty(tr)); - TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys)) - .intern(Interner) + Ty::new_tup_from_iter(interner, inner_tys) } TypeRef::Path(path) => { let (ty, res_) = @@ -325,81 +407,61 @@ impl<'db> TyLoweringContext<'db> { } &TypeRef::TypeParam(type_param_id) => { res = Some(TypeNs::GenericParam(type_param_id)); - match self.type_param_mode { - ParamLoweringMode::Placeholder => { - let generics = self.generics(); - let idx = generics.type_or_const_param_idx(type_param_id.into()).unwrap(); - TyKind::Placeholder(to_placeholder_idx( - self.db, - type_param_id.into(), - idx as u32, - )) - } - ParamLoweringMode::Variable => { - let idx = - self.generics().type_or_const_param_idx(type_param_id.into()).unwrap(); - TyKind::BoundVar(BoundVar::new(self.in_binders, idx)) - } - } - .intern(Interner) + + let generics = self.generics(); + let (idx, _data) = + generics.type_or_const_param(type_param_id.into()).expect("matching generics"); + self.type_param(type_param_id, idx as u32) } &TypeRef::RawPtr(inner, mutability) => { let inner_ty = self.lower_ty(inner); - TyKind::Raw(lower_to_chalk_mutability(mutability), inner_ty).intern(Interner) + Ty::new(interner, TyKind::RawPtr(inner_ty, lower_mutability(mutability))) } TypeRef::Array(array) => { let inner_ty = self.lower_ty(array.ty); - let const_len = self.lower_const(&array.len, TyBuilder::usize()); - TyKind::Array(inner_ty, const_len).intern(Interner) + let const_len = self.lower_const(array.len, Ty::new_usize(interner)); + Ty::new_array_with_const_len(interner, inner_ty, const_len) } &TypeRef::Slice(inner) => { let inner_ty = self.lower_ty(inner); - TyKind::Slice(inner_ty).intern(Interner) + Ty::new_slice(interner, inner_ty) } TypeRef::Reference(ref_) => { let inner_ty = self.lower_ty(ref_.ty); - // FIXME: It should infer the eldided lifetimes instead of stubbing with static + // FIXME: It should infer the eldided lifetimes instead of stubbing with error let lifetime = ref_ .lifetime - .as_ref() - .map_or_else(error_lifetime, |&lr| self.lower_lifetime(lr)); - TyKind::Ref(lower_to_chalk_mutability(ref_.mutability), lifetime, inner_ty) - .intern(Interner) + .map_or_else(|| Region::error(interner), |lr| self.lower_lifetime(lr)); + Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability)) } - TypeRef::Placeholder => TyKind::Error.intern(Interner), + TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed), TypeRef::Fn(fn_) => { - let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { - let (params, ret) = fn_.split_params_and_ret(); - let mut subst = Vec::with_capacity(fn_.params.len()); - ctx.with_lifetime_elision( - LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false }, - |ctx| { - subst.extend(params.iter().map(|&(_, tr)| ctx.lower_ty(tr))); - }, - ); - ctx.with_lifetime_elision(LifetimeElisionKind::for_fn_ret(), |ctx| { - subst.push(ctx.lower_ty(ret)); - }); - Substitution::from_iter(Interner, subst) - }); - TyKind::Function(FnPointer { - num_binders: 0, // FIXME lower `for<'a> fn()` correctly - sig: FnSig { + let substs = self.with_shifted_in( + DebruijnIndex::from_u32(1), + |ctx: &mut TyLoweringContext<'_, '_>| { + Tys::new_from_iter( + interner, + fn_.params.iter().map(|&(_, tr)| ctx.lower_ty(tr)), + ) + }, + ); + Ty::new_fn_ptr( + interner, + Binder::dummy(FnSig { abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol), safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe }, - variadic: fn_.is_varargs, - }, - substitution: FnSubst(substs), - }) - .intern(Interner) + c_variadic: fn_.is_varargs, + inputs_and_output: substs, + }), + ) } TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds), TypeRef::ImplTrait(bounds) => { match self.impl_trait_mode.mode { ImplTraitLoweringMode::Opaque => { - let origin = match self.def { - GenericDefId::FunctionId(it) => Either::Left(it), - GenericDefId::TypeAliasId(it) => Either::Right(it), + let origin = match self.resolver.generic_def() { + Some(GenericDefId::FunctionId(it)) => Either::Left(it), + Some(GenericDefId::TypeAliasId(it)) => Either::Right(it), _ => panic!( "opaque impl trait lowering must be in function or type alias" ), @@ -408,9 +470,19 @@ impl<'db> TyLoweringContext<'db> { // this dance is to make sure the data is in the right // place even if we encounter more opaque types while // lowering the bounds - let idx = self.impl_trait_mode.opaque_type_data.alloc(ImplTrait { - bounds: crate::make_single_type_binders(Vec::default()), - }); + let idx = self + .impl_trait_mode + .opaque_type_data + .alloc(ImplTrait { predicates: Vec::default() }); + + // FIXME(next-solver): this from_raw/into_raw dance isn't nice, but it's minimal + let impl_trait_id = origin.either( + |f| ImplTraitId::ReturnTypeImplTrait(f, Idx::from_raw(idx.into_raw())), + |a| ImplTraitId::TypeAliasImplTrait(a, Idx::from_raw(idx.into_raw())), + ); + let opaque_ty_id: SolverDefId = + self.db.intern_impl_trait_id(impl_trait_id).into(); + // We don't want to lower the bounds inside the binders // we're currently in, because they don't end up inside // those binders. E.g. when we have `impl Trait TyLoweringContext<'db> { // parameter of the outer function, it's just one binder // away instead of two. let actual_opaque_type_data = self - .with_debruijn(DebruijnIndex::INNERMOST, |ctx| { - ctx.lower_impl_trait(bounds, self.resolver.krate()) + .with_debruijn(DebruijnIndex::ZERO, |ctx| { + ctx.lower_impl_trait(opaque_ty_id, bounds, self.resolver.krate()) }); self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data; - let impl_trait_id = origin.either( - |f| ImplTraitId::ReturnTypeImplTrait(f, idx), - |a| ImplTraitId::TypeAliasImplTrait(a, idx), - ); - let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); - let generics = generics(self.db, origin.either(|f| f.into(), |a| a.into())); - let parameters = generics.bound_vars_subst(self.db, self.in_binders); - TyKind::OpaqueType(opaque_ty_id, parameters).intern(Interner) + let args = GenericArgs::identity_for_item(self.interner, opaque_ty_id); + Ty::new_alias( + self.interner, + AliasTyKind::Opaque, + AliasTy::new_from_args(self.interner, opaque_ty_id, args), + ) } ImplTraitLoweringMode::Disallowed => { // FIXME: report error - TyKind::Error.intern(Interner) + Ty::new_error(self.interner, ErrorGuaranteed) } } } - TypeRef::Error => TyKind::Error.intern(Interner), + TypeRef::Error => Ty::new_error(self.interner, ErrorGuaranteed), }; (ty, res) } @@ -449,8 +519,8 @@ impl<'db> TyLoweringContext<'db> { /// This is only for `generic_predicates_for_param`, where we can't just /// lower the self types of the predicates since that could lead to cycles. /// So we just check here if the `type_ref` resolves to a generic param, and which. - fn lower_ty_only_param(&mut self, type_ref_id: TypeRefId) -> Option { - let type_ref = &self.store[type_ref_id]; + fn lower_ty_only_param(&self, type_ref: TypeRefId) -> Option { + let type_ref = &self.store[type_ref]; let path = match type_ref { TypeRef::Path(path) => path, &TypeRef::TypeParam(idx) => return Some(idx.into()), @@ -462,9 +532,8 @@ impl<'db> TyLoweringContext<'db> { if path.segments().len() > 1 { return None; } - let mut ctx = self.at_path(PathId::from_type_ref_unchecked(type_ref_id)); - let resolution = match ctx.resolve_path_in_type_ns() { - Some((it, None)) => it, + let resolution = match self.resolver.resolve_path_in_type_ns(self.db, path) { + Some((it, None, _)) => it, _ => return None, }; match resolution { @@ -474,7 +543,7 @@ impl<'db> TyLoweringContext<'db> { } #[inline] - fn on_path_diagnostic_callback<'a>(type_ref: TypeRefId) -> PathDiagnosticCallback<'a, 'db> { + fn on_path_diagnostic_callback<'b>(type_ref: TypeRefId) -> PathDiagnosticCallback<'b, 'db> { PathDiagnosticCallback { data: Either::Left(PathDiagnosticCallbackData(type_ref)), callback: |data, this, diag| { @@ -485,7 +554,7 @@ impl<'db> TyLoweringContext<'db> { } #[inline] - fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'db> { + fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a, 'db> { PathLoweringContext::new( self, Self::on_path_diagnostic_callback(path_id.type_ref()), @@ -493,7 +562,7 @@ impl<'db> TyLoweringContext<'db> { ) } - pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty, Option) { + pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty<'db>, Option) { // Resolve the path (in type namespace) if let Some(type_ref) = path.type_anchor() { let (ty, res) = self.lower_ty_ext(type_ref); @@ -504,7 +573,7 @@ impl<'db> TyLoweringContext<'db> { let mut ctx = self.at_path(path_id); let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() { Some(it) => it, - None => return (TyKind::Error.intern(Interner), None), + None => return (Ty::new_error(self.interner, ErrorGuaranteed), None), }; if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() { @@ -520,8 +589,8 @@ impl<'db> TyLoweringContext<'db> { fn lower_trait_ref_from_path( &mut self, path_id: PathId, - explicit_self_ty: Ty, - ) -> Option<(TraitRef, PathLoweringContext<'_, 'db>)> { + explicit_self_ty: Ty<'db>, + ) -> Option<(TraitRef<'db>, PathLoweringContext<'_, 'a, 'db>)> { let mut ctx = self.at_path(path_id); let resolved = match ctx.resolve_path_in_type_ns_fully()? { // FIXME(trait_alias): We need to handle trait alias here. @@ -531,26 +600,57 @@ impl<'db> TyLoweringContext<'db> { Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx)) } - /// When lowering predicates from parents (impl, traits) for children defs (fns, consts, types), `generics` should - /// contain the `Generics` for the **child**, while `predicate_owner` should contain the `GenericDefId` of the - /// **parent**. This is important so we generate the correct bound var/placeholder. + fn lower_trait_ref( + &mut self, + trait_ref: &HirTraitRef, + explicit_self_ty: Ty<'db>, + ) -> Option> { + self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0) + } + pub(crate) fn lower_where_predicate<'b>( &'b mut self, where_predicate: &'b WherePredicate, ignore_bindings: bool, - ) -> impl Iterator + use<'db, 'b> { + generics: &Generics, + predicate_filter: PredicateFilter, + ) -> impl Iterator> + use<'a, 'b, 'db> { match where_predicate { WherePredicate::ForLifetime { target, bound, .. } | WherePredicate::TypeBound { target, bound } => { + if let PredicateFilter::SelfTrait = predicate_filter { + let target_type = &self.store[*target]; + let self_type = 'is_self: { + if let TypeRef::Path(path) = target_type + && path.is_self_type() + { + break 'is_self true; + } + if let TypeRef::TypeParam(param) = target_type + && generics[param.local_id()].is_trait_self() + { + break 'is_self true; + } + false + }; + if !self_type { + return Either::Left(Either::Left(iter::empty())); + } + } let self_ty = self.lower_ty(*target); - Either::Left(self.lower_type_bound(bound, self_ty, ignore_bindings)) + Either::Left(Either::Right(self.lower_type_bound(bound, self_ty, ignore_bindings))) + } + &WherePredicate::Lifetime { bound, target } => { + Either::Right(iter::once(Clause(Predicate::new( + self.interner, + Binder::dummy(rustc_type_ir::PredicateKind::Clause( + rustc_type_ir::ClauseKind::RegionOutlives(OutlivesPredicate( + self.lower_lifetime(bound), + self.lower_lifetime(target), + )), + )), + )))) } - &WherePredicate::Lifetime { bound, target } => Either::Right(iter::once( - crate::wrap_empty_binders(WhereClause::LifetimeOutlives(LifetimeOutlives { - a: self.lower_lifetime(bound), - b: self.lower_lifetime(target), - })), - )), } .into_iter() } @@ -558,40 +658,40 @@ impl<'db> TyLoweringContext<'db> { pub(crate) fn lower_type_bound<'b>( &'b mut self, bound: &'b TypeBound, - self_ty: Ty, + self_ty: Ty<'db>, ignore_bindings: bool, - ) -> impl Iterator + use<'b, 'db> { + ) -> impl Iterator> + use<'b, 'a, 'db> { + let interner = self.interner; let mut assoc_bounds = None; let mut clause = None; match bound { &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => { // FIXME Don't silently drop the hrtb lifetimes here - if let Some((trait_ref, mut ctx)) = - self.lower_trait_ref_from_path(path, self_ty.clone()) - { + if let Some((trait_ref, mut ctx)) = self.lower_trait_ref_from_path(path, self_ty) { // FIXME(sized-hierarchy): Remove this bound modifications once we have implemented // sized-hierarchy correctly. let meta_sized = LangItem::MetaSized .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate()); let pointee_sized = LangItem::PointeeSized .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate()); - let destruct = LangItem::Destruct - .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate()); - let hir_trait_id = trait_ref.hir_trait_id(); - if meta_sized.is_some_and(|it| it == hir_trait_id) - || destruct.is_some_and(|it| it == hir_trait_id) - { + if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) { // Ignore this bound - } else if pointee_sized.is_some_and(|it| it == hir_trait_id) { + } else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) { // Regard this as `?Sized` bound ctx.ty_ctx().unsized_types.insert(self_ty); } else { if !ignore_bindings { - assoc_bounds = - ctx.assoc_type_bindings_from_type_bound(trait_ref.clone()); + assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref); } - clause = - Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref))); + clause = Some(Clause(Predicate::new( + interner, + Binder::dummy(rustc_type_ir::PredicateKind::Clause( + rustc_type_ir::ClauseKind::Trait(TraitPredicate { + trait_ref, + polarity: rustc_type_ir::PredicatePolarity::Positive, + }), + )), + ))); } } } @@ -601,95 +701,137 @@ impl<'db> TyLoweringContext<'db> { // `?Sized` has no of them. // If we got another trait here ignore the bound completely. let trait_id = self - .lower_trait_ref_from_path(path, self_ty.clone()) - .map(|(trait_ref, _)| trait_ref.hir_trait_id()); + .lower_trait_ref_from_path(path, self_ty) + .map(|(trait_ref, _)| trait_ref.def_id.0); if trait_id == sized_trait { self.unsized_types.insert(self_ty); } } &TypeBound::Lifetime(l) => { let lifetime = self.lower_lifetime(l); - clause = Some(crate::wrap_empty_binders(WhereClause::TypeOutlives(TypeOutlives { - ty: self_ty, - lifetime, - }))); + clause = Some(Clause(Predicate::new( + self.interner, + Binder::dummy(rustc_type_ir::PredicateKind::Clause( + rustc_type_ir::ClauseKind::TypeOutlives(OutlivesPredicate( + self_ty, lifetime, + )), + )), + ))); } TypeBound::Use(_) | TypeBound::Error => {} } clause.into_iter().chain(assoc_bounds.into_iter().flatten()) } - fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty { - let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner); + fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> { + let interner = self.interner; + // FIXME: we should never create non-existential predicates in the first place + // For now, use an error type so we don't run into dummy binder issues + let self_ty = Ty::new_error(interner, ErrorGuaranteed); // INVARIANT: The principal trait bound, if present, must come first. Others may be in any // order but should be in the same order for the same set but possibly different order of // bounds in the input. // INVARIANT: If this function returns `DynTy`, there should be at least one trait bound. // These invariants are utilized by `TyExt::dyn_trait()` and chalk. let mut lifetime = None; - let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { - let mut lowered_bounds = Vec::new(); + let bounds = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| { + let mut lowered_bounds: Vec< + rustc_type_ir::Binder, ExistentialPredicate>>, + > = Vec::new(); for b in bounds { - ctx.lower_type_bound(b, self_ty.clone(), false).for_each(|b| { - let filter = match b.skip_binders() { - WhereClause::Implemented(_) | WhereClause::AliasEq(_) => true, - WhereClause::LifetimeOutlives(_) => false, - WhereClause::TypeOutlives(t) => { - lifetime = Some(t.lifetime.clone()); - false - } - }; - if filter { - lowered_bounds.push(b); + let db = ctx.db; + ctx.lower_type_bound(b, self_ty, false).for_each(|b| { + if let Some(bound) = b + .kind() + .map_bound(|c| match c { + rustc_type_ir::ClauseKind::Trait(t) => { + let id = t.def_id(); + let is_auto = + db.trait_signature(id.0).flags.contains(TraitFlags::AUTO); + if is_auto { + Some(ExistentialPredicate::AutoTrait(t.def_id())) + } else { + Some(ExistentialPredicate::Trait( + ExistentialTraitRef::new_from_args( + interner, + t.def_id(), + GenericArgs::new_from_iter( + interner, + t.trait_ref.args.iter().skip(1), + ), + ), + )) + } + } + rustc_type_ir::ClauseKind::Projection(p) => { + Some(ExistentialPredicate::Projection( + ExistentialProjection::new_from_args( + interner, + p.def_id(), + GenericArgs::new_from_iter( + interner, + p.projection_term.args.iter().skip(1), + ), + p.term, + ), + )) + } + rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => { + lifetime = Some(outlives_predicate.1); + None + } + rustc_type_ir::ClauseKind::RegionOutlives(_) + | rustc_type_ir::ClauseKind::ConstArgHasType(_, _) + | rustc_type_ir::ClauseKind::WellFormed(_) + | rustc_type_ir::ClauseKind::ConstEvaluatable(_) + | rustc_type_ir::ClauseKind::HostEffect(_) + | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(), + }) + .transpose() + { + lowered_bounds.push(bound); } - }); + }) } let mut multiple_regular_traits = false; let mut multiple_same_projection = false; lowered_bounds.sort_unstable_by(|lhs, rhs| { use std::cmp::Ordering; - match (lhs.skip_binders(), rhs.skip_binders()) { - (WhereClause::Implemented(lhs), WhereClause::Implemented(rhs)) => { - let lhs_id = lhs.trait_id; - let lhs_is_auto = ctx - .db - .trait_signature(from_chalk_trait_id(lhs_id)) - .flags - .contains(TraitFlags::AUTO); - let rhs_id = rhs.trait_id; - let rhs_is_auto = ctx - .db - .trait_signature(from_chalk_trait_id(rhs_id)) - .flags - .contains(TraitFlags::AUTO); - - if !lhs_is_auto && !rhs_is_auto { - multiple_regular_traits = true; - } - // Note that the ordering here is important; this ensures the invariant - // mentioned above. - (lhs_is_auto, lhs_id).cmp(&(rhs_is_auto, rhs_id)) + match ((*lhs).skip_binder(), (*rhs).skip_binder()) { + (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => { + multiple_regular_traits = true; + // Order doesn't matter - we error + Ordering::Equal } - (WhereClause::Implemented(_), _) => Ordering::Less, - (_, WhereClause::Implemented(_)) => Ordering::Greater, - (WhereClause::AliasEq(lhs), WhereClause::AliasEq(rhs)) => { - match (&lhs.alias, &rhs.alias) { - (AliasTy::Projection(lhs_proj), AliasTy::Projection(rhs_proj)) => { - // We only compare the `associated_ty_id`s. We shouldn't have - // multiple bounds for an associated type in the correct Rust code, - // and if we do, we error out. - if lhs_proj.associated_ty_id == rhs_proj.associated_ty_id { - multiple_same_projection = true; - } - lhs_proj.associated_ty_id.cmp(&rhs_proj.associated_ty_id) - } - // We don't produce `AliasTy::Opaque`s yet. + ( + ExistentialPredicate::AutoTrait(lhs_id), + ExistentialPredicate::AutoTrait(rhs_id), + ) => lhs_id.0.cmp(&rhs_id.0), + (ExistentialPredicate::Trait(_), _) => Ordering::Less, + (_, ExistentialPredicate::Trait(_)) => Ordering::Greater, + (ExistentialPredicate::AutoTrait(_), _) => Ordering::Less, + (_, ExistentialPredicate::AutoTrait(_)) => Ordering::Greater, + ( + ExistentialPredicate::Projection(lhs), + ExistentialPredicate::Projection(rhs), + ) => { + let lhs_id = match lhs.def_id { + SolverDefId::TypeAliasId(id) => id, _ => unreachable!(), + }; + let rhs_id = match rhs.def_id { + SolverDefId::TypeAliasId(id) => id, + _ => unreachable!(), + }; + // We only compare the `associated_ty_id`s. We shouldn't have + // multiple bounds for an associated type in the correct Rust code, + // and if we do, we error out. + if lhs_id == rhs_id { + multiple_same_projection = true; } + lhs_id.as_id().index().cmp(&rhs_id.as_id().index()) } - // `WhereClause::{TypeOutlives, LifetimeOutlives}` have been filtered out - _ => unreachable!(), } }); @@ -697,568 +839,193 @@ impl<'db> TyLoweringContext<'db> { return None; } - lowered_bounds.first().and_then(|b| b.trait_id())?; + if !lowered_bounds.first().map_or(false, |b| { + matches!( + b.as_ref().skip_binder(), + ExistentialPredicate::Trait(_) | ExistentialPredicate::AutoTrait(_) + ) + }) { + return None; + } // As multiple occurrences of the same auto traits *are* permitted, we deduplicate the // bounds. We shouldn't have repeated elements besides auto traits at this point. lowered_bounds.dedup(); - Some(QuantifiedWhereClauses::from_iter(Interner, lowered_bounds)) + Some(BoundExistentialPredicates::new_from_iter(interner, lowered_bounds)) }); if let Some(bounds) = bounds { - let bounds = crate::make_single_type_binders(bounds); - TyKind::Dyn(DynTy { - bounds, - lifetime: match lifetime { - Some(it) => match it.bound_var(Interner) { - Some(bound_var) => bound_var - .shifted_out_to(DebruijnIndex::new(2)) - .map(|bound_var| LifetimeData::BoundVar(bound_var).intern(Interner)) - .unwrap_or(it), - None => it, - }, - None => error_lifetime(), + let region = match lifetime { + Some(it) => match it.kind() { + rustc_type_ir::RegionKind::ReBound(db, var) => Region::new_bound( + self.interner, + db.shifted_out_to_binder(DebruijnIndex::from_u32(2)), + var, + ), + _ => it, }, - }) - .intern(Interner) + None => Region::new_static(self.interner), + }; + Ty::new_dynamic(self.interner, bounds, region) } else { // FIXME: report error // (additional non-auto traits, associated type rebound, or no resolved trait) - TyKind::Error.intern(Interner) + Ty::new_error(self.interner, ErrorGuaranteed) } } - fn lower_impl_trait(&mut self, bounds: &[TypeBound], krate: Crate) -> ImplTrait { + fn lower_impl_trait( + &mut self, + def_id: SolverDefId, + bounds: &[TypeBound], + krate: Crate, + ) -> ImplTrait<'db> { + let interner = self.interner; cov_mark::hit!(lower_rpit); - let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner); - let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { + let args = GenericArgs::identity_for_item(interner, def_id); + let self_ty = Ty::new_alias( + self.interner, + rustc_type_ir::AliasTyKind::Opaque, + AliasTy::new_from_args(interner, def_id, args), + ); + let predicates = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| { let mut predicates = Vec::new(); for b in bounds { - predicates.extend(ctx.lower_type_bound(b, self_ty.clone(), false)); + predicates.extend(ctx.lower_type_bound(b, self_ty, false)); } if !ctx.unsized_types.contains(&self_ty) { - let sized_trait = - LangItem::Sized.resolve_trait(ctx.db, krate).map(to_chalk_trait_id); + let sized_trait = LangItem::Sized.resolve_trait(self.db, krate); let sized_clause = sized_trait.map(|trait_id| { - let clause = WhereClause::Implemented(TraitRef { - trait_id, - substitution: Substitution::from1(Interner, self_ty.clone()), - }); - crate::wrap_empty_binders(clause) + let trait_ref = TraitRef::new_from_args( + interner, + trait_id.into(), + GenericArgs::new_from_iter(interner, [self_ty.into()]), + ); + Clause(Predicate::new( + interner, + Binder::dummy(rustc_type_ir::PredicateKind::Clause( + rustc_type_ir::ClauseKind::Trait(TraitPredicate { + trait_ref, + polarity: rustc_type_ir::PredicatePolarity::Positive, + }), + )), + )) }); predicates.extend(sized_clause); } predicates.shrink_to_fit(); predicates }); - ImplTrait { bounds: crate::make_single_type_binders(predicates) } + ImplTrait { predicates } } - pub(crate) fn lower_lifetime(&self, lifetime: LifetimeRefId) -> Lifetime { + pub(crate) fn lower_lifetime(&mut self, lifetime: LifetimeRefId) -> Region<'db> { match self.resolver.resolve_lifetime(&self.store[lifetime]) { Some(resolution) => match resolution { - LifetimeNs::Static => static_lifetime(), - LifetimeNs::LifetimeParam(id) => match self.type_param_mode { - ParamLoweringMode::Placeholder => { - let generics = self.generics(); - let idx = generics.lifetime_idx(id).unwrap(); - LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id, idx as u32)) - } - ParamLoweringMode::Variable => { - let idx = match self.generics().lifetime_idx(id) { - None => return error_lifetime(), - Some(idx) => idx, - }; - - LifetimeData::BoundVar(BoundVar::new(self.in_binders, idx)) - } + LifetimeNs::Static => Region::new_static(self.interner), + LifetimeNs::LifetimeParam(id) => { + let idx = match self.generics().lifetime_idx(id) { + None => return Region::error(self.interner), + Some(idx) => idx, + }; + self.region_param(id, idx as u32) } - .intern(Interner), }, - None => error_lifetime(), + None => Region::error(self.interner), } } } -fn named_associated_type_shorthand_candidates( - db: &dyn HirDatabase, - // If the type parameter is defined in an impl and we're in a method, there - // might be additional where clauses to consider - def: GenericDefId, - res: TypeNs, - assoc_name: Option, - // Do NOT let `cb` touch `TraitRef` outside of `TyLoweringContext`. Its substitution contains - // free `BoundVar`s that need to be shifted and only `TyLoweringContext` knows how to do that - // properly (see `TyLoweringContext::select_associated_type()`). - mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option, -) -> Option { - let mut search = |t| { - all_super_trait_refs(db, t, |t| { - let data = t.hir_trait_id().trait_items(db); - - for (name, assoc_id) in &data.items { - if let AssocItemId::TypeAliasId(alias) = assoc_id - && let Some(result) = cb(name, &t, *alias) - { - return Some(result); - } - } - None - }) - }; - - let interner = DbInterner::new_with(db, None, None); - match res { - TypeNs::SelfType(impl_id) => { - let trait_ref = db.impl_trait(impl_id)?; - - let impl_id_as_generic_def: GenericDefId = impl_id.into(); - if impl_id_as_generic_def != def { - let subst = TyBuilder::subst_for_def(db, impl_id, None) - .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) - .build(); - let args: crate::next_solver::GenericArgs<'_> = subst.to_nextsolver(interner); - let trait_ref = trait_ref.instantiate(interner, args).to_chalk(interner); - search(trait_ref) - } else { - search(trait_ref.skip_binder().to_chalk(interner)) - } - } - TypeNs::GenericParam(param_id) => { - let predicates = db.generic_predicates_for_param(def, param_id.into(), assoc_name); - let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() { - // FIXME: how to correctly handle higher-ranked bounds here? - WhereClause::Implemented(tr) => search( - tr.clone() - .shifted_out_to(Interner, DebruijnIndex::ONE) - .expect("FIXME unexpected higher-ranked trait bound"), - ), - _ => None, - }); - if res.is_some() { - return res; - } - // Handle `Self::Type` referring to own associated type in trait definitions - if let GenericDefId::TraitId(trait_id) = param_id.parent() { - let trait_generics = generics(db, trait_id.into()); - if trait_generics[param_id.local_id()].is_trait_self() { - let trait_ref = TyBuilder::trait_ref(db, trait_id) - .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) - .build(); - return search(trait_ref); - } - } - None - } - _ => None, +pub(crate) fn lower_mutability(m: hir_def::type_ref::Mutability) -> Mutability { + match m { + hir_def::type_ref::Mutability::Shared => Mutability::Not, + hir_def::type_ref::Mutability::Mut => Mutability::Mut, } } +fn unknown_const(_ty: Ty<'_>) -> Const<'_> { + Const::new(DbInterner::conjure(), ConstKind::Error(ErrorGuaranteed)) +} + pub(crate) type Diagnostics = Option>; pub(crate) fn create_diagnostics(diagnostics: Vec) -> Diagnostics { (!diagnostics.is_empty()).then(|| ThinArc::from_header_and_iter((), diagnostics.into_iter())) } -pub(crate) fn field_types_query( - db: &dyn HirDatabase, - variant_id: VariantId, -) -> Arc>> { - field_types_with_diagnostics_query(db, variant_id).0 -} - -/// Build the type of all specific fields of a struct or enum variant. -pub(crate) fn field_types_with_diagnostics_query( - db: &dyn HirDatabase, - variant_id: VariantId, -) -> (Arc>>, Diagnostics) { - let var_data = variant_id.fields(db); - let fields = var_data.fields(); - if fields.is_empty() { - return (Arc::new(ArenaMap::default()), None); - } - - let (resolver, def): (_, GenericDefId) = match variant_id { - VariantId::StructId(it) => (it.resolver(db), it.into()), - VariantId::UnionId(it) => (it.resolver(db), it.into()), - VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()), - }; - let generics = generics(db, def); - let mut res = ArenaMap::default(); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &var_data.store, - def, - LifetimeElisionKind::AnonymousReportError, - ) - .with_type_param_mode(ParamLoweringMode::Variable); - for (field_id, field_data) in fields.iter() { - res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref))); - } - (Arc::new(res), create_diagnostics(ctx.diagnostics)) -} - -/// This query exists only to be used when resolving short-hand associated types -/// like `T::Item`. -/// -/// See the analogous query in rustc and its comment: -/// -/// This is a query mostly to handle cycles somewhat gracefully; e.g. the -/// following bounds are disallowed: `T: Foo, U: Foo`, but -/// these are fine: `T: Foo, U: Foo<()>`. -pub(crate) fn generic_predicates_for_param_query( - db: &dyn HirDatabase, - def: GenericDefId, - param_id: TypeOrConstParamId, - assoc_name: Option, -) -> GenericPredicates { - let generics = generics(db, def); - if generics.has_no_predicates() && generics.is_empty() { - return GenericPredicates(None); - } - - let resolver = def.resolver(db); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - generics.store(), - def, - LifetimeElisionKind::AnonymousReportError, - ) - .with_type_param_mode(ParamLoweringMode::Variable); - - // we have to filter out all other predicates *first*, before attempting to lower them - let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_>| match pred { - WherePredicate::ForLifetime { target, bound, .. } - | WherePredicate::TypeBound { target, bound, .. } => { - let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) }; - if invalid_target { - // FIXME(sized-hierarchy): Revisit and adjust this properly once we have implemented - // sized-hierarchy correctly. - // If this is filtered out without lowering, `?Sized` or `PointeeSized` is not gathered into - // `ctx.unsized_types` - let lower = || -> bool { - match bound { - TypeBound::Path(_, TraitBoundModifier::Maybe) => true, - TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => { - let TypeRef::Path(path) = &ctx.store[path.type_ref()] else { - return false; - }; - let Some(pointee_sized) = - LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate()) - else { - return false; - }; - // Lower the path directly with `Resolver` instead of PathLoweringContext` - // to prevent diagnostics duplications. - ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and( - |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized), - ) - } - _ => false, - } - }(); - if lower { - ctx.lower_where_predicate(pred, true).for_each(drop); - } - return false; - } - - match bound { - &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => { - // Only lower the bound if the trait could possibly define the associated - // type we're looking for. - let path = &ctx.store[path]; - - let Some(assoc_name) = &assoc_name else { return true }; - let Some(TypeNs::TraitId(tr)) = - resolver.resolve_path_in_type_ns_fully(db, path) - else { - return false; - }; - - all_super_traits(db, tr).iter().any(|tr| { - tr.trait_items(db).items.iter().any(|(name, item)| { - matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name - }) - }) - } - TypeBound::Use(_) | TypeBound::Lifetime(_) | TypeBound::Error => false, - } - } - WherePredicate::Lifetime { .. } => false, - }; - let mut predicates = Vec::new(); - for maybe_parent_generics in - std::iter::successors(Some(&generics), |generics| generics.parent_generics()) - { - ctx.store = maybe_parent_generics.store(); - for pred in maybe_parent_generics.where_predicates() { - if predicate(pred, &mut ctx) { - predicates.extend( - ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p)), - ); - } - } - } - - let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); - if !subst.is_empty(Interner) { - let explicitly_unsized_tys = ctx.unsized_types; - if let Some(implicitly_sized_predicates) = implicitly_sized_clauses( - db, - param_id.parent, - &explicitly_unsized_tys, - &subst, - &resolver, - ) { - predicates.extend( - implicitly_sized_predicates - .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))), - ); - }; - } - GenericPredicates(predicates.is_empty().not().then(|| predicates.into())) -} - -pub(crate) fn generic_predicates_for_param_cycle_result( - _db: &dyn HirDatabase, - _def: GenericDefId, - _param_id: TypeOrConstParamId, - _assoc_name: Option, -) -> GenericPredicates { - GenericPredicates(None) -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct GenericPredicates(Option]>>); - -impl ops::Deref for GenericPredicates { - type Target = [Binders]; - - fn deref(&self) -> &Self::Target { - self.0.as_deref().unwrap_or(&[]) - } -} - -/// Resolve the where clause(s) of an item with generics. -pub(crate) fn generic_predicates_query( - db: &dyn HirDatabase, - def: GenericDefId, -) -> GenericPredicates { - generic_predicates_filtered_by(db, def, |_, _| true).0 -} - -/// Resolve the where clause(s) of an item with generics, -/// with a given filter -fn generic_predicates_filtered_by( - db: &dyn HirDatabase, - def: GenericDefId, - filter: F, -) -> (GenericPredicates, Diagnostics) -where - F: Fn(&WherePredicate, GenericDefId) -> bool, -{ - let generics = generics(db, def); - if generics.has_no_predicates() && generics.is_empty() { - return (GenericPredicates(None), None); - } - - let resolver = def.resolver(db); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - generics.store(), - def, - LifetimeElisionKind::AnonymousReportError, - ) - .with_type_param_mode(ParamLoweringMode::Variable); - - let mut predicates = Vec::new(); - for maybe_parent_generics in - std::iter::successors(Some(&generics), |generics| generics.parent_generics()) - { - ctx.store = maybe_parent_generics.store(); - for pred in maybe_parent_generics.where_predicates() { - if filter(pred, maybe_parent_generics.def()) { - // We deliberately use `generics` and not `maybe_parent_generics` here. This is not a mistake! - // If we use the parent generics - predicates.extend( - ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p)), - ); - } - } - } - - if !generics.is_empty() { - let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST); - let explicitly_unsized_tys = ctx.unsized_types; - if let Some(implicitly_sized_predicates) = - implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver) - { - predicates.extend( - implicitly_sized_predicates - .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))), - ); - }; - } - - ( - GenericPredicates(predicates.is_empty().not().then(|| predicates.into())), - create_diagnostics(ctx.diagnostics), - ) -} - -/// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound. -/// Exception is Self of a trait def. -fn implicitly_sized_clauses<'db, 'a, 'subst: 'a>( +pub(crate) fn impl_trait_query<'db>( db: &'db dyn HirDatabase, - def: GenericDefId, - explicitly_unsized_tys: &'a FxHashSet, - substitution: &'subst Substitution, - resolver: &Resolver<'db>, -) -> Option> { - let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id)?; - - let trait_self_idx = trait_self_param_idx(db, def); - - Some( - substitution - .iter(Interner) - .enumerate() - .filter_map( - move |(idx, generic_arg)| { - if Some(idx) == trait_self_idx { None } else { Some(generic_arg) } - }, - ) - .filter_map(|generic_arg| generic_arg.ty(Interner)) - .filter(move |&self_ty| !explicitly_unsized_tys.contains(self_ty)) - .map(move |self_ty| { - WhereClause::Implemented(TraitRef { - trait_id: sized_trait, - substitution: Substitution::from1(Interner, self_ty.clone()), - }) - }), - ) + impl_id: ImplId, +) -> Option>> { + db.impl_trait_with_diagnostics(impl_id).map(|it| it.0) } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct GenericDefaults(Option]>>); - -impl ops::Deref for GenericDefaults { - type Target = [Binders]; - - fn deref(&self) -> &Self::Target { - self.0.as_deref().unwrap_or(&[]) - } -} - -pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaults { - db.generic_defaults_with_diagnostics(def).0 -} - -/// Resolve the default type params from generics. -/// -/// Diagnostics are only returned for this `GenericDefId` (returned defaults include parents). -pub(crate) fn generic_defaults_with_diagnostics_query( - db: &dyn HirDatabase, - def: GenericDefId, -) -> (GenericDefaults, Diagnostics) { - let generic_params = generics(db, def); - if generic_params.is_empty() { - return (GenericDefaults(None), None); - } - let resolver = def.resolver(db); - +pub(crate) fn impl_trait_with_diagnostics_query<'db>( + db: &'db dyn HirDatabase, + impl_id: ImplId, +) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)> { + let impl_data = db.impl_signature(impl_id); + let resolver = impl_id.resolver(db); let mut ctx = TyLoweringContext::new( db, &resolver, - generic_params.store(), - def, - LifetimeElisionKind::AnonymousReportError, - ) - .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed) - .with_type_param_mode(ParamLoweringMode::Variable); - let mut idx = 0; - let mut has_any_default = false; - let mut defaults = generic_params - .iter_parents_with_store() - .map(|((id, p), store)| { - ctx.store = store; - let (result, has_default) = handle_generic_param(&mut ctx, idx, id, p, &generic_params); - has_any_default |= has_default; - idx += 1; - result - }) - .collect::>(); - ctx.diagnostics.clear(); // Don't include diagnostics from the parent. - defaults.extend(generic_params.iter_self().map(|(id, p)| { - let (result, has_default) = handle_generic_param(&mut ctx, idx, id, p, &generic_params); - has_any_default |= has_default; - idx += 1; - result - })); - let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics)); - let defaults = if has_any_default { - GenericDefaults(Some(Arc::from_iter(defaults))) + &impl_data.store, + impl_id.into(), + LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }, + ); + let self_ty = db.impl_self_ty(impl_id).skip_binder(); + let target_trait = impl_data.target_trait.as_ref()?; + let trait_ref = EarlyBinder::bind(ctx.lower_trait_ref(target_trait, self_ty)?); + Some((trait_ref, create_diagnostics(ctx.diagnostics))) +} + +pub(crate) fn return_type_impl_traits<'db>( + db: &'db dyn HirDatabase, + def: hir_def::FunctionId, +) -> Option>>> { + // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe + let data = db.function_signature(def); + let resolver = def.resolver(db); + let mut ctx_ret = + TyLoweringContext::new(db, &resolver, &data.store, def.into(), LifetimeElisionKind::Infer) + .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); + if let Some(ret_type) = data.ret_type { + let _ret = ctx_ret.lower_ty(ret_type); + } + let return_type_impl_traits = + ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data }; + if return_type_impl_traits.impl_traits.is_empty() { + None } else { - GenericDefaults(None) - }; - return (defaults, diagnostics); - - fn handle_generic_param( - ctx: &mut TyLoweringContext<'_>, - idx: usize, - id: GenericParamId, - p: GenericParamDataRef<'_>, - generic_params: &Generics, - ) -> (Binders, bool) { - let binders = variable_kinds_from_iter(ctx.db, generic_params.iter_id().take(idx)); - match p { - GenericParamDataRef::TypeParamData(p) => { - let ty = p.default.as_ref().map_or_else( - || TyKind::Error.intern(Interner), - |ty| { - // Each default can only refer to previous parameters. - // Type variable default referring to parameter coming - // after it is forbidden (FIXME: report diagnostic) - fallback_bound_vars(ctx.lower_ty(*ty), idx) - }, - ); - (Binders::new(binders, ty.cast(Interner)), p.default.is_some()) - } - GenericParamDataRef::ConstParamData(p) => { - let GenericParamId::ConstParamId(id) = id else { - unreachable!("Unexpected lifetime or type argument") - }; - - let mut val = p.default.as_ref().map_or_else( - || unknown_const_as_generic(ctx.db.const_param_ty(id)), - |c| { - let param_ty = ctx.lower_ty(p.ty); - let c = ctx.lower_const(c, param_ty); - c.cast(Interner) - }, - ); - // Each default can only refer to previous parameters, see above. - val = fallback_bound_vars(val, idx); - (Binders::new(binders, val), p.default.is_some()) - } - GenericParamDataRef::LifetimeParamData(_) => { - (Binders::new(binders, error_lifetime().cast(Interner)), false) - } - } + Some(Arc::new(EarlyBinder::bind(return_type_impl_traits))) } } -pub(crate) fn generic_defaults_with_diagnostics_cycle_result( - _db: &dyn HirDatabase, - _def: GenericDefId, -) -> (GenericDefaults, Diagnostics) { - (GenericDefaults(None), None) +pub(crate) fn type_alias_impl_traits<'db>( + db: &'db dyn HirDatabase, + def: hir_def::TypeAliasId, +) -> Option>>> { + let data = db.type_alias_signature(def); + let resolver = def.resolver(db); + let mut ctx = TyLoweringContext::new( + db, + &resolver, + &data.store, + def.into(), + LifetimeElisionKind::AnonymousReportError, + ) + .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); + if let Some(type_ref) = data.ty { + let _ty = ctx.lower_ty(type_ref); + } + let type_alias_impl_traits = ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data }; + if type_alias_impl_traits.impl_traits.is_empty() { + None + } else { + Some(Arc::new(EarlyBinder::bind(type_alias_impl_traits))) + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -1293,18 +1060,203 @@ impl ValueTyDefId { } } -pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { - const_param_ty_with_diagnostics_query(db, def).0 +/// Build the declared type of an item. This depends on the namespace; e.g. for +/// `struct Foo(usize)`, we have two types: The type of the struct itself, and +/// the constructor function `(usize) -> Foo` which lives in the values +/// namespace. +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(Ty::from_builtin_type(interner, it)), + TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt( + interner, + it, + GenericArgs::identity_for_item(interner, it.into()), + )), + TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0, + } +} + +/// Build the declared type of a function. This should not need to look at the +/// function body. +fn type_for_fn<'db>(db: &'db dyn HirDatabase, def: FunctionId) -> EarlyBinder<'db, Ty<'db>> { + let interner = DbInterner::new_with(db, None, None); + EarlyBinder::bind(Ty::new_fn_def( + interner, + CallableDefId::FunctionId(def).into(), + GenericArgs::identity_for_item(interner, def.into()), + )) +} + +/// Build the declared type of a const. +fn type_for_const<'db>(db: &'db dyn HirDatabase, def: ConstId) -> EarlyBinder<'db, Ty<'db>> { + let resolver = def.resolver(db); + let data = db.const_signature(def); + let parent = def.loc(db).container; + let mut ctx = TyLoweringContext::new( + db, + &resolver, + &data.store, + def.into(), + LifetimeElisionKind::AnonymousReportError, + ); + ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent)); + EarlyBinder::bind(ctx.lower_ty(data.type_ref)) +} + +/// Build the declared type of a static. +fn type_for_static<'db>(db: &'db dyn HirDatabase, def: StaticId) -> EarlyBinder<'db, Ty<'db>> { + let resolver = def.resolver(db); + let data = db.static_signature(def); + let mut ctx = TyLoweringContext::new( + db, + &resolver, + &data.store, + def.into(), + LifetimeElisionKind::AnonymousReportError, + ); + ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner))); + EarlyBinder::bind(ctx.lower_ty(data.type_ref)) +} + +/// Build the type of a tuple struct constructor. +fn type_for_struct_constructor<'db>( + db: &'db dyn HirDatabase, + def: StructId, +) -> Option>> { + let struct_data = def.fields(db); + match struct_data.shape { + FieldsShape::Record => None, + FieldsShape::Unit => Some(type_for_adt(db, def.into())), + FieldsShape::Tuple => { + let interner = DbInterner::new_with(db, None, None); + Some(EarlyBinder::bind(Ty::new_fn_def( + interner, + CallableDefId::StructId(def).into(), + GenericArgs::identity_for_item(interner, def.into()), + ))) + } + } +} + +/// Build the type of a tuple enum variant constructor. +fn type_for_enum_variant_constructor<'db>( + db: &'db dyn HirDatabase, + def: EnumVariantId, +) -> Option>> { + let struct_data = def.fields(db); + match struct_data.shape { + FieldsShape::Record => None, + FieldsShape::Unit => Some(type_for_adt(db, def.loc(db).parent.into())), + FieldsShape::Tuple => { + let interner = DbInterner::new_with(db, None, None); + Some(EarlyBinder::bind(Ty::new_fn_def( + interner, + CallableDefId::EnumVariantId(def).into(), + GenericArgs::identity_for_item(interner, def.loc(db).parent.into()), + ))) + } + } +} + +pub(crate) fn value_ty_query<'db>( + db: &'db dyn HirDatabase, + def: ValueTyDefId, +) -> Option>> { + match def { + ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)), + ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), + ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())), + ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it), + ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)), + ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)), + } +} + +pub(crate) fn type_for_type_alias_with_diagnostics_query<'db>( + db: &'db dyn HirDatabase, + t: TypeAliasId, +) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { + let type_alias_data = db.type_alias_signature(t); + let mut diags = None; + let resolver = t.resolver(db); + let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) { + EarlyBinder::bind(Ty::new_foreign(interner, t.into())) + } else { + let mut ctx = TyLoweringContext::new( + db, + &resolver, + &type_alias_data.store, + t.into(), + LifetimeElisionKind::AnonymousReportError, + ) + .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); + let res = EarlyBinder::bind( + type_alias_data + .ty + .map(|type_ref| ctx.lower_ty(type_ref)) + .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)), + ); + diags = create_diagnostics(ctx.diagnostics); + res + }; + (inner, diags) +} + +pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>( + db: &'db dyn HirDatabase, + _adt: TypeAliasId, +) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { + (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None) +} + +pub(crate) fn impl_self_ty_query<'db>( + db: &'db dyn HirDatabase, + impl_id: ImplId, +) -> EarlyBinder<'db, Ty<'db>> { + db.impl_self_ty_with_diagnostics(impl_id).0 +} + +pub(crate) fn impl_self_ty_with_diagnostics_query<'db>( + db: &'db dyn HirDatabase, + impl_id: ImplId, +) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { + let resolver = impl_id.resolver(db); + + let impl_data = db.impl_signature(impl_id); + let mut ctx = TyLoweringContext::new( + db, + &resolver, + &impl_data.store, + impl_id.into(), + LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }, + ); + let ty = ctx.lower_ty(impl_data.self_ty); + assert!(!ty.has_escaping_bound_vars()); + (EarlyBinder::bind(ty), create_diagnostics(ctx.diagnostics)) +} + +pub(crate) fn impl_self_ty_with_diagnostics_cycle_result( + db: &dyn HirDatabase, + _impl_id: ImplId, +) -> (EarlyBinder<'_, Ty<'_>>, Diagnostics) { + (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None) +} + +pub(crate) fn const_param_ty_query<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> { + db.const_param_ty_with_diagnostics(def).0 } // returns None if def is a type arg -pub(crate) fn const_param_ty_with_diagnostics_query( - db: &dyn HirDatabase, +pub(crate) fn const_param_ty_with_diagnostics_query<'db>( + db: &'db dyn HirDatabase, def: ConstParamId, -) -> (Ty, Diagnostics) { +) -> (Ty<'db>, Diagnostics) { let (parent_data, store) = db.generic_params_and_store(def.parent()); let data = &parent_data[def.local_id()]; let resolver = def.parent().resolver(db); + let interner = DbInterner::new_with(db, Some(resolver.krate()), None); let mut ctx = TyLoweringContext::new( db, &resolver, @@ -1315,103 +1267,912 @@ pub(crate) fn const_param_ty_with_diagnostics_query( let ty = match data { TypeOrConstParamData::TypeParamData(_) => { never!(); - Ty::new(Interner, TyKind::Error) + Ty::new_error(interner, ErrorGuaranteed) } TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty), }; (ty, create_diagnostics(ctx.diagnostics)) } -pub(crate) fn const_param_ty_cycle_result( - _: &dyn HirDatabase, +pub(crate) fn const_param_ty_with_diagnostics_cycle_result<'db>( + db: &'db dyn HirDatabase, _: crate::db::HirDatabaseData, - _: ConstParamId, -) -> Ty { - TyKind::Error.intern(Interner) + def: ConstParamId, +) -> (Ty<'db>, Diagnostics) { + let resolver = def.parent().resolver(db); + let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + (Ty::new_error(interner, ErrorGuaranteed), None) } -pub(crate) fn return_type_impl_traits( - db: &dyn HirDatabase, - def: hir_def::FunctionId, -) -> Option>> { - // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe - let data = db.function_signature(def); - let resolver = def.resolver(db); - let mut ctx_ret = - TyLoweringContext::new(db, &resolver, &data.store, def.into(), LifetimeElisionKind::Infer) - .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) - .with_type_param_mode(ParamLoweringMode::Variable); - if let Some(ret_type) = data.ret_type { - let _ret = ctx_ret.lower_ty(ret_type); - } - let generics = generics(db, def.into()); - let return_type_impl_traits = - ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data }; - if return_type_impl_traits.impl_traits.is_empty() { - None - } else { - Some(Arc::new(make_binders(db, &generics, return_type_impl_traits))) - } +pub(crate) fn field_types_query<'db>( + db: &'db dyn HirDatabase, + variant_id: VariantId, +) -> Arc>>> { + db.field_types_with_diagnostics(variant_id).0 } -pub(crate) fn type_alias_impl_traits( - db: &dyn HirDatabase, - def: hir_def::TypeAliasId, -) -> Option>> { - let data = db.type_alias_signature(def); +/// Build the type of all specific fields of a struct or enum variant. +pub(crate) fn field_types_with_diagnostics_query<'db>( + db: &'db dyn HirDatabase, + variant_id: VariantId, +) -> (Arc>>>, Diagnostics) { + let var_data = variant_id.fields(db); + let fields = var_data.fields(); + if fields.is_empty() { + return (Arc::new(ArenaMap::default()), None); + } + + let (resolver, def): (_, GenericDefId) = match variant_id { + VariantId::StructId(it) => (it.resolver(db), it.into()), + VariantId::UnionId(it) => (it.resolver(db), it.into()), + VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()), + }; + let mut res = ArenaMap::default(); + let mut ctx = TyLoweringContext::new( + db, + &resolver, + &var_data.store, + def, + LifetimeElisionKind::AnonymousReportError, + ); + for (field_id, field_data) in var_data.fields().iter() { + res.insert(field_id, EarlyBinder::bind(ctx.lower_ty(field_data.type_ref))); + } + (Arc::new(res), create_diagnostics(ctx.diagnostics)) +} + +/// This query exists only to be used when resolving short-hand associated types +/// like `T::Item`. +/// +/// See the analogous query in rustc and its comment: +/// +/// This is a query mostly to handle cycles somewhat gracefully; e.g. the +/// following bounds are disallowed: `T: Foo, U: Foo`, but +/// these are fine: `T: Foo, U: Foo<()>`. +#[tracing::instrument(skip(db), ret)] +pub(crate) fn generic_predicates_for_param_query<'db>( + db: &'db dyn HirDatabase, + def: GenericDefId, + param_id: TypeOrConstParamId, + assoc_name: Option, +) -> GenericPredicates<'db> { + let generics = generics(db, def); + let interner = DbInterner::new_with(db, None, None); let resolver = def.resolver(db); let mut ctx = TyLoweringContext::new( db, &resolver, - &data.store, - def.into(), + generics.store(), + def, + LifetimeElisionKind::AnonymousReportError, + ); + + // we have to filter out all other predicates *first*, before attempting to lower them + let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_, '_>| match pred { + WherePredicate::ForLifetime { target, bound, .. } + | WherePredicate::TypeBound { target, bound, .. } => { + let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) }; + if invalid_target { + // FIXME(sized-hierarchy): Revisit and adjust this properly once we have implemented + // sized-hierarchy correctly. + // If this is filtered out without lowering, `?Sized` or `PointeeSized` is not gathered into + // `ctx.unsized_types` + let lower = || -> bool { + match bound { + TypeBound::Path(_, TraitBoundModifier::Maybe) => true, + TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => { + let TypeRef::Path(path) = &ctx.store[path.type_ref()] else { + return false; + }; + let Some(pointee_sized) = + LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate()) + else { + return false; + }; + // Lower the path directly with `Resolver` instead of PathLoweringContext` + // to prevent diagnostics duplications. + ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and( + |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized), + ) + } + _ => false, + } + }(); + if lower { + ctx.lower_where_predicate(pred, true, &generics, PredicateFilter::All) + .for_each(drop); + } + return false; + } + + match bound { + &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => { + // Only lower the bound if the trait could possibly define the associated + // type we're looking for. + let path = &ctx.store[path]; + + let Some(assoc_name) = &assoc_name else { return true }; + let Some(TypeNs::TraitId(tr)) = + resolver.resolve_path_in_type_ns_fully(db, path) + else { + return false; + }; + + rustc_type_ir::elaborate::supertrait_def_ids(interner, tr.into()).any(|tr| { + tr.0.trait_items(db).items.iter().any(|(name, item)| { + matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name + }) + }) + } + TypeBound::Use(_) | TypeBound::Lifetime(_) | TypeBound::Error => false, + } + } + WherePredicate::Lifetime { .. } => false, + }; + let mut predicates = Vec::new(); + for maybe_parent_generics in + std::iter::successors(Some(&generics), |generics| generics.parent_generics()) + { + ctx.store = maybe_parent_generics.store(); + for pred in maybe_parent_generics.where_predicates() { + if predicate(pred, &mut ctx) { + predicates.extend(ctx.lower_where_predicate( + pred, + true, + maybe_parent_generics, + PredicateFilter::All, + )); + } + } + } + + let args = GenericArgs::identity_for_item(interner, def.into()); + if !args.is_empty() { + let explicitly_unsized_tys = ctx.unsized_types; + if let Some(implicitly_sized_predicates) = + implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &args, &resolver) + { + predicates.extend(implicitly_sized_predicates); + }; + } + GenericPredicates(predicates.is_empty().not().then(|| predicates.into())) +} + +pub(crate) fn generic_predicates_for_param_cycle_result( + _db: &dyn HirDatabase, + _def: GenericDefId, + _param_id: TypeOrConstParamId, + _assoc_name: Option, +) -> GenericPredicates<'_> { + GenericPredicates(None) +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct GenericPredicates<'db>(Option]>>); + +impl<'db> GenericPredicates<'db> { + #[inline] + pub fn instantiate( + &self, + interner: DbInterner<'db>, + args: GenericArgs<'db>, + ) -> Option>> { + self.0 + .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> { + type Target = [Clause<'db>]; + + fn deref(&self) -> &Self::Target { + self.0.as_deref().unwrap_or(&[]) + } +} + +pub(crate) fn trait_environment_for_body_query( + db: &dyn HirDatabase, + def: DefWithBodyId, +) -> Arc> { + let Some(def) = def.as_generic_def_id(db) else { + let krate = def.module(db).krate(); + return TraitEnvironment::empty(krate); + }; + db.trait_environment(def) +} + +pub(crate) fn trait_environment_query<'db>( + db: &'db dyn HirDatabase, + def: GenericDefId, +) -> Arc> { + let generics = generics(db, def); + if generics.has_no_predicates() && generics.is_empty() { + return TraitEnvironment::empty(def.krate(db)); + } + + let resolver = def.resolver(db); + let mut ctx = TyLoweringContext::new( + db, + &resolver, + generics.store(), + def, + LifetimeElisionKind::AnonymousReportError, + ); + let mut traits_in_scope = Vec::new(); + let mut clauses = Vec::new(); + for maybe_parent_generics in + std::iter::successors(Some(&generics), |generics| generics.parent_generics()) + { + ctx.store = maybe_parent_generics.store(); + 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((tr.self_ty(), tr.def_id().0)); + } + clauses.push(pred); + } + } + } + + if let Some(trait_id) = def.assoc_trait_container(db) { + // add `Self: Trait` to the environment in trait + // function default implementations (and speculative code + // inside consts or type aliases) + cov_mark::hit!(trait_self_implements_self); + let trait_ref = TraitRef::identity(ctx.interner, trait_id.into()); + let clause = Clause(Predicate::new( + ctx.interner, + Binder::dummy(rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Trait( + TraitPredicate { trait_ref, polarity: rustc_type_ir::PredicatePolarity::Positive }, + ))), + )); + clauses.push(clause); + } + + let explicitly_unsized_tys = ctx.unsized_types; + + let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()); + if let Some(sized_trait) = sized_trait { + let (mut generics, mut def_id) = + (crate::next_solver::generics::generics(db, def.into()), def); + loop { + let self_idx = trait_self_param_idx(db, def_id); + for (idx, p) in generics.own_params.iter().enumerate() { + if let Some(self_idx) = self_idx + && p.index() as usize == self_idx + { + continue; + } + let GenericParamId::TypeParamId(param_id) = p.id else { + continue; + }; + let idx = idx as u32 + generics.parent_count as u32; + let param_ty = Ty::new_param(ctx.interner, param_id, idx); + if explicitly_unsized_tys.contains(¶m_ty) { + continue; + } + let trait_ref = TraitRef::new_from_args( + ctx.interner, + sized_trait.into(), + GenericArgs::new_from_iter(ctx.interner, [param_ty.into()]), + ); + let clause = Clause(Predicate::new( + ctx.interner, + Binder::dummy(rustc_type_ir::PredicateKind::Clause( + rustc_type_ir::ClauseKind::Trait(TraitPredicate { + trait_ref, + polarity: rustc_type_ir::PredicatePolarity::Positive, + }), + )), + )); + clauses.push(clause); + } + + if let Some(g) = generics.parent { + generics = crate::next_solver::generics::generics(db, g.into()); + def_id = g; + } else { + break; + } + } + } + + let clauses = rustc_type_ir::elaborate::elaborate(ctx.interner, clauses); + let clauses = Clauses::new_from_iter(ctx.interner, clauses); + let env = ParamEnv { clauses }; + + TraitEnvironment::new(resolver.krate(), None, traits_in_scope.into_boxed_slice(), env) +} + +#[derive(Copy, Clone, Debug)] +pub(crate) enum PredicateFilter { + SelfTrait, + All, +} + +/// Resolve the where clause(s) of an item with generics. +#[tracing::instrument(skip(db))] +pub(crate) fn generic_predicates_query<'db>( + db: &'db dyn HirDatabase, + def: GenericDefId, +) -> GenericPredicates<'db> { + generic_predicates_filtered_by(db, def, PredicateFilter::All, |_| true).0 +} + +pub(crate) fn generic_predicates_without_parent_query<'db>( + db: &'db dyn HirDatabase, + def: GenericDefId, +) -> GenericPredicates<'db> { + generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def).0 +} + +/// Resolve the where clause(s) of an item with generics, +/// except the ones inherited from the parent +pub(crate) fn generic_predicates_without_parent_with_diagnostics_query<'db>( + db: &'db dyn HirDatabase, + def: GenericDefId, +) -> (GenericPredicates<'db>, Diagnostics) { + generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def) +} + +/// Resolve the where clause(s) of an item with generics, +/// with a given filter +#[tracing::instrument(skip(db, filter), ret)] +pub(crate) fn generic_predicates_filtered_by<'db, F>( + db: &'db dyn HirDatabase, + def: GenericDefId, + predicate_filter: PredicateFilter, + filter: F, +) -> (GenericPredicates<'db>, Diagnostics) +where + F: Fn(GenericDefId) -> bool, +{ + let generics = generics(db, def); + let resolver = def.resolver(db); + let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let mut ctx = TyLoweringContext::new( + db, + &resolver, + generics.store(), + def, + LifetimeElisionKind::AnonymousReportError, + ); + + let mut predicates = Vec::new(); + for maybe_parent_generics in + std::iter::successors(Some(&generics), |generics| generics.parent_generics()) + { + ctx.store = maybe_parent_generics.store(); + for pred in maybe_parent_generics.where_predicates() { + tracing::debug!(?pred); + if filter(maybe_parent_generics.def()) { + predicates.extend(ctx.lower_where_predicate( + pred, + false, + maybe_parent_generics, + predicate_filter, + )); + } + } + } + + let explicitly_unsized_tys = ctx.unsized_types; + + let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()); + if let Some(sized_trait) = sized_trait { + let mut add_sized_clause = |param_idx, param_id, param_data| { + let ( + GenericParamId::TypeParamId(param_id), + GenericParamDataRef::TypeParamData(param_data), + ) = (param_id, param_data) + else { + return; + }; + + if param_data.provenance == TypeParamProvenance::TraitSelf { + return; + } + + let param_ty = Ty::new_param(interner, param_id, param_idx); + if explicitly_unsized_tys.contains(¶m_ty) { + return; + } + let trait_ref = TraitRef::new_from_args( + interner, + sized_trait.into(), + GenericArgs::new_from_iter(interner, [param_ty.into()]), + ); + let clause = Clause(Predicate::new( + interner, + Binder::dummy(rustc_type_ir::PredicateKind::Clause( + rustc_type_ir::ClauseKind::Trait(TraitPredicate { + trait_ref, + polarity: rustc_type_ir::PredicatePolarity::Positive, + }), + )), + )); + predicates.push(clause); + }; + if generics.parent_generics().is_some_and(|parent| filter(parent.def())) { + generics.iter_parent().enumerate().for_each(|(param_idx, (param_id, param_data))| { + add_sized_clause(param_idx as u32, param_id, param_data); + }); + } + if filter(def) { + let parent_params_len = generics.len_parent(); + generics.iter_self().enumerate().for_each(|(param_idx, (param_id, param_data))| { + add_sized_clause((param_idx + parent_params_len) as u32, param_id, param_data); + }); + } + } + + // FIXME: rustc gathers more predicates by recursing through resulting trait predicates. + // See https://github.com/rust-lang/rust/blob/76c5ed2847cdb26ef2822a3a165d710f6b772217/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L689-L715 + + ( + GenericPredicates(predicates.is_empty().not().then(|| predicates.into())), + create_diagnostics(ctx.diagnostics), + ) +} + +/// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound. +/// Exception is Self of a trait def. +fn implicitly_sized_clauses<'a, 'subst, 'db>( + db: &'db dyn HirDatabase, + def: GenericDefId, + explicitly_unsized_tys: &'a FxHashSet>, + args: &'subst GenericArgs<'db>, + resolver: &Resolver<'db>, +) -> Option> + Captures<'a> + Captures<'subst>> { + let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate())?; + + let trait_self_idx = trait_self_param_idx(db, def); + + Some( + args.iter() + .enumerate() + .filter_map( + move |(idx, generic_arg)| { + if Some(idx) == trait_self_idx { None } else { Some(generic_arg) } + }, + ) + .filter_map(|generic_arg| generic_arg.as_type()) + .filter(move |self_ty| !explicitly_unsized_tys.contains(self_ty)) + .map(move |self_ty| { + let trait_ref = TraitRef::new_from_args( + interner, + sized_trait.into(), + GenericArgs::new_from_iter(interner, [self_ty.into()]), + ); + Clause(Predicate::new( + interner, + Binder::dummy(rustc_type_ir::PredicateKind::Clause( + rustc_type_ir::ClauseKind::Trait(TraitPredicate { + trait_ref, + polarity: rustc_type_ir::PredicatePolarity::Positive, + }), + )), + )) + }), + ) +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct GenericDefaults<'db>(Option>>]>>); + +impl<'db> GenericDefaults<'db> { + #[inline] + pub fn get(&self, idx: usize) -> Option>> { + self.0.as_ref()?[idx] + } +} + +pub(crate) fn generic_defaults_query( + db: &dyn HirDatabase, + def: GenericDefId, +) -> GenericDefaults<'_> { + db.generic_defaults_with_diagnostics(def).0 +} + +/// Resolve the default type params from generics. +/// +/// Diagnostics are only returned for this `GenericDefId` (returned defaults include parents). +pub(crate) fn generic_defaults_with_diagnostics_query( + db: &dyn HirDatabase, + def: GenericDefId, +) -> (GenericDefaults<'_>, Diagnostics) { + let generic_params = generics(db, def); + if generic_params.is_empty() { + return (GenericDefaults(None), None); + } + let resolver = def.resolver(db); + + let mut ctx = TyLoweringContext::new( + db, + &resolver, + generic_params.store(), + def, LifetimeElisionKind::AnonymousReportError, ) - .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) - .with_type_param_mode(ParamLoweringMode::Variable); - if let Some(type_ref) = data.ty { - let _ty = ctx.lower_ty(type_ref); - } - let type_alias_impl_traits = ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data }; - if type_alias_impl_traits.impl_traits.is_empty() { - None + .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed); + let mut idx = 0; + let mut has_any_default = false; + let mut defaults = generic_params + .iter_parents_with_store() + .map(|((_id, p), store)| { + ctx.store = store; + let (result, has_default) = handle_generic_param(&mut ctx, idx, p); + has_any_default |= has_default; + idx += 1; + result + }) + .collect::>(); + ctx.diagnostics.clear(); // Don't include diagnostics from the parent. + defaults.extend(generic_params.iter_self().map(|(_id, p)| { + let (result, has_default) = handle_generic_param(&mut ctx, idx, p); + has_any_default |= has_default; + idx += 1; + result + })); + let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics)); + let defaults = if has_any_default { + GenericDefaults(Some(Arc::from_iter(defaults))) } else { - let generics = generics(db, def.into()); - Some(Arc::new(make_binders(db, &generics, type_alias_impl_traits))) + GenericDefaults(None) + }; + return (defaults, diagnostics); + + fn handle_generic_param<'db>( + ctx: &mut TyLoweringContext<'db, '_>, + idx: usize, + p: GenericParamDataRef<'_>, + ) -> (Option>>, bool) { + ctx.lowering_param_default(idx as u32); + match p { + GenericParamDataRef::TypeParamData(p) => { + let ty = p.default.map(|ty| ctx.lower_ty(ty)); + (ty.map(|ty| EarlyBinder::bind(ty.into())), p.default.is_some()) + } + GenericParamDataRef::ConstParamData(p) => { + let val = p.default.map(|c| { + let param_ty = ctx.lower_ty(p.ty); + let c = ctx.lower_const(c, param_ty); + c.into() + }); + (val.map(EarlyBinder::bind), p.default.is_some()) + } + GenericParamDataRef::LifetimeParamData(_) => (None, false), + } } } -pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mutability { - match m { - hir_def::type_ref::Mutability::Shared => Mutability::Not, - hir_def::type_ref::Mutability::Mut => Mutability::Mut, +pub(crate) fn generic_defaults_with_diagnostics_cycle_result( + _db: &dyn HirDatabase, + _def: GenericDefId, +) -> (GenericDefaults<'_>, Diagnostics) { + (GenericDefaults(None), None) +} + +/// Build the signature of a callable item (function, struct or enum variant). +pub(crate) fn callable_item_signature_query<'db>( + db: &'db dyn HirDatabase, + def: CallableDefId, +) -> EarlyBinder<'db, PolyFnSig<'db>> { + match def { + CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f), + CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s), + CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e), } } -/// Replaces any 'free' `BoundVar`s in `s` by `TyKind::Error` from the perspective of generic -/// parameter whose index is `param_index`. A `BoundVar` is free when it appears after the -/// generic parameter of `param_index`. -fn fallback_bound_vars + HasInterner>( - s: T, - param_index: usize, -) -> T { - let is_allowed = |index| (0..param_index).contains(&index); +fn fn_sig_for_fn<'db>( + db: &'db dyn HirDatabase, + def: FunctionId, +) -> EarlyBinder<'db, PolyFnSig<'db>> { + let data = db.function_signature(def); + let resolver = def.resolver(db); + let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let mut ctx_params = TyLoweringContext::new( + db, + &resolver, + &data.store, + def.into(), + LifetimeElisionKind::for_fn_params(&data), + ); + let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr)); - crate::fold_free_vars( - s, - |bound, binders| { - if bound.index_if_innermost().is_none_or(is_allowed) { - bound.shifted_in_from(binders).to_ty(Interner) - } else { - TyKind::Error.intern(Interner) - } - }, - |ty, bound, binders| { - if bound.index_if_innermost().is_none_or(is_allowed) { - bound.shifted_in_from(binders).to_const(Interner, ty) - } else { - unknown_const(ty) - } - }, - ) + let ret = match data.ret_type { + Some(ret_type) => { + let mut ctx_ret = TyLoweringContext::new( + db, + &resolver, + &data.store, + def.into(), + LifetimeElisionKind::for_fn_ret(interner), + ) + .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); + ctx_ret.lower_ty(ret_type) + } + None => Ty::new_tup(interner, &[]), + }; + + let inputs_and_output = Tys::new_from_iter(interner, params.chain(Some(ret))); + // If/when we track late bound vars, we need to switch this to not be `dummy` + EarlyBinder::bind(rustc_type_ir::Binder::dummy(FnSig { + abi: data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol), + c_variadic: data.is_varargs(), + safety: if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe }, + inputs_and_output, + })) +} + +fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> { + let interner = DbInterner::new_with(db, None, None); + let args = GenericArgs::identity_for_item(interner, adt.into()); + let ty = Ty::new_adt(interner, adt, args); + EarlyBinder::bind(ty) +} + +fn fn_sig_for_struct_constructor<'db>( + db: &'db dyn HirDatabase, + def: StructId, +) -> EarlyBinder<'db, PolyFnSig<'db>> { + let field_tys = db.field_types(def.into()); + let params = field_tys.iter().map(|(_, ty)| ty.skip_binder()); + let ret = type_for_adt(db, def.into()).skip_binder(); + + let inputs_and_output = + Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret))); + EarlyBinder::bind(Binder::dummy(FnSig { + abi: FnAbi::RustCall, + c_variadic: false, + safety: Safety::Safe, + inputs_and_output, + })) +} + +fn fn_sig_for_enum_variant_constructor<'db>( + db: &'db dyn HirDatabase, + def: EnumVariantId, +) -> EarlyBinder<'db, PolyFnSig<'db>> { + let field_tys = db.field_types(def.into()); + let params = field_tys.iter().map(|(_, ty)| ty.skip_binder()); + let parent = def.lookup(db).parent; + let ret = type_for_adt(db, parent.into()).skip_binder(); + + let inputs_and_output = + Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret))); + EarlyBinder::bind(Binder::dummy(FnSig { + abi: FnAbi::RustCall, + c_variadic: false, + safety: Safety::Safe, + inputs_and_output, + })) +} + +// FIXME(next-solver): should merge this with `explicit_item_bounds` in some way +pub(crate) fn associated_ty_item_bounds<'db>( + db: &'db dyn HirDatabase, + type_alias: TypeAliasId, +) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> { + let type_alias_data = db.type_alias_signature(type_alias); + let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db); + let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let mut ctx = TyLoweringContext::new( + db, + &resolver, + &type_alias_data.store, + type_alias.into(), + LifetimeElisionKind::AnonymousReportError, + ); + // FIXME: we should never create non-existential predicates in the first place + // For now, use an error type so we don't run into dummy binder issues + let self_ty = Ty::new_error(interner, ErrorGuaranteed); + + let mut bounds = Vec::new(); + for bound in &type_alias_data.bounds { + ctx.lower_type_bound(bound, self_ty, false).for_each(|pred| { + if let Some(bound) = pred + .kind() + .map_bound(|c| match c { + rustc_type_ir::ClauseKind::Trait(t) => { + let id = t.def_id(); + let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO); + if is_auto { + Some(ExistentialPredicate::AutoTrait(t.def_id())) + } else { + Some(ExistentialPredicate::Trait(ExistentialTraitRef::new_from_args( + interner, + t.def_id(), + GenericArgs::new_from_iter( + interner, + t.trait_ref.args.iter().skip(1), + ), + ))) + } + } + rustc_type_ir::ClauseKind::Projection(p) => Some( + ExistentialPredicate::Projection(ExistentialProjection::new_from_args( + interner, + p.def_id(), + GenericArgs::new_from_iter( + interner, + p.projection_term.args.iter().skip(1), + ), + p.term, + )), + ), + rustc_type_ir::ClauseKind::TypeOutlives(_) => None, + rustc_type_ir::ClauseKind::RegionOutlives(_) + | rustc_type_ir::ClauseKind::ConstArgHasType(_, _) + | rustc_type_ir::ClauseKind::WellFormed(_) + | rustc_type_ir::ClauseKind::ConstEvaluatable(_) + | rustc_type_ir::ClauseKind::HostEffect(_) + | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(), + }) + .transpose() + { + bounds.push(bound); + } + }); + } + + if !ctx.unsized_types.contains(&self_ty) + && let Some(sized_trait) = LangItem::Sized.resolve_trait(db, resolver.krate()) + { + let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new( + interner, + sized_trait.into(), + [] as [GenericArg<'_>; 0], + ))); + bounds.push(sized_clause); + } + + EarlyBinder::bind(BoundExistentialPredicates::new_from_iter(interner, bounds)) +} + +pub(crate) fn associated_type_by_name_including_super_traits<'db>( + db: &'db dyn HirDatabase, + trait_ref: TraitRef<'db>, + name: &Name, +) -> Option<(TraitRef<'db>, TypeAliasId)> { + let interner = DbInterner::new_with(db, None, None); + rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| { + let trait_id = t.as_ref().skip_binder().def_id.0; + let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?; + Some((t.skip_binder(), assoc_type)) + }) +} + +pub fn associated_type_shorthand_candidates( + db: &dyn HirDatabase, + def: GenericDefId, + res: TypeNs, + mut cb: impl FnMut(&Name, TypeAliasId) -> bool, +) -> Option { + let interner = DbInterner::new_with(db, None, None); + named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| { + cb(name, id).then_some(id) + }) +} + +#[tracing::instrument(skip(interner, check_alias))] +fn named_associated_type_shorthand_candidates<'db, R>( + interner: DbInterner<'db>, + // If the type parameter is defined in an impl and we're in a method, there + // might be additional where clauses to consider + def: GenericDefId, + res: TypeNs, + assoc_name: Option, + mut check_alias: impl FnMut(&Name, TraitRef<'db>, TypeAliasId) -> Option, +) -> Option { + let db = interner.db; + let mut search = |t: TraitRef<'db>| -> Option { + let mut checked_traits = FxHashSet::default(); + let mut check_trait = |trait_ref: TraitRef<'db>| { + let trait_id = trait_ref.def_id.0; + let name = &db.trait_signature(trait_id).name; + tracing::debug!(?trait_id, ?name); + if !checked_traits.insert(trait_id) { + return None; + } + let data = trait_id.trait_items(db); + + tracing::debug!(?data.items); + for (name, assoc_id) in &data.items { + if let &AssocItemId::TypeAliasId(alias) = assoc_id + && let Some(ty) = check_alias(name, trait_ref, alias) + { + return Some(ty); + } + } + None + }; + let mut stack: SmallVec<[_; 4]> = smallvec![t]; + while let Some(trait_ref) = stack.pop() { + if let Some(alias) = check_trait(trait_ref) { + return Some(alias); + } + for pred in generic_predicates_filtered_by( + db, + GenericDefId::TraitId(trait_ref.def_id.0), + PredicateFilter::SelfTrait, + // We are likely in the midst of lowering generic predicates of `def`. + // So, if we allow `pred == def` we might fall into an infinite recursion. + // Actually, we have already checked for the case `pred == def` above as we started + // with a stack including `trait_id` + |pred| pred != def && pred == GenericDefId::TraitId(trait_ref.def_id.0), + ) + .0 + .deref() + { + tracing::debug!(?pred); + let sup_trait_ref = match pred.kind().skip_binder() { + rustc_type_ir::ClauseKind::Trait(pred) => pred.trait_ref, + _ => continue, + }; + let sup_trait_ref = + EarlyBinder::bind(sup_trait_ref).instantiate(interner, trait_ref.args); + stack.push(sup_trait_ref); + } + tracing::debug!(?stack); + } + + None + }; + + match res { + TypeNs::SelfType(impl_id) => { + let trait_ref = db.impl_trait(impl_id)?; + + // FIXME(next-solver): same method in `lower` checks for impl or not + // Is that needed here? + + // we're _in_ the impl -- the binders get added back later. Correct, + // but it would be nice to make this more explicit + search(trait_ref.skip_binder()) + } + TypeNs::GenericParam(param_id) => { + // Handle `Self::Type` referring to own associated type in trait definitions + // This *must* be done first to avoid cycles with + // `generic_predicates_for_param`, but not sure that it's sufficient, + if let GenericDefId::TraitId(trait_id) = param_id.parent() { + let trait_name = &db.trait_signature(trait_id).name; + tracing::debug!(?trait_name); + let trait_generics = generics(db, trait_id.into()); + tracing::debug!(?trait_generics); + if trait_generics[param_id.local_id()].is_trait_self() { + let args = GenericArgs::identity_for_item(interner, trait_id.into()); + let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args); + tracing::debug!(?args, ?trait_ref); + return search(trait_ref); + } + } + + let predicates = + db.generic_predicates_for_param(def, param_id.into(), assoc_name.clone()); + predicates + .iter() + .find_map(|pred| match (*pred).kind().skip_binder() { + rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate), + _ => None, + }) + .and_then(|trait_predicate| { + let trait_ref = trait_predicate.trait_ref; + assert!( + !trait_ref.has_escaping_bound_vars(), + "FIXME unexpected higher-ranked trait bound" + ); + search(trait_ref) + }) + } + _ => None, + } } 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 42723dc9e1dd..9ba0da6f4964 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 @@ -1,42 +1,52 @@ //! A wrapper around [`TyLoweringContext`] specifically for lowering paths. -use chalk_ir::{BoundVar, cast::Cast, fold::Shift}; use either::Either; use hir_def::{ - GenericDefId, GenericParamId, TraitId, + GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId, expr_store::{ - ExpressionStore, - path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments}, + ExpressionStore, HygieneId, + path::{ + GenericArg as HirGenericArg, GenericArgs as HirGenericArgs, GenericArgsParentheses, + Path, PathSegment, PathSegments, + }, }, hir::generics::{ GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance, }, - resolver::TypeNs, + resolver::{ResolveValueResult, TypeNs, ValueNs}, signatures::TraitFlags, type_ref::{TypeRef, TypeRefId}, }; +use hir_expand::name::Name; +use rustc_type_ir::{ + AliasTerm, AliasTy, AliasTyKind, + inherent::{GenericArgs as _, Region as _, SliceLike, Ty as _}, +}; use smallvec::SmallVec; use stdx::never; use crate::{ - AliasEq, AliasTy, GenericArgsProhibitedReason, ImplTraitLoweringMode, IncorrectGenericsLenKind, - Interner, ParamLoweringMode, PathGenericsSource, PathLoweringDiagnostic, ProjectionTy, - QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyDefId, TyKind, WhereClause, - consteval_chalk::{unknown_const, unknown_const_as_generic}, + GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource, + PathLoweringDiagnostic, TyDefId, ValueTyDefId, + consteval::{unknown_const, unknown_const_as_generic}, db::HirDatabase, - error_lifetime, generics::{Generics, generics}, - lower::{LifetimeElisionKind, TyLoweringContext, named_associated_type_shorthand_candidates}, - next_solver::{ - DbInterner, - mapping::{ChalkToNextSolver, NextSolverToChalk}, + lower::{ + LifetimeElisionKind, PathDiagnosticCallbackData, named_associated_type_shorthand_candidates, }, - to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, - utils::associated_type_by_name_including_super_traits, + next_solver::{ + Binder, Clause, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Predicate, + ProjectionPredicate, Region, TraitRef, Ty, + }, +}; + +use super::{ + ImplTraitLoweringMode, TyLoweringContext, associated_type_by_name_including_super_traits, + const_param_ty_query, ty_query, }; type CallbackData<'a, 'db> = Either< - super::PathDiagnosticCallbackData, + PathDiagnosticCallbackData, crate::infer::diagnostics::PathDiagnosticCallbackData<'a, 'db>, >; @@ -45,12 +55,12 @@ type CallbackData<'a, 'db> = Either< pub(crate) struct PathDiagnosticCallback<'a, 'db> { pub(crate) data: CallbackData<'a, 'db>, pub(crate) callback: - fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'_>, PathLoweringDiagnostic), + fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic), } -pub(crate) struct PathLoweringContext<'a, 'b> { - ctx: &'a mut TyLoweringContext<'b>, - on_diagnostic: PathDiagnosticCallback<'a, 'b>, +pub(crate) struct PathLoweringContext<'a, 'b, 'db> { + ctx: &'a mut TyLoweringContext<'db, 'b>, + on_diagnostic: PathDiagnosticCallback<'a, 'db>, path: &'a Path, segments: PathSegments<'a>, current_segment_idx: usize, @@ -58,11 +68,11 @@ pub(crate) struct PathLoweringContext<'a, 'b> { current_or_prev_segment: PathSegment<'a>, } -impl<'a, 'b> PathLoweringContext<'a, 'b> { +impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { #[inline] pub(crate) fn new( - ctx: &'a mut TyLoweringContext<'b>, - on_diagnostic: PathDiagnosticCallback<'a, 'b>, + ctx: &'a mut TyLoweringContext<'db, 'b>, + on_diagnostic: PathDiagnosticCallback<'a, 'db>, path: &'a Path, ) -> Self { let segments = path.segments(); @@ -84,7 +94,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { } #[inline] - pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'b> { + pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'db, 'b> { self.ctx } @@ -109,11 +119,25 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { self.segments.get(self.current_segment_idx).unwrap_or(self.current_or_prev_segment); } + #[inline] + pub(crate) fn ignore_last_segment(&mut self) { + self.segments = self.segments.strip_last(); + } + + #[inline] + pub(crate) fn set_current_segment(&mut self, segment: usize) { + self.current_segment_idx = segment; + self.current_or_prev_segment = self + .segments + .get(segment) + .expect("invalid segment passed to PathLoweringContext::set_current_segment()"); + } + #[inline] fn with_lifetime_elision( &mut self, - lifetime_elision: LifetimeElisionKind, - f: impl FnOnce(&mut PathLoweringContext<'_, '_>) -> T, + lifetime_elision: LifetimeElisionKind<'db>, + f: impl FnOnce(&mut PathLoweringContext<'_, '_, 'db>) -> T, ) -> T { let old_lifetime_elision = std::mem::replace(&mut self.ctx.lifetime_elision, lifetime_elision); @@ -124,12 +148,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { pub(crate) fn lower_ty_relative_path( &mut self, - ty: Ty, + ty: Ty<'db>, // We need the original resolution to lower `Self::AssocTy` correctly res: Option, infer_args: bool, - ) -> (Ty, Option) { - match self.segments.len() - self.current_segment_idx { + ) -> (Ty<'db>, Option) { + let remaining_segments = self.segments.len() - self.current_segment_idx; + match remaining_segments { 0 => (ty, res), 1 => { // resolve unselected assoc types @@ -137,7 +162,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { } _ => { // FIXME report error (ambiguous associated type) - (TyKind::Error.intern(Interner), None) + (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None) } } } @@ -147,8 +172,11 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { &mut self, resolution: TypeNs, infer_args: bool, - ) -> (Ty, Option) { + ) -> (Ty<'db>, Option) { let remaining_segments = self.segments.skip(self.current_segment_idx + 1); + tracing::debug!(?remaining_segments); + let rem_seg_len = remaining_segments.len(); + tracing::debug!(?rem_seg_len); let ty = match resolution { TypeNs::TraitId(trait_) => { @@ -156,15 +184,17 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { 1 => { let trait_ref = self.lower_trait_ref_from_resolved_path( trait_, - TyKind::Error.intern(Interner), - infer_args, + Ty::new_error(self.ctx.interner, ErrorGuaranteed), + false, ); - + tracing::debug!(?trait_ref); self.skip_resolved_segment(); let segment = self.current_or_prev_segment; + let trait_id = trait_ref.def_id.0; let found = - trait_.trait_items(self.ctx.db).associated_type_by_name(segment.name); + trait_id.trait_items(self.ctx.db).associated_type_by_name(segment.name); + tracing::debug!(?found); match found { Some(associated_ty) => { // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent @@ -173,27 +203,30 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { // this point (`trait_ref.substitution`). let substitution = self.substs_from_path_segment( associated_ty.into(), - infer_args, + false, None, true, ); - let substitution = Substitution::from_iter( - Interner, - trait_ref.substitution.iter(Interner).chain( - substitution - .iter(Interner) - .skip(trait_ref.substitution.len(Interner)), - ), + let args = GenericArgs::new_from_iter( + self.ctx.interner, + trait_ref + .args + .iter() + .chain(substitution.iter().skip(trait_ref.args.len())), ); - TyKind::Alias(AliasTy::Projection(ProjectionTy { - associated_ty_id: to_assoc_type_id(associated_ty), - substitution, - })) - .intern(Interner) + Ty::new_alias( + self.ctx.interner, + AliasTyKind::Projection, + AliasTy::new_from_args( + self.ctx.interner, + associated_ty.into(), + args, + ), + ) } None => { // FIXME: report error (associated type not found) - TyKind::Error.intern(Interner) + Ty::new_error(self.ctx.interner, ErrorGuaranteed) } } } @@ -201,73 +234,34 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { // Trait object type without dyn; this should be handled in upstream. See // `lower_path()`. stdx::never!("unexpected fully resolved trait path"); - TyKind::Error.intern(Interner) + Ty::new_error(self.ctx.interner, ErrorGuaranteed) } _ => { // FIXME report error (ambiguous associated type) - TyKind::Error.intern(Interner) + Ty::new_error(self.ctx.interner, ErrorGuaranteed) } }; return (ty, None); } - TypeNs::GenericParam(param_id) => match self.ctx.type_param_mode { - ParamLoweringMode::Placeholder => { - let generics = self.ctx.generics(); - let idx = generics.type_or_const_param_idx(param_id.into()).unwrap(); - TyKind::Placeholder(to_placeholder_idx( - self.ctx.db, - param_id.into(), - idx as u32, - )) - } - ParamLoweringMode::Variable => { - let idx = match self.ctx.generics().type_or_const_param_idx(param_id.into()) { - None => { - never!("no matching generics"); - return (TyKind::Error.intern(Interner), None); - } - Some(idx) => idx, - }; - - TyKind::BoundVar(BoundVar::new(self.ctx.in_binders, idx)) - } - } - .intern(Interner), - TypeNs::SelfType(impl_id) => { + TypeNs::GenericParam(param_id) => { let generics = self.ctx.generics(); - - match self.ctx.type_param_mode { - ParamLoweringMode::Placeholder => { - // `def` can be either impl itself or item within, and we need impl itself - // now. - let generics = generics.parent_or_self(); - let interner = DbInterner::new_with(self.ctx.db, None, None); - let subst = generics.placeholder_subst(self.ctx.db); - let args: crate::next_solver::GenericArgs<'_> = - subst.to_nextsolver(interner); - self.ctx - .db - .impl_self_ty(impl_id) - .instantiate(interner, args) - .to_chalk(interner) + let idx = generics.type_or_const_param_idx(param_id.into()); + match idx { + None => { + never!("no matching generics"); + Ty::new_error(self.ctx.interner, ErrorGuaranteed) + } + Some(idx) => { + let (pidx, _param) = generics.iter().nth(idx).unwrap(); + assert_eq!(pidx, param_id.into()); + self.ctx.type_param(param_id, idx as u32) } - ParamLoweringMode::Variable => TyBuilder::impl_self_ty(self.ctx.db, impl_id) - .fill_with_bound_vars(self.ctx.in_binders, 0) - .build(DbInterner::conjure()) - .to_chalk(DbInterner::conjure()), } } + TypeNs::SelfType(impl_id) => self.ctx.db.impl_self_ty(impl_id).skip_binder(), TypeNs::AdtSelfType(adt) => { - let generics = generics(self.ctx.db, adt.into()); - let substs = match self.ctx.type_param_mode { - ParamLoweringMode::Placeholder => generics.placeholder_subst(self.ctx.db), - ParamLoweringMode::Variable => { - generics.bound_vars_subst(self.ctx.db, self.ctx.in_binders) - } - }; - let interner = DbInterner::conjure(); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - self.ctx.db.ty(adt.into()).instantiate(interner, args).to_chalk(interner) + let args = GenericArgs::identity_for_item(self.ctx.interner, adt.into()); + Ty::new_adt(self.ctx.interner, adt, args) } TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args), @@ -275,15 +269,19 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args), // FIXME: report error TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => { - return (TyKind::Error.intern(Interner), None); + return (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None); } }; + tracing::debug!(?ty); + self.skip_resolved_segment(); self.lower_ty_relative_path(ty, Some(resolution), infer_args) } - fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) { + /// This returns whether to keep the resolution (`true`) of throw it (`false`). + #[must_use] + fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) -> bool { let mut prohibit_generics_on_resolved = |reason| { if self.current_or_prev_segment.args_and_bindings.is_some() { let segment = self.current_segment_u32(); @@ -302,7 +300,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { prohibit_generics_on_resolved(GenericArgsProhibitedReason::TyParam) } TypeNs::AdtSelfType(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy) + prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy); + + if self.ctx.lowering_param_default.is_some() { + // Generic defaults are not allowed to refer to `Self`. + // FIXME: Emit an error. + return false; + } } TypeNs::BuiltinType(_) => { prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy) @@ -315,6 +319,8 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { | TypeNs::TypeAliasId(_) | TypeNs::TraitId(_) => {} } + + true } pub(crate) fn resolve_path_in_type_ns_fully(&mut self) -> Option { @@ -325,6 +331,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { Some(res) } + #[tracing::instrument(skip(self), ret)] pub(crate) fn resolve_path_in_type_ns(&mut self) -> Option<(TypeNs, Option)> { let (resolution, remaining_index, _, prefix_info) = self.ctx.resolver.resolve_path_in_type_ns_with_prefix_info(self.ctx.db, self.path)?; @@ -347,11 +354,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { self.current_or_prev_segment = segments.get(resolved_segment_idx).expect("should have resolved segment"); - if matches!(self.path, Path::BarePath(..)) { - // Bare paths cannot have generics, so skip them as an optimization. - return Some((resolution, remaining_index)); - } - for (i, mod_segment) in module_segments.iter().enumerate() { if mod_segment.args_and_bindings.is_some() { self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { @@ -371,90 +373,233 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { }); } - self.handle_type_ns_resolution(&resolution); + if !self.handle_type_ns_resolution(&resolution) { + return None; + } Some((resolution, remaining_index)) } - fn select_associated_type(&mut self, res: Option, infer_args: bool) -> Ty { - let Some(res) = res else { - return TyKind::Error.intern(Interner); - }; - let segment = self.current_or_prev_segment; - let ty = named_associated_type_shorthand_candidates( + pub(crate) fn resolve_path_in_value_ns( + &mut self, + hygiene_id: HygieneId, + ) -> Option { + let (res, prefix_info) = self.ctx.resolver.resolve_path_in_value_ns_with_prefix_info( self.ctx.db, - self.ctx.def, - res, - Some(segment.name.clone()), - move |name, t, associated_ty| { - if name != segment.name { - return None; - } - let generics = self.ctx.generics(); + self.path, + hygiene_id, + )?; - let parent_subst = t.substitution.clone(); - let parent_subst = match self.ctx.type_param_mode { - ParamLoweringMode::Placeholder => { - // if we're lowering to placeholders, we have to put them in now. - let s = generics.placeholder_subst(self.ctx.db); - s.apply(parent_subst, Interner) - } - ParamLoweringMode::Variable => { - // We need to shift in the bound vars, since - // `named_associated_type_shorthand_candidates` does not do that. - parent_subst.shifted_in_from(Interner, self.ctx.in_binders) + let segments = self.segments; + if segments.is_empty() || matches!(self.path, Path::LangItem(..)) { + // `segments.is_empty()` can occur with `self`. + return Some(res); + } + + let (mod_segments, enum_segment, resolved_segment_idx) = match res { + ResolveValueResult::Partial(_, unresolved_segment, _) => { + (segments.take(unresolved_segment - 1), None, unresolved_segment - 1) + } + ResolveValueResult::ValueNs(ValueNs::EnumVariantId(_), _) + if prefix_info.enum_variant => + { + (segments.strip_last_two(), segments.len().checked_sub(2), segments.len() - 1) + } + ResolveValueResult::ValueNs(..) => (segments.strip_last(), None, segments.len() - 1), + }; + + self.current_segment_idx = resolved_segment_idx; + self.current_or_prev_segment = + segments.get(resolved_segment_idx).expect("should have resolved segment"); + + for (i, mod_segment) in mod_segments.iter().enumerate() { + if mod_segment.args_and_bindings.is_some() { + self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { + segment: i as u32, + reason: GenericArgsProhibitedReason::Module, + }); + } + } + + if let Some(enum_segment) = enum_segment + && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some()) + && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some()) + { + self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { + segment: (enum_segment + 1) as u32, + reason: GenericArgsProhibitedReason::EnumVariant, + }); + } + + match &res { + ResolveValueResult::ValueNs(resolution, _) => { + let resolved_segment_idx = self.current_segment_u32(); + let resolved_segment = self.current_or_prev_segment; + + let mut prohibit_generics_on_resolved = |reason| { + if resolved_segment.args_and_bindings.is_some() { + self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { + segment: resolved_segment_idx, + reason, + }); } }; - // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent - // generic params. It's inefficient to splice the `Substitution`s, so we may want - // that method to optionally take parent `Substitution` as we already know them at - // this point (`t.substitution`). - let substs = - self.substs_from_path_segment(associated_ty.into(), infer_args, None, true); - - let substs = Substitution::from_iter( - Interner, - parent_subst - .iter(Interner) - .chain(substs.iter(Interner).skip(parent_subst.len(Interner))), - ); - - Some( - TyKind::Alias(AliasTy::Projection(ProjectionTy { - associated_ty_id: to_assoc_type_id(associated_ty), - substitution: substs, - })) - .intern(Interner), - ) - }, - ); - - ty.unwrap_or_else(|| TyKind::Error.intern(Interner)) + match resolution { + ValueNs::ImplSelf(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy); + } + // FIXME: rustc generates E0107 (incorrect number of generic arguments) and not + // E0109 (generic arguments provided for a type that doesn't accept them) for + // consts and statics, presumably as a defense against future in which consts + // and statics can be generic, or just because it was easier for rustc implementors. + // That means we'll show the wrong error code. Because of us it's easier to do it + // this way :) + ValueNs::GenericParam(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const) + } + ValueNs::StaticId(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static) + } + ValueNs::LocalBinding(_) => { + prohibit_generics_on_resolved(GenericArgsProhibitedReason::LocalVariable) + } + ValueNs::FunctionId(_) + | ValueNs::StructId(_) + | ValueNs::EnumVariantId(_) + | ValueNs::ConstId(_) => {} + } + } + ResolveValueResult::Partial(resolution, _, _) => { + if !self.handle_type_ns_resolution(resolution) { + return None; + } + } + }; + Some(res) } - fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty { - let interner = DbInterner::conjure(); + #[tracing::instrument(skip(self), ret)] + fn select_associated_type(&mut self, res: Option, infer_args: bool) -> Ty<'db> { + let interner = self.ctx.interner; + let Some(res) = res else { + return Ty::new_error(self.ctx.interner, ErrorGuaranteed); + }; + let def = self.ctx.def; + let segment = self.current_or_prev_segment; + let assoc_name = segment.name; + let check_alias = |name: &Name, t: TraitRef<'db>, associated_ty: TypeAliasId| { + if name != assoc_name { + return None; + } + + // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent + // generic params. It's inefficient to splice the `Substitution`s, so we may want + // that method to optionally take parent `Substitution` as we already know them at + // this point (`t.substitution`). + let substs = + self.substs_from_path_segment(associated_ty.into(), infer_args, None, true); + + let substs = GenericArgs::new_from_iter( + interner, + t.args.iter().chain(substs.iter().skip(t.args.len())), + ); + + Some(Ty::new_alias( + interner, + AliasTyKind::Projection, + AliasTy::new(interner, associated_ty.into(), substs), + )) + }; + named_associated_type_shorthand_candidates( + interner, + def, + res, + Some(assoc_name.clone()), + check_alias, + ) + .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)) + } + + fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> { let generic_def = match typeable { - TyDefId::BuiltinType(builtin) => { - return crate::next_solver::Ty::from_builtin_type(interner, builtin) - .to_chalk(interner); + TyDefId::BuiltinType(builtinty) => { + return Ty::from_builtin_type(self.ctx.interner, builtinty); } TyDefId::AdtId(it) => it.into(), TyDefId::TypeAliasId(it) => it.into(), }; - let substs = self.substs_from_path_segment(generic_def, infer_args, None, false); - let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner); - self.ctx.db.ty(typeable).instantiate(interner, args).to_chalk(interner) + let args = self.substs_from_path_segment(generic_def, infer_args, None, false); + let ty = ty_query(self.ctx.db, typeable); + ty.instantiate(self.ctx.interner, args) + } + + /// Collect generic arguments from a path into a `Substs`. See also + /// `create_substs_for_ast_path` and `def_to_ty` in rustc. + pub(crate) fn substs_from_path( + &mut self, + // Note that we don't call `db.value_type(resolved)` here, + // `ValueTyDefId` is just a convenient way to pass generics and + // special-case enum variants + resolved: ValueTyDefId, + infer_args: bool, + lowering_assoc_type_generics: bool, + ) -> GenericArgs<'db> { + let interner = self.ctx.interner; + let prev_current_segment_idx = self.current_segment_idx; + let prev_current_segment = self.current_or_prev_segment; + + let generic_def = match resolved { + ValueTyDefId::FunctionId(it) => it.into(), + ValueTyDefId::StructId(it) => it.into(), + ValueTyDefId::UnionId(it) => it.into(), + ValueTyDefId::ConstId(it) => it.into(), + ValueTyDefId::StaticId(_) => { + return GenericArgs::new_from_iter(interner, []); + } + ValueTyDefId::EnumVariantId(var) => { + // the generic args for an enum variant may be either specified + // on the segment referring to the enum, or on the segment + // referring to the variant. So `Option::::None` and + // `Option::None::` are both allowed (though the former is + // FIXME: This isn't strictly correct, enum variants may be used not through the enum + // (via `use Enum::Variant`). The resolver returns whether they were, but we don't have its result + // available here. The worst that can happen is that we will show some confusing diagnostics to the user, + // if generics exist on the module and they don't match with the variant. + // preferred). See also `def_ids_for_path_segments` in rustc. + // + // `wrapping_sub(1)` will return a number which `get` will return None for if current_segment_idx<2. + // This simplifies the code a bit. + let penultimate_idx = self.current_segment_idx.wrapping_sub(1); + let penultimate = self.segments.get(penultimate_idx); + if let Some(penultimate) = penultimate + && self.current_or_prev_segment.args_and_bindings.is_none() + && penultimate.args_and_bindings.is_some() + { + self.current_segment_idx = penultimate_idx; + self.current_or_prev_segment = penultimate; + } + var.lookup(self.ctx.db).parent.into() + } + }; + let result = self.substs_from_path_segment( + generic_def, + infer_args, + None, + lowering_assoc_type_generics, + ); + self.current_segment_idx = prev_current_segment_idx; + self.current_or_prev_segment = prev_current_segment; + result } pub(crate) fn substs_from_path_segment( &mut self, def: GenericDefId, infer_args: bool, - explicit_self_ty: Option, + explicit_self_ty: Option>, lowering_assoc_type_generics: bool, - ) -> Substitution { + ) -> GenericArgs<'db> { let old_lifetime_elision = self.ctx.lifetime_elision.clone(); if let Some(args) = self.current_or_prev_segment.args_and_bindings @@ -481,7 +626,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment }, ); - return TyBuilder::unknown_subst(self.ctx.db, def); + return unknown_subst(self.ctx.interner, def); } // `Fn()`-style generics are treated like functions for the purpose of lifetime elision. @@ -504,20 +649,20 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { pub(super) fn substs_from_args_and_bindings( &mut self, - args_and_bindings: Option<&GenericArgs>, + args_and_bindings: Option<&HirGenericArgs>, def: GenericDefId, infer_args: bool, - explicit_self_ty: Option, + explicit_self_ty: Option>, generics_source: PathGenericsSource, lowering_assoc_type_generics: bool, - lifetime_elision: LifetimeElisionKind, - ) -> Substitution { - struct LowererCtx<'a, 'b, 'c> { - ctx: &'a mut PathLoweringContext<'b, 'c>, + lifetime_elision: LifetimeElisionKind<'db>, + ) -> GenericArgs<'db> { + struct LowererCtx<'a, 'b, 'c, 'db> { + ctx: &'a mut PathLoweringContext<'b, 'c, 'db>, generics_source: PathGenericsSource, } - impl GenericArgsLowerer for LowererCtx<'_, '_, '_> { + impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, '_, 'db> { fn report_len_mismatch( &mut self, def: GenericDefId, @@ -552,23 +697,24 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { &mut self, param_id: GenericParamId, param: GenericParamDataRef<'_>, - arg: &GenericArg, - ) -> crate::GenericArg { - match (param, arg) { - (GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => { - self.ctx.ctx.lower_lifetime(*lifetime).cast(Interner) + arg: &HirGenericArg, + ) -> GenericArg<'db> { + match (param, *arg) { + ( + GenericParamDataRef::LifetimeParamData(_), + HirGenericArg::Lifetime(lifetime), + ) => self.ctx.ctx.lower_lifetime(lifetime).into(), + (GenericParamDataRef::TypeParamData(_), HirGenericArg::Type(type_ref)) => { + self.ctx.ctx.lower_ty(type_ref).into() } - (GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => { - self.ctx.ctx.lower_ty(*type_ref).cast(Interner) - } - (GenericParamDataRef::ConstParamData(_), GenericArg::Const(konst)) => { + (GenericParamDataRef::ConstParamData(_), HirGenericArg::Const(konst)) => { let GenericParamId::ConstParamId(const_id) = param_id else { unreachable!("non-const param ID for const param"); }; self.ctx .ctx - .lower_const(konst, self.ctx.ctx.db.const_param_ty(const_id)) - .cast(Interner) + .lower_const(konst, const_param_ty_query(self.ctx.ctx.db, const_id)) + .into() } _ => unreachable!("unmatching param kinds were passed to `provided_kind()`"), } @@ -576,9 +722,9 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { fn provided_type_like_const( &mut self, - const_ty: Ty, + const_ty: Ty<'db>, arg: TypeLikeConst<'_>, - ) -> crate::Const { + ) -> Const<'db> { match arg { TypeLikeConst::Path(path) => self.ctx.ctx.lower_path_as_const(path, const_ty), TypeLikeConst::Infer => unknown_const(const_ty), @@ -591,18 +737,19 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { param_id: GenericParamId, param: GenericParamDataRef<'_>, infer_args: bool, - preceding_args: &[crate::GenericArg], - ) -> crate::GenericArg { - let default = || { - self.ctx - .ctx - .db - .generic_defaults(def) - .get(preceding_args.len()) - .map(|default| default.clone().substitute(Interner, preceding_args)) - }; + preceding_args: &[GenericArg<'db>], + ) -> GenericArg<'db> { + let default = + || { + self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map( + |default| default.instantiate(self.ctx.ctx.interner, preceding_args), + ) + }; match param { - GenericParamDataRef::LifetimeParamData(_) => error_lifetime().cast(Interner), + GenericParamDataRef::LifetimeParamData(_) => { + Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed)) + .into() + } GenericParamDataRef::TypeParamData(param) => { if !infer_args && param.default.is_some() @@ -610,7 +757,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { { return default; } - TyKind::Error.intern(Interner).cast(Interner) + Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into() } GenericParamDataRef::ConstParamData(param) => { if !infer_args @@ -622,19 +769,23 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { let GenericParamId::ConstParamId(const_id) = param_id else { unreachable!("non-const param ID for const param"); }; - unknown_const_as_generic(self.ctx.ctx.db.const_param_ty(const_id)) - .cast(Interner) + unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id)) } } } - fn parent_arg(&mut self, param_id: GenericParamId) -> crate::GenericArg { + fn parent_arg(&mut self, param_id: GenericParamId) -> GenericArg<'db> { match param_id { - GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner), - GenericParamId::ConstParamId(const_id) => { - unknown_const_as_generic(self.ctx.ctx.db.const_param_ty(const_id)) + GenericParamId::TypeParamId(_) => { + Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into() + } + GenericParamId::ConstParamId(const_id) => { + unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id)) + } + GenericParamId::LifetimeParamId(_) => { + Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed)) + .into() } - GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner), } } @@ -652,6 +803,14 @@ 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, @@ -677,38 +836,39 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { pub(crate) fn lower_trait_ref_from_resolved_path( &mut self, resolved: TraitId, - explicit_self_ty: Ty, + explicit_self_ty: Ty<'db>, infer_args: bool, - ) -> TraitRef { - let substs = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args); - TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } + ) -> TraitRef<'db> { + let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args); + TraitRef::new_from_args(self.ctx.interner, resolved.into(), args) } fn trait_ref_substs_from_path( &mut self, resolved: TraitId, - explicit_self_ty: Ty, + explicit_self_ty: Ty<'db>, infer_args: bool, - ) -> Substitution { + ) -> GenericArgs<'db> { self.substs_from_path_segment(resolved.into(), infer_args, Some(explicit_self_ty), false) } pub(super) fn assoc_type_bindings_from_type_bound<'c>( mut self, - trait_ref: TraitRef, - ) -> Option + use<'a, 'b, 'c>> { + trait_ref: TraitRef<'db>, + ) -> Option> + use<'a, 'b, 'c, 'db>> { + let interner = self.ctx.interner; self.current_or_prev_segment.args_and_bindings.map(|args_and_bindings| { args_and_bindings.bindings.iter().enumerate().flat_map(move |(binding_idx, binding)| { let found = associated_type_by_name_including_super_traits( self.ctx.db, - trait_ref.clone(), + trait_ref, &binding.name, ); let (super_trait_ref, associated_ty) = match found { None => return SmallVec::new(), Some(t) => t, }; - let substitution = + let args = self.with_lifetime_elision(LifetimeElisionKind::AnonymousReportError, |this| { // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent // generic params. It's inefficient to splice the `Substitution`s, so we may want @@ -718,7 +878,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { binding.args.as_ref(), associated_ty.into(), false, // this is not relevant - Some(super_trait_ref.self_type_parameter(Interner)), + Some(super_trait_ref.self_ty()), PathGenericsSource::AssocType { segment: this.current_segment_u32(), assoc_type: binding_idx as u32, @@ -727,27 +887,20 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { this.ctx.lifetime_elision.clone(), ) }); - let substitution = Substitution::from_iter( - Interner, - super_trait_ref.substitution.iter(Interner).chain( - substitution - .iter(Interner) - .skip(super_trait_ref.substitution.len(Interner)), - ), + let args = GenericArgs::new_from_iter( + interner, + super_trait_ref.args.iter().chain(args.iter().skip(super_trait_ref.args.len())), ); - let projection_ty = ProjectionTy { - associated_ty_id: to_assoc_type_id(associated_ty), - substitution, - }; + let projection_term = + AliasTerm::new_from_args(interner, associated_ty.into(), args); let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity( binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), ); - if let Some(type_ref) = binding.type_ref { let lifetime_elision = if args_and_bindings.parenthesized == GenericArgsParentheses::ParenSugar { // `Fn()`-style generics are elided like functions. This is `Output` (we lower to it in hir-def). - LifetimeElisionKind::for_fn_ret() + LifetimeElisionKind::for_fn_ret(self.ctx.interner) } else { self.ctx.lifetime_elision.clone() }; @@ -759,31 +912,33 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque, ) => { let ty = this.ctx.lower_ty(type_ref); - let alias_eq = AliasEq { - alias: AliasTy::Projection(projection_ty.clone()), - ty, - }; - predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq( - alias_eq, - ))); + let pred = Clause(Predicate::new( + interner, + Binder::dummy(rustc_type_ir::PredicateKind::Clause( + rustc_type_ir::ClauseKind::Projection( + ProjectionPredicate { + projection_term, + term: ty.into(), + }, + ), + )), + )); + predicates.push(pred); } } - }); + }) + } + for bound in binding.bounds.iter() { + predicates.extend(self.ctx.lower_type_bound( + bound, + Ty::new_alias( + self.ctx.interner, + AliasTyKind::Projection, + AliasTy::new_from_args(self.ctx.interner, associated_ty.into(), args), + ), + false, + )); } - - self.with_lifetime_elision(LifetimeElisionKind::AnonymousReportError, |this| { - for bound in binding.bounds.iter() { - predicates.extend( - this.ctx.lower_type_bound( - bound, - TyKind::Alias(AliasTy::Projection(projection_ty.clone())) - .intern(Interner), - false, - ), - ); - } - }); - predicates }) }) @@ -796,7 +951,7 @@ pub(crate) enum TypeLikeConst<'a> { Path(&'a Path), } -pub(crate) trait GenericArgsLowerer { +pub(crate) trait GenericArgsLowerer<'db> { fn report_elided_lifetimes_in_path( &mut self, def: GenericDefId, @@ -804,6 +959,8 @@ 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( @@ -820,10 +977,11 @@ pub(crate) trait GenericArgsLowerer { &mut self, param_id: GenericParamId, param: GenericParamDataRef<'_>, - arg: &GenericArg, - ) -> crate::GenericArg; + arg: &HirGenericArg, + ) -> GenericArg<'db>; - fn provided_type_like_const(&mut self, const_ty: Ty, arg: TypeLikeConst<'_>) -> crate::Const; + fn provided_type_like_const(&mut self, const_ty: Ty<'db>, arg: TypeLikeConst<'_>) + -> Const<'db>; fn inferred_kind( &mut self, @@ -831,21 +989,21 @@ pub(crate) trait GenericArgsLowerer { param_id: GenericParamId, param: GenericParamDataRef<'_>, infer_args: bool, - preceding_args: &[crate::GenericArg], - ) -> crate::GenericArg; + preceding_args: &[GenericArg<'db>], + ) -> GenericArg<'db>; - fn parent_arg(&mut self, param_id: GenericParamId) -> crate::GenericArg; + fn parent_arg(&mut self, param_id: GenericParamId) -> GenericArg<'db>; } /// Returns true if there was an error. -fn check_generic_args_len( - args_and_bindings: Option<&GenericArgs>, +fn check_generic_args_len<'db>( + args_and_bindings: Option<&HirGenericArgs>, def: GenericDefId, def_generics: &Generics, infer_args: bool, - lifetime_elision: &LifetimeElisionKind, + lifetime_elision: &LifetimeElisionKind<'db>, lowering_assoc_type_generics: bool, - ctx: &mut impl GenericArgsLowerer, + ctx: &mut impl GenericArgsLowerer<'db>, ) -> bool { let mut had_error = false; @@ -854,8 +1012,10 @@ fn check_generic_args_len( let args_no_self = &args_and_bindings.args[usize::from(args_and_bindings.has_self_type)..]; for arg in args_no_self { match arg { - GenericArg::Lifetime(_) => provided_lifetimes_count += 1, - GenericArg::Type(_) | GenericArg::Const(_) => provided_types_and_consts_count += 1, + HirGenericArg::Lifetime(_) => provided_lifetimes_count += 1, + HirGenericArg::Type(_) | HirGenericArg::Const(_) => { + provided_types_and_consts_count += 1 + } } } } @@ -876,6 +1036,13 @@ 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); } @@ -922,17 +1089,21 @@ fn check_generic_args_len( had_error } -pub(crate) fn substs_from_args_and_bindings( - db: &dyn HirDatabase, +pub(crate) fn substs_from_args_and_bindings<'db>( + db: &'db dyn HirDatabase, store: &ExpressionStore, - args_and_bindings: Option<&GenericArgs>, + args_and_bindings: Option<&HirGenericArgs>, def: GenericDefId, mut infer_args: bool, - lifetime_elision: LifetimeElisionKind, + lifetime_elision: LifetimeElisionKind<'db>, lowering_assoc_type_generics: bool, - explicit_self_ty: Option, - ctx: &mut impl GenericArgsLowerer, -) -> Substitution { + explicit_self_ty: Option>, + ctx: &mut impl GenericArgsLowerer<'db>, +) -> GenericArgs<'db> { + let interner = DbInterner::new_with(db, None, None); + + tracing::debug!(?args_and_bindings); + // Order is // - Parent parameters // - Optional Self parameter @@ -943,7 +1114,7 @@ pub(crate) fn substs_from_args_and_bindings( // We do not allow inference if there are specified args, i.e. we do not allow partial inference. let has_non_lifetime_args = - args_slice.iter().any(|arg| !matches!(arg, GenericArg::Lifetime(_))); + args_slice.iter().any(|arg| !matches!(arg, HirGenericArg::Lifetime(_))); infer_args &= !has_non_lifetime_args; let had_count_error = check_generic_args_len( @@ -984,7 +1155,7 @@ pub(crate) fn substs_from_args_and_bindings( let (_, self_ty) = args.next().expect("has_self_type=true, should have Self type"); ctx.provided_kind(self_param_id, self_param, self_ty) } else { - explicit_self_ty.map(|it| it.cast(Interner)).unwrap_or_else(|| { + explicit_self_ty.map(|it| it.into()).unwrap_or_else(|| { ctx.inferred_kind(def, self_param_id, self_param, infer_args, &substs) }) }; @@ -999,7 +1170,7 @@ pub(crate) fn substs_from_args_and_bindings( // input. We try to handle both sensibly. match (args.peek(), params.peek()) { (Some(&(arg_idx, arg)), Some(&(param_id, param))) => match (arg, param) { - (GenericArg::Type(_), GenericParamDataRef::TypeParamData(type_param)) + (HirGenericArg::Type(_), GenericParamDataRef::TypeParamData(type_param)) if type_param.provenance == TypeParamProvenance::ArgumentImplTrait => { // Do not allow specifying `impl Trait` explicitly. We already err at that, but if we won't handle it here @@ -1007,15 +1178,15 @@ pub(crate) fn substs_from_args_and_bindings( substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs)); params.next(); } - (GenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_)) - | (GenericArg::Type(_), GenericParamDataRef::TypeParamData(_)) - | (GenericArg::Const(_), GenericParamDataRef::ConstParamData(_)) => { + (HirGenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_)) + | (HirGenericArg::Type(_), GenericParamDataRef::TypeParamData(_)) + | (HirGenericArg::Const(_), GenericParamDataRef::ConstParamData(_)) => { substs.push(ctx.provided_kind(param_id, param, arg)); args.next(); params.next(); } ( - GenericArg::Type(_) | GenericArg::Const(_), + HirGenericArg::Type(_) | HirGenericArg::Const(_), GenericParamDataRef::LifetimeParamData(_), ) => { // We expected a lifetime argument, but got a type or const @@ -1024,13 +1195,13 @@ pub(crate) fn substs_from_args_and_bindings( params.next(); force_infer_lt = Some((arg_idx as u32, param_id)); } - (GenericArg::Type(type_ref), GenericParamDataRef::ConstParamData(_)) => { + (HirGenericArg::Type(type_ref), GenericParamDataRef::ConstParamData(_)) => { if let Some(konst) = type_looks_like_const(store, *type_ref) { let GenericParamId::ConstParamId(param_id) = param_id else { panic!("unmatching param kinds"); }; - let const_ty = db.const_param_ty(param_id); - substs.push(ctx.provided_type_like_const(const_ty, konst).cast(Interner)); + let const_ty = const_param_ty_query(db, param_id); + substs.push(ctx.provided_type_like_const(const_ty, konst).into()); args.next(); params.next(); } else { @@ -1069,7 +1240,7 @@ pub(crate) fn substs_from_args_and_bindings( // after a type or const). We want to throw an error in this case. if !had_count_error { assert!( - matches!(arg, GenericArg::Lifetime(_)), + matches!(arg, HirGenericArg::Lifetime(_)), "the only possible situation here is incorrect lifetime order" ); let (provided_arg_idx, param_id) = @@ -1084,12 +1255,16 @@ 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::AnonymousCreateParameter { report_in_path: true } + LifetimeElisionKind::ElisionFailure + | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true } | LifetimeElisionKind::AnonymousReportError => { assert!(had_count_error); ctx.inferred_kind(def, param_id, param, infer_args, &substs) } - LifetimeElisionKind::Elided(lifetime) => lifetime.clone().cast(Interner), + LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => { + Region::new_static(interner).into() + } + LifetimeElisionKind::Elided(lifetime) => (*lifetime).into(), LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false } | LifetimeElisionKind::Infer => { // FIXME: With `AnonymousCreateParameter`, we need to create a new lifetime parameter here @@ -1108,7 +1283,7 @@ pub(crate) fn substs_from_args_and_bindings( } } - Substitution::from_iter(Interner, substs) + GenericArgs::new_from_iter(interner, substs) } fn type_looks_like_const( @@ -1127,3 +1302,17 @@ fn type_looks_like_const( _ => None, } } + +fn unknown_subst<'db>(interner: DbInterner<'db>, def: impl Into) -> GenericArgs<'db> { + let params = generics(interner.db(), def.into()); + GenericArgs::new_from_iter( + interner, + params.iter_id().map(|id| match id { + GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(), + GenericParamId::ConstParamId(id) => { + unknown_const_as_generic(const_param_ty_query(interner.db(), id)) + } + GenericParamId::LifetimeParamId(_) => Region::error(interner).into(), + }), + ) +} 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 deleted file mode 100644 index 76ee1a4f2d2b..000000000000 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver.rs +++ /dev/null @@ -1,2138 +0,0 @@ -//! Methods for lowering the HIR to types. There are two main cases here: -//! -//! - Lowering a type reference like `&usize` or `Option` to a -//! type: The entry point for this is `TyLoweringContext::lower_ty`. -//! - Building the type for an item: This happens through the `ty` query. -//! -//! This usually involves resolving names, collecting generic arguments etc. -pub(crate) mod path; - -use std::{ - cell::OnceCell, - iter, mem, - ops::{self, Deref, Not as _}, -}; - -use base_db::Crate; -use either::Either; -use hir_def::{ - AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId, - FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId, - LocalFieldId, Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, TypeParamId, - VariantId, - expr_store::{ExpressionStore, HygieneId, path::Path}, - hir::generics::{ - GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate, - }, - item_tree::FieldsShape, - lang_item::LangItem, - resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs}, - signatures::{FunctionSignature, TraitFlags, TypeAliasFlags}, - type_ref::{ - ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier, - TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId, - }, -}; -use hir_expand::name::Name; -use la_arena::{Arena, ArenaMap, Idx}; -use path::{PathDiagnosticCallback, PathLoweringContext}; -use rustc_ast_ir::Mutability; -use rustc_hash::FxHashSet; -use rustc_pattern_analysis::Captures; -use rustc_type_ir::{ - AliasTyKind, ConstKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection, - ExistentialTraitRef, FnSig, OutlivesPredicate, - TyKind::{self}, - TypeVisitableExt, - inherent::{GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, Ty as _}, -}; -use salsa::plumbing::AsId; -use smallvec::{SmallVec, smallvec}; -use stdx::never; -use triomphe::Arc; - -use crate::{ - FnAbi, ImplTraitId, TraitEnvironment, TyDefId, TyLoweringDiagnostic, TyLoweringDiagnosticKind, - ValueTyDefId, - consteval::intern_const_ref, - db::HirDatabase, - generics::{Generics, generics, trait_self_param_idx}, - lower::{Diagnostics, PathDiagnosticCallbackData, create_diagnostics}, - next_solver::{ - AliasTy, Binder, BoundExistentialPredicates, Clause, Clauses, Const, DbInterner, - EarlyBinder, EarlyParamRegion, ErrorGuaranteed, GenericArg, GenericArgs, ParamConst, - ParamEnv, PolyFnSig, Predicate, Region, SolverDefId, TraitPredicate, TraitRef, Ty, Tys, - UnevaluatedConst, abi::Safety, - }, -}; - -#[derive(PartialEq, Eq, Debug, Hash)] -pub struct ImplTraits<'db> { - pub(crate) impl_traits: Arena>, -} - -#[derive(PartialEq, Eq, Debug, Hash)] -pub struct ImplTrait<'db> { - pub(crate) predicates: Vec>, -} - -pub type ImplTraitIdx<'db> = Idx>; - -#[derive(Debug, Default)] -struct ImplTraitLoweringState<'db> { - /// When turning `impl Trait` into opaque types, we have to collect the - /// bounds at the same time to get the IDs correct (without becoming too - /// complicated). - mode: ImplTraitLoweringMode, - // This is structured as a struct with fields and not as an enum because it helps with the borrow checker. - opaque_type_data: Arena>, -} - -impl<'db> ImplTraitLoweringState<'db> { - fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState<'db> { - Self { mode, opaque_type_data: Arena::new() } - } -} - -#[derive(Debug, Clone)] -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: - /// ```compile_fail - /// struct Foo<'a> { x: &'a () } - /// async fn foo(x: Foo) {} - /// ``` - /// - /// Note: the error should not trigger when the elided lifetime is in a pattern or - /// expression-position path: - /// ``` - /// struct Foo<'a> { x: &'a () } - /// async fn foo(Foo { x: _ }: Foo<'_>) {} - /// ``` - AnonymousCreateParameter { report_in_path: bool }, - - /// Replace all anonymous lifetimes by provided lifetime. - Elided(Region<'db>), - - /// Give a hard error when either `&` or `'_` is written. Used to - /// rule out things like `where T: Foo<'_>`. Does not imply an - /// 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, -} - -impl<'db> LifetimeElisionKind<'db> { - #[inline] - pub(crate) fn for_const( - interner: DbInterner<'db>, - const_parent: ItemContainerId, - ) -> LifetimeElisionKind<'db> { - match const_parent { - ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => { - LifetimeElisionKind::Elided(Region::new_static(interner)) - } - ItemContainerId::ImplId(_) => { - LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true } - } - ItemContainerId::TraitId(_) => { - LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false } - } - } - } - - #[inline] - pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind<'db> { - LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() } - } - - #[inline] - pub(crate) fn for_fn_ret(interner: DbInterner<'db>) -> LifetimeElisionKind<'db> { - // FIXME: We should use the elided lifetime here, or `ElisionFailure`. - LifetimeElisionKind::Elided(Region::error(interner)) - } -} - -#[derive(Debug)] -pub struct TyLoweringContext<'db, 'a> { - pub db: &'db dyn HirDatabase, - interner: DbInterner<'db>, - resolver: &'a Resolver<'db>, - store: &'a ExpressionStore, - def: GenericDefId, - generics: OnceCell, - in_binders: DebruijnIndex, - impl_trait_mode: ImplTraitLoweringState<'db>, - /// Tracks types with explicit `?Sized` bounds. - pub(crate) unsized_types: FxHashSet>, - pub(crate) diagnostics: Vec, - lifetime_elision: LifetimeElisionKind<'db>, - /// When lowering the defaults for generic params, this contains the index of the currently lowered param. - /// We disallow referring to later params, or to ADT's `Self`. - lowering_param_default: Option, -} - -impl<'db, 'a> TyLoweringContext<'db, 'a> { - pub fn new( - db: &'db dyn HirDatabase, - resolver: &'a Resolver<'db>, - store: &'a ExpressionStore, - def: GenericDefId, - lifetime_elision: LifetimeElisionKind<'db>, - ) -> Self { - let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed); - let in_binders = DebruijnIndex::ZERO; - Self { - db, - interner: DbInterner::new_with(db, Some(resolver.krate()), None), - resolver, - def, - generics: Default::default(), - store, - in_binders, - impl_trait_mode, - unsized_types: FxHashSet::default(), - diagnostics: Vec::new(), - lifetime_elision, - lowering_param_default: None, - } - } - - pub(crate) fn set_lifetime_elision(&mut self, lifetime_elision: LifetimeElisionKind<'db>) { - self.lifetime_elision = lifetime_elision; - } - - pub(crate) fn with_debruijn( - &mut self, - debruijn: DebruijnIndex, - f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T, - ) -> T { - let old_debruijn = mem::replace(&mut self.in_binders, debruijn); - let result = f(self); - self.in_binders = old_debruijn; - result - } - - pub(crate) fn with_shifted_in( - &mut self, - debruijn: DebruijnIndex, - f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T, - ) -> T { - self.with_debruijn(self.in_binders.shifted_in(debruijn.as_u32()), f) - } - - pub(crate) fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { - Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self } - } - - pub(crate) fn impl_trait_mode(&mut self, impl_trait_mode: ImplTraitLoweringMode) -> &mut Self { - self.impl_trait_mode = ImplTraitLoweringState::new(impl_trait_mode); - self - } - - pub(crate) fn lowering_param_default(&mut self, index: u32) { - self.lowering_param_default = Some(index); - } - - pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { - self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind }); - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] -pub(crate) enum ImplTraitLoweringMode { - /// `impl Trait` gets lowered into an opaque type that doesn't unify with - /// anything except itself. This is used in places where values flow 'out', - /// i.e. for arguments of the function we're currently checking, and return - /// types of functions we're calling. - Opaque, - /// `impl Trait` is disallowed and will be an error. - #[default] - Disallowed, -} - -impl<'db, 'a> TyLoweringContext<'db, 'a> { - pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> { - self.lower_ty_ext(type_ref).0 - } - - pub(crate) fn lower_const(&mut self, const_ref: ConstRef, const_type: Ty<'db>) -> Const<'db> { - let const_ref = &self.store[const_ref.expr]; - match const_ref { - hir_def::hir::Expr::Path(path) => { - self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type)) - } - hir_def::hir::Expr::Literal(literal) => intern_const_ref( - self.db, - &match *literal { - hir_def::hir::Literal::Float(_, _) - | hir_def::hir::Literal::String(_) - | hir_def::hir::Literal::ByteString(_) - | hir_def::hir::Literal::CString(_) => LiteralConstRef::Unknown, - hir_def::hir::Literal::Char(c) => LiteralConstRef::Char(c), - hir_def::hir::Literal::Bool(b) => LiteralConstRef::Bool(b), - hir_def::hir::Literal::Int(val, _) => LiteralConstRef::Int(val), - hir_def::hir::Literal::Uint(val, _) => LiteralConstRef::UInt(val), - }, - const_type, - self.resolver.krate(), - ), - hir_def::hir::Expr::UnaryOp { expr: inner_expr, op: hir_def::hir::UnaryOp::Neg } => { - if let hir_def::hir::Expr::Literal(literal) = &self.store[*inner_expr] { - // Only handle negation for signed integers and floats - match literal { - hir_def::hir::Literal::Int(_, _) | hir_def::hir::Literal::Float(_, _) => { - if let Some(negated_literal) = literal.clone().negate() { - intern_const_ref( - self.db, - &negated_literal.into(), - const_type, - self.resolver.krate(), - ) - } else { - unknown_const(const_type) - } - } - // For unsigned integers, chars, bools, etc., negation is not meaningful - _ => unknown_const(const_type), - } - } else { - unknown_const(const_type) - } - } - _ => unknown_const(const_type), - } - } - - pub(crate) fn path_to_const(&mut self, path: &Path) -> Option> { - match self.resolver.resolve_path_in_value_ns_fully(self.db, path, HygieneId::ROOT) { - Some(ValueNs::GenericParam(p)) => { - let args = self.generics(); - match args.type_or_const_param_idx(p.into()) { - Some(idx) => Some(self.const_param(p, idx as u32)), - None => { - never!( - "Generic list doesn't contain this param: {:?}, {:?}, {:?}", - args, - path, - p - ); - None - } - } - } - Some(ValueNs::ConstId(c)) => { - let args = GenericArgs::new_from_iter(self.interner, []); - Some(Const::new( - self.interner, - rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new( - SolverDefId::ConstId(c), - args, - )), - )) - } - _ => None, - } - } - - pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty<'db>) -> Const<'db> { - self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type)) - } - - fn generics(&self) -> &Generics { - self.generics.get_or_init(|| generics(self.db, self.def)) - } - - fn param_index_is_disallowed(&self, index: u32) -> bool { - self.lowering_param_default - .is_some_and(|disallow_params_after| index >= disallow_params_after) - } - - fn type_param(&mut self, id: TypeParamId, index: u32) -> Ty<'db> { - if self.param_index_is_disallowed(index) { - // FIXME: Report an error. - Ty::new_error(self.interner, ErrorGuaranteed) - } else { - Ty::new_param(self.interner, id, index) - } - } - - fn const_param(&mut self, id: ConstParamId, index: u32) -> Const<'db> { - if self.param_index_is_disallowed(index) { - // FIXME: Report an error. - Const::error(self.interner) - } else { - Const::new_param(self.interner, ParamConst { id, index }) - } - } - - fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> { - if self.param_index_is_disallowed(index) { - // FIXME: Report an error. - Region::error(self.interner) - } else { - Region::new_early_param(self.interner, EarlyParamRegion { id, index }) - } - } - - #[tracing::instrument(skip(self), ret)] - 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]; - tracing::debug!(?type_ref); - let ty = match type_ref { - TypeRef::Never => Ty::new(interner, TyKind::Never), - TypeRef::Tuple(inner) => { - let inner_tys = inner.iter().map(|&tr| self.lower_ty(tr)); - Ty::new_tup_from_iter(interner, inner_tys) - } - TypeRef::Path(path) => { - let (ty, res_) = - self.lower_path(path, PathId::from_type_ref_unchecked(type_ref_id)); - res = res_; - ty - } - &TypeRef::TypeParam(type_param_id) => { - res = Some(TypeNs::GenericParam(type_param_id)); - - let generics = self.generics(); - let (idx, _data) = - generics.type_or_const_param(type_param_id.into()).expect("matching generics"); - self.type_param(type_param_id, idx as u32) - } - &TypeRef::RawPtr(inner, mutability) => { - let inner_ty = self.lower_ty(inner); - Ty::new(interner, TyKind::RawPtr(inner_ty, lower_mutability(mutability))) - } - TypeRef::Array(array) => { - let inner_ty = self.lower_ty(array.ty); - let const_len = self.lower_const(array.len, Ty::new_usize(interner)); - Ty::new_array_with_const_len(interner, inner_ty, const_len) - } - &TypeRef::Slice(inner) => { - let inner_ty = self.lower_ty(inner); - Ty::new_slice(interner, inner_ty) - } - TypeRef::Reference(ref_) => { - let inner_ty = self.lower_ty(ref_.ty); - // FIXME: It should infer the eldided lifetimes instead of stubbing with error - let lifetime = ref_ - .lifetime - .map_or_else(|| Region::error(interner), |lr| self.lower_lifetime(lr)); - Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability)) - } - TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed), - TypeRef::Fn(fn_) => { - let substs = self.with_shifted_in( - DebruijnIndex::from_u32(1), - |ctx: &mut TyLoweringContext<'_, '_>| { - Tys::new_from_iter( - interner, - fn_.params.iter().map(|&(_, tr)| ctx.lower_ty(tr)), - ) - }, - ); - Ty::new_fn_ptr( - interner, - Binder::dummy(FnSig { - abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol), - safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe }, - c_variadic: fn_.is_varargs, - inputs_and_output: substs, - }), - ) - } - TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds), - TypeRef::ImplTrait(bounds) => { - match self.impl_trait_mode.mode { - ImplTraitLoweringMode::Opaque => { - let origin = match self.resolver.generic_def() { - Some(GenericDefId::FunctionId(it)) => Either::Left(it), - Some(GenericDefId::TypeAliasId(it)) => Either::Right(it), - _ => panic!( - "opaque impl trait lowering must be in function or type alias" - ), - }; - - // this dance is to make sure the data is in the right - // place even if we encounter more opaque types while - // lowering the bounds - let idx = self - .impl_trait_mode - .opaque_type_data - .alloc(ImplTrait { predicates: Vec::default() }); - - // FIXME(next-solver): this from_raw/into_raw dance isn't nice, but it's minimal - let impl_trait_id = origin.either( - |f| ImplTraitId::ReturnTypeImplTrait(f, Idx::from_raw(idx.into_raw())), - |a| ImplTraitId::TypeAliasImplTrait(a, Idx::from_raw(idx.into_raw())), - ); - let opaque_ty_id: SolverDefId = - self.db.intern_impl_trait_id(impl_trait_id).into(); - - // We don't want to lower the bounds inside the binders - // we're currently in, because they don't end up inside - // those binders. E.g. when we have `impl Trait>`, the `impl OtherTrait` can't refer - // to the self parameter from `impl Trait`, and the - // bounds aren't actually stored nested within each - // other, but separately. So if the `T` refers to a type - // parameter of the outer function, it's just one binder - // away instead of two. - let actual_opaque_type_data = self - .with_debruijn(DebruijnIndex::ZERO, |ctx| { - ctx.lower_impl_trait(opaque_ty_id, bounds, self.resolver.krate()) - }); - self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data; - - let args = GenericArgs::identity_for_item(self.interner, opaque_ty_id); - Ty::new_alias( - self.interner, - AliasTyKind::Opaque, - AliasTy::new_from_args(self.interner, opaque_ty_id, args), - ) - } - ImplTraitLoweringMode::Disallowed => { - // FIXME: report error - Ty::new_error(self.interner, ErrorGuaranteed) - } - } - } - TypeRef::Error => Ty::new_error(self.interner, ErrorGuaranteed), - }; - (ty, res) - } - - /// This is only for `generic_predicates_for_param`, where we can't just - /// lower the self types of the predicates since that could lead to cycles. - /// So we just check here if the `type_ref` resolves to a generic param, and which. - fn lower_ty_only_param(&self, type_ref: TypeRefId) -> Option { - let type_ref = &self.store[type_ref]; - let path = match type_ref { - TypeRef::Path(path) => path, - &TypeRef::TypeParam(idx) => return Some(idx.into()), - _ => return None, - }; - if path.type_anchor().is_some() { - return None; - } - if path.segments().len() > 1 { - return None; - } - let resolution = match self.resolver.resolve_path_in_type_ns(self.db, path) { - Some((it, None, _)) => it, - _ => return None, - }; - match resolution { - TypeNs::GenericParam(param_id) => Some(param_id.into()), - _ => None, - } - } - - #[inline] - fn on_path_diagnostic_callback<'b>(type_ref: TypeRefId) -> PathDiagnosticCallback<'b, 'db> { - PathDiagnosticCallback { - data: Either::Left(PathDiagnosticCallbackData(type_ref)), - callback: |data, this, diag| { - let type_ref = data.as_ref().left().unwrap().0; - this.push_diagnostic(type_ref, TyLoweringDiagnosticKind::PathDiagnostic(diag)) - }, - } - } - - #[inline] - fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a, 'db> { - PathLoweringContext::new( - self, - Self::on_path_diagnostic_callback(path_id.type_ref()), - &self.store[path_id], - ) - } - - pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty<'db>, Option) { - // Resolve the path (in type namespace) - if let Some(type_ref) = path.type_anchor() { - let (ty, res) = self.lower_ty_ext(type_ref); - let mut ctx = self.at_path(path_id); - return ctx.lower_ty_relative_path(ty, res, false); - } - - let mut ctx = self.at_path(path_id); - let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() { - Some(it) => it, - None => return (Ty::new_error(self.interner, ErrorGuaranteed), None), - }; - - if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() { - // trait object type without dyn - let bound = TypeBound::Path(path_id, TraitBoundModifier::None); - let ty = self.lower_dyn_trait(&[bound]); - return (ty, None); - } - - ctx.lower_partly_resolved_path(resolution, false) - } - - fn lower_trait_ref_from_path( - &mut self, - path_id: PathId, - explicit_self_ty: Ty<'db>, - ) -> Option<(TraitRef<'db>, PathLoweringContext<'_, 'a, 'db>)> { - let mut ctx = self.at_path(path_id); - let resolved = match ctx.resolve_path_in_type_ns_fully()? { - // FIXME(trait_alias): We need to handle trait alias here. - TypeNs::TraitId(tr) => tr, - _ => return None, - }; - Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx)) - } - - fn lower_trait_ref( - &mut self, - trait_ref: &HirTraitRef, - explicit_self_ty: Ty<'db>, - ) -> Option> { - self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0) - } - - pub(crate) fn lower_where_predicate<'b>( - &'b mut self, - where_predicate: &'b WherePredicate, - ignore_bindings: bool, - generics: &Generics, - predicate_filter: PredicateFilter, - ) -> impl Iterator> + use<'a, 'b, 'db> { - match where_predicate { - WherePredicate::ForLifetime { target, bound, .. } - | WherePredicate::TypeBound { target, bound } => { - if let PredicateFilter::SelfTrait = predicate_filter { - let target_type = &self.store[*target]; - let self_type = 'is_self: { - if let TypeRef::Path(path) = target_type - && path.is_self_type() - { - break 'is_self true; - } - if let TypeRef::TypeParam(param) = target_type - && generics[param.local_id()].is_trait_self() - { - break 'is_self true; - } - false - }; - if !self_type { - return Either::Left(Either::Left(iter::empty())); - } - } - let self_ty = self.lower_ty(*target); - Either::Left(Either::Right(self.lower_type_bound(bound, self_ty, ignore_bindings))) - } - &WherePredicate::Lifetime { bound, target } => { - Either::Right(iter::once(Clause(Predicate::new( - self.interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::RegionOutlives(OutlivesPredicate( - self.lower_lifetime(bound), - self.lower_lifetime(target), - )), - )), - )))) - } - } - .into_iter() - } - - pub(crate) fn lower_type_bound<'b>( - &'b mut self, - bound: &'b TypeBound, - self_ty: Ty<'db>, - ignore_bindings: bool, - ) -> impl Iterator> + use<'b, 'a, 'db> { - let interner = self.interner; - let mut assoc_bounds = None; - let mut clause = None; - match bound { - &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => { - // FIXME Don't silently drop the hrtb lifetimes here - if let Some((trait_ref, mut ctx)) = self.lower_trait_ref_from_path(path, self_ty) { - // FIXME(sized-hierarchy): Remove this bound modifications once we have implemented - // sized-hierarchy correctly. - let meta_sized = LangItem::MetaSized - .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate()); - let pointee_sized = LangItem::PointeeSized - .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate()); - if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) { - // Ignore this bound - } else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) { - // Regard this as `?Sized` bound - ctx.ty_ctx().unsized_types.insert(self_ty); - } else { - if !ignore_bindings { - assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref); - } - clause = Some(Clause(Predicate::new( - interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: rustc_type_ir::PredicatePolarity::Positive, - }), - )), - ))); - } - } - } - &TypeBound::Path(path, TraitBoundModifier::Maybe) => { - let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate()); - // Don't lower associated type bindings as the only possible relaxed trait bound - // `?Sized` has no of them. - // If we got another trait here ignore the bound completely. - let trait_id = self - .lower_trait_ref_from_path(path, self_ty) - .map(|(trait_ref, _)| trait_ref.def_id.0); - if trait_id == sized_trait { - self.unsized_types.insert(self_ty); - } - } - &TypeBound::Lifetime(l) => { - let lifetime = self.lower_lifetime(l); - clause = Some(Clause(Predicate::new( - self.interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::TypeOutlives(OutlivesPredicate( - self_ty, lifetime, - )), - )), - ))); - } - TypeBound::Use(_) | TypeBound::Error => {} - } - clause.into_iter().chain(assoc_bounds.into_iter().flatten()) - } - - fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> { - let interner = self.interner; - // FIXME: we should never create non-existential predicates in the first place - // For now, use an error type so we don't run into dummy binder issues - let self_ty = Ty::new_error(interner, ErrorGuaranteed); - // INVARIANT: The principal trait bound, if present, must come first. Others may be in any - // order but should be in the same order for the same set but possibly different order of - // bounds in the input. - // INVARIANT: If this function returns `DynTy`, there should be at least one trait bound. - // These invariants are utilized by `TyExt::dyn_trait()` and chalk. - let mut lifetime = None; - let bounds = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| { - let mut lowered_bounds: Vec< - rustc_type_ir::Binder, ExistentialPredicate>>, - > = Vec::new(); - for b in bounds { - let db = ctx.db; - ctx.lower_type_bound(b, self_ty, false).for_each(|b| { - if let Some(bound) = b - .kind() - .map_bound(|c| match c { - rustc_type_ir::ClauseKind::Trait(t) => { - let id = t.def_id(); - let is_auto = - db.trait_signature(id.0).flags.contains(TraitFlags::AUTO); - if is_auto { - Some(ExistentialPredicate::AutoTrait(t.def_id())) - } else { - Some(ExistentialPredicate::Trait( - ExistentialTraitRef::new_from_args( - interner, - t.def_id(), - GenericArgs::new_from_iter( - interner, - t.trait_ref.args.iter().skip(1), - ), - ), - )) - } - } - rustc_type_ir::ClauseKind::Projection(p) => { - Some(ExistentialPredicate::Projection( - ExistentialProjection::new_from_args( - interner, - p.def_id(), - GenericArgs::new_from_iter( - interner, - p.projection_term.args.iter().skip(1), - ), - p.term, - ), - )) - } - rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => { - lifetime = Some(outlives_predicate.1); - None - } - rustc_type_ir::ClauseKind::RegionOutlives(_) - | rustc_type_ir::ClauseKind::ConstArgHasType(_, _) - | rustc_type_ir::ClauseKind::WellFormed(_) - | rustc_type_ir::ClauseKind::ConstEvaluatable(_) - | rustc_type_ir::ClauseKind::HostEffect(_) - | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(), - }) - .transpose() - { - lowered_bounds.push(bound); - } - }) - } - - let mut multiple_regular_traits = false; - let mut multiple_same_projection = false; - lowered_bounds.sort_unstable_by(|lhs, rhs| { - use std::cmp::Ordering; - match ((*lhs).skip_binder(), (*rhs).skip_binder()) { - (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => { - multiple_regular_traits = true; - // Order doesn't matter - we error - Ordering::Equal - } - ( - ExistentialPredicate::AutoTrait(lhs_id), - ExistentialPredicate::AutoTrait(rhs_id), - ) => lhs_id.0.cmp(&rhs_id.0), - (ExistentialPredicate::Trait(_), _) => Ordering::Less, - (_, ExistentialPredicate::Trait(_)) => Ordering::Greater, - (ExistentialPredicate::AutoTrait(_), _) => Ordering::Less, - (_, ExistentialPredicate::AutoTrait(_)) => Ordering::Greater, - ( - ExistentialPredicate::Projection(lhs), - ExistentialPredicate::Projection(rhs), - ) => { - let lhs_id = match lhs.def_id { - SolverDefId::TypeAliasId(id) => id, - _ => unreachable!(), - }; - let rhs_id = match rhs.def_id { - SolverDefId::TypeAliasId(id) => id, - _ => unreachable!(), - }; - // We only compare the `associated_ty_id`s. We shouldn't have - // multiple bounds for an associated type in the correct Rust code, - // and if we do, we error out. - if lhs_id == rhs_id { - multiple_same_projection = true; - } - lhs_id.as_id().index().cmp(&rhs_id.as_id().index()) - } - } - }); - - if multiple_regular_traits || multiple_same_projection { - return None; - } - - if !lowered_bounds.first().map_or(false, |b| { - matches!( - b.as_ref().skip_binder(), - ExistentialPredicate::Trait(_) | ExistentialPredicate::AutoTrait(_) - ) - }) { - return None; - } - - // As multiple occurrences of the same auto traits *are* permitted, we deduplicate the - // bounds. We shouldn't have repeated elements besides auto traits at this point. - lowered_bounds.dedup(); - - Some(BoundExistentialPredicates::new_from_iter(interner, lowered_bounds)) - }); - - if let Some(bounds) = bounds { - let region = match lifetime { - Some(it) => match it.kind() { - rustc_type_ir::RegionKind::ReBound(db, var) => Region::new_bound( - self.interner, - db.shifted_out_to_binder(DebruijnIndex::from_u32(2)), - var, - ), - _ => it, - }, - None => Region::new_static(self.interner), - }; - Ty::new_dynamic(self.interner, bounds, region) - } else { - // FIXME: report error - // (additional non-auto traits, associated type rebound, or no resolved trait) - Ty::new_error(self.interner, ErrorGuaranteed) - } - } - - fn lower_impl_trait( - &mut self, - def_id: SolverDefId, - bounds: &[TypeBound], - krate: Crate, - ) -> ImplTrait<'db> { - let interner = self.interner; - cov_mark::hit!(lower_rpit); - let args = GenericArgs::identity_for_item(interner, def_id); - let self_ty = Ty::new_alias( - self.interner, - rustc_type_ir::AliasTyKind::Opaque, - AliasTy::new_from_args(interner, def_id, args), - ); - let predicates = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| { - let mut predicates = Vec::new(); - for b in bounds { - predicates.extend(ctx.lower_type_bound(b, self_ty, false)); - } - - if !ctx.unsized_types.contains(&self_ty) { - let sized_trait = LangItem::Sized.resolve_trait(self.db, krate); - let sized_clause = sized_trait.map(|trait_id| { - let trait_ref = TraitRef::new_from_args( - interner, - trait_id.into(), - GenericArgs::new_from_iter(interner, [self_ty.into()]), - ); - Clause(Predicate::new( - interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: rustc_type_ir::PredicatePolarity::Positive, - }), - )), - )) - }); - predicates.extend(sized_clause); - } - predicates.shrink_to_fit(); - predicates - }); - ImplTrait { predicates } - } - - pub(crate) fn lower_lifetime(&mut self, lifetime: LifetimeRefId) -> Region<'db> { - match self.resolver.resolve_lifetime(&self.store[lifetime]) { - Some(resolution) => match resolution { - LifetimeNs::Static => Region::new_static(self.interner), - LifetimeNs::LifetimeParam(id) => { - let idx = match self.generics().lifetime_idx(id) { - None => return Region::error(self.interner), - Some(idx) => idx, - }; - self.region_param(id, idx as u32) - } - }, - None => Region::error(self.interner), - } - } -} - -pub(crate) fn lower_mutability(m: hir_def::type_ref::Mutability) -> Mutability { - match m { - hir_def::type_ref::Mutability::Shared => Mutability::Not, - hir_def::type_ref::Mutability::Mut => Mutability::Mut, - } -} - -fn unknown_const(_ty: Ty<'_>) -> Const<'_> { - Const::new(DbInterner::conjure(), ConstKind::Error(ErrorGuaranteed)) -} - -pub(crate) fn impl_trait_query<'db>( - db: &'db dyn HirDatabase, - impl_id: ImplId, -) -> Option>> { - db.impl_trait_with_diagnostics(impl_id).map(|it| it.0) -} - -pub(crate) fn impl_trait_with_diagnostics_query<'db>( - db: &'db dyn HirDatabase, - impl_id: ImplId, -) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)> { - let impl_data = db.impl_signature(impl_id); - let resolver = impl_id.resolver(db); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &impl_data.store, - impl_id.into(), - LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }, - ); - let self_ty = db.impl_self_ty(impl_id).skip_binder(); - let target_trait = impl_data.target_trait.as_ref()?; - let trait_ref = EarlyBinder::bind(ctx.lower_trait_ref(target_trait, self_ty)?); - Some((trait_ref, create_diagnostics(ctx.diagnostics))) -} - -pub(crate) fn return_type_impl_traits<'db>( - db: &'db dyn HirDatabase, - def: hir_def::FunctionId, -) -> Option>>> { - // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe - let data = db.function_signature(def); - let resolver = def.resolver(db); - let mut ctx_ret = - TyLoweringContext::new(db, &resolver, &data.store, def.into(), LifetimeElisionKind::Infer) - .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); - if let Some(ret_type) = data.ret_type { - let _ret = ctx_ret.lower_ty(ret_type); - } - let return_type_impl_traits = - ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data }; - if return_type_impl_traits.impl_traits.is_empty() { - None - } else { - Some(Arc::new(EarlyBinder::bind(return_type_impl_traits))) - } -} - -pub(crate) fn type_alias_impl_traits<'db>( - db: &'db dyn HirDatabase, - def: hir_def::TypeAliasId, -) -> Option>>> { - let data = db.type_alias_signature(def); - let resolver = def.resolver(db); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &data.store, - def.into(), - LifetimeElisionKind::AnonymousReportError, - ) - .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); - if let Some(type_ref) = data.ty { - let _ty = ctx.lower_ty(type_ref); - } - let type_alias_impl_traits = ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data }; - if type_alias_impl_traits.impl_traits.is_empty() { - None - } else { - Some(Arc::new(EarlyBinder::bind(type_alias_impl_traits))) - } -} - -/// Build the declared type of an item. This depends on the namespace; e.g. for -/// `struct Foo(usize)`, we have two types: The type of the struct itself, and -/// the constructor function `(usize) -> Foo` which lives in the values -/// namespace. -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(Ty::from_builtin_type(interner, it)), - TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt( - interner, - it, - GenericArgs::identity_for_item(interner, it.into()), - )), - TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0, - } -} - -/// Build the declared type of a function. This should not need to look at the -/// function body. -fn type_for_fn<'db>(db: &'db dyn HirDatabase, def: FunctionId) -> EarlyBinder<'db, Ty<'db>> { - let interner = DbInterner::new_with(db, None, None); - EarlyBinder::bind(Ty::new_fn_def( - interner, - CallableDefId::FunctionId(def).into(), - GenericArgs::identity_for_item(interner, def.into()), - )) -} - -/// Build the declared type of a const. -fn type_for_const<'db>(db: &'db dyn HirDatabase, def: ConstId) -> EarlyBinder<'db, Ty<'db>> { - let resolver = def.resolver(db); - let data = db.const_signature(def); - let parent = def.loc(db).container; - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &data.store, - def.into(), - LifetimeElisionKind::AnonymousReportError, - ); - ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent)); - EarlyBinder::bind(ctx.lower_ty(data.type_ref)) -} - -/// Build the declared type of a static. -fn type_for_static<'db>(db: &'db dyn HirDatabase, def: StaticId) -> EarlyBinder<'db, Ty<'db>> { - let resolver = def.resolver(db); - let data = db.static_signature(def); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &data.store, - def.into(), - LifetimeElisionKind::AnonymousReportError, - ); - ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner))); - EarlyBinder::bind(ctx.lower_ty(data.type_ref)) -} - -/// Build the type of a tuple struct constructor. -fn type_for_struct_constructor<'db>( - db: &'db dyn HirDatabase, - def: StructId, -) -> Option>> { - let struct_data = def.fields(db); - match struct_data.shape { - FieldsShape::Record => None, - FieldsShape::Unit => Some(type_for_adt(db, def.into())), - FieldsShape::Tuple => { - let interner = DbInterner::new_with(db, None, None); - Some(EarlyBinder::bind(Ty::new_fn_def( - interner, - CallableDefId::StructId(def).into(), - GenericArgs::identity_for_item(interner, def.into()), - ))) - } - } -} - -/// Build the type of a tuple enum variant constructor. -fn type_for_enum_variant_constructor<'db>( - db: &'db dyn HirDatabase, - def: EnumVariantId, -) -> Option>> { - let struct_data = def.fields(db); - match struct_data.shape { - FieldsShape::Record => None, - FieldsShape::Unit => Some(type_for_adt(db, def.loc(db).parent.into())), - FieldsShape::Tuple => { - let interner = DbInterner::new_with(db, None, None); - Some(EarlyBinder::bind(Ty::new_fn_def( - interner, - CallableDefId::EnumVariantId(def).into(), - GenericArgs::identity_for_item(interner, def.loc(db).parent.into()), - ))) - } - } -} - -pub(crate) fn value_ty_query<'db>( - db: &'db dyn HirDatabase, - def: ValueTyDefId, -) -> Option>> { - match def { - ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)), - ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), - ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())), - ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it), - ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)), - ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)), - } -} - -pub(crate) fn type_for_type_alias_with_diagnostics_query<'db>( - db: &'db dyn HirDatabase, - t: TypeAliasId, -) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { - let type_alias_data = db.type_alias_signature(t); - let mut diags = None; - let resolver = t.resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) { - EarlyBinder::bind(Ty::new_foreign(interner, t.into())) - } else { - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &type_alias_data.store, - t.into(), - LifetimeElisionKind::AnonymousReportError, - ) - .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); - let res = EarlyBinder::bind( - type_alias_data - .ty - .map(|type_ref| ctx.lower_ty(type_ref)) - .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)), - ); - diags = create_diagnostics(ctx.diagnostics); - res - }; - (inner, diags) -} - -pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>( - db: &'db dyn HirDatabase, - _adt: TypeAliasId, -) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { - (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None) -} - -pub(crate) fn impl_self_ty_query<'db>( - db: &'db dyn HirDatabase, - impl_id: ImplId, -) -> EarlyBinder<'db, Ty<'db>> { - db.impl_self_ty_with_diagnostics(impl_id).0 -} - -pub(crate) fn impl_self_ty_with_diagnostics_query<'db>( - db: &'db dyn HirDatabase, - impl_id: ImplId, -) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { - let resolver = impl_id.resolver(db); - - let impl_data = db.impl_signature(impl_id); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &impl_data.store, - impl_id.into(), - LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }, - ); - let ty = ctx.lower_ty(impl_data.self_ty); - assert!(!ty.has_escaping_bound_vars()); - (EarlyBinder::bind(ty), create_diagnostics(ctx.diagnostics)) -} - -pub(crate) fn impl_self_ty_with_diagnostics_cycle_result( - db: &dyn HirDatabase, - _impl_id: ImplId, -) -> (EarlyBinder<'_, Ty<'_>>, Diagnostics) { - (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None) -} - -pub(crate) fn const_param_ty_query<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> { - db.const_param_ty_with_diagnostics(def).0 -} - -// returns None if def is a type arg -pub(crate) fn const_param_ty_with_diagnostics_query<'db>( - db: &'db dyn HirDatabase, - def: ConstParamId, -) -> (Ty<'db>, Diagnostics) { - let (parent_data, store) = db.generic_params_and_store(def.parent()); - let data = &parent_data[def.local_id()]; - let resolver = def.parent().resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &store, - def.parent(), - LifetimeElisionKind::AnonymousReportError, - ); - let ty = match data { - TypeOrConstParamData::TypeParamData(_) => { - never!(); - Ty::new_error(interner, ErrorGuaranteed) - } - TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty), - }; - (ty, create_diagnostics(ctx.diagnostics)) -} - -pub(crate) fn const_param_ty_with_diagnostics_cycle_result<'db>( - db: &'db dyn HirDatabase, - _: crate::db::HirDatabaseData, - def: ConstParamId, -) -> (Ty<'db>, Diagnostics) { - let resolver = def.parent().resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - (Ty::new_error(interner, ErrorGuaranteed), None) -} - -pub(crate) fn field_types_query<'db>( - db: &'db dyn HirDatabase, - variant_id: VariantId, -) -> Arc>>> { - db.field_types_with_diagnostics(variant_id).0 -} - -/// Build the type of all specific fields of a struct or enum variant. -pub(crate) fn field_types_with_diagnostics_query<'db>( - db: &'db dyn HirDatabase, - variant_id: VariantId, -) -> (Arc>>>, Diagnostics) { - let var_data = variant_id.fields(db); - let fields = var_data.fields(); - if fields.is_empty() { - return (Arc::new(ArenaMap::default()), None); - } - - let (resolver, def): (_, GenericDefId) = match variant_id { - VariantId::StructId(it) => (it.resolver(db), it.into()), - VariantId::UnionId(it) => (it.resolver(db), it.into()), - VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()), - }; - let mut res = ArenaMap::default(); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &var_data.store, - def, - LifetimeElisionKind::AnonymousReportError, - ); - for (field_id, field_data) in var_data.fields().iter() { - res.insert(field_id, EarlyBinder::bind(ctx.lower_ty(field_data.type_ref))); - } - (Arc::new(res), create_diagnostics(ctx.diagnostics)) -} - -/// This query exists only to be used when resolving short-hand associated types -/// like `T::Item`. -/// -/// See the analogous query in rustc and its comment: -/// -/// This is a query mostly to handle cycles somewhat gracefully; e.g. the -/// following bounds are disallowed: `T: Foo, U: Foo`, but -/// these are fine: `T: Foo, U: Foo<()>`. -#[tracing::instrument(skip(db), ret)] -pub(crate) fn generic_predicates_for_param_query<'db>( - db: &'db dyn HirDatabase, - def: GenericDefId, - param_id: TypeOrConstParamId, - assoc_name: Option, -) -> GenericPredicates<'db> { - let generics = generics(db, def); - let interner = DbInterner::new_with(db, None, None); - let resolver = def.resolver(db); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - generics.store(), - def, - LifetimeElisionKind::AnonymousReportError, - ); - - // we have to filter out all other predicates *first*, before attempting to lower them - let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_, '_>| match pred { - WherePredicate::ForLifetime { target, bound, .. } - | WherePredicate::TypeBound { target, bound, .. } => { - let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) }; - if invalid_target { - // FIXME(sized-hierarchy): Revisit and adjust this properly once we have implemented - // sized-hierarchy correctly. - // If this is filtered out without lowering, `?Sized` or `PointeeSized` is not gathered into - // `ctx.unsized_types` - let lower = || -> bool { - match bound { - TypeBound::Path(_, TraitBoundModifier::Maybe) => true, - TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => { - let TypeRef::Path(path) = &ctx.store[path.type_ref()] else { - return false; - }; - let Some(pointee_sized) = - LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate()) - else { - return false; - }; - // Lower the path directly with `Resolver` instead of PathLoweringContext` - // to prevent diagnostics duplications. - ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and( - |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized), - ) - } - _ => false, - } - }(); - if lower { - ctx.lower_where_predicate(pred, true, &generics, PredicateFilter::All) - .for_each(drop); - } - return false; - } - - match bound { - &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => { - // Only lower the bound if the trait could possibly define the associated - // type we're looking for. - let path = &ctx.store[path]; - - let Some(assoc_name) = &assoc_name else { return true }; - let Some(TypeNs::TraitId(tr)) = - resolver.resolve_path_in_type_ns_fully(db, path) - else { - return false; - }; - - rustc_type_ir::elaborate::supertrait_def_ids(interner, tr.into()).any(|tr| { - tr.0.trait_items(db).items.iter().any(|(name, item)| { - matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name - }) - }) - } - TypeBound::Use(_) | TypeBound::Lifetime(_) | TypeBound::Error => false, - } - } - WherePredicate::Lifetime { .. } => false, - }; - let mut predicates = Vec::new(); - for maybe_parent_generics in - std::iter::successors(Some(&generics), |generics| generics.parent_generics()) - { - ctx.store = maybe_parent_generics.store(); - for pred in maybe_parent_generics.where_predicates() { - if predicate(pred, &mut ctx) { - predicates.extend(ctx.lower_where_predicate( - pred, - true, - maybe_parent_generics, - PredicateFilter::All, - )); - } - } - } - - let args = GenericArgs::identity_for_item(interner, def.into()); - if !args.is_empty() { - let explicitly_unsized_tys = ctx.unsized_types; - if let Some(implicitly_sized_predicates) = - implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &args, &resolver) - { - predicates.extend(implicitly_sized_predicates); - }; - } - GenericPredicates(predicates.is_empty().not().then(|| predicates.into())) -} - -pub(crate) fn generic_predicates_for_param_cycle_result( - _db: &dyn HirDatabase, - _def: GenericDefId, - _param_id: TypeOrConstParamId, - _assoc_name: Option, -) -> GenericPredicates<'_> { - GenericPredicates(None) -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct GenericPredicates<'db>(Option]>>); - -impl<'db> GenericPredicates<'db> { - #[inline] - pub fn instantiate( - &self, - interner: DbInterner<'db>, - args: GenericArgs<'db>, - ) -> Option>> { - self.0 - .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> { - type Target = [Clause<'db>]; - - fn deref(&self) -> &Self::Target { - self.0.as_deref().unwrap_or(&[]) - } -} - -pub(crate) fn trait_environment_for_body_query( - db: &dyn HirDatabase, - def: DefWithBodyId, -) -> Arc> { - let Some(def) = def.as_generic_def_id(db) else { - let krate = def.module(db).krate(); - return TraitEnvironment::empty(krate); - }; - db.trait_environment(def) -} - -pub(crate) fn trait_environment_query<'db>( - db: &'db dyn HirDatabase, - def: GenericDefId, -) -> Arc> { - let generics = generics(db, def); - if generics.has_no_predicates() && generics.is_empty() { - return TraitEnvironment::empty(def.krate(db)); - } - - let resolver = def.resolver(db); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - generics.store(), - def, - LifetimeElisionKind::AnonymousReportError, - ); - let mut traits_in_scope = Vec::new(); - let mut clauses = Vec::new(); - for maybe_parent_generics in - std::iter::successors(Some(&generics), |generics| generics.parent_generics()) - { - ctx.store = maybe_parent_generics.store(); - 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((tr.self_ty(), tr.def_id().0)); - } - clauses.push(pred); - } - } - } - - if let Some(trait_id) = def.assoc_trait_container(db) { - // add `Self: Trait` to the environment in trait - // function default implementations (and speculative code - // inside consts or type aliases) - cov_mark::hit!(trait_self_implements_self); - let trait_ref = TraitRef::identity(ctx.interner, trait_id.into()); - let clause = Clause(Predicate::new( - ctx.interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Trait( - TraitPredicate { trait_ref, polarity: rustc_type_ir::PredicatePolarity::Positive }, - ))), - )); - clauses.push(clause); - } - - let explicitly_unsized_tys = ctx.unsized_types; - - let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()); - if let Some(sized_trait) = sized_trait { - let (mut generics, mut def_id) = - (crate::next_solver::generics::generics(db, def.into()), def); - loop { - let self_idx = trait_self_param_idx(db, def_id); - for (idx, p) in generics.own_params.iter().enumerate() { - if let Some(self_idx) = self_idx - && p.index() as usize == self_idx - { - continue; - } - let GenericParamId::TypeParamId(param_id) = p.id else { - continue; - }; - let idx = idx as u32 + generics.parent_count as u32; - let param_ty = Ty::new_param(ctx.interner, param_id, idx); - if explicitly_unsized_tys.contains(¶m_ty) { - continue; - } - let trait_ref = TraitRef::new_from_args( - ctx.interner, - sized_trait.into(), - GenericArgs::new_from_iter(ctx.interner, [param_ty.into()]), - ); - let clause = Clause(Predicate::new( - ctx.interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: rustc_type_ir::PredicatePolarity::Positive, - }), - )), - )); - clauses.push(clause); - } - - if let Some(g) = generics.parent { - generics = crate::next_solver::generics::generics(db, g.into()); - def_id = g; - } else { - break; - } - } - } - - let clauses = rustc_type_ir::elaborate::elaborate(ctx.interner, clauses); - let clauses = Clauses::new_from_iter(ctx.interner, clauses); - let env = ParamEnv { clauses }; - - TraitEnvironment::new(resolver.krate(), None, traits_in_scope.into_boxed_slice(), env) -} - -#[derive(Copy, Clone, Debug)] -pub(crate) enum PredicateFilter { - SelfTrait, - All, -} - -/// Resolve the where clause(s) of an item with generics. -#[tracing::instrument(skip(db))] -pub(crate) fn generic_predicates_query<'db>( - db: &'db dyn HirDatabase, - def: GenericDefId, -) -> GenericPredicates<'db> { - generic_predicates_filtered_by(db, def, PredicateFilter::All, |_| true).0 -} - -pub(crate) fn generic_predicates_without_parent_query<'db>( - db: &'db dyn HirDatabase, - def: GenericDefId, -) -> GenericPredicates<'db> { - generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def).0 -} - -/// Resolve the where clause(s) of an item with generics, -/// except the ones inherited from the parent -pub(crate) fn generic_predicates_without_parent_with_diagnostics_query<'db>( - db: &'db dyn HirDatabase, - def: GenericDefId, -) -> (GenericPredicates<'db>, Diagnostics) { - generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def) -} - -/// Resolve the where clause(s) of an item with generics, -/// with a given filter -#[tracing::instrument(skip(db, filter), ret)] -pub(crate) fn generic_predicates_filtered_by<'db, F>( - db: &'db dyn HirDatabase, - def: GenericDefId, - predicate_filter: PredicateFilter, - filter: F, -) -> (GenericPredicates<'db>, Diagnostics) -where - F: Fn(GenericDefId) -> bool, -{ - let generics = generics(db, def); - let resolver = def.resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - generics.store(), - def, - LifetimeElisionKind::AnonymousReportError, - ); - - let mut predicates = Vec::new(); - for maybe_parent_generics in - std::iter::successors(Some(&generics), |generics| generics.parent_generics()) - { - ctx.store = maybe_parent_generics.store(); - for pred in maybe_parent_generics.where_predicates() { - tracing::debug!(?pred); - if filter(maybe_parent_generics.def()) { - predicates.extend(ctx.lower_where_predicate( - pred, - false, - maybe_parent_generics, - predicate_filter, - )); - } - } - } - - let explicitly_unsized_tys = ctx.unsized_types; - - let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()); - if let Some(sized_trait) = sized_trait { - let mut add_sized_clause = |param_idx, param_id, param_data| { - let ( - GenericParamId::TypeParamId(param_id), - GenericParamDataRef::TypeParamData(param_data), - ) = (param_id, param_data) - else { - return; - }; - - if param_data.provenance == TypeParamProvenance::TraitSelf { - return; - } - - let param_ty = Ty::new_param(interner, param_id, param_idx); - if explicitly_unsized_tys.contains(¶m_ty) { - return; - } - let trait_ref = TraitRef::new_from_args( - interner, - sized_trait.into(), - GenericArgs::new_from_iter(interner, [param_ty.into()]), - ); - let clause = Clause(Predicate::new( - interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: rustc_type_ir::PredicatePolarity::Positive, - }), - )), - )); - predicates.push(clause); - }; - if generics.parent_generics().is_some_and(|parent| filter(parent.def())) { - generics.iter_parent().enumerate().for_each(|(param_idx, (param_id, param_data))| { - add_sized_clause(param_idx as u32, param_id, param_data); - }); - } - if filter(def) { - let parent_params_len = generics.len_parent(); - generics.iter_self().enumerate().for_each(|(param_idx, (param_id, param_data))| { - add_sized_clause((param_idx + parent_params_len) as u32, param_id, param_data); - }); - } - } - - // FIXME: rustc gathers more predicates by recursing through resulting trait predicates. - // See https://github.com/rust-lang/rust/blob/76c5ed2847cdb26ef2822a3a165d710f6b772217/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L689-L715 - - ( - GenericPredicates(predicates.is_empty().not().then(|| predicates.into())), - create_diagnostics(ctx.diagnostics), - ) -} - -/// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound. -/// Exception is Self of a trait def. -fn implicitly_sized_clauses<'a, 'subst, 'db>( - db: &'db dyn HirDatabase, - def: GenericDefId, - explicitly_unsized_tys: &'a FxHashSet>, - args: &'subst GenericArgs<'db>, - resolver: &Resolver<'db>, -) -> Option> + Captures<'a> + Captures<'subst>> { - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate())?; - - let trait_self_idx = trait_self_param_idx(db, def); - - Some( - args.iter() - .enumerate() - .filter_map( - move |(idx, generic_arg)| { - if Some(idx) == trait_self_idx { None } else { Some(generic_arg) } - }, - ) - .filter_map(|generic_arg| generic_arg.as_type()) - .filter(move |self_ty| !explicitly_unsized_tys.contains(self_ty)) - .map(move |self_ty| { - let trait_ref = TraitRef::new_from_args( - interner, - sized_trait.into(), - GenericArgs::new_from_iter(interner, [self_ty.into()]), - ); - Clause(Predicate::new( - interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: rustc_type_ir::PredicatePolarity::Positive, - }), - )), - )) - }), - ) -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct GenericDefaults<'db>(Option>>]>>); - -impl<'db> GenericDefaults<'db> { - #[inline] - pub fn get(&self, idx: usize) -> Option>> { - self.0.as_ref()?[idx] - } -} - -pub(crate) fn generic_defaults_query( - db: &dyn HirDatabase, - def: GenericDefId, -) -> GenericDefaults<'_> { - db.generic_defaults_ns_with_diagnostics(def).0 -} - -/// Resolve the default type params from generics. -/// -/// Diagnostics are only returned for this `GenericDefId` (returned defaults include parents). -pub(crate) fn generic_defaults_with_diagnostics_query( - db: &dyn HirDatabase, - def: GenericDefId, -) -> (GenericDefaults<'_>, Diagnostics) { - let generic_params = generics(db, def); - if generic_params.is_empty() { - return (GenericDefaults(None), None); - } - let resolver = def.resolver(db); - - let mut ctx = TyLoweringContext::new( - db, - &resolver, - generic_params.store(), - def, - LifetimeElisionKind::AnonymousReportError, - ) - .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed); - let mut idx = 0; - let mut has_any_default = false; - let mut defaults = generic_params - .iter_parents_with_store() - .map(|((_id, p), store)| { - ctx.store = store; - let (result, has_default) = handle_generic_param(&mut ctx, idx, p); - has_any_default |= has_default; - idx += 1; - result - }) - .collect::>(); - ctx.diagnostics.clear(); // Don't include diagnostics from the parent. - defaults.extend(generic_params.iter_self().map(|(_id, p)| { - let (result, has_default) = handle_generic_param(&mut ctx, idx, p); - has_any_default |= has_default; - idx += 1; - result - })); - let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics)); - let defaults = if has_any_default { - GenericDefaults(Some(Arc::from_iter(defaults))) - } else { - GenericDefaults(None) - }; - return (defaults, diagnostics); - - fn handle_generic_param<'db>( - ctx: &mut TyLoweringContext<'db, '_>, - idx: usize, - p: GenericParamDataRef<'_>, - ) -> (Option>>, bool) { - ctx.lowering_param_default(idx as u32); - match p { - GenericParamDataRef::TypeParamData(p) => { - let ty = p.default.map(|ty| ctx.lower_ty(ty)); - (ty.map(|ty| EarlyBinder::bind(ty.into())), p.default.is_some()) - } - GenericParamDataRef::ConstParamData(p) => { - let val = p.default.map(|c| { - let param_ty = ctx.lower_ty(p.ty); - let c = ctx.lower_const(c, param_ty); - c.into() - }); - (val.map(EarlyBinder::bind), p.default.is_some()) - } - GenericParamDataRef::LifetimeParamData(_) => (None, false), - } - } -} - -pub(crate) fn generic_defaults_with_diagnostics_cycle_result( - _db: &dyn HirDatabase, - _def: GenericDefId, -) -> (GenericDefaults<'_>, Diagnostics) { - (GenericDefaults(None), None) -} - -/// Build the signature of a callable item (function, struct or enum variant). -pub(crate) fn callable_item_signature_query<'db>( - db: &'db dyn HirDatabase, - def: CallableDefId, -) -> EarlyBinder<'db, PolyFnSig<'db>> { - match def { - CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f), - CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s), - CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e), - } -} - -fn fn_sig_for_fn<'db>( - db: &'db dyn HirDatabase, - def: FunctionId, -) -> EarlyBinder<'db, PolyFnSig<'db>> { - let data = db.function_signature(def); - let resolver = def.resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - let mut ctx_params = TyLoweringContext::new( - db, - &resolver, - &data.store, - def.into(), - LifetimeElisionKind::for_fn_params(&data), - ); - let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr)); - - let ret = match data.ret_type { - Some(ret_type) => { - let mut ctx_ret = TyLoweringContext::new( - db, - &resolver, - &data.store, - def.into(), - LifetimeElisionKind::for_fn_ret(interner), - ) - .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); - ctx_ret.lower_ty(ret_type) - } - None => Ty::new_tup(interner, &[]), - }; - - let inputs_and_output = Tys::new_from_iter(interner, params.chain(Some(ret))); - // If/when we track late bound vars, we need to switch this to not be `dummy` - EarlyBinder::bind(rustc_type_ir::Binder::dummy(FnSig { - abi: data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol), - c_variadic: data.is_varargs(), - safety: if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe }, - inputs_and_output, - })) -} - -fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> { - let interner = DbInterner::new_with(db, None, None); - let args = GenericArgs::identity_for_item(interner, adt.into()); - let ty = Ty::new_adt(interner, adt, args); - EarlyBinder::bind(ty) -} - -fn fn_sig_for_struct_constructor<'db>( - db: &'db dyn HirDatabase, - def: StructId, -) -> EarlyBinder<'db, PolyFnSig<'db>> { - let field_tys = db.field_types_ns(def.into()); - let params = field_tys.iter().map(|(_, ty)| ty.skip_binder()); - let ret = type_for_adt(db, def.into()).skip_binder(); - - let inputs_and_output = - Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret))); - EarlyBinder::bind(Binder::dummy(FnSig { - abi: FnAbi::RustCall, - c_variadic: false, - safety: Safety::Safe, - inputs_and_output, - })) -} - -fn fn_sig_for_enum_variant_constructor<'db>( - db: &'db dyn HirDatabase, - def: EnumVariantId, -) -> EarlyBinder<'db, PolyFnSig<'db>> { - let field_tys = db.field_types_ns(def.into()); - let params = field_tys.iter().map(|(_, ty)| ty.skip_binder()); - let parent = def.lookup(db).parent; - let ret = type_for_adt(db, parent.into()).skip_binder(); - - let inputs_and_output = - Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret))); - EarlyBinder::bind(Binder::dummy(FnSig { - abi: FnAbi::RustCall, - c_variadic: false, - safety: Safety::Safe, - inputs_and_output, - })) -} - -// FIXME(next-solver): should merge this with `explicit_item_bounds` in some way -pub(crate) fn associated_ty_item_bounds<'db>( - db: &'db dyn HirDatabase, - type_alias: TypeAliasId, -) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> { - let type_alias_data = db.type_alias_signature(type_alias); - let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - let mut ctx = TyLoweringContext::new( - db, - &resolver, - &type_alias_data.store, - type_alias.into(), - LifetimeElisionKind::AnonymousReportError, - ); - // FIXME: we should never create non-existential predicates in the first place - // For now, use an error type so we don't run into dummy binder issues - let self_ty = Ty::new_error(interner, ErrorGuaranteed); - - let mut bounds = Vec::new(); - for bound in &type_alias_data.bounds { - ctx.lower_type_bound(bound, self_ty, false).for_each(|pred| { - if let Some(bound) = pred - .kind() - .map_bound(|c| match c { - rustc_type_ir::ClauseKind::Trait(t) => { - let id = t.def_id(); - let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO); - if is_auto { - Some(ExistentialPredicate::AutoTrait(t.def_id())) - } else { - Some(ExistentialPredicate::Trait(ExistentialTraitRef::new_from_args( - interner, - t.def_id(), - GenericArgs::new_from_iter( - interner, - t.trait_ref.args.iter().skip(1), - ), - ))) - } - } - rustc_type_ir::ClauseKind::Projection(p) => Some( - ExistentialPredicate::Projection(ExistentialProjection::new_from_args( - interner, - p.def_id(), - GenericArgs::new_from_iter( - interner, - p.projection_term.args.iter().skip(1), - ), - p.term, - )), - ), - rustc_type_ir::ClauseKind::TypeOutlives(_) => None, - rustc_type_ir::ClauseKind::RegionOutlives(_) - | rustc_type_ir::ClauseKind::ConstArgHasType(_, _) - | rustc_type_ir::ClauseKind::WellFormed(_) - | rustc_type_ir::ClauseKind::ConstEvaluatable(_) - | rustc_type_ir::ClauseKind::HostEffect(_) - | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(), - }) - .transpose() - { - bounds.push(bound); - } - }); - } - - if !ctx.unsized_types.contains(&self_ty) - && let Some(sized_trait) = LangItem::Sized.resolve_trait(db, resolver.krate()) - { - let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new( - interner, - sized_trait.into(), - [] as [GenericArg<'_>; 0], - ))); - bounds.push(sized_clause); - } - - EarlyBinder::bind(BoundExistentialPredicates::new_from_iter(interner, bounds)) -} - -pub(crate) fn associated_type_by_name_including_super_traits<'db>( - db: &'db dyn HirDatabase, - trait_ref: TraitRef<'db>, - name: &Name, -) -> Option<(TraitRef<'db>, TypeAliasId)> { - let interner = DbInterner::new_with(db, None, None); - rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| { - let trait_id = t.as_ref().skip_binder().def_id.0; - let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?; - Some((t.skip_binder(), assoc_type)) - }) -} - -pub fn associated_type_shorthand_candidates( - db: &dyn HirDatabase, - def: GenericDefId, - res: TypeNs, - mut cb: impl FnMut(&Name, TypeAliasId) -> bool, -) -> Option { - let interner = DbInterner::new_with(db, None, None); - named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| { - cb(name, id).then_some(id) - }) -} - -#[tracing::instrument(skip(interner, check_alias))] -fn named_associated_type_shorthand_candidates<'db, R>( - interner: DbInterner<'db>, - // If the type parameter is defined in an impl and we're in a method, there - // might be additional where clauses to consider - def: GenericDefId, - res: TypeNs, - assoc_name: Option, - mut check_alias: impl FnMut(&Name, TraitRef<'db>, TypeAliasId) -> Option, -) -> Option { - let db = interner.db; - let mut search = |t: TraitRef<'db>| -> Option { - let mut checked_traits = FxHashSet::default(); - let mut check_trait = |trait_ref: TraitRef<'db>| { - let trait_id = trait_ref.def_id.0; - let name = &db.trait_signature(trait_id).name; - tracing::debug!(?trait_id, ?name); - if !checked_traits.insert(trait_id) { - return None; - } - let data = trait_id.trait_items(db); - - tracing::debug!(?data.items); - for (name, assoc_id) in &data.items { - if let &AssocItemId::TypeAliasId(alias) = assoc_id - && let Some(ty) = check_alias(name, trait_ref, alias) - { - return Some(ty); - } - } - None - }; - let mut stack: SmallVec<[_; 4]> = smallvec![t]; - while let Some(trait_ref) = stack.pop() { - if let Some(alias) = check_trait(trait_ref) { - return Some(alias); - } - for pred in generic_predicates_filtered_by( - db, - GenericDefId::TraitId(trait_ref.def_id.0), - PredicateFilter::SelfTrait, - // We are likely in the midst of lowering generic predicates of `def`. - // So, if we allow `pred == def` we might fall into an infinite recursion. - // Actually, we have already checked for the case `pred == def` above as we started - // with a stack including `trait_id` - |pred| pred != def && pred == GenericDefId::TraitId(trait_ref.def_id.0), - ) - .0 - .deref() - { - tracing::debug!(?pred); - let sup_trait_ref = match pred.kind().skip_binder() { - rustc_type_ir::ClauseKind::Trait(pred) => pred.trait_ref, - _ => continue, - }; - let sup_trait_ref = - EarlyBinder::bind(sup_trait_ref).instantiate(interner, trait_ref.args); - stack.push(sup_trait_ref); - } - tracing::debug!(?stack); - } - - None - }; - - match res { - TypeNs::SelfType(impl_id) => { - let trait_ref = db.impl_trait(impl_id)?; - - // FIXME(next-solver): same method in `lower` checks for impl or not - // Is that needed here? - - // we're _in_ the impl -- the binders get added back later. Correct, - // but it would be nice to make this more explicit - search(trait_ref.skip_binder()) - } - TypeNs::GenericParam(param_id) => { - // Handle `Self::Type` referring to own associated type in trait definitions - // This *must* be done first to avoid cycles with - // `generic_predicates_for_param`, but not sure that it's sufficient, - if let GenericDefId::TraitId(trait_id) = param_id.parent() { - let trait_name = &db.trait_signature(trait_id).name; - tracing::debug!(?trait_name); - let trait_generics = generics(db, trait_id.into()); - tracing::debug!(?trait_generics); - if trait_generics[param_id.local_id()].is_trait_self() { - let args = GenericArgs::identity_for_item(interner, trait_id.into()); - let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args); - tracing::debug!(?args, ?trait_ref); - return search(trait_ref); - } - } - - let predicates = - db.generic_predicates_for_param_ns(def, param_id.into(), assoc_name.clone()); - predicates - .iter() - .find_map(|pred| match (*pred).kind().skip_binder() { - rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate), - _ => None, - }) - .and_then(|trait_predicate| { - let trait_ref = trait_predicate.trait_ref; - assert!( - !trait_ref.has_escaping_bound_vars(), - "FIXME unexpected higher-ranked trait bound" - ); - search(trait_ref) - }) - } - _ => None, - } -} 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 deleted file mode 100644 index a4ff47e3892a..000000000000 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs +++ /dev/null @@ -1,1327 +0,0 @@ -//! A wrapper around [`TyLoweringContext`] specifically for lowering paths. - -use either::Either; -use hir_def::{ - GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId, - expr_store::{ - ExpressionStore, HygieneId, - path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments}, - }, - hir::generics::{ - GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance, - }, - resolver::{ResolveValueResult, TypeNs, ValueNs}, - signatures::TraitFlags, - type_ref::{TypeRef, TypeRefId}, -}; -use hir_expand::name::Name; -use rustc_type_ir::{ - AliasTerm, AliasTy, AliasTyKind, - inherent::{GenericArgs as _, Region as _, SliceLike, Ty as _}, -}; -use smallvec::SmallVec; -use stdx::never; - -use crate::{ - GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource, - PathLoweringDiagnostic, TyDefId, ValueTyDefId, - consteval::{unknown_const, unknown_const_as_generic}, - db::HirDatabase, - generics::{Generics, generics}, - lower::PathDiagnosticCallbackData, - lower_nextsolver::{LifetimeElisionKind, named_associated_type_shorthand_candidates}, - next_solver::{ - Binder, Clause, Const, DbInterner, ErrorGuaranteed, Predicate, ProjectionPredicate, Region, - TraitRef, Ty, - mapping::{ChalkToNextSolver, convert_binder_to_early_binder}, - }, -}; - -use super::{ - ImplTraitLoweringMode, TyLoweringContext, associated_type_by_name_including_super_traits, - const_param_ty_query, ty_query, -}; - -type CallbackData<'a, 'db> = Either< - PathDiagnosticCallbackData, - crate::infer::diagnostics::PathDiagnosticCallbackData<'a, 'db>, ->; - -// We cannot use `&mut dyn FnMut()` because of lifetime issues, and we don't want to use `Box` -// because of the allocation, so we create a lifetime-less callback, tailored for our needs. -pub(crate) struct PathDiagnosticCallback<'a, 'db> { - pub(crate) data: CallbackData<'a, 'db>, - pub(crate) callback: - fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic), -} - -pub(crate) struct PathLoweringContext<'a, 'b, 'db> { - ctx: &'a mut TyLoweringContext<'db, 'b>, - on_diagnostic: PathDiagnosticCallback<'a, 'db>, - path: &'a Path, - segments: PathSegments<'a>, - current_segment_idx: usize, - /// Contains the previous segment if `current_segment_idx == segments.len()` - current_or_prev_segment: PathSegment<'a>, -} - -impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { - #[inline] - pub(crate) fn new( - ctx: &'a mut TyLoweringContext<'db, 'b>, - on_diagnostic: PathDiagnosticCallback<'a, 'db>, - path: &'a Path, - ) -> Self { - let segments = path.segments(); - let first_segment = segments.first().unwrap_or(PathSegment::MISSING); - Self { - ctx, - on_diagnostic, - path, - segments, - current_segment_idx: 0, - current_or_prev_segment: first_segment, - } - } - - #[inline] - #[cold] - fn on_diagnostic(&mut self, diag: PathLoweringDiagnostic) { - (self.on_diagnostic.callback)(&self.on_diagnostic.data, self.ctx, diag); - } - - #[inline] - pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'db, 'b> { - self.ctx - } - - #[inline] - fn current_segment_u32(&self) -> u32 { - self.current_segment_idx as u32 - } - - #[inline] - fn skip_resolved_segment(&mut self) { - if !matches!(self.path, Path::LangItem(..)) { - // In lang items, the resolved "segment" is not one of the segments. Perhaps we should've put it - // point at -1, but I don't feel this is clearer. - self.current_segment_idx += 1; - } - self.update_current_segment(); - } - - #[inline] - fn update_current_segment(&mut self) { - self.current_or_prev_segment = - self.segments.get(self.current_segment_idx).unwrap_or(self.current_or_prev_segment); - } - - #[inline] - pub(crate) fn ignore_last_segment(&mut self) { - self.segments = self.segments.strip_last(); - } - - #[inline] - pub(crate) fn set_current_segment(&mut self, segment: usize) { - self.current_segment_idx = segment; - self.current_or_prev_segment = self - .segments - .get(segment) - .expect("invalid segment passed to PathLoweringContext::set_current_segment()"); - } - - #[inline] - fn with_lifetime_elision( - &mut self, - lifetime_elision: LifetimeElisionKind<'db>, - f: impl FnOnce(&mut PathLoweringContext<'_, '_, 'db>) -> T, - ) -> T { - let old_lifetime_elision = - std::mem::replace(&mut self.ctx.lifetime_elision, lifetime_elision); - let result = f(self); - self.ctx.lifetime_elision = old_lifetime_elision; - result - } - - pub(crate) fn lower_ty_relative_path( - &mut self, - ty: Ty<'db>, - // We need the original resolution to lower `Self::AssocTy` correctly - res: Option, - infer_args: bool, - ) -> (Ty<'db>, Option) { - let remaining_segments = self.segments.len() - self.current_segment_idx; - match remaining_segments { - 0 => (ty, res), - 1 => { - // resolve unselected assoc types - (self.select_associated_type(res, infer_args), None) - } - _ => { - // FIXME report error (ambiguous associated type) - (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None) - } - } - } - - // When calling this, the current segment is the resolved segment (we don't advance it yet). - pub(crate) fn lower_partly_resolved_path( - &mut self, - resolution: TypeNs, - infer_args: bool, - ) -> (Ty<'db>, Option) { - let remaining_segments = self.segments.skip(self.current_segment_idx + 1); - tracing::debug!(?remaining_segments); - let rem_seg_len = remaining_segments.len(); - tracing::debug!(?rem_seg_len); - - let ty = match resolution { - TypeNs::TraitId(trait_) => { - let ty = match remaining_segments.len() { - 1 => { - let trait_ref = self.lower_trait_ref_from_resolved_path( - trait_, - Ty::new_error(self.ctx.interner, ErrorGuaranteed), - false, - ); - tracing::debug!(?trait_ref); - self.skip_resolved_segment(); - let segment = self.current_or_prev_segment; - let trait_id = trait_ref.def_id.0; - let found = - trait_id.trait_items(self.ctx.db).associated_type_by_name(segment.name); - - tracing::debug!(?found); - match found { - Some(associated_ty) => { - // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent - // generic params. It's inefficient to splice the `Substitution`s, so we may want - // that method to optionally take parent `Substitution` as we already know them at - // this point (`trait_ref.substitution`). - let substitution = self.substs_from_path_segment( - associated_ty.into(), - false, - None, - true, - ); - let args = crate::next_solver::GenericArgs::new_from_iter( - self.ctx.interner, - trait_ref - .args - .iter() - .chain(substitution.iter().skip(trait_ref.args.len())), - ); - Ty::new_alias( - self.ctx.interner, - AliasTyKind::Projection, - AliasTy::new_from_args( - self.ctx.interner, - associated_ty.into(), - args, - ), - ) - } - None => { - // FIXME: report error (associated type not found) - Ty::new_error(self.ctx.interner, ErrorGuaranteed) - } - } - } - 0 => { - // Trait object type without dyn; this should be handled in upstream. See - // `lower_path()`. - stdx::never!("unexpected fully resolved trait path"); - Ty::new_error(self.ctx.interner, ErrorGuaranteed) - } - _ => { - // FIXME report error (ambiguous associated type) - Ty::new_error(self.ctx.interner, ErrorGuaranteed) - } - }; - return (ty, None); - } - TypeNs::GenericParam(param_id) => { - let generics = self.ctx.generics(); - let idx = generics.type_or_const_param_idx(param_id.into()); - match idx { - None => { - never!("no matching generics"); - Ty::new_error(self.ctx.interner, ErrorGuaranteed) - } - Some(idx) => { - let (pidx, _param) = generics.iter().nth(idx).unwrap(); - assert_eq!(pidx, param_id.into()); - self.ctx.type_param(param_id, idx as u32) - } - } - } - TypeNs::SelfType(impl_id) => self.ctx.db.impl_self_ty(impl_id).skip_binder(), - TypeNs::AdtSelfType(adt) => { - let args = crate::next_solver::GenericArgs::identity_for_item( - self.ctx.interner, - adt.into(), - ); - Ty::new_adt(self.ctx.interner, adt, args) - } - - TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args), - TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args), - TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args), - // FIXME: report error - TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => { - return (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None); - } - }; - - tracing::debug!(?ty); - - self.skip_resolved_segment(); - self.lower_ty_relative_path(ty, Some(resolution), infer_args) - } - - /// This returns whether to keep the resolution (`true`) of throw it (`false`). - #[must_use] - fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) -> bool { - let mut prohibit_generics_on_resolved = |reason| { - if self.current_or_prev_segment.args_and_bindings.is_some() { - let segment = self.current_segment_u32(); - self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { - segment, - reason, - }); - } - }; - - match resolution { - TypeNs::SelfType(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy) - } - TypeNs::GenericParam(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::TyParam) - } - TypeNs::AdtSelfType(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy); - - if self.ctx.lowering_param_default.is_some() { - // Generic defaults are not allowed to refer to `Self`. - // FIXME: Emit an error. - return false; - } - } - TypeNs::BuiltinType(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy) - } - TypeNs::ModuleId(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::Module) - } - TypeNs::AdtId(_) - | TypeNs::EnumVariantId(_) - | TypeNs::TypeAliasId(_) - | TypeNs::TraitId(_) => {} - } - - true - } - - pub(crate) fn resolve_path_in_type_ns_fully(&mut self) -> Option { - let (res, unresolved) = self.resolve_path_in_type_ns()?; - if unresolved.is_some() { - return None; - } - Some(res) - } - - #[tracing::instrument(skip(self), ret)] - pub(crate) fn resolve_path_in_type_ns(&mut self) -> Option<(TypeNs, Option)> { - let (resolution, remaining_index, _, prefix_info) = - self.ctx.resolver.resolve_path_in_type_ns_with_prefix_info(self.ctx.db, self.path)?; - - let segments = self.segments; - if segments.is_empty() || matches!(self.path, Path::LangItem(..)) { - // `segments.is_empty()` can occur with `self`. - return Some((resolution, remaining_index)); - } - - let (module_segments, resolved_segment_idx, enum_segment) = match remaining_index { - None if prefix_info.enum_variant => { - (segments.strip_last_two(), segments.len() - 1, Some(segments.len() - 2)) - } - None => (segments.strip_last(), segments.len() - 1, None), - Some(i) => (segments.take(i - 1), i - 1, None), - }; - - self.current_segment_idx = resolved_segment_idx; - self.current_or_prev_segment = - segments.get(resolved_segment_idx).expect("should have resolved segment"); - - for (i, mod_segment) in module_segments.iter().enumerate() { - if mod_segment.args_and_bindings.is_some() { - self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { - segment: i as u32, - reason: GenericArgsProhibitedReason::Module, - }); - } - } - - if let Some(enum_segment) = enum_segment - && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some()) - && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some()) - { - self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { - segment: (enum_segment + 1) as u32, - reason: GenericArgsProhibitedReason::EnumVariant, - }); - } - - if !self.handle_type_ns_resolution(&resolution) { - return None; - } - - Some((resolution, remaining_index)) - } - - pub(crate) fn resolve_path_in_value_ns( - &mut self, - hygiene_id: HygieneId, - ) -> Option { - let (res, prefix_info) = self.ctx.resolver.resolve_path_in_value_ns_with_prefix_info( - self.ctx.db, - self.path, - hygiene_id, - )?; - - let segments = self.segments; - if segments.is_empty() || matches!(self.path, Path::LangItem(..)) { - // `segments.is_empty()` can occur with `self`. - return Some(res); - } - - let (mod_segments, enum_segment, resolved_segment_idx) = match res { - ResolveValueResult::Partial(_, unresolved_segment, _) => { - (segments.take(unresolved_segment - 1), None, unresolved_segment - 1) - } - ResolveValueResult::ValueNs(ValueNs::EnumVariantId(_), _) - if prefix_info.enum_variant => - { - (segments.strip_last_two(), segments.len().checked_sub(2), segments.len() - 1) - } - ResolveValueResult::ValueNs(..) => (segments.strip_last(), None, segments.len() - 1), - }; - - self.current_segment_idx = resolved_segment_idx; - self.current_or_prev_segment = - segments.get(resolved_segment_idx).expect("should have resolved segment"); - - for (i, mod_segment) in mod_segments.iter().enumerate() { - if mod_segment.args_and_bindings.is_some() { - self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { - segment: i as u32, - reason: GenericArgsProhibitedReason::Module, - }); - } - } - - if let Some(enum_segment) = enum_segment - && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some()) - && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some()) - { - self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { - segment: (enum_segment + 1) as u32, - reason: GenericArgsProhibitedReason::EnumVariant, - }); - } - - match &res { - ResolveValueResult::ValueNs(resolution, _) => { - let resolved_segment_idx = self.current_segment_u32(); - let resolved_segment = self.current_or_prev_segment; - - let mut prohibit_generics_on_resolved = |reason| { - if resolved_segment.args_and_bindings.is_some() { - self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited { - segment: resolved_segment_idx, - reason, - }); - } - }; - - match resolution { - ValueNs::ImplSelf(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy); - } - // FIXME: rustc generates E0107 (incorrect number of generic arguments) and not - // E0109 (generic arguments provided for a type that doesn't accept them) for - // consts and statics, presumably as a defense against future in which consts - // and statics can be generic, or just because it was easier for rustc implementors. - // That means we'll show the wrong error code. Because of us it's easier to do it - // this way :) - ValueNs::GenericParam(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const) - } - ValueNs::StaticId(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static) - } - ValueNs::LocalBinding(_) => { - prohibit_generics_on_resolved(GenericArgsProhibitedReason::LocalVariable) - } - ValueNs::FunctionId(_) - | ValueNs::StructId(_) - | ValueNs::EnumVariantId(_) - | ValueNs::ConstId(_) => {} - } - } - ResolveValueResult::Partial(resolution, _, _) => { - if !self.handle_type_ns_resolution(resolution) { - return None; - } - } - }; - Some(res) - } - - #[tracing::instrument(skip(self), ret)] - fn select_associated_type(&mut self, res: Option, infer_args: bool) -> Ty<'db> { - let interner = self.ctx.interner; - let Some(res) = res else { - return Ty::new_error(self.ctx.interner, ErrorGuaranteed); - }; - let def = self.ctx.def; - let segment = self.current_or_prev_segment; - let assoc_name = segment.name; - let check_alias = |name: &Name, t: TraitRef<'db>, associated_ty: TypeAliasId| { - if name != assoc_name { - return None; - } - - // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent - // generic params. It's inefficient to splice the `Substitution`s, so we may want - // that method to optionally take parent `Substitution` as we already know them at - // this point (`t.substitution`). - let substs = - self.substs_from_path_segment(associated_ty.into(), infer_args, None, true); - - let substs = crate::next_solver::GenericArgs::new_from_iter( - interner, - t.args.iter().chain(substs.iter().skip(t.args.len())), - ); - - Some(Ty::new_alias( - interner, - AliasTyKind::Projection, - AliasTy::new(interner, associated_ty.into(), substs), - )) - }; - named_associated_type_shorthand_candidates( - interner, - def, - res, - Some(assoc_name.clone()), - check_alias, - ) - .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)) - } - - fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> { - let generic_def = match typeable { - TyDefId::BuiltinType(builtinty) => { - return Ty::from_builtin_type(self.ctx.interner, builtinty); - } - TyDefId::AdtId(it) => it.into(), - TyDefId::TypeAliasId(it) => it.into(), - }; - let args = self.substs_from_path_segment(generic_def, infer_args, None, false); - let ty = ty_query(self.ctx.db, typeable); - ty.instantiate(self.ctx.interner, args) - } - - /// Collect generic arguments from a path into a `Substs`. See also - /// `create_substs_for_ast_path` and `def_to_ty` in rustc. - pub(crate) fn substs_from_path( - &mut self, - // Note that we don't call `db.value_type(resolved)` here, - // `ValueTyDefId` is just a convenient way to pass generics and - // special-case enum variants - resolved: ValueTyDefId, - infer_args: bool, - lowering_assoc_type_generics: bool, - ) -> crate::next_solver::GenericArgs<'db> { - let interner = self.ctx.interner; - let prev_current_segment_idx = self.current_segment_idx; - let prev_current_segment = self.current_or_prev_segment; - - let generic_def = match resolved { - ValueTyDefId::FunctionId(it) => it.into(), - ValueTyDefId::StructId(it) => it.into(), - ValueTyDefId::UnionId(it) => it.into(), - ValueTyDefId::ConstId(it) => it.into(), - ValueTyDefId::StaticId(_) => { - return crate::next_solver::GenericArgs::new_from_iter(interner, []); - } - ValueTyDefId::EnumVariantId(var) => { - // the generic args for an enum variant may be either specified - // on the segment referring to the enum, or on the segment - // referring to the variant. So `Option::::None` and - // `Option::None::` are both allowed (though the former is - // FIXME: This isn't strictly correct, enum variants may be used not through the enum - // (via `use Enum::Variant`). The resolver returns whether they were, but we don't have its result - // available here. The worst that can happen is that we will show some confusing diagnostics to the user, - // if generics exist on the module and they don't match with the variant. - // preferred). See also `def_ids_for_path_segments` in rustc. - // - // `wrapping_sub(1)` will return a number which `get` will return None for if current_segment_idx<2. - // This simplifies the code a bit. - let penultimate_idx = self.current_segment_idx.wrapping_sub(1); - let penultimate = self.segments.get(penultimate_idx); - if let Some(penultimate) = penultimate - && self.current_or_prev_segment.args_and_bindings.is_none() - && penultimate.args_and_bindings.is_some() - { - self.current_segment_idx = penultimate_idx; - self.current_or_prev_segment = penultimate; - } - var.lookup(self.ctx.db).parent.into() - } - }; - let result = self.substs_from_path_segment( - generic_def, - infer_args, - None, - lowering_assoc_type_generics, - ); - self.current_segment_idx = prev_current_segment_idx; - self.current_or_prev_segment = prev_current_segment; - result - } - - pub(crate) fn substs_from_path_segment( - &mut self, - def: GenericDefId, - infer_args: bool, - explicit_self_ty: Option>, - lowering_assoc_type_generics: bool, - ) -> crate::next_solver::GenericArgs<'db> { - let old_lifetime_elision = self.ctx.lifetime_elision.clone(); - - if let Some(args) = self.current_or_prev_segment.args_and_bindings - && args.parenthesized != GenericArgsParentheses::No - { - let prohibit_parens = match def { - GenericDefId::TraitId(trait_) => { - // RTN is prohibited anyways if we got here. - let is_rtn = args.parenthesized == GenericArgsParentheses::ReturnTypeNotation; - let is_fn_trait = self - .ctx - .db - .trait_signature(trait_) - .flags - .contains(TraitFlags::RUSTC_PAREN_SUGAR); - is_rtn || !is_fn_trait - } - _ => true, - }; - - if prohibit_parens { - let segment = self.current_segment_u32(); - self.on_diagnostic( - PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment }, - ); - - return unknown_subst(self.ctx.interner, def); - } - - // `Fn()`-style generics are treated like functions for the purpose of lifetime elision. - self.ctx.lifetime_elision = - LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false }; - } - - let result = self.substs_from_args_and_bindings( - self.current_or_prev_segment.args_and_bindings, - def, - infer_args, - explicit_self_ty, - PathGenericsSource::Segment(self.current_segment_u32()), - lowering_assoc_type_generics, - self.ctx.lifetime_elision.clone(), - ); - self.ctx.lifetime_elision = old_lifetime_elision; - result - } - - pub(super) fn substs_from_args_and_bindings( - &mut self, - args_and_bindings: Option<&GenericArgs>, - def: GenericDefId, - infer_args: bool, - explicit_self_ty: Option>, - generics_source: PathGenericsSource, - lowering_assoc_type_generics: bool, - lifetime_elision: LifetimeElisionKind<'db>, - ) -> crate::next_solver::GenericArgs<'db> { - struct LowererCtx<'a, 'b, 'c, 'db> { - ctx: &'a mut PathLoweringContext<'b, 'c, 'db>, - generics_source: PathGenericsSource, - } - - impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, '_, 'db> { - fn report_len_mismatch( - &mut self, - def: GenericDefId, - provided_count: u32, - expected_count: u32, - kind: IncorrectGenericsLenKind, - ) { - self.ctx.on_diagnostic(PathLoweringDiagnostic::IncorrectGenericsLen { - generics_source: self.generics_source, - provided_count, - expected_count, - kind, - def, - }); - } - - fn report_arg_mismatch( - &mut self, - param_id: GenericParamId, - arg_idx: u32, - has_self_arg: bool, - ) { - self.ctx.on_diagnostic(PathLoweringDiagnostic::IncorrectGenericsOrder { - generics_source: self.generics_source, - param_id, - arg_idx, - has_self_arg, - }); - } - - fn provided_kind( - &mut self, - param_id: GenericParamId, - param: GenericParamDataRef<'_>, - arg: &GenericArg, - ) -> crate::next_solver::GenericArg<'db> { - match (param, *arg) { - (GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => { - self.ctx.ctx.lower_lifetime(lifetime).into() - } - (GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => { - self.ctx.ctx.lower_ty(type_ref).into() - } - (GenericParamDataRef::ConstParamData(_), GenericArg::Const(konst)) => { - let GenericParamId::ConstParamId(const_id) = param_id else { - unreachable!("non-const param ID for const param"); - }; - self.ctx - .ctx - .lower_const(konst, const_param_ty_query(self.ctx.ctx.db, const_id)) - .into() - } - _ => unreachable!("unmatching param kinds were passed to `provided_kind()`"), - } - } - - fn provided_type_like_const( - &mut self, - const_ty: Ty<'db>, - arg: TypeLikeConst<'_>, - ) -> crate::next_solver::Const<'db> { - match arg { - TypeLikeConst::Path(path) => self.ctx.ctx.lower_path_as_const(path, const_ty), - TypeLikeConst::Infer => unknown_const(const_ty), - } - } - - fn inferred_kind( - &mut self, - def: GenericDefId, - param_id: GenericParamId, - param: GenericParamDataRef<'_>, - infer_args: bool, - preceding_args: &[crate::next_solver::GenericArg<'db>], - ) -> crate::next_solver::GenericArg<'db> { - let default = || { - self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map(|default| { - convert_binder_to_early_binder( - self.ctx.ctx.interner, - def, - default.to_nextsolver(self.ctx.ctx.interner), - ) - .instantiate(self.ctx.ctx.interner, preceding_args) - }) - }; - match param { - GenericParamDataRef::LifetimeParamData(_) => { - Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed)) - .into() - } - GenericParamDataRef::TypeParamData(param) => { - if !infer_args - && param.default.is_some() - && let Some(default) = default() - { - return default; - } - Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into() - } - GenericParamDataRef::ConstParamData(param) => { - if !infer_args - && param.default.is_some() - && let Some(default) = default() - { - return default; - } - let GenericParamId::ConstParamId(const_id) = param_id else { - unreachable!("non-const param ID for const param"); - }; - unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id)) - } - } - } - - fn parent_arg( - &mut self, - param_id: GenericParamId, - ) -> crate::next_solver::GenericArg<'db> { - match param_id { - GenericParamId::TypeParamId(_) => { - Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into() - } - GenericParamId::ConstParamId(const_id) => { - unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id)) - } - GenericParamId::LifetimeParamId(_) => { - Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed)) - .into() - } - } - } - - fn report_elided_lifetimes_in_path( - &mut self, - def: GenericDefId, - expected_count: u32, - hard_error: bool, - ) { - self.ctx.on_diagnostic(PathLoweringDiagnostic::ElidedLifetimesInPath { - generics_source: self.generics_source, - def, - expected_count, - hard_error, - }); - } - - 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, - def, - expected_count, - }); - } - } - - substs_from_args_and_bindings( - self.ctx.db, - self.ctx.store, - args_and_bindings, - def, - infer_args, - lifetime_elision, - lowering_assoc_type_generics, - explicit_self_ty, - &mut LowererCtx { ctx: self, generics_source }, - ) - } - - pub(crate) fn lower_trait_ref_from_resolved_path( - &mut self, - resolved: TraitId, - explicit_self_ty: Ty<'db>, - infer_args: bool, - ) -> TraitRef<'db> { - let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args); - TraitRef::new_from_args(self.ctx.interner, resolved.into(), args) - } - - fn trait_ref_substs_from_path( - &mut self, - resolved: TraitId, - explicit_self_ty: Ty<'db>, - infer_args: bool, - ) -> crate::next_solver::GenericArgs<'db> { - self.substs_from_path_segment(resolved.into(), infer_args, Some(explicit_self_ty), false) - } - - pub(super) fn assoc_type_bindings_from_type_bound<'c>( - mut self, - trait_ref: TraitRef<'db>, - ) -> Option> + use<'a, 'b, 'c, 'db>> { - let interner = self.ctx.interner; - self.current_or_prev_segment.args_and_bindings.map(|args_and_bindings| { - args_and_bindings.bindings.iter().enumerate().flat_map(move |(binding_idx, binding)| { - let found = associated_type_by_name_including_super_traits( - self.ctx.db, - trait_ref, - &binding.name, - ); - let (super_trait_ref, associated_ty) = match found { - None => return SmallVec::new(), - Some(t) => t, - }; - let args = - self.with_lifetime_elision(LifetimeElisionKind::AnonymousReportError, |this| { - // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent - // generic params. It's inefficient to splice the `Substitution`s, so we may want - // that method to optionally take parent `Substitution` as we already know them at - // this point (`super_trait_ref.substitution`). - this.substs_from_args_and_bindings( - binding.args.as_ref(), - associated_ty.into(), - false, // this is not relevant - Some(super_trait_ref.self_ty()), - PathGenericsSource::AssocType { - segment: this.current_segment_u32(), - assoc_type: binding_idx as u32, - }, - false, - this.ctx.lifetime_elision.clone(), - ) - }); - let args = crate::next_solver::GenericArgs::new_from_iter( - interner, - super_trait_ref.args.iter().chain(args.iter().skip(super_trait_ref.args.len())), - ); - let projection_term = - AliasTerm::new_from_args(interner, associated_ty.into(), args); - let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity( - binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), - ); - if let Some(type_ref) = binding.type_ref { - let lifetime_elision = - if args_and_bindings.parenthesized == GenericArgsParentheses::ParenSugar { - // `Fn()`-style generics are elided like functions. This is `Output` (we lower to it in hir-def). - LifetimeElisionKind::for_fn_ret(self.ctx.interner) - } else { - self.ctx.lifetime_elision.clone() - }; - self.with_lifetime_elision(lifetime_elision, |this| { - match (&this.ctx.store[type_ref], this.ctx.impl_trait_mode.mode) { - (TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (), - ( - _, - ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque, - ) => { - let ty = this.ctx.lower_ty(type_ref); - let pred = Clause(Predicate::new( - interner, - Binder::dummy(rustc_type_ir::PredicateKind::Clause( - rustc_type_ir::ClauseKind::Projection( - ProjectionPredicate { - projection_term, - term: ty.into(), - }, - ), - )), - )); - predicates.push(pred); - } - } - }) - } - for bound in binding.bounds.iter() { - predicates.extend(self.ctx.lower_type_bound( - bound, - Ty::new_alias( - self.ctx.interner, - AliasTyKind::Projection, - AliasTy::new_from_args(self.ctx.interner, associated_ty.into(), args), - ), - false, - )); - } - predicates - }) - }) - } -} - -/// A const that were parsed like a type. -pub(crate) enum TypeLikeConst<'a> { - Infer, - Path(&'a Path), -} - -pub(crate) trait GenericArgsLowerer<'db> { - fn report_elided_lifetimes_in_path( - &mut self, - def: GenericDefId, - expected_count: u32, - 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( - &mut self, - def: GenericDefId, - provided_count: u32, - expected_count: u32, - kind: IncorrectGenericsLenKind, - ); - - fn report_arg_mismatch(&mut self, param_id: GenericParamId, arg_idx: u32, has_self_arg: bool); - - fn provided_kind( - &mut self, - param_id: GenericParamId, - param: GenericParamDataRef<'_>, - arg: &GenericArg, - ) -> crate::next_solver::GenericArg<'db>; - - fn provided_type_like_const(&mut self, const_ty: Ty<'db>, arg: TypeLikeConst<'_>) - -> Const<'db>; - - fn inferred_kind( - &mut self, - def: GenericDefId, - param_id: GenericParamId, - param: GenericParamDataRef<'_>, - infer_args: bool, - preceding_args: &[crate::next_solver::GenericArg<'db>], - ) -> crate::next_solver::GenericArg<'db>; - - fn parent_arg(&mut self, param_id: GenericParamId) -> crate::next_solver::GenericArg<'db>; -} - -/// Returns true if there was an error. -fn check_generic_args_len<'db>( - args_and_bindings: Option<&GenericArgs>, - def: GenericDefId, - def_generics: &Generics, - infer_args: bool, - lifetime_elision: &LifetimeElisionKind<'db>, - lowering_assoc_type_generics: bool, - ctx: &mut impl GenericArgsLowerer<'db>, -) -> bool { - let mut had_error = false; - - let (mut provided_lifetimes_count, mut provided_types_and_consts_count) = (0usize, 0usize); - if let Some(args_and_bindings) = args_and_bindings { - let args_no_self = &args_and_bindings.args[usize::from(args_and_bindings.has_self_type)..]; - for arg in args_no_self { - match arg { - GenericArg::Lifetime(_) => provided_lifetimes_count += 1, - GenericArg::Type(_) | GenericArg::Const(_) => provided_types_and_consts_count += 1, - } - } - } - - let lifetime_args_len = def_generics.len_lifetimes_self(); - if provided_lifetimes_count == 0 - && lifetime_args_len > 0 - && (!lowering_assoc_type_generics || infer_args) - { - // In generic associated types, we never allow inferring the lifetimes, but only in type context, that is - // when `infer_args == false`. In expression/pattern context we always allow inferring them, even for GATs. - match lifetime_elision { - &LifetimeElisionKind::AnonymousCreateParameter { report_in_path } => { - ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, report_in_path); - had_error |= report_in_path; - } - LifetimeElisionKind::AnonymousReportError => { - 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); - } - LifetimeElisionKind::Infer => { - // Allow eliding lifetimes. - } - } - } else if lifetime_args_len != provided_lifetimes_count { - ctx.report_len_mismatch( - def, - provided_lifetimes_count as u32, - lifetime_args_len as u32, - IncorrectGenericsLenKind::Lifetimes, - ); - had_error = true; - } - - let defaults_count = - def_generics.iter_self_type_or_consts().filter(|(_, param)| param.has_default()).count(); - let named_type_and_const_params_count = def_generics - .iter_self_type_or_consts() - .filter(|(_, param)| match param { - TypeOrConstParamData::TypeParamData(param) => { - param.provenance == TypeParamProvenance::TypeParamList - } - TypeOrConstParamData::ConstParamData(_) => true, - }) - .count(); - let expected_max = named_type_and_const_params_count; - let expected_min = - if infer_args { 0 } else { named_type_and_const_params_count - defaults_count }; - if provided_types_and_consts_count < expected_min - || expected_max < provided_types_and_consts_count - { - ctx.report_len_mismatch( - def, - provided_types_and_consts_count as u32, - named_type_and_const_params_count as u32, - IncorrectGenericsLenKind::TypesAndConsts, - ); - had_error = true; - } - - had_error -} - -pub(crate) fn substs_from_args_and_bindings<'db>( - db: &'db dyn HirDatabase, - store: &ExpressionStore, - args_and_bindings: Option<&GenericArgs>, - def: GenericDefId, - mut infer_args: bool, - lifetime_elision: LifetimeElisionKind<'db>, - lowering_assoc_type_generics: bool, - explicit_self_ty: Option>, - ctx: &mut impl GenericArgsLowerer<'db>, -) -> crate::next_solver::GenericArgs<'db> { - let interner = DbInterner::new_with(db, None, None); - - tracing::debug!(?args_and_bindings); - - // Order is - // - Parent parameters - // - Optional Self parameter - // - Lifetime parameters - // - Type or Const parameters - let def_generics = generics(db, def); - let args_slice = args_and_bindings.map(|it| &*it.args).unwrap_or_default(); - - // We do not allow inference if there are specified args, i.e. we do not allow partial inference. - let has_non_lifetime_args = - args_slice.iter().any(|arg| !matches!(arg, GenericArg::Lifetime(_))); - infer_args &= !has_non_lifetime_args; - - let had_count_error = check_generic_args_len( - args_and_bindings, - def, - &def_generics, - infer_args, - &lifetime_elision, - lowering_assoc_type_generics, - ctx, - ); - - let mut substs = Vec::with_capacity(def_generics.len()); - - substs.extend(def_generics.iter_parent_id().map(|id| ctx.parent_arg(id))); - - let mut args = args_slice.iter().enumerate().peekable(); - let mut params = def_generics.iter_self().peekable(); - - // If we encounter a type or const when we expect a lifetime, we infer the lifetimes. - // If we later encounter a lifetime, we know that the arguments were provided in the - // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be - // inferred, so we can use it for diagnostics later. - let mut force_infer_lt = None; - - let has_self_arg = args_and_bindings.is_some_and(|it| it.has_self_type); - // First, handle `Self` parameter. Consume it from the args if provided, otherwise from `explicit_self_ty`, - // and lastly infer it. - if let Some(&( - self_param_id, - self_param @ GenericParamDataRef::TypeParamData(TypeParamData { - provenance: TypeParamProvenance::TraitSelf, - .. - }), - )) = params.peek() - { - let self_ty = if has_self_arg { - let (_, self_ty) = args.next().expect("has_self_type=true, should have Self type"); - ctx.provided_kind(self_param_id, self_param, self_ty) - } else { - explicit_self_ty.map(|it| it.into()).unwrap_or_else(|| { - ctx.inferred_kind(def, self_param_id, self_param, infer_args, &substs) - }) - }; - params.next(); - substs.push(self_ty); - } - - loop { - // We're going to iterate through the generic arguments that the user - // provided, matching them with the generic parameters we expect. - // Mismatches can occur as a result of elided lifetimes, or for malformed - // input. We try to handle both sensibly. - match (args.peek(), params.peek()) { - (Some(&(arg_idx, arg)), Some(&(param_id, param))) => match (arg, param) { - (GenericArg::Type(_), GenericParamDataRef::TypeParamData(type_param)) - if type_param.provenance == TypeParamProvenance::ArgumentImplTrait => - { - // Do not allow specifying `impl Trait` explicitly. We already err at that, but if we won't handle it here - // we will handle it as if it was specified, instead of inferring it. - substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs)); - params.next(); - } - (GenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_)) - | (GenericArg::Type(_), GenericParamDataRef::TypeParamData(_)) - | (GenericArg::Const(_), GenericParamDataRef::ConstParamData(_)) => { - substs.push(ctx.provided_kind(param_id, param, arg)); - args.next(); - params.next(); - } - ( - GenericArg::Type(_) | GenericArg::Const(_), - GenericParamDataRef::LifetimeParamData(_), - ) => { - // We expected a lifetime argument, but got a type or const - // argument. That means we're inferring the lifetime. - substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs)); - params.next(); - force_infer_lt = Some((arg_idx as u32, param_id)); - } - (GenericArg::Type(type_ref), GenericParamDataRef::ConstParamData(_)) => { - if let Some(konst) = type_looks_like_const(store, *type_ref) { - let GenericParamId::ConstParamId(param_id) = param_id else { - panic!("unmatching param kinds"); - }; - let const_ty = const_param_ty_query(db, param_id); - substs.push(ctx.provided_type_like_const(const_ty, konst).into()); - args.next(); - params.next(); - } else { - // See the `_ => { ... }` branch. - if !had_count_error { - ctx.report_arg_mismatch(param_id, arg_idx as u32, has_self_arg); - } - while args.next().is_some() {} - } - } - _ => { - // We expected one kind of parameter, but the user provided - // another. This is an error. However, if we already know that - // the arguments don't match up with the parameters, we won't issue - // an additional error, as the user already knows what's wrong. - if !had_count_error { - ctx.report_arg_mismatch(param_id, arg_idx as u32, has_self_arg); - } - - // We've reported the error, but we want to make sure that this - // problem doesn't bubble down and create additional, irrelevant - // errors. In this case, we're simply going to ignore the argument - // and any following arguments. The rest of the parameters will be - // inferred. - while args.next().is_some() {} - } - }, - - (Some(&(_, arg)), None) => { - // We should never be able to reach this point with well-formed input. - // There are two situations in which we can encounter this issue. - // - // 1. The number of arguments is incorrect. In this case, an error - // will already have been emitted, and we can ignore it. - // 2. We've inferred some lifetimes, which have been provided later (i.e. - // after a type or const). We want to throw an error in this case. - if !had_count_error { - assert!( - matches!(arg, GenericArg::Lifetime(_)), - "the only possible situation here is incorrect lifetime order" - ); - let (provided_arg_idx, param_id) = - force_infer_lt.expect("lifetimes ought to have been inferred"); - ctx.report_arg_mismatch(param_id, provided_arg_idx, has_self_arg); - } - - break; - } - - (None, Some(&(param_id, param))) => { - // 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::AnonymousReportError => { - assert!(had_count_error); - ctx.inferred_kind(def, param_id, param, infer_args, &substs) - } - LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => { - Region::new_static(interner).into() - } - LifetimeElisionKind::Elided(lifetime) => (*lifetime).into(), - LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false } - | LifetimeElisionKind::Infer => { - // FIXME: With `AnonymousCreateParameter`, we need to create a new lifetime parameter here - // (but this will probably be done in hir-def lowering instead). - ctx.inferred_kind(def, param_id, param, infer_args, &substs) - } - } - } else { - ctx.inferred_kind(def, param_id, param, infer_args, &substs) - }; - substs.push(param); - params.next(); - } - - (None, None) => break, - } - } - - crate::next_solver::GenericArgs::new_from_iter(interner, substs) -} - -fn type_looks_like_const( - store: &ExpressionStore, - type_ref: TypeRefId, -) -> Option> { - // A path/`_` const will be parsed as a type, instead of a const, because when parsing/lowering - // in hir-def we don't yet know the expected argument kind. rustc does this a bit differently, - // when lowering to HIR it resolves the path, and if it doesn't resolve to the type namespace - // it is lowered as a const. Our behavior could deviate from rustc when the value is resolvable - // in both the type and value namespaces, but I believe we only allow more code. - let type_ref = &store[type_ref]; - match type_ref { - TypeRef::Path(path) => Some(TypeLikeConst::Path(path)), - TypeRef::Placeholder => Some(TypeLikeConst::Infer), - _ => None, - } -} - -fn unknown_subst<'db>( - interner: DbInterner<'db>, - def: impl Into, -) -> crate::next_solver::GenericArgs<'db> { - let params = generics(interner.db(), def.into()); - crate::next_solver::GenericArgs::new_from_iter( - interner, - params.iter_id().map(|id| match id { - GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(), - GenericParamId::ConstParamId(id) => { - unknown_const_as_generic(const_param_ty_query(interner.db(), id)) - } - GenericParamId::LifetimeParamId(_) => { - crate::next_solver::Region::error(interner).into() - } - }), - ) -} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs deleted file mode 100644 index 5125a38825cb..000000000000 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs +++ /dev/null @@ -1,169 +0,0 @@ -//! This module contains the implementations of the `ToChalk` trait, which -//! handles conversion between our data types and their corresponding types in -//! Chalk (in both directions); plus some helper functions for more specialized -//! conversions. - -use hir_def::{LifetimeParamId, TraitId, TypeAliasId, TypeOrConstParamId}; -use salsa::{ - Id, - plumbing::{AsId, FromId}, -}; - -use crate::{ - AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, Interner, OpaqueTyId, - PlaceholderIndex, chalk_db, - db::{HirDatabase, InternedLifetimeParamId, InternedTypeOrConstParamId}, -}; - -pub trait ToChalk { - type Chalk; - fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; - fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; -} - -pub(crate) fn from_chalk(db: &dyn HirDatabase, chalk: ChalkT) -> T -where - T: ToChalk, -{ - T::from_chalk(db, chalk) -} - -impl ToChalk for hir_def::ImplId { - type Chalk = chalk_db::ImplId; - - fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::ImplId { - chalk_ir::ImplId(self.as_id()) - } - - fn from_chalk(_db: &dyn HirDatabase, impl_id: chalk_db::ImplId) -> hir_def::ImplId { - FromId::from_id(impl_id.0.as_id()) - } -} - -impl ToChalk for CallableDefId { - type Chalk = FnDefId; - - fn to_chalk(self, _db: &dyn HirDatabase) -> FnDefId { - chalk_ir::FnDefId(salsa::plumbing::AsId::as_id(&self)) - } - - fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId { - salsa::plumbing::FromIdWithDb::from_id(fn_def_id.0, db.zalsa()) - } -} - -impl From for crate::db::InternedOpaqueTyId { - fn from(id: OpaqueTyId) -> Self { - FromId::from_id(id.0) - } -} - -impl From for OpaqueTyId { - fn from(id: crate::db::InternedOpaqueTyId) -> Self { - chalk_ir::OpaqueTyId(id.as_id()) - } -} - -impl From> for crate::db::InternedClosureId { - fn from(id: chalk_ir::ClosureId) -> Self { - FromId::from_id(id.0) - } -} - -impl From for chalk_ir::ClosureId { - fn from(id: crate::db::InternedClosureId) -> Self { - chalk_ir::ClosureId(id.as_id()) - } -} - -impl From> for crate::db::InternedCoroutineId { - fn from(id: chalk_ir::CoroutineId) -> Self { - Self::from_id(id.0) - } -} - -impl From for chalk_ir::CoroutineId { - fn from(id: crate::db::InternedCoroutineId) -> Self { - chalk_ir::CoroutineId(id.as_id()) - } -} - -pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { - chalk_ir::ForeignDefId(id.as_id()) -} - -pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId { - FromId::from_id(id.0) -} - -pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId { - chalk_ir::AssocTypeId(id.as_id()) -} - -pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId { - FromId::from_id(id.0) -} - -pub fn from_placeholder_idx( - db: &dyn HirDatabase, - idx: PlaceholderIndex, -) -> (TypeOrConstParamId, u32) { - assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); - // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound. - let interned_id = - InternedTypeOrConstParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) }); - interned_id.loc(db) -} - -pub fn to_placeholder_idx( - db: &dyn HirDatabase, - id: TypeOrConstParamId, - idx: u32, -) -> PlaceholderIndex { - let interned_id = InternedTypeOrConstParamId::new(db, (id, idx)); - PlaceholderIndex { - ui: chalk_ir::UniverseIndex::ROOT, - idx: interned_id.as_id().index() as usize, - } -} - -pub fn to_placeholder_idx_no_index( - db: &dyn HirDatabase, - id: TypeOrConstParamId, -) -> PlaceholderIndex { - let index = crate::generics::generics(db, id.parent) - .type_or_const_param_idx(id) - .expect("param not found"); - to_placeholder_idx(db, id, index as u32) -} - -pub fn lt_from_placeholder_idx( - db: &dyn HirDatabase, - idx: PlaceholderIndex, -) -> (LifetimeParamId, u32) { - assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); - // SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound. - let interned_id = - InternedLifetimeParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) }); - interned_id.loc(db) -} - -pub fn lt_to_placeholder_idx( - db: &dyn HirDatabase, - id: LifetimeParamId, - idx: u32, -) -> PlaceholderIndex { - let interned_id = InternedLifetimeParamId::new(db, (id, idx)); - PlaceholderIndex { - ui: chalk_ir::UniverseIndex::ROOT, - idx: interned_id.as_id().index() as usize, - } -} - -pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { - chalk_ir::TraitId(id.as_id()) -} - -pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId { - FromId::from_id(id.0) -} 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 bce17905037c..cec63566338f 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 @@ -25,10 +25,8 @@ use smallvec::{SmallVec, smallvec}; use stdx::never; use triomphe::Arc; -use crate::next_solver::infer::InferCtxt; -use crate::next_solver::infer::select::ImplSource; use crate::{ - TraitEnvironment, TyBuilder, + TraitEnvironment, autoderef::{self, AutoderefKind}, db::HirDatabase, infer::{Adjust, Adjustment, OverloadedDeref, PointerCast, unify::InferenceTable}, @@ -37,7 +35,8 @@ use crate::{ Canonical, DbInterner, ErrorGuaranteed, GenericArgs, Goal, Predicate, Region, SolverDefId, TraitRef, Ty, TyKind, TypingMode, infer::{ - DbInternerInferExt, + DbInternerInferExt, InferCtxt, + select::ImplSource, traits::{Obligation, ObligationCause, PredicateObligation}, }, obligation_ctxt::ObligationCtxt, @@ -1597,9 +1596,9 @@ fn is_valid_impl_method_candidate<'db>( return IsValidCandidate::NotVisible; } let self_ty_matches = table.run_in_snapshot(|table| { - let expected_self_ty = TyBuilder::impl_self_ty(db, impl_id) - .fill_with_inference_vars(table) - .build(table.interner()); + let impl_args = table.fresh_args_for_item(impl_id.into()); + let expected_self_ty = + db.impl_self_ty(impl_id).instantiate(table.interner(), impl_args); table.unify(expected_self_ty, self_ty) }); if !self_ty_matches { @@ -1727,7 +1726,7 @@ fn is_valid_impl_fn_candidate<'db>( // We need to consider the bounds on the impl to distinguish functions of the same name // for a type. - let predicates = db.generic_predicates_ns(impl_id.into()); + let predicates = db.generic_predicates(impl_id.into()); let Some(predicates) = predicates.instantiate(table.interner(), impl_subst) else { return IsValidCandidate::Yes; }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index 936895fb7fd3..7aebe17e5b4e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -196,7 +196,7 @@ impl ProjectionElem { }, ProjectionElem::Field(Either::Left(f)) => match base.kind() { TyKind::Adt(_, subst) => { - db.field_types_ns(f.parent)[f.local_id].instantiate(interner, subst) + db.field_types(f.parent)[f.local_id].instantiate(interner, subst) } ty => { never!("Only adt has field, found {:?}", ty); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 444336ca3f9b..6e62bcbbddef 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -1696,7 +1696,7 @@ impl<'db> Evaluator<'db> { if let TyKind::Adt(adt_ef, subst) = kind && let AdtId::StructId(struct_id) = adt_ef.def_id().0 { - let field_types = self.db.field_types_ns(struct_id.into()); + let field_types = self.db.field_types(struct_id.into()); if let Some(ty) = field_types.iter().last().map(|it| it.1.instantiate(self.interner(), subst)) { @@ -1775,9 +1775,9 @@ impl<'db> Evaluator<'db> { else { not_supported!("unsizing struct without field"); }; - let target_last_field = self.db.field_types_ns(id.into())[last_field] + let target_last_field = self.db.field_types(id.into())[last_field] .instantiate(self.interner(), target_subst); - let current_last_field = self.db.field_types_ns(id.into())[last_field] + let current_last_field = self.db.field_types(id.into())[last_field] .instantiate(self.interner(), current_subst); return self.unsizing_ptr_from_addr( target_last_field, @@ -2268,7 +2268,7 @@ impl<'db> Evaluator<'db> { AdtId::StructId(s) => { let data = s.fields(this.db); let layout = this.layout(ty)?; - let field_types = this.db.field_types_ns(s.into()); + let field_types = this.db.field_types(s.into()); for (f, _) in data.fields().iter() { let offset = layout .fields @@ -2296,7 +2296,7 @@ impl<'db> Evaluator<'db> { e, ) { let data = v.fields(this.db); - let field_types = this.db.field_types_ns(v.into()); + let field_types = this.db.field_types(v.into()); for (f, _) in data.fields().iter() { let offset = l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize(); @@ -2373,7 +2373,7 @@ impl<'db> Evaluator<'db> { } TyKind::Adt(id, args) => match id.def_id().0 { AdtId::StructId(s) => { - for (i, (_, ty)) in self.db.field_types_ns(s.into()).iter().enumerate() { + for (i, (_, ty)) in self.db.field_types(s.into()).iter().enumerate() { let offset = layout.fields.offset(i).bytes_usize(); let ty = ty.instantiate(self.interner(), args); self.patch_addresses( @@ -2394,7 +2394,7 @@ impl<'db> Evaluator<'db> { self.read_memory(addr, layout.size.bytes_usize())?, e, ) { - for (i, (_, ty)) in self.db.field_types_ns(ev.into()).iter().enumerate() { + for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() { let offset = layout.fields.offset(i).bytes_usize(); let ty = ty.instantiate(self.interner(), args); self.patch_addresses( @@ -2895,7 +2895,7 @@ impl<'db> Evaluator<'db> { let variant_fields = s.fields(self.db); match variant_fields.shape { FieldsShape::Record | FieldsShape::Tuple => { - let field_types = self.db.field_types_ns(s.into()); + let field_types = self.db.field_types(s.into()); for (field, _) in variant_fields.fields().iter() { let offset = layout .fields diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index c45ae9dcc3d3..4b1adecf8c87 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -1383,7 +1383,7 @@ impl<'db> Evaluator<'db> { AdtId::StructId(s) => s, _ => not_supported!("unsized enum or union"), }; - let field_types = self.db.field_types_ns(id.into()); + let field_types = self.db.field_types(id.into()); let last_field_ty = field_types.iter().next_back().unwrap().1.instantiate(self.interner(), subst); let sized_part_size = diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs index ade94b94c0ee..4c64a70a7a62 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs @@ -34,7 +34,7 @@ impl<'db> Evaluator<'db> { let Some((first_field, _)) = fields.iter().next() else { not_supported!("simd type with no field"); }; - let field_ty = self.db.field_types_ns(id.into())[first_field] + let field_ty = self.db.field_types(id.into())[first_field] .instantiate(self.interner(), subst); return Ok((fields.len(), field_ty)); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs index f5b4fa1e2a00..1fb9a82ac9e0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs @@ -32,7 +32,7 @@ pub use region::*; pub use solver::*; pub use ty::*; -pub use crate::lower_nextsolver::ImplTraitIdx; +pub use crate::lower::ImplTraitIdx; pub use rustc_ast_ir::Mutability; pub type Binder<'db, T> = rustc_type_ir::Binder, T>; 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 8d81a382c362..c28af948bfc8 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 @@ -14,8 +14,7 @@ use rustc_type_ir::{ use crate::{ MemoryMap, - interner::InternedWrapperNoDebug, - next_solver::{ClauseKind, ParamEnv}, + next_solver::{ClauseKind, ParamEnv, interner::InternedWrapperNoDebug}, }; use super::{BoundVarKind, DbInterner, ErrorGuaranteed, GenericArgs, Placeholder, Ty}; 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 b2632ba63709..24f22bcb0c3e 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 @@ -207,7 +207,7 @@ impl<'db> GenericArgs<'db> { where F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, { - let defaults = interner.db.generic_defaults_ns(def_id); + let defaults = interner.db.generic_defaults(def_id); Self::for_item(interner, def_id.into(), |idx, id, prev| match defaults.get(idx as usize) { Some(default) => default.instantiate(interner, prev), None => fallback(idx, id, prev), @@ -240,7 +240,7 @@ impl<'db> GenericArgs<'db> { where F: FnMut(u32, GenericParamId, &[GenericArg<'db>]) -> GenericArg<'db>, { - let defaults = interner.db.generic_defaults_ns(def_id); + let defaults = interner.db.generic_defaults(def_id); Self::fill_rest(interner, def_id.into(), first, |idx, id, prev| { defaults .get(idx as usize) 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 331bcdcb26d3..42f1d926d7db 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 @@ -32,8 +32,8 @@ use crate::{ method_resolution::{ALL_FLOAT_FPS, ALL_INT_FPS, TyFingerprint}, next_solver::{ AdtIdWrapper, BoundConst, CallableIdWrapper, CanonicalVarKind, ClosureIdWrapper, - CoroutineIdWrapper, Ctor, FnSig, FxIndexMap, ImplIdWrapper, InternedWrapperNoDebug, - RegionAssumptions, SolverContext, SolverDefIds, TraitIdWrapper, TypeAliasIdWrapper, + CoroutineIdWrapper, Ctor, FnSig, FxIndexMap, ImplIdWrapper, RegionAssumptions, + SolverContext, SolverDefIds, TraitIdWrapper, TypeAliasIdWrapper, util::{ContainsTypeErrors, explicit_item_bounds, for_trait_impls}, }, }; @@ -53,6 +53,9 @@ use super::{ util::sizedness_constraint_for_ty, }; +#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)] +pub struct InternedWrapperNoDebug(pub(crate) T); + #[macro_export] #[doc(hidden)] macro_rules! _interned_vec_nolifetime_salsa { @@ -611,7 +614,7 @@ impl<'db> inherent::AdtDef> for AdtDef { return None; }; let id: VariantId = struct_id.into(); - let field_types = interner.db().field_types_ns(id); + let field_types = interner.db().field_types(id); field_types.iter().last().map(|f| *f.1) } @@ -623,7 +626,7 @@ impl<'db> inherent::AdtDef> for AdtDef { let db = interner.db(); // FIXME: this is disabled just to match the behavior with chalk right now let _field_tys = |id: VariantId| { - db.field_types_ns(id).iter().map(|(_, ty)| ty.skip_binder()).collect::>() + db.field_types(id).iter().map(|(_, ty)| ty.skip_binder()).collect::>() }; let field_tys = |_id: VariantId| vec![]; let tys: Vec<_> = match self.inner().id { @@ -1284,7 +1287,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { self, def_id: Self::DefId, ) -> EarlyBinder> { - let predicates = self.db().generic_predicates_ns(def_id.try_into().unwrap()); + let predicates = self.db().generic_predicates(def_id.try_into().unwrap()); let predicates: Vec<_> = predicates.iter().cloned().collect(); EarlyBinder::bind(predicates.into_iter()) } @@ -1311,7 +1314,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { let predicates: Vec<(Clause<'db>, Span)> = self .db() - .generic_predicates_ns(def_id.0.into()) + .generic_predicates(def_id.0.into()) .iter() .filter(|p| match p.kind().skip_binder() { // rustc has the following assertion: @@ -1345,7 +1348,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { let predicates: Vec<(Clause<'db>, Span)> = self .db() - .generic_predicates_ns(def_id.try_into().unwrap()) + .generic_predicates(def_id.try_into().unwrap()) .iter() .filter(|p| match p.kind().skip_binder() { rustc_type_ir::ClauseKind::Trait(it) => is_self_or_assoc(it.self_ty()), @@ -1765,7 +1768,7 @@ impl<'db> rustc_type_ir::Interner for DbInterner<'db> { return UnsizingParams(DenseBitSet::new_empty(num_params)); }; - let field_types = self.db().field_types_ns(variant.id()); + let field_types = self.db().field_types(variant.id()); let mut unsizing_params = DenseBitSet::new_empty(num_params); let ty = field_types[tail_field.0]; for arg in ty.instantiate_identity().walk() { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/mapping.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/mapping.rs index 671f06f1b88a..2b29561393ee 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/mapping.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/mapping.rs @@ -1,1736 +1,13 @@ //! Things useful for mapping to/from Chalk and next-trait-solver types. -use chalk_ir::{ - InferenceVar, Substitution, TyVariableKind, WellFormed, cast::Cast, fold::Shift, - interner::HasInterner, -}; -use hir_def::{CallableDefId, ConstParamId, GeneralConstId, TypeParamId, signatures::TraitFlags}; -use hir_def::{GenericDefId, GenericParamId}; -use rustc_type_ir::{ - AliasTerm, BoundVar, DebruijnIndex, ExistentialProjection, ExistentialTraitRef, - OutlivesPredicate, ProjectionPredicate, TypeFoldable, TypeSuperFoldable, TypeVisitable, - UniverseIndex, elaborate, - inherent::{BoundVarLike, IntoKind, SliceLike, Ty as _}, - shift_vars, - solve::Goal, -}; +use crate::next_solver::interner::DbInterner; -use crate::next_solver::BoundConst; -use crate::{ - ConstScalar, Interner, MemoryMap, - db::{InternedClosureId, InternedCoroutineId, InternedOpaqueTyId}, - from_assoc_type_id, from_chalk_trait_id, - mapping::ToChalk, - next_solver::{ - Binder, ClauseKind, ConstBytes, TraitPredicate, UnevaluatedConst, - interner::{AdtDef, BoundVarKind, BoundVarKinds, DbInterner}, - }, - to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id, -}; -use crate::{ - from_placeholder_idx, lt_from_placeholder_idx, lt_to_placeholder_idx, to_placeholder_idx, -}; - -use super::{ - BoundExistentialPredicates, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, Canonical, - CanonicalVars, Clause, Clauses, Const, EarlyParamRegion, ErrorGuaranteed, ExistentialPredicate, - GenericArg, GenericArgs, ParamConst, ParamEnv, ParamTy, Predicate, PredicateKind, Region, - SolverDefId, SubtypePredicate, Term, TraitRef, Ty, Tys, ValueConst, -}; - -// FIXME: This should urgently go (as soon as we finish the migration off Chalk, that is). -pub fn convert_binder_to_early_binder<'db, T: rustc_type_ir::TypeFoldable>>( - interner: DbInterner<'db>, - def: GenericDefId, - binder: rustc_type_ir::Binder, T>, -) -> rustc_type_ir::EarlyBinder, T> { - let mut folder = BinderToEarlyBinder { - interner, - debruijn: rustc_type_ir::DebruijnIndex::ZERO, - params: crate::generics::generics(interner.db, def).iter_id().collect(), - }; - rustc_type_ir::EarlyBinder::bind(binder.skip_binder().fold_with(&mut folder)) -} - -struct BinderToEarlyBinder<'db> { - interner: DbInterner<'db>, - debruijn: rustc_type_ir::DebruijnIndex, - params: Vec, -} - -impl<'db> rustc_type_ir::TypeFolder> for BinderToEarlyBinder<'db> { - fn cx(&self) -> DbInterner<'db> { - self.interner - } - - fn fold_binder( - &mut self, - t: rustc_type_ir::Binder, T>, - ) -> rustc_type_ir::Binder, T> - where - T: TypeFoldable>, - { - self.debruijn.shift_in(1); - let result = t.super_fold_with(self); - self.debruijn.shift_out(1); - result - } - - fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> { - match t.kind() { - rustc_type_ir::TyKind::Bound(debruijn, bound_ty) if self.debruijn == debruijn => { - let var: rustc_type_ir::BoundVar = bound_ty.var(); - let GenericParamId::TypeParamId(id) = self.params[bound_ty.var.as_usize()] else { - unreachable!() - }; - Ty::new( - self.cx(), - rustc_type_ir::TyKind::Param(ParamTy { index: var.as_u32(), id }), - ) - } - _ => t.super_fold_with(self), - } - } - - fn fold_region(&mut self, r: Region<'db>) -> Region<'db> { - match r.kind() { - rustc_type_ir::ReBound(debruijn, bound_region) if self.debruijn == debruijn => { - let var: rustc_type_ir::BoundVar = bound_region.var(); - let GenericParamId::LifetimeParamId(id) = self.params[bound_region.var.as_usize()] - else { - unreachable!() - }; - Region::new( - self.cx(), - rustc_type_ir::RegionKind::ReEarlyParam(EarlyParamRegion { - index: var.as_u32(), - id, - }), - ) - } - _ => r, - } - } - - fn fold_const(&mut self, c: Const<'db>) -> Const<'db> { - match c.kind() { - rustc_type_ir::ConstKind::Bound(debruijn, var) if self.debruijn == debruijn => { - let GenericParamId::ConstParamId(id) = self.params[var.var.as_usize()] else { - unreachable!() - }; - Const::new( - self.cx(), - rustc_type_ir::ConstKind::Param(ParamConst { index: var.var.as_u32(), id }), - ) - } - _ => c.super_fold_with(self), - } - } -} - -pub trait ChalkToNextSolver<'db, Out> { +pub(crate) trait ChalkToNextSolver<'db, Out> { fn to_nextsolver(&self, interner: DbInterner<'db>) -> Out; } -impl<'db, A, OutA, B, OutB> ChalkToNextSolver<'db, (OutA, OutB)> for (A, B) -where - A: ChalkToNextSolver<'db, OutA>, - B: ChalkToNextSolver<'db, OutB>, -{ - fn to_nextsolver(&self, interner: DbInterner<'db>) -> (OutA, OutB) { - (self.0.to_nextsolver(interner), self.1.to_nextsolver(interner)) - } -} - -pub trait NextSolverToChalk<'db, Out> { - fn to_chalk(self, interner: DbInterner<'db>) -> Out; -} - -impl<'db, T, Out> NextSolverToChalk<'db, Option> for Option -where - T: NextSolverToChalk<'db, Out>, -{ - fn to_chalk(self, interner: DbInterner<'db>) -> Option { - self.map(|it| it.to_chalk(interner)) - } -} - -impl NextSolverToChalk<'_, chalk_ir::Mutability> for rustc_ast_ir::Mutability { - fn to_chalk(self, _interner: DbInterner<'_>) -> chalk_ir::Mutability { - match self { - rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not, - rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut, - } - } -} - -impl NextSolverToChalk<'_, chalk_ir::Safety> for crate::next_solver::abi::Safety { - fn to_chalk(self, _interner: DbInterner<'_>) -> chalk_ir::Safety { - match self { - crate::next_solver::abi::Safety::Unsafe => chalk_ir::Safety::Unsafe, - crate::next_solver::abi::Safety::Safe => chalk_ir::Safety::Safe, - } - } -} - -impl<'db> ChalkToNextSolver<'db, Ty<'db>> for chalk_ir::Ty { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> Ty<'db> { - Ty::new( - interner, - match self.kind(Interner) { - chalk_ir::TyKind::Adt(adt_id, substitution) => { - let def = AdtDef::new(adt_id.0, interner); - let args = substitution.to_nextsolver(interner); - rustc_type_ir::TyKind::Adt(def, args) - } - chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution) => { - let def_id = SolverDefId::TypeAliasId(from_assoc_type_id(*assoc_type_id)); - let args: GenericArgs<'db> = substitution.to_nextsolver(interner); - let alias_ty = rustc_type_ir::AliasTy::new(interner, def_id, args.iter()); - rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Projection, alias_ty) - } - chalk_ir::TyKind::Scalar(scalar) => match scalar { - chalk_ir::Scalar::Bool => rustc_type_ir::TyKind::Bool, - chalk_ir::Scalar::Char => rustc_type_ir::TyKind::Char, - chalk_ir::Scalar::Int(chalk_ir::IntTy::Isize) => { - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::Isize) - } - chalk_ir::Scalar::Int(chalk_ir::IntTy::I8) => { - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I8) - } - chalk_ir::Scalar::Int(chalk_ir::IntTy::I16) => { - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I16) - } - chalk_ir::Scalar::Int(chalk_ir::IntTy::I32) => { - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I32) - } - chalk_ir::Scalar::Int(chalk_ir::IntTy::I64) => { - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I64) - } - chalk_ir::Scalar::Int(chalk_ir::IntTy::I128) => { - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I128) - } - chalk_ir::Scalar::Uint(chalk_ir::UintTy::Usize) => { - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::Usize) - } - chalk_ir::Scalar::Uint(chalk_ir::UintTy::U8) => { - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U8) - } - chalk_ir::Scalar::Uint(chalk_ir::UintTy::U16) => { - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U16) - } - chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32) => { - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U32) - } - chalk_ir::Scalar::Uint(chalk_ir::UintTy::U64) => { - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U64) - } - chalk_ir::Scalar::Uint(chalk_ir::UintTy::U128) => { - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U128) - } - chalk_ir::Scalar::Float(chalk_ir::FloatTy::F16) => { - rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F16) - } - chalk_ir::Scalar::Float(chalk_ir::FloatTy::F32) => { - rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F32) - } - chalk_ir::Scalar::Float(chalk_ir::FloatTy::F64) => { - rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F64) - } - chalk_ir::Scalar::Float(chalk_ir::FloatTy::F128) => { - rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F128) - } - }, - chalk_ir::TyKind::Tuple(_, substitution) => { - let args = substitution.to_nextsolver(interner); - rustc_type_ir::TyKind::Tuple(args) - } - chalk_ir::TyKind::Array(ty, len) => rustc_type_ir::TyKind::Array( - ty.to_nextsolver(interner), - len.to_nextsolver(interner), - ), - chalk_ir::TyKind::Slice(ty) => { - rustc_type_ir::TyKind::Slice(ty.to_nextsolver(interner)) - } - chalk_ir::TyKind::Raw(mutability, ty) => rustc_type_ir::RawPtr( - ty.to_nextsolver(interner), - mutability.to_nextsolver(interner), - ), - chalk_ir::TyKind::Ref(mutability, lifetime, ty) => rustc_type_ir::TyKind::Ref( - lifetime.to_nextsolver(interner), - ty.to_nextsolver(interner), - mutability.to_nextsolver(interner), - ), - chalk_ir::TyKind::OpaqueType(def_id, substitution) => { - let id: InternedOpaqueTyId = (*def_id).into(); - let args: GenericArgs<'db> = substitution.to_nextsolver(interner); - let alias_ty = rustc_type_ir::AliasTy::new(interner, id.into(), args); - rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Opaque, alias_ty) - } - chalk_ir::TyKind::FnDef(fn_def_id, substitution) => { - let def_id = CallableDefId::from_chalk(interner.db(), *fn_def_id); - rustc_type_ir::TyKind::FnDef( - def_id.into(), - substitution.to_nextsolver(interner), - ) - } - chalk_ir::TyKind::Str => rustc_type_ir::TyKind::Str, - chalk_ir::TyKind::Never => rustc_type_ir::TyKind::Never, - chalk_ir::TyKind::Closure(closure_id, substitution) => { - let id: InternedClosureId = (*closure_id).into(); - rustc_type_ir::TyKind::Closure(id.into(), substitution.to_nextsolver(interner)) - } - chalk_ir::TyKind::Coroutine(coroutine_id, substitution) => { - let id: InternedCoroutineId = (*coroutine_id).into(); - rustc_type_ir::TyKind::Coroutine( - id.into(), - substitution.to_nextsolver(interner), - ) - } - chalk_ir::TyKind::CoroutineWitness(coroutine_id, substitution) => { - let id: InternedCoroutineId = (*coroutine_id).into(); - rustc_type_ir::TyKind::CoroutineWitness( - id.into(), - substitution.to_nextsolver(interner), - ) - } - chalk_ir::TyKind::Foreign(foreign_def_id) => rustc_type_ir::TyKind::Foreign( - crate::from_foreign_def_id(*foreign_def_id).into(), - ), - chalk_ir::TyKind::Error => rustc_type_ir::TyKind::Error(ErrorGuaranteed), - chalk_ir::TyKind::Dyn(dyn_ty) => { - // exists { for<...> ^1.0: ... } - let bounds = BoundExistentialPredicates::new_from_iter( - interner, - dyn_ty.bounds.skip_binders().iter(Interner).filter_map(|pred| { - // for<...> ^1.0: ... - let (val, binders) = pred.clone().into_value_and_skipped_binders(); - let bound_vars = binders.to_nextsolver(interner); - let clause = match val { - chalk_ir::WhereClause::Implemented(trait_ref) => { - let trait_id = from_chalk_trait_id(trait_ref.trait_id); - if interner - .db() - .trait_signature(trait_id) - .flags - .contains(TraitFlags::AUTO) - { - ExistentialPredicate::AutoTrait(trait_id.into()) - } else { - let args = GenericArgs::new_from_iter( - interner, - trait_ref - .substitution - .iter(Interner) - .skip(1) - .map(|a| a.clone().shifted_out(Interner).unwrap()) - .map(|a| a.to_nextsolver(interner)), - ); - let trait_ref = ExistentialTraitRef::new_from_args( - interner, trait_id.into(), args, - ); - ExistentialPredicate::Trait(trait_ref) - } - } - chalk_ir::WhereClause::AliasEq(alias_eq) => { - let (def_id, args) = match &alias_eq.alias { - chalk_ir::AliasTy::Projection(projection) => { - let id = - from_assoc_type_id(projection.associated_ty_id); - let def_id = SolverDefId::TypeAliasId(id); - let substs = projection.substitution.iter(Interner).skip(1); - - let args = GenericArgs::new_from_iter( - interner, - substs - .map(|a| { - a.clone().shifted_out(Interner).unwrap() - }) - .map(|a| a.to_nextsolver(interner)), - ); - (def_id, args) - } - chalk_ir::AliasTy::Opaque(_opaque_ty) => { - panic!("Invalid ExistentialPredicate (opaques can't be named)."); - } - }; - let term = alias_eq - .ty - .clone() - .shifted_out(Interner) - .unwrap() - .to_nextsolver(interner) - .into(); - let projection = ExistentialProjection::new_from_args( - interner, def_id, args, term, - ); - ExistentialPredicate::Projection(projection) - } - chalk_ir::WhereClause::LifetimeOutlives(_lifetime_outlives) => { - return None; - } - chalk_ir::WhereClause::TypeOutlives(_type_outlives) => return None, - }; - - Some(Binder::bind_with_vars(clause, bound_vars)) - }), - ); - let region = dyn_ty.lifetime.to_nextsolver(interner); - rustc_type_ir::TyKind::Dynamic(bounds, region) - } - chalk_ir::TyKind::Alias(alias_ty) => match alias_ty { - chalk_ir::AliasTy::Projection(projection_ty) => { - let def_id = SolverDefId::TypeAliasId(from_assoc_type_id( - projection_ty.associated_ty_id, - )); - let alias_ty = rustc_type_ir::AliasTy::new_from_args( - interner, - def_id, - projection_ty.substitution.to_nextsolver(interner), - ); - rustc_type_ir::TyKind::Alias( - rustc_type_ir::AliasTyKind::Projection, - alias_ty, - ) - } - chalk_ir::AliasTy::Opaque(opaque_ty) => { - let id: InternedOpaqueTyId = opaque_ty.opaque_ty_id.into(); - let def_id = SolverDefId::InternedOpaqueTyId(id); - let alias_ty = rustc_type_ir::AliasTy::new_from_args( - interner, - def_id, - opaque_ty.substitution.to_nextsolver(interner), - ); - rustc_type_ir::TyKind::Alias(rustc_type_ir::AliasTyKind::Opaque, alias_ty) - } - }, - chalk_ir::TyKind::Function(fn_pointer) => { - let sig_tys = fn_pointer.clone().into_binders(Interner).to_nextsolver(interner); - let header = rustc_type_ir::FnHeader { - abi: fn_pointer.sig.abi, - c_variadic: fn_pointer.sig.variadic, - safety: match fn_pointer.sig.safety { - chalk_ir::Safety::Safe => super::abi::Safety::Safe, - chalk_ir::Safety::Unsafe => super::abi::Safety::Unsafe, - }, - }; - - rustc_type_ir::TyKind::FnPtr(sig_tys, header) - } - // The schema here is quite confusing. - // The new solver, like rustc, uses `Param` and `EarlyBinder` for generic params. It uses `BoundVar` - // and `Placeholder` together with `Binder` for HRTB, which we mostly don't handle. - // Chalk uses `Placeholder` for generic params and `BoundVar` quite liberally, and this is quite a - // problem. `chalk_ir::TyKind::BoundVar` can represent either HRTB or generic params, depending on the - // context. When returned from signature queries, the outer `Binders` represent the generic params. - // But there are also inner `Binders` for HRTB. - // AFAIK there is no way to tell which of the meanings is relevant, so we just use `rustc_type_ir::Bound` - // here, and hope for the best. If you are working with new solver types, therefore, use the new solver - // lower queries. - // Hopefully sooner than later Chalk will be ripped from the codebase and we can avoid that problem. - // For details about the rustc setup, read: https://rustc-dev-guide.rust-lang.org/generic_parameters_summary.html - // and the following chapters. - chalk_ir::TyKind::Placeholder(placeholder_index) => { - let (id, index) = from_placeholder_idx(interner.db, *placeholder_index); - rustc_type_ir::TyKind::Param(ParamTy { - id: TypeParamId::from_unchecked(id), - index, - }) - } - chalk_ir::TyKind::BoundVar(bound_var) => rustc_type_ir::TyKind::Bound( - bound_var.debruijn.to_nextsolver(interner), - BoundTy { - var: rustc_type_ir::BoundVar::from_usize(bound_var.index), - kind: BoundTyKind::Anon, - }, - ), - chalk_ir::TyKind::InferenceVar(inference_var, ty_variable_kind) => { - rustc_type_ir::TyKind::Infer( - (*inference_var, *ty_variable_kind).to_nextsolver(interner), - ) - } - }, - ) - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::Ty> for Ty<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Ty { - convert_ty_for_result(interner, self) - } -} - -impl<'db> ChalkToNextSolver<'db, Region<'db>> for chalk_ir::Lifetime { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> Region<'db> { - Region::new( - interner, - match self.data(Interner) { - chalk_ir::LifetimeData::BoundVar(bound_var) => rustc_type_ir::RegionKind::ReBound( - bound_var.debruijn.to_nextsolver(interner), - BoundRegion { - var: rustc_type_ir::BoundVar::from_u32(bound_var.index as u32), - kind: BoundRegionKind::Anon, - }, - ), - chalk_ir::LifetimeData::InferenceVar(inference_var) => { - rustc_type_ir::RegionKind::ReVar(rustc_type_ir::RegionVid::from_u32( - inference_var.index(), - )) - } - chalk_ir::LifetimeData::Placeholder(placeholder_index) => { - let (id, index) = lt_from_placeholder_idx(interner.db, *placeholder_index); - rustc_type_ir::RegionKind::ReEarlyParam(EarlyParamRegion { id, index }) - } - chalk_ir::LifetimeData::Static => rustc_type_ir::RegionKind::ReStatic, - chalk_ir::LifetimeData::Erased => rustc_type_ir::RegionKind::ReErased, - chalk_ir::LifetimeData::Phantom(_, _) => { - unreachable!() - } - chalk_ir::LifetimeData::Error => { - rustc_type_ir::RegionKind::ReError(ErrorGuaranteed) - } - }, - ) - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::Lifetime> for Region<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Lifetime { - convert_region_for_result(interner, self) - } -} - -impl<'db> ChalkToNextSolver<'db, Const<'db>> for chalk_ir::Const { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> Const<'db> { - let data = self.data(Interner); - Const::new( - interner, - match &data.value { - chalk_ir::ConstValue::BoundVar(bound_var) => rustc_type_ir::ConstKind::Bound( - bound_var.debruijn.to_nextsolver(interner), - BoundConst { var: rustc_type_ir::BoundVar::from_usize(bound_var.index) }, - ), - chalk_ir::ConstValue::InferenceVar(inference_var) => { - rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Var( - rustc_type_ir::ConstVid::from_u32(inference_var.index()), - )) - } - chalk_ir::ConstValue::Placeholder(placeholder_index) => { - let (id, index) = from_placeholder_idx(interner.db, *placeholder_index); - rustc_type_ir::ConstKind::Param(ParamConst { - id: ConstParamId::from_unchecked(id), - index, - }) - } - chalk_ir::ConstValue::Concrete(concrete_const) => match &concrete_const.interned { - ConstScalar::Bytes(bytes, memory) => { - rustc_type_ir::ConstKind::Value(ValueConst::new( - data.ty.to_nextsolver(interner), - ConstBytes { memory: bytes.clone(), memory_map: memory.clone() }, - )) - } - ConstScalar::UnevaluatedConst(c, subst) => { - let def = match *c { - GeneralConstId::ConstId(id) => SolverDefId::ConstId(id), - GeneralConstId::StaticId(id) => SolverDefId::StaticId(id), - }; - let args = subst.to_nextsolver(interner); - rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new(def, args)) - } - ConstScalar::Unknown => rustc_type_ir::ConstKind::Error(ErrorGuaranteed), - }, - }, - ) - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::Const> for Const<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Const { - convert_const_for_result(interner, self) - } -} - -impl<'db> ChalkToNextSolver<'db, rustc_type_ir::FnSigTys>> - for chalk_ir::FnSubst -{ - fn to_nextsolver(&self, interner: DbInterner<'db>) -> rustc_type_ir::FnSigTys> { - rustc_type_ir::FnSigTys { - inputs_and_output: Tys::new_from_iter( - interner, - self.0.iter(Interner).map(|g| g.assert_ty_ref(Interner).to_nextsolver(interner)), - ), - } - } -} - -impl< - 'db, - U: TypeVisitable>, - T: Clone + ChalkToNextSolver<'db, U> + HasInterner, -> ChalkToNextSolver<'db, rustc_type_ir::Binder, U>> for chalk_ir::Binders -{ - fn to_nextsolver( - &self, - interner: DbInterner<'db>, - ) -> rustc_type_ir::Binder, U> { - let (val, binders) = self.clone().into_value_and_skipped_binders(); - rustc_type_ir::Binder::bind_with_vars( - val.to_nextsolver(interner), - binders.to_nextsolver(interner), - ) - } -} - -impl<'db, T: NextSolverToChalk<'db, U>, U: HasInterner> - NextSolverToChalk<'db, chalk_ir::Binders> for rustc_type_ir::Binder, T> -{ - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Binders { - chalk_ir::Binders::new( - self.bound_vars().to_chalk(interner), - self.skip_binder().to_chalk(interner), - ) - } -} - -impl<'db> ChalkToNextSolver<'db, BoundVarKinds<'db>> for chalk_ir::VariableKinds { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> BoundVarKinds<'db> { - BoundVarKinds::new_from_iter( - interner, - self.iter(Interner).map(|v| v.to_nextsolver(interner)), - ) - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::VariableKinds> for BoundVarKinds<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::VariableKinds { - chalk_ir::VariableKinds::from_iter(Interner, self.iter().map(|v| v.to_chalk(interner))) - } -} - -impl<'db> ChalkToNextSolver<'db, BoundVarKind> for chalk_ir::VariableKind { - fn to_nextsolver(&self, _interner: DbInterner<'db>) -> BoundVarKind { - match self { - chalk_ir::VariableKind::Ty(_ty_variable_kind) => BoundVarKind::Ty(BoundTyKind::Anon), - chalk_ir::VariableKind::Lifetime => BoundVarKind::Region(BoundRegionKind::Anon), - chalk_ir::VariableKind::Const(_ty) => BoundVarKind::Const, - } - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::VariableKind> for BoundVarKind { - fn to_chalk(self, _interner: DbInterner<'db>) -> chalk_ir::VariableKind { - match self { - BoundVarKind::Ty(_) => chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), - BoundVarKind::Region(_) => chalk_ir::VariableKind::Lifetime, - BoundVarKind::Const => { - chalk_ir::VariableKind::Const(chalk_ir::TyKind::Error.intern(Interner)) - } - } - } -} - -impl<'db> ChalkToNextSolver<'db, GenericArg<'db>> for chalk_ir::GenericArg { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> GenericArg<'db> { - match self.data(Interner) { - chalk_ir::GenericArgData::Ty(ty) => ty.to_nextsolver(interner).into(), - chalk_ir::GenericArgData::Lifetime(lifetime) => lifetime.to_nextsolver(interner).into(), - chalk_ir::GenericArgData::Const(const_) => const_.to_nextsolver(interner).into(), - } - } -} - -impl<'db> NextSolverToChalk<'db, crate::GenericArg> for GenericArg<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> crate::GenericArg { - match self { - GenericArg::Ty(ty) => ty.to_chalk(interner).cast(Interner), - GenericArg::Lifetime(region) => region.to_chalk(interner).cast(Interner), - GenericArg::Const(konst) => konst.to_chalk(interner).cast(Interner), - } - } -} - -impl<'db> ChalkToNextSolver<'db, GenericArgs<'db>> for chalk_ir::Substitution { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> GenericArgs<'db> { - GenericArgs::new_from_iter( - interner, - self.iter(Interner).map(|arg| -> GenericArg<'db> { arg.to_nextsolver(interner) }), - ) - } -} - -impl<'db> ChalkToNextSolver<'db, crate::lower_nextsolver::ImplTraitIdx<'db>> - for crate::ImplTraitIdx -{ - fn to_nextsolver( - &self, - _interner: DbInterner<'db>, - ) -> crate::lower_nextsolver::ImplTraitIdx<'db> { - crate::lower_nextsolver::ImplTraitIdx::from_raw(self.into_raw()) - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::Substitution> for GenericArgs<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Substitution { - convert_args_for_result(interner, self.as_slice()) - } -} - -impl<'db> ChalkToNextSolver<'db, Tys<'db>> for chalk_ir::Substitution { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> Tys<'db> { - Tys::new_from_iter( - interner, - self.iter(Interner).map(|arg| -> Ty<'db> { - match arg.data(Interner) { - chalk_ir::GenericArgData::Ty(ty) => ty.to_nextsolver(interner), - chalk_ir::GenericArgData::Lifetime(_) => unreachable!(), - chalk_ir::GenericArgData::Const(_) => unreachable!(), - } - }), - ) - } -} - -impl<'db> NextSolverToChalk<'db, crate::Substitution> for Tys<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> crate::Substitution { - Substitution::from_iter( - Interner, - self.inner().iter().map(|ty| ty.to_chalk(interner).cast(Interner)), - ) - } -} - -impl<'db> ChalkToNextSolver<'db, rustc_type_ir::DebruijnIndex> for chalk_ir::DebruijnIndex { - fn to_nextsolver(&self, _interner: DbInterner<'db>) -> rustc_type_ir::DebruijnIndex { - rustc_type_ir::DebruijnIndex::from_u32(self.depth()) - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::DebruijnIndex> for rustc_type_ir::DebruijnIndex { - fn to_chalk(self, _interner: DbInterner<'db>) -> chalk_ir::DebruijnIndex { - chalk_ir::DebruijnIndex::new(self.index() as u32) - } -} - -impl<'db> ChalkToNextSolver<'db, rustc_type_ir::UniverseIndex> for chalk_ir::UniverseIndex { - fn to_nextsolver(&self, _interner: DbInterner<'db>) -> rustc_type_ir::UniverseIndex { - rustc_type_ir::UniverseIndex::from_u32(self.counter as u32) - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::UniverseIndex> for rustc_type_ir::UniverseIndex { - fn to_chalk(self, _interner: DbInterner<'db>) -> chalk_ir::UniverseIndex { - chalk_ir::UniverseIndex { counter: self.index() } - } -} - -impl<'db> ChalkToNextSolver<'db, rustc_type_ir::InferTy> - for (chalk_ir::InferenceVar, chalk_ir::TyVariableKind) -{ - fn to_nextsolver(&self, _interner: DbInterner<'db>) -> rustc_type_ir::InferTy { - match self.1 { - chalk_ir::TyVariableKind::General => { - rustc_type_ir::InferTy::TyVar(rustc_type_ir::TyVid::from_u32(self.0.index())) - } - chalk_ir::TyVariableKind::Integer => { - rustc_type_ir::InferTy::IntVar(rustc_type_ir::IntVid::from_u32(self.0.index())) - } - chalk_ir::TyVariableKind::Float => { - rustc_type_ir::InferTy::FloatVar(rustc_type_ir::FloatVid::from_u32(self.0.index())) - } - } - } -} - -impl<'db> ChalkToNextSolver<'db, rustc_ast_ir::Mutability> for chalk_ir::Mutability { - fn to_nextsolver(&self, _interner: DbInterner<'db>) -> rustc_ast_ir::Mutability { - match self { - chalk_ir::Mutability::Mut => rustc_ast_ir::Mutability::Mut, - chalk_ir::Mutability::Not => rustc_ast_ir::Mutability::Not, - } - } -} - -impl<'db> ChalkToNextSolver<'db, Goal, Predicate<'db>>> - for chalk_ir::InEnvironment> -{ - fn to_nextsolver(&self, interner: DbInterner<'db>) -> Goal, Predicate<'db>> { - Goal::new( - interner, - self.environment.to_nextsolver(interner), - self.goal.to_nextsolver(interner), - ) - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::InEnvironment>> - for Goal, Predicate<'db>> -{ - fn to_chalk( - self, - interner: DbInterner<'db>, - ) -> chalk_ir::InEnvironment> { - chalk_ir::InEnvironment { - environment: self.param_env.to_chalk(interner), - goal: self.predicate.to_chalk(interner), - } - } -} - -impl<'db, T: HasInterner + ChalkToNextSolver<'db, U>, U> - ChalkToNextSolver<'db, Canonical<'db, U>> for chalk_ir::Canonical -{ - fn to_nextsolver(&self, interner: DbInterner<'db>) -> Canonical<'db, U> { - let variables = CanonicalVars::new_from_iter( - interner, - self.binders.iter(Interner).map(|k| match &k.kind { - chalk_ir::VariableKind::Ty(ty_variable_kind) => match ty_variable_kind { - // FIXME(next-solver): the info is incorrect, but we have no way to store the information in Chalk. - TyVariableKind::General => rustc_type_ir::CanonicalVarKind::Ty { - ui: UniverseIndex::ROOT, - sub_root: BoundVar::from_u32(0), - }, - TyVariableKind::Integer => rustc_type_ir::CanonicalVarKind::Int, - TyVariableKind::Float => rustc_type_ir::CanonicalVarKind::Float, - }, - chalk_ir::VariableKind::Lifetime => { - rustc_type_ir::CanonicalVarKind::Region(UniverseIndex::ROOT) - } - chalk_ir::VariableKind::Const(_ty) => { - rustc_type_ir::CanonicalVarKind::Const(UniverseIndex::ROOT) - } - }), - ); - Canonical { - max_universe: UniverseIndex::ROOT, - value: self.value.to_nextsolver(interner), - variables, - } - } -} - -impl<'db, T: NextSolverToChalk<'db, U>, U: HasInterner> - NextSolverToChalk<'db, chalk_ir::Canonical> for Canonical<'db, T> -{ - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Canonical { - let binders = chalk_ir::CanonicalVarKinds::from_iter( - Interner, - self.variables.iter().map(|v| match v { - rustc_type_ir::CanonicalVarKind::Ty { ui, sub_root: _ } => { - chalk_ir::CanonicalVarKind::new( - chalk_ir::VariableKind::Ty(TyVariableKind::General), - chalk_ir::UniverseIndex { counter: ui.as_usize() }, - ) - } - rustc_type_ir::CanonicalVarKind::Int => chalk_ir::CanonicalVarKind::new( - chalk_ir::VariableKind::Ty(TyVariableKind::Integer), - chalk_ir::UniverseIndex::root(), - ), - rustc_type_ir::CanonicalVarKind::Float => chalk_ir::CanonicalVarKind::new( - chalk_ir::VariableKind::Ty(TyVariableKind::Float), - chalk_ir::UniverseIndex::root(), - ), - rustc_type_ir::CanonicalVarKind::Region(ui) => chalk_ir::CanonicalVarKind::new( - chalk_ir::VariableKind::Lifetime, - chalk_ir::UniverseIndex { counter: ui.as_usize() }, - ), - rustc_type_ir::CanonicalVarKind::Const(ui) => chalk_ir::CanonicalVarKind::new( - chalk_ir::VariableKind::Const(chalk_ir::TyKind::Error.intern(Interner)), - chalk_ir::UniverseIndex { counter: ui.as_usize() }, - ), - rustc_type_ir::CanonicalVarKind::PlaceholderTy(_) => unimplemented!(), - rustc_type_ir::CanonicalVarKind::PlaceholderRegion(_) => unimplemented!(), - rustc_type_ir::CanonicalVarKind::PlaceholderConst(_) => unimplemented!(), - }), - ); - let value = self.value.to_chalk(interner); - chalk_ir::Canonical { binders, value } - } -} - -impl<'db> ChalkToNextSolver<'db, Predicate<'db>> for chalk_ir::Goal { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> Predicate<'db> { - match self.data(Interner) { - chalk_ir::GoalData::Quantified(_quantifier_kind, binders) => { - if !binders.binders.is_empty(Interner) { - panic!("Should not be constructed."); - } - let (val, _) = binders.clone().into_value_and_skipped_binders(); - val.shifted_out(Interner).unwrap().to_nextsolver(interner) - } - chalk_ir::GoalData::Implies(_program_clauses, _goal) => { - panic!("Should not be constructed.") - } - chalk_ir::GoalData::All(_goals) => panic!("Should not be constructed."), - chalk_ir::GoalData::Not(_goal) => panic!("Should not be constructed."), - chalk_ir::GoalData::EqGoal(eq_goal) => { - let arg_to_term = |g: &chalk_ir::GenericArg| match g.data(Interner) { - chalk_ir::GenericArgData::Ty(ty) => Term::Ty(ty.to_nextsolver(interner)), - chalk_ir::GenericArgData::Const(const_) => { - Term::Const(const_.to_nextsolver(interner)) - } - chalk_ir::GenericArgData::Lifetime(_lifetime) => unreachable!(), - }; - let pred_kind = PredicateKind::AliasRelate( - arg_to_term(&eq_goal.a), - arg_to_term(&eq_goal.b), - rustc_type_ir::AliasRelationDirection::Equate, - ); - let pred_kind = - Binder::bind_with_vars(pred_kind, BoundVarKinds::new_from_iter(interner, [])); - Predicate::new(interner, pred_kind) - } - chalk_ir::GoalData::SubtypeGoal(subtype_goal) => { - let subtype_predicate = SubtypePredicate { - a: subtype_goal.a.to_nextsolver(interner), - b: subtype_goal.b.to_nextsolver(interner), - a_is_expected: true, - }; - let pred_kind = PredicateKind::Subtype(subtype_predicate); - let pred_kind = Binder::bind_with_vars( - shift_vars(interner, pred_kind, 1), - BoundVarKinds::new_from_iter(interner, []), - ); - Predicate::new(interner, pred_kind) - } - chalk_ir::GoalData::DomainGoal(domain_goal) => { - let pred_kind = domain_goal.to_nextsolver(interner); - let pred_kind = Binder::bind_with_vars( - shift_vars(interner, pred_kind, 1), - BoundVarKinds::new_from_iter(interner, []), - ); - Predicate::new(interner, pred_kind) - } - chalk_ir::GoalData::CannotProve => panic!("Should not be constructed."), - } - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::Goal> for Predicate<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Goal { - chalk_ir::Goal::new(Interner, self.kind().skip_binder().to_chalk(interner)) - } -} - -impl<'db> NextSolverToChalk<'db, crate::ProjectionTy> for crate::next_solver::AliasTy<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> crate::ProjectionTy { - let SolverDefId::TypeAliasId(assoc_id) = self.def_id else { unreachable!() }; - crate::ProjectionTy { - associated_ty_id: to_assoc_type_id(assoc_id), - substitution: self.args.to_chalk(interner), - } - } -} - -impl<'db> ChalkToNextSolver<'db, ParamEnv<'db>> for chalk_ir::Environment { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> ParamEnv<'db> { - let clauses = Clauses::new_from_iter( - interner, - self.clauses.iter(Interner).map(|c| c.to_nextsolver(interner)), - ); - let clauses = - Clauses::new_from_iter(interner, elaborate::elaborate(interner, clauses.iter())); - ParamEnv { clauses } - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::Environment> for ParamEnv<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::Environment { - let clauses = chalk_ir::ProgramClauses::from_iter( - Interner, - self.clauses.iter().filter_map(|c| -> Option> { - c.to_chalk(interner) - }), - ); - chalk_ir::Environment { clauses } - } -} - -impl<'db> ChalkToNextSolver<'db, Clause<'db>> for chalk_ir::ProgramClause { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> Clause<'db> { - Clause(Predicate::new(interner, self.data(Interner).0.to_nextsolver(interner))) - } -} - -impl<'db> NextSolverToChalk<'db, Option>> for Clause<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> Option> { - let value: chalk_ir::ProgramClauseImplication = - as NextSolverToChalk< - 'db, - Option>, - >>::to_chalk(self.0.kind().skip_binder(), interner)?; - Some(chalk_ir::ProgramClause::new( - Interner, - chalk_ir::ProgramClauseData(chalk_ir::Binders::empty(Interner, value)), - )) - } -} - -impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>> - for chalk_ir::ProgramClauseImplication -{ - fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> { - assert!(self.conditions.is_empty(Interner)); - assert!(self.constraints.is_empty(Interner)); - self.consequence.to_nextsolver(interner) - } -} - -impl<'db> NextSolverToChalk<'db, Option>> - for PredicateKind<'db> -{ - fn to_chalk( - self, - interner: DbInterner<'db>, - ) -> Option> { - let chalk_ir::GoalData::DomainGoal(consequence) = self.to_chalk(interner) else { - return None; - }; - - Some(chalk_ir::ProgramClauseImplication { - consequence, - conditions: chalk_ir::Goals::empty(Interner), - constraints: chalk_ir::Constraints::empty(Interner), - priority: chalk_ir::ClausePriority::High, - }) - } -} - -impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>> for chalk_ir::DomainGoal { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> { - match self { - chalk_ir::DomainGoal::Holds(where_clause) => match where_clause { - chalk_ir::WhereClause::Implemented(trait_ref) => { - let predicate = TraitPredicate { - trait_ref: trait_ref.to_nextsolver(interner), - polarity: rustc_type_ir::PredicatePolarity::Positive, - }; - PredicateKind::Clause(ClauseKind::Trait(predicate)) - } - chalk_ir::WhereClause::AliasEq(alias_eq) => match &alias_eq.alias { - chalk_ir::AliasTy::Projection(p) => { - let def_id = - SolverDefId::TypeAliasId(from_assoc_type_id(p.associated_ty_id)); - let args = p.substitution.to_nextsolver(interner); - let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner); - let term: Term<'db> = term.into(); - let predicate = ProjectionPredicate { - projection_term: AliasTerm::new_from_args(interner, def_id, args), - term, - }; - PredicateKind::Clause(ClauseKind::Projection(predicate)) - } - chalk_ir::AliasTy::Opaque(opaque) => { - let id: InternedOpaqueTyId = opaque.opaque_ty_id.into(); - let def_id = SolverDefId::InternedOpaqueTyId(id); - let args = opaque.substitution.to_nextsolver(interner); - let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner); - let term: Term<'db> = term.into(); - let opaque_ty = Ty::new( - interner, - rustc_type_ir::TyKind::Alias( - rustc_type_ir::AliasTyKind::Opaque, - rustc_type_ir::AliasTy::new_from_args(interner, def_id, args), - ), - ) - .into(); - PredicateKind::AliasRelate( - opaque_ty, - term, - rustc_type_ir::AliasRelationDirection::Equate, - ) - } - }, - chalk_ir::WhereClause::LifetimeOutlives(lifetime_outlives) => { - let predicate = OutlivesPredicate( - lifetime_outlives.a.to_nextsolver(interner), - lifetime_outlives.b.to_nextsolver(interner), - ); - PredicateKind::Clause(ClauseKind::RegionOutlives(predicate)) - } - chalk_ir::WhereClause::TypeOutlives(type_outlives) => { - let predicate = OutlivesPredicate( - type_outlives.ty.to_nextsolver(interner), - type_outlives.lifetime.to_nextsolver(interner), - ); - PredicateKind::Clause(ClauseKind::TypeOutlives(predicate)) - } - }, - chalk_ir::DomainGoal::Normalize(normalize) => { - let proj_ty = match &normalize.alias { - chalk_ir::AliasTy::Projection(proj) => proj, - _ => unimplemented!(), - }; - let args: GenericArgs<'db> = proj_ty.substitution.to_nextsolver(interner); - let alias = Ty::new( - interner, - rustc_type_ir::TyKind::Alias( - rustc_type_ir::AliasTyKind::Projection, - rustc_type_ir::AliasTy::new( - interner, - from_assoc_type_id(proj_ty.associated_ty_id).into(), - args, - ), - ), - ) - .into(); - let term = normalize.ty.to_nextsolver(interner).into(); - PredicateKind::AliasRelate( - alias, - term, - rustc_type_ir::AliasRelationDirection::Equate, - ) - } - chalk_ir::DomainGoal::WellFormed(well_formed) => { - let term = match well_formed { - WellFormed::Trait(_) => panic!("Should not be constructed."), - WellFormed::Ty(ty) => Term::Ty(ty.to_nextsolver(interner)), - }; - PredicateKind::Clause(rustc_type_ir::ClauseKind::WellFormed(term)) - } - chalk_ir::DomainGoal::FromEnv(from_env) => match from_env { - chalk_ir::FromEnv::Trait(trait_ref) => { - let predicate = TraitPredicate { - trait_ref: trait_ref.to_nextsolver(interner), - polarity: rustc_type_ir::PredicatePolarity::Positive, - }; - PredicateKind::Clause(ClauseKind::Trait(predicate)) - } - chalk_ir::FromEnv::Ty(ty) => PredicateKind::Clause(ClauseKind::WellFormed( - Term::Ty(ty.to_nextsolver(interner)), - )), - }, - chalk_ir::DomainGoal::IsLocal(_ty) => panic!("Should not be constructed."), - chalk_ir::DomainGoal::IsUpstream(_ty) => panic!("Should not be constructed."), - chalk_ir::DomainGoal::IsFullyVisible(_ty) => panic!("Should not be constructed."), - chalk_ir::DomainGoal::LocalImplAllowed(_trait_ref) => { - panic!("Should not be constructed.") - } - chalk_ir::DomainGoal::Compatible => panic!("Should not be constructed."), - chalk_ir::DomainGoal::DownstreamType(_ty) => panic!("Should not be constructed."), - chalk_ir::DomainGoal::Reveal => panic!("Should not be constructed."), - chalk_ir::DomainGoal::ObjectSafe(_trait_id) => panic!("Should not be constructed."), - } - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::GoalData> for PredicateKind<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::GoalData { - match self { - rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Trait(trait_pred)) => { - let trait_ref = trait_pred.trait_ref.to_chalk(interner); - let where_clause = chalk_ir::WhereClause::Implemented(trait_ref); - chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause)) - } - rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Projection( - proj_predicate, - )) => { - let associated_ty_id = match proj_predicate.def_id() { - SolverDefId::TypeAliasId(id) => to_assoc_type_id(id), - _ => unreachable!(), - }; - let substitution = proj_predicate.projection_term.args.to_chalk(interner); - let alias = chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { - associated_ty_id, - substitution, - }); - let ty = match proj_predicate.term.kind() { - rustc_type_ir::TermKind::Ty(ty) => ty, - rustc_type_ir::TermKind::Const(_) => unimplemented!(), - }; - let ty = ty.to_chalk(interner); - let alias_eq = chalk_ir::AliasEq { alias, ty }; - let where_clause = chalk_ir::WhereClause::AliasEq(alias_eq); - chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause)) - } - rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::TypeOutlives( - outlives, - )) => { - let lifetime = outlives.1.to_chalk(interner); - let ty = outlives.0.to_chalk(interner); - let where_clause = - chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives { lifetime, ty }); - chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause)) - } - rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::RegionOutlives( - outlives, - )) => { - let a = outlives.0.to_chalk(interner); - let b = outlives.1.to_chalk(interner); - let where_clause = - chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives { a, b }); - chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(where_clause)) - } - rustc_type_ir::PredicateKind::AliasRelate( - alias_term, - target_term, - _alias_relation_direction, - ) => { - let term_to_generic_arg = |term: Term<'db>| match term { - Term::Ty(ty) => chalk_ir::GenericArg::new( - Interner, - chalk_ir::GenericArgData::Ty(ty.to_chalk(interner)), - ), - Term::Const(const_) => chalk_ir::GenericArg::new( - Interner, - chalk_ir::GenericArgData::Const(const_.to_chalk(interner)), - ), - }; - - chalk_ir::GoalData::EqGoal(chalk_ir::EqGoal { - a: term_to_generic_arg(alias_term), - b: term_to_generic_arg(target_term), - }) - } - rustc_type_ir::PredicateKind::Clause(_) => unimplemented!(), - rustc_type_ir::PredicateKind::DynCompatible(_) => unimplemented!(), - rustc_type_ir::PredicateKind::Subtype(_) => unimplemented!(), - rustc_type_ir::PredicateKind::Coerce(_) => unimplemented!(), - rustc_type_ir::PredicateKind::ConstEquate(_, _) => unimplemented!(), - rustc_type_ir::PredicateKind::Ambiguous => unimplemented!(), - rustc_type_ir::PredicateKind::NormalizesTo(_) => unimplemented!(), - } - } -} - -impl<'db> ChalkToNextSolver<'db, TraitRef<'db>> for chalk_ir::TraitRef { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> TraitRef<'db> { - let args = self.substitution.to_nextsolver(interner); - TraitRef::new_from_args(interner, from_chalk_trait_id(self.trait_id).into(), args) - } -} - -impl<'db> NextSolverToChalk<'db, chalk_ir::TraitRef> for TraitRef<'db> { - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::TraitRef { - let trait_id = to_chalk_trait_id(self.def_id.0); - let substitution = self.args.to_chalk(interner); - chalk_ir::TraitRef { trait_id, substitution } - } -} - -impl<'db> ChalkToNextSolver<'db, PredicateKind<'db>> for chalk_ir::WhereClause { - fn to_nextsolver(&self, interner: DbInterner<'db>) -> PredicateKind<'db> { - match self { - chalk_ir::WhereClause::Implemented(trait_ref) => { - let predicate = TraitPredicate { - trait_ref: trait_ref.to_nextsolver(interner), - polarity: rustc_type_ir::PredicatePolarity::Positive, - }; - PredicateKind::Clause(ClauseKind::Trait(predicate)) - } - chalk_ir::WhereClause::AliasEq(alias_eq) => { - let projection = match &alias_eq.alias { - chalk_ir::AliasTy::Projection(p) => p, - _ => unimplemented!(), - }; - let def_id = - SolverDefId::TypeAliasId(from_assoc_type_id(projection.associated_ty_id)); - let args = projection.substitution.to_nextsolver(interner); - let term: Ty<'db> = alias_eq.ty.to_nextsolver(interner); - let term: Term<'db> = term.into(); - let predicate = ProjectionPredicate { - projection_term: AliasTerm::new_from_args(interner, def_id, args), - term, - }; - PredicateKind::Clause(ClauseKind::Projection(predicate)) - } - chalk_ir::WhereClause::TypeOutlives(type_outlives) => { - let ty = type_outlives.ty.to_nextsolver(interner); - let r = type_outlives.lifetime.to_nextsolver(interner); - PredicateKind::Clause(ClauseKind::TypeOutlives(OutlivesPredicate(ty, r))) - } - chalk_ir::WhereClause::LifetimeOutlives(lifetime_outlives) => { - let a = lifetime_outlives.a.to_nextsolver(interner); - let b = lifetime_outlives.b.to_nextsolver(interner); - PredicateKind::Clause(ClauseKind::RegionOutlives(OutlivesPredicate(a, b))) - } - } - } -} - -impl<'db, I> NextSolverToChalk<'db, chalk_ir::ConstrainedSubst> for I -where - I: IntoIterator>, -{ - fn to_chalk(self, interner: DbInterner<'db>) -> chalk_ir::ConstrainedSubst { - chalk_ir::ConstrainedSubst { - constraints: chalk_ir::Constraints::empty(Interner), - subst: GenericArgs::new_from_iter(interner, self).to_chalk(interner), - } - } -} - -impl<'db> NextSolverToChalk<'db, crate::CallableSig> for rustc_type_ir::FnSig> { - fn to_chalk(self, interner: DbInterner<'db>) -> crate::CallableSig { - crate::CallableSig { - abi: self.abi, - is_varargs: self.c_variadic, - safety: match self.safety { - super::abi::Safety::Safe => chalk_ir::Safety::Safe, - super::abi::Safety::Unsafe => chalk_ir::Safety::Unsafe, - }, - params_and_return: triomphe::Arc::from_iter( - self.inputs_and_output.iter().map(|ty| convert_ty_for_result(interner, ty)), - ), - } - } -} - -pub fn convert_canonical_args_for_result<'db>( - interner: DbInterner<'db>, - args: Canonical<'db, Vec>>, -) -> chalk_ir::Canonical> { - args.to_chalk(interner) -} - -pub fn convert_args_for_result<'db>( - interner: DbInterner<'db>, - args: &[GenericArg<'db>], -) -> crate::Substitution { - let mut substs = Vec::with_capacity(args.len()); - for arg in args { - match (*arg).kind() { - rustc_type_ir::GenericArgKind::Type(ty) => { - let ty = convert_ty_for_result(interner, ty); - substs.push(chalk_ir::GenericArgData::Ty(ty).intern(Interner)); - } - rustc_type_ir::GenericArgKind::Lifetime(region) => { - let lifetime = convert_region_for_result(interner, region); - substs.push(chalk_ir::GenericArgData::Lifetime(lifetime).intern(Interner)); - } - rustc_type_ir::GenericArgKind::Const(const_) => { - substs.push( - chalk_ir::GenericArgData::Const(convert_const_for_result(interner, const_)) - .intern(Interner), - ); - } - } - } - Substitution::from_iter(Interner, substs) -} - -pub fn convert_ty_for_result<'db>(interner: DbInterner<'db>, ty: Ty<'db>) -> crate::Ty { - use crate::{Scalar, TyKind}; - use chalk_ir::{FloatTy, IntTy, UintTy}; - match ty.kind() { - rustc_type_ir::TyKind::Bool => TyKind::Scalar(Scalar::Bool), - rustc_type_ir::TyKind::Char => TyKind::Scalar(Scalar::Char), - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I8) => { - TyKind::Scalar(Scalar::Int(IntTy::I8)) - } - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I16) => { - TyKind::Scalar(Scalar::Int(IntTy::I16)) - } - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I32) => { - TyKind::Scalar(Scalar::Int(IntTy::I32)) - } - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I64) => { - TyKind::Scalar(Scalar::Int(IntTy::I64)) - } - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::I128) => { - TyKind::Scalar(Scalar::Int(IntTy::I128)) - } - rustc_type_ir::TyKind::Int(rustc_type_ir::IntTy::Isize) => { - TyKind::Scalar(Scalar::Int(IntTy::Isize)) - } - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U8) => { - TyKind::Scalar(Scalar::Uint(UintTy::U8)) - } - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U16) => { - TyKind::Scalar(Scalar::Uint(UintTy::U16)) - } - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U32) => { - TyKind::Scalar(Scalar::Uint(UintTy::U32)) - } - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U64) => { - TyKind::Scalar(Scalar::Uint(UintTy::U64)) - } - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::U128) => { - TyKind::Scalar(Scalar::Uint(UintTy::U128)) - } - rustc_type_ir::TyKind::Uint(rustc_type_ir::UintTy::Usize) => { - TyKind::Scalar(Scalar::Uint(UintTy::Usize)) - } - rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F16) => { - TyKind::Scalar(Scalar::Float(FloatTy::F16)) - } - rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F32) => { - TyKind::Scalar(Scalar::Float(FloatTy::F32)) - } - rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F64) => { - TyKind::Scalar(Scalar::Float(FloatTy::F64)) - } - rustc_type_ir::TyKind::Float(rustc_type_ir::FloatTy::F128) => { - TyKind::Scalar(Scalar::Float(FloatTy::F128)) - } - rustc_type_ir::TyKind::Str => TyKind::Str, - rustc_type_ir::TyKind::Error(_) => TyKind::Error, - rustc_type_ir::TyKind::Never => TyKind::Never, - - rustc_type_ir::TyKind::Adt(def, args) => { - let adt_id = def.inner().id; - let subst = convert_args_for_result(interner, args.as_slice()); - TyKind::Adt(chalk_ir::AdtId(adt_id), subst) - } - - rustc_type_ir::TyKind::Infer(infer_ty) => { - let (var, kind) = match infer_ty { - rustc_type_ir::InferTy::TyVar(var) => { - (InferenceVar::from(var.as_u32()), TyVariableKind::General) - } - rustc_type_ir::InferTy::IntVar(var) => { - (InferenceVar::from(var.as_u32()), TyVariableKind::Integer) - } - rustc_type_ir::InferTy::FloatVar(var) => { - (InferenceVar::from(var.as_u32()), TyVariableKind::Float) - } - rustc_type_ir::InferTy::FreshFloatTy(..) - | rustc_type_ir::InferTy::FreshIntTy(..) - | rustc_type_ir::InferTy::FreshTy(..) => { - panic!("Freshening shouldn't happen.") - } - }; - TyKind::InferenceVar(var, kind) - } - - rustc_type_ir::TyKind::Ref(r, ty, mutability) => { - let mutability = match mutability { - rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut, - rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not, - }; - let r = convert_region_for_result(interner, r); - let ty = convert_ty_for_result(interner, ty); - TyKind::Ref(mutability, r, ty) - } - - rustc_type_ir::TyKind::Tuple(tys) => { - let size = tys.len(); - let subst = Substitution::from_iter( - Interner, - tys.iter().map(|ty| { - chalk_ir::GenericArgData::Ty(convert_ty_for_result(interner, ty)) - .intern(Interner) - }), - ); - TyKind::Tuple(size, subst) - } - - rustc_type_ir::TyKind::Array(ty, const_) => { - let ty = convert_ty_for_result(interner, ty); - let const_ = convert_const_for_result(interner, const_); - TyKind::Array(ty, const_) - } - - rustc_type_ir::TyKind::Alias(alias_ty_kind, alias_ty) => match alias_ty_kind { - rustc_type_ir::AliasTyKind::Projection => { - let assoc_ty_id = match alias_ty.def_id { - SolverDefId::TypeAliasId(id) => id, - _ => unreachable!(), - }; - let associated_ty_id = to_assoc_type_id(assoc_ty_id); - let substitution = convert_args_for_result(interner, alias_ty.args.as_slice()); - TyKind::Alias(crate::AliasTy::Projection(crate::ProjectionTy { - associated_ty_id, - substitution, - })) - } - rustc_type_ir::AliasTyKind::Opaque => { - let opaque_ty_id = match alias_ty.def_id { - SolverDefId::InternedOpaqueTyId(id) => id, - _ => unreachable!(), - }; - let substitution = convert_args_for_result(interner, alias_ty.args.as_slice()); - TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { - opaque_ty_id: opaque_ty_id.into(), - substitution, - })) - } - rustc_type_ir::AliasTyKind::Inherent => unimplemented!(), - rustc_type_ir::AliasTyKind::Free => unimplemented!(), - }, - - // For `Placeholder`, `Bound` and `Param`, see the comment on the reverse conversion. - rustc_type_ir::TyKind::Placeholder(_placeholder) => { - unimplemented!( - "A `rustc_type_ir::TyKind::Placeholder` doesn't have a direct \ - correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\ - It therefore feels safer to leave it panicking, but if you hit this panic \ - feel free to do the same as in `rustc_type_ir::TyKind::Bound` here." - ) - } - rustc_type_ir::TyKind::Bound(debruijn_index, ty) => TyKind::BoundVar(chalk_ir::BoundVar { - debruijn: chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()), - index: ty.var.as_usize(), - }), - rustc_type_ir::TyKind::Param(param) => { - let placeholder = to_placeholder_idx(interner.db, param.id.into(), param.index); - TyKind::Placeholder(placeholder) - } - - rustc_type_ir::TyKind::FnPtr(bound_sig, fn_header) => { - let num_binders = bound_sig.bound_vars().len(); - let sig = chalk_ir::FnSig { - abi: fn_header.abi, - safety: match fn_header.safety { - crate::next_solver::abi::Safety::Safe => chalk_ir::Safety::Safe, - crate::next_solver::abi::Safety::Unsafe => chalk_ir::Safety::Unsafe, - }, - variadic: fn_header.c_variadic, - }; - let args = GenericArgs::new_from_iter( - interner, - bound_sig.skip_binder().inputs_and_output.iter().map(|a| a.into()), - ); - let substitution = convert_args_for_result(interner, args.as_slice()); - let substitution = chalk_ir::FnSubst(substitution); - let fnptr = chalk_ir::FnPointer { num_binders, sig, substitution }; - TyKind::Function(fnptr) - } - - rustc_type_ir::TyKind::Dynamic(preds, region) => { - let self_ty = Ty::new_bound( - interner, - DebruijnIndex::from_u32(1), - BoundTy { kind: BoundTyKind::Anon, var: BoundVar::from_u32(0) }, - ); - let bounds = chalk_ir::QuantifiedWhereClauses::from_iter( - Interner, - preds.iter().map(|p| { - let binders = chalk_ir::VariableKinds::from_iter( - Interner, - p.bound_vars().iter().map(|b| match b { - BoundVarKind::Ty(_kind) => { - chalk_ir::VariableKind::Ty(TyVariableKind::General) - } - BoundVarKind::Region(_kind) => chalk_ir::VariableKind::Lifetime, - BoundVarKind::Const => { - chalk_ir::VariableKind::Const(crate::TyKind::Error.intern(Interner)) - } - }), - ); - - // Rust and chalk have slightly different - // representation for trait objects. - // - // Chalk uses `for for<'a> T0: Trait<'a>` while rustc - // uses `ExistentialPredicate`s, which do not have a self ty. - // We need to shift escaping bound vars by 1 to accommodate - // the newly introduced `for` binder. - let p = shift_vars(interner, p, 1); - - let where_clause = match p.skip_binder() { - rustc_type_ir::ExistentialPredicate::Trait(trait_ref) => { - let trait_ref = TraitRef::new( - interner, - trait_ref.def_id, - [self_ty.into()].into_iter().chain(trait_ref.args.iter()), - ); - let trait_id = to_chalk_trait_id(trait_ref.def_id.0); - let substitution = - convert_args_for_result(interner, trait_ref.args.as_slice()); - let trait_ref = chalk_ir::TraitRef { trait_id, substitution }; - chalk_ir::WhereClause::Implemented(trait_ref) - } - rustc_type_ir::ExistentialPredicate::AutoTrait(trait_) => { - let trait_id = to_chalk_trait_id(trait_.0); - let substitution = chalk_ir::Substitution::from1( - Interner, - convert_ty_for_result(interner, self_ty), - ); - let trait_ref = chalk_ir::TraitRef { trait_id, substitution }; - chalk_ir::WhereClause::Implemented(trait_ref) - } - rustc_type_ir::ExistentialPredicate::Projection(existential_projection) => { - let projection = ProjectionPredicate { - projection_term: AliasTerm::new( - interner, - existential_projection.def_id, - [self_ty.into()] - .iter() - .chain(existential_projection.args.iter()), - ), - term: existential_projection.term, - }; - let associated_ty_id = match projection.projection_term.def_id { - SolverDefId::TypeAliasId(id) => to_assoc_type_id(id), - _ => unreachable!(), - }; - let substitution = convert_args_for_result( - interner, - projection.projection_term.args.as_slice(), - ); - let alias = chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { - associated_ty_id, - substitution, - }); - let ty = match projection.term { - Term::Ty(ty) => ty, - _ => unreachable!(), - }; - let ty = convert_ty_for_result(interner, ty); - let alias_eq = chalk_ir::AliasEq { alias, ty }; - chalk_ir::WhereClause::AliasEq(alias_eq) - } - }; - chalk_ir::Binders::new(binders, where_clause) - }), - ); - let binders = chalk_ir::VariableKinds::from1( - Interner, - chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), - ); - let bounds = chalk_ir::Binders::new(binders, bounds); - let dyn_ty = - chalk_ir::DynTy { bounds, lifetime: convert_region_for_result(interner, region) }; - TyKind::Dyn(dyn_ty) - } - - rustc_type_ir::TyKind::Slice(ty) => { - let ty = convert_ty_for_result(interner, ty); - TyKind::Slice(ty) - } - - rustc_type_ir::TyKind::Foreign(foreign) => TyKind::Foreign(to_foreign_def_id(foreign.0)), - rustc_type_ir::TyKind::Pat(_, _) => unimplemented!(), - rustc_type_ir::TyKind::RawPtr(ty, mutability) => { - let mutability = match mutability { - rustc_ast_ir::Mutability::Mut => chalk_ir::Mutability::Mut, - rustc_ast_ir::Mutability::Not => chalk_ir::Mutability::Not, - }; - let ty = convert_ty_for_result(interner, ty); - TyKind::Raw(mutability, ty) - } - rustc_type_ir::TyKind::FnDef(def_id, args) => { - let subst = convert_args_for_result(interner, args.as_slice()); - TyKind::FnDef(def_id.0.to_chalk(interner.db()), subst) - } - - rustc_type_ir::TyKind::Closure(def_id, args) => { - let subst = convert_args_for_result(interner, args.as_slice()); - TyKind::Closure(def_id.0.into(), subst) - } - rustc_type_ir::TyKind::CoroutineClosure(_, _) => unimplemented!(), - rustc_type_ir::TyKind::Coroutine(def_id, args) => { - let subst = convert_args_for_result(interner, args.as_slice()); - TyKind::Coroutine(def_id.0.into(), subst) - } - rustc_type_ir::TyKind::CoroutineWitness(def_id, args) => { - let subst = convert_args_for_result(interner, args.as_slice()); - TyKind::CoroutineWitness(def_id.0.into(), subst) - } - - rustc_type_ir::TyKind::UnsafeBinder(_) => unimplemented!(), - } - .intern(Interner) -} - -pub fn convert_const_for_result<'db>( - interner: DbInterner<'db>, - const_: Const<'db>, -) -> crate::Const { - let value: chalk_ir::ConstValue = match const_.kind() { - rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Var(var)) => { - chalk_ir::ConstValue::InferenceVar(chalk_ir::InferenceVar::from(var.as_u32())) - } - rustc_type_ir::ConstKind::Infer(rustc_type_ir::InferConst::Fresh(_fresh)) => { - panic!("Vars should not be freshened.") - } - rustc_type_ir::ConstKind::Param(param) => { - let placeholder = to_placeholder_idx(interner.db, param.id.into(), param.index); - chalk_ir::ConstValue::Placeholder(placeholder) - } - rustc_type_ir::ConstKind::Bound(debruijn_index, var) => { - chalk_ir::ConstValue::BoundVar(chalk_ir::BoundVar::new( - chalk_ir::DebruijnIndex::new(debruijn_index.as_u32()), - var.var.index(), - )) - } - rustc_type_ir::ConstKind::Placeholder(_placeholder_const) => { - unimplemented!( - "A `rustc_type_ir::ConstKind::Placeholder` doesn't have a direct \ - correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\ - It therefore feels safer to leave it panicking, but if you hit this panic \ - feel free to do the same as in `rustc_type_ir::ConstKind::Bound` here." - ) - } - rustc_type_ir::ConstKind::Unevaluated(unevaluated_const) => { - let id = match unevaluated_const.def { - SolverDefId::ConstId(id) => GeneralConstId::ConstId(id), - SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), - _ => unreachable!(), - }; - let subst = convert_args_for_result(interner, unevaluated_const.args.as_slice()); - chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { - interned: ConstScalar::UnevaluatedConst(id, subst), - }) - } - rustc_type_ir::ConstKind::Value(value_const) => { - let bytes = value_const.value.inner(); - let value = chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { - // SAFETY: we will never actually use this without a database - interned: ConstScalar::Bytes(bytes.memory.clone(), unsafe { - std::mem::transmute::, MemoryMap<'static>>( - bytes.memory_map.clone(), - ) - }), - }); - return chalk_ir::ConstData { - ty: convert_ty_for_result(interner, value_const.ty), - value, - } - .intern(Interner); - } - rustc_type_ir::ConstKind::Error(_) => { - chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { - interned: ConstScalar::Unknown, - }) - } - rustc_type_ir::ConstKind::Expr(_) => unimplemented!(), - }; - chalk_ir::ConstData { ty: crate::TyKind::Error.intern(Interner), value }.intern(Interner) -} - -pub fn convert_region_for_result<'db>( - interner: DbInterner<'db>, - region: Region<'db>, -) -> crate::Lifetime { - let lifetime = match region.kind() { - rustc_type_ir::RegionKind::ReEarlyParam(early) => { - let placeholder = lt_to_placeholder_idx(interner.db, early.id, early.index); - chalk_ir::LifetimeData::Placeholder(placeholder) - } - rustc_type_ir::RegionKind::ReBound(db, bound) => { - chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new( - chalk_ir::DebruijnIndex::new(db.as_u32()), - bound.var.as_usize(), - )) - } - rustc_type_ir::RegionKind::RePlaceholder(_placeholder) => unimplemented!( - "A `rustc_type_ir::RegionKind::RePlaceholder` doesn't have a direct \ - correspondence in Chalk, as it represents a universally instantiated `Bound`.\n\ - It therefore feels safer to leave it panicking, but if you hit this panic \ - feel free to do the same as in `rustc_type_ir::RegionKind::ReBound` here." - ), - rustc_type_ir::RegionKind::ReLateParam(_) => unimplemented!(), - rustc_type_ir::RegionKind::ReStatic => chalk_ir::LifetimeData::Static, - rustc_type_ir::RegionKind::ReVar(vid) => { - chalk_ir::LifetimeData::InferenceVar(chalk_ir::InferenceVar::from(vid.as_u32())) - } - rustc_type_ir::RegionKind::ReErased => chalk_ir::LifetimeData::Erased, - rustc_type_ir::RegionKind::ReError(_) => chalk_ir::LifetimeData::Error, - }; - chalk_ir::Lifetime::new(Interner, lifetime) -} - -pub trait InferenceVarExt { - fn to_vid(self) -> rustc_type_ir::TyVid; - fn from_vid(vid: rustc_type_ir::TyVid) -> InferenceVar; -} - -impl InferenceVarExt for InferenceVar { - fn to_vid(self) -> rustc_type_ir::TyVid { - rustc_type_ir::TyVid::from_u32(self.index()) - } - fn from_vid(vid: rustc_type_ir::TyVid) -> InferenceVar { - InferenceVar::from(vid.as_u32()) +impl<'db> ChalkToNextSolver<'db, crate::lower::ImplTraitIdx<'db>> for crate::ImplTraitIdx { + fn to_nextsolver(&self, _interner: DbInterner<'db>) -> crate::lower::ImplTraitIdx<'db> { + crate::lower::ImplTraitIdx::from_raw(self.into_raw()) } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs index 70b6f20ede04..3438b755fb9e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs @@ -13,7 +13,7 @@ use rustc_type_ir::{ }; use smallvec::SmallVec; -use crate::next_solver::TraitIdWrapper; +use crate::next_solver::{InternedWrapperNoDebug, TraitIdWrapper}; use super::{Binder, BoundVarKinds, DbInterner, Region, Ty, interned_vec_db}; @@ -171,9 +171,6 @@ impl<'db> rustc_type_ir::relate::Relate> for BoundExistentialPre } } -#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)] -pub struct InternedWrapperNoDebug(pub(crate) T); - #[salsa::interned(constructor = new_)] pub struct Predicate<'db> { #[returns(ref)] 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 8932f519785c..7cf23b82f63d 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 @@ -26,11 +26,11 @@ use rustc_type_ir::{ use crate::{ ImplTraitId, db::HirDatabase, - interner::InternedWrapperNoDebug, next_solver::{ AdtDef, Binder, CallableIdWrapper, Clause, ClauseKind, ClosureIdWrapper, Const, CoroutineIdWrapper, FnSig, GenericArg, PolyFnSig, Region, TraitRef, TypeAliasIdWrapper, abi::Safety, + interner::InternedWrapperNoDebug, mapping::ChalkToNextSolver, util::{CoroutineArgsExt, IntegerTypeExt}, }, @@ -531,7 +531,7 @@ impl<'db> Ty<'db> { 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| { + db.return_type_impl_traits(func).map(|it| { let data = (*it).as_ref().map_bound(|rpit| { &rpit.impl_traits[idx.to_nextsolver(interner)].predicates }); @@ -540,7 +540,7 @@ impl<'db> Ty<'db> { }) } ImplTraitId::TypeAliasImplTrait(alias, idx) => { - db.type_alias_impl_traits_ns(alias).map(|it| { + db.type_alias_impl_traits(alias).map(|it| { let data = (*it).as_ref().map_bound(|rpit| { &rpit.impl_traits[idx.to_nextsolver(interner)].predicates }); @@ -575,7 +575,7 @@ impl<'db> Ty<'db> { TypeOrConstParamData::TypeParamData(p) => match p.provenance { TypeParamProvenance::ArgumentImplTrait => { let predicates = db - .generic_predicates_ns(param.id.parent()) + .generic_predicates(param.id.parent()) .instantiate_identity() .into_iter() .flatten() diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/util.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/util.rs index 97f536305805..bb0d0552c710 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/util.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/util.rs @@ -1,46 +1,42 @@ //! Various utilities for the next-trait-solver. -use std::iter; -use std::ops::{self, ControlFlow}; +use std::{ + iter, + ops::{self, ControlFlow}, +}; use base_db::Crate; -use hir_def::lang_item::LangItem; -use hir_def::{BlockId, HasModule}; +use hir_def::{BlockId, HasModule, lang_item::LangItem}; use intern::sym; use la_arena::Idx; use rustc_abi::{Float, HasDataLayout, Integer, IntegerType, Primitive, ReprOptions}; -use rustc_type_ir::data_structures::IndexMap; -use rustc_type_ir::inherent::{ - AdtDef, GenericArg as _, GenericArgs as _, ParamEnv as _, SliceLike, Ty as _, -}; -use rustc_type_ir::lang_items::SolverTraitLangItem; -use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::{ - BoundVar, Canonical, DebruijnIndex, GenericArgKind, INNERMOST, Interner, PredicatePolarity, - TypeVisitableExt, + ConstKind, CoroutineArgs, DebruijnIndex, FloatTy, GenericArgKind, INNERMOST, IntTy, Interner, + PredicatePolarity, RegionKind, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, + TypeVisitableExt, TypeVisitor, UintTy, UniverseIndex, + inherent::{ + AdtDef, GenericArg as _, GenericArgs as _, IntoKind, ParamEnv as _, SliceLike, Ty as _, + }, + lang_items::SolverTraitLangItem, + solve::SizedTraitKind, }; -use rustc_type_ir::{ - ConstKind, CoroutineArgs, FloatTy, IntTy, RegionKind, TypeFolder, TypeSuperFoldable, - TypeSuperVisitable, TypeVisitor, UintTy, UniverseIndex, inherent::IntoKind, -}; -use rustc_type_ir::{InferCtxtLike, TypeFoldable}; -use crate::lower_nextsolver::{LifetimeElisionKind, TyLoweringContext}; -use crate::next_solver::infer::InferCtxt; -use crate::next_solver::{ - BoundConst, FxIndexMap, ParamEnv, Placeholder, PlaceholderConst, PlaceholderRegion, -}; use crate::{ db::HirDatabase, + lower::{LifetimeElisionKind, TyLoweringContext}, method_resolution::{TraitImpls, TyFingerprint}, + next_solver::{ + BoundConst, FxIndexMap, ParamEnv, Placeholder, PlaceholderConst, PlaceholderRegion, + infer::InferCtxt, + }, }; -use super::fold::{BoundVarReplacer, FnMutDelegate}; use super::{ AliasTerm, AliasTy, Binder, BoundRegion, BoundTy, BoundTyKind, BoundVarKind, BoundVarKinds, - CanonicalVars, Clause, ClauseKind, Clauses, Const, DbInterner, EarlyBinder, GenericArg, - GenericArgs, Predicate, PredicateKind, ProjectionPredicate, Region, SolverContext, SolverDefId, - Term, TraitPredicate, TraitRef, Ty, TyKind, + Clause, ClauseKind, Clauses, Const, DbInterner, EarlyBinder, GenericArgs, Predicate, + PredicateKind, ProjectionPredicate, Region, SolverDefId, Term, TraitPredicate, TraitRef, Ty, + TyKind, + fold::{BoundVarReplacer, FnMutDelegate}, }; #[derive(Clone, Debug)] @@ -510,151 +506,6 @@ pub fn apply_args_to_binder<'db, T: TypeFoldable>>( b.skip_binder().fold_with(&mut instantiate) } -pub(crate) fn mini_canonicalize<'db, T: TypeFoldable>>( - mut context: SolverContext<'db>, - val: T, -) -> Canonical, T> { - let mut canon = MiniCanonicalizer { - context: &mut context, - db: DebruijnIndex::ZERO, - vars: IndexMap::default(), - }; - let canon_val = val.fold_with(&mut canon); - let vars = canon.vars; - Canonical { - value: canon_val, - max_universe: UniverseIndex::from_u32(1), - variables: CanonicalVars::new_from_iter( - context.cx(), - vars.iter().enumerate().map(|(idx, (k, _v))| match (*k).kind() { - GenericArgKind::Type(ty) => match ty.kind() { - TyKind::Int(..) | TyKind::Uint(..) => rustc_type_ir::CanonicalVarKind::Int, - TyKind::Float(..) => rustc_type_ir::CanonicalVarKind::Float, - _ => rustc_type_ir::CanonicalVarKind::Ty { - ui: UniverseIndex::ZERO, - sub_root: BoundVar::from_usize(idx), - }, - }, - GenericArgKind::Lifetime(_) => { - rustc_type_ir::CanonicalVarKind::Region(UniverseIndex::ZERO) - } - GenericArgKind::Const(_) => { - rustc_type_ir::CanonicalVarKind::Const(UniverseIndex::ZERO) - } - }), - ), - } -} - -struct MiniCanonicalizer<'a, 'db> { - context: &'a mut SolverContext<'db>, - db: DebruijnIndex, - vars: IndexMap, usize>, -} - -impl<'db> TypeFolder> for MiniCanonicalizer<'_, 'db> { - fn cx(&self) -> DbInterner<'db> { - self.context.cx() - } - - fn fold_binder>>( - &mut self, - t: rustc_type_ir::Binder, T>, - ) -> rustc_type_ir::Binder, T> { - self.db.shift_in(1); - let res = t.map_bound(|t| t.fold_with(self)); - self.db.shift_out(1); - res - } - - fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> { - match t.kind() { - rustc_type_ir::TyKind::Bound(db, _) => { - if db >= self.db { - panic!("Unexpected bound var"); - } - t - } - rustc_type_ir::TyKind::Infer(infer) => { - let t = match infer { - rustc_type_ir::InferTy::TyVar(vid) => { - self.context.opportunistic_resolve_ty_var(vid) - } - rustc_type_ir::InferTy::IntVar(vid) => { - self.context.opportunistic_resolve_int_var(vid) - } - rustc_type_ir::InferTy::FloatVar(vid) => { - self.context.opportunistic_resolve_float_var(vid) - } - _ => t, - }; - let len = self.vars.len(); - let var = *self.vars.entry(t.into()).or_insert(len); - Ty::new( - self.cx(), - TyKind::Bound( - self.db, - BoundTy { kind: super::BoundTyKind::Anon, var: BoundVar::from_usize(var) }, - ), - ) - } - _ => t.super_fold_with(self), - } - } - - fn fold_region( - &mut self, - r: as rustc_type_ir::Interner>::Region, - ) -> as rustc_type_ir::Interner>::Region { - match r.kind() { - RegionKind::ReBound(db, _) => { - if db >= self.db { - panic!("Unexpected bound var"); - } - r - } - RegionKind::ReVar(_vid) => { - let len = self.vars.len(); - let var = *self.vars.entry(r.into()).or_insert(len); - Region::new( - self.cx(), - RegionKind::ReBound( - self.db, - BoundRegion { - kind: super::BoundRegionKind::Anon, - var: BoundVar::from_usize(var), - }, - ), - ) - } - _ => r, - } - } - - fn fold_const( - &mut self, - c: as rustc_type_ir::Interner>::Const, - ) -> as rustc_type_ir::Interner>::Const { - match c.kind() { - ConstKind::Bound(db, _) => { - if db >= self.db { - panic!("Unexpected bound var"); - } - c - } - ConstKind::Infer(_infer) => { - let len = self.vars.len(); - let var = *self.vars.entry(c.into()).or_insert(len); - Const::new( - self.cx(), - ConstKind::Bound(self.db, BoundConst { var: BoundVar::from_usize(var) }), - ) - } - _ => c.super_fold_with(self), - } - } -} - pub fn explicit_item_bounds<'db>( interner: DbInterner<'db>, def_id: SolverDefId, @@ -713,7 +564,7 @@ pub fn explicit_item_bounds<'db>( match full_id { crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => { let datas = db - .return_type_impl_traits_ns(func) + .return_type_impl_traits(func) .expect("impl trait id without impl traits"); let datas = (*datas).as_ref().skip_binder(); let data = &datas.impl_traits[Idx::from_raw(idx.into_raw())]; @@ -721,7 +572,7 @@ pub fn explicit_item_bounds<'db>( } crate::ImplTraitId::TypeAliasImplTrait(alias, idx) => { let datas = db - .type_alias_impl_traits_ns(alias) + .type_alias_impl_traits(alias) .expect("impl trait id without impl traits"); let datas = (*datas).as_ref().skip_binder(); let data = &datas.impl_traits[Idx::from_raw(idx.into_raw())]; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs index 76cd5f7ab330..bc4701970c76 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs @@ -44,7 +44,7 @@ fn foo() -> i32 { "body_shim", "body_with_source_map_shim", "trait_environment_shim", - "return_type_impl_traits_ns_shim", + "return_type_impl_traits_shim", "expr_scopes_shim", "lang_item", "crate_lang_items", @@ -131,7 +131,7 @@ fn baz() -> i32 { "body_shim", "body_with_source_map_shim", "trait_environment_shim", - "return_type_impl_traits_ns_shim", + "return_type_impl_traits_shim", "expr_scopes_shim", "lang_item", "crate_lang_items", @@ -143,7 +143,7 @@ fn baz() -> i32 { "body_shim", "body_with_source_map_shim", "trait_environment_shim", - "return_type_impl_traits_ns_shim", + "return_type_impl_traits_shim", "expr_scopes_shim", "infer_shim", "function_signature_shim", @@ -151,7 +151,7 @@ fn baz() -> i32 { "body_shim", "body_with_source_map_shim", "trait_environment_shim", - "return_type_impl_traits_ns_shim", + "return_type_impl_traits_shim", "expr_scopes_shim", ] "#]], @@ -585,8 +585,8 @@ fn main() { "crate_lang_items", "attrs_shim", "attrs_shim", - "generic_predicates_ns_shim", - "return_type_impl_traits_ns_shim", + "generic_predicates_shim", + "return_type_impl_traits_shim", "infer_shim", "function_signature_shim", "function_signature_with_source_map_shim", @@ -594,7 +594,7 @@ fn main() { "expr_scopes_shim", "struct_signature_shim", "struct_signature_with_source_map_shim", - "generic_predicates_ns_shim", + "generic_predicates_shim", "value_ty_shim", "VariantFields::firewall_", "VariantFields::query_", @@ -608,9 +608,9 @@ fn main() { "trait_impls_in_crate_shim", "impl_trait_with_diagnostics_shim", "impl_self_ty_with_diagnostics_shim", - "generic_predicates_ns_shim", + "generic_predicates_shim", "value_ty_shim", - "generic_predicates_ns_shim", + "generic_predicates_shim", ] "#]], ); @@ -682,13 +682,13 @@ fn main() { "attrs_shim", "attrs_shim", "attrs_shim", - "generic_predicates_ns_shim", - "return_type_impl_traits_ns_shim", + "generic_predicates_shim", + "return_type_impl_traits_shim", "infer_shim", "function_signature_with_source_map_shim", "expr_scopes_shim", "struct_signature_with_source_map_shim", - "generic_predicates_ns_shim", + "generic_predicates_shim", "VariantFields::query_", "inherent_impls_in_crate_shim", "impl_signature_with_source_map_shim", @@ -697,8 +697,8 @@ fn main() { "trait_impls_in_crate_shim", "impl_trait_with_diagnostics_shim", "impl_self_ty_with_diagnostics_shim", - "generic_predicates_ns_shim", - "generic_predicates_ns_shim", + "generic_predicates_shim", + "generic_predicates_shim", ] "#]], ); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs deleted file mode 100644 index fe4cf7a3da52..000000000000 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tls.rs +++ /dev/null @@ -1,155 +0,0 @@ -//! Implementation of Chalk debug helper functions using TLS. -use std::fmt::{self, Display}; - -use itertools::Itertools; -use span::Edition; - -use crate::{ - CallableDefId, Interner, ProjectionTyExt, chalk_db, db::HirDatabase, from_assoc_type_id, - from_chalk_trait_id, mapping::from_chalk, -}; -use hir_def::{AdtId, ItemContainerId, Lookup, TypeAliasId}; - -#[allow(unused)] -pub(crate) use unsafe_tls::{set_current_program, with_current_program}; - -pub(crate) struct DebugContext<'a>(&'a dyn HirDatabase); - -impl DebugContext<'_> { - pub(crate) fn debug_struct_id( - &self, - id: chalk_db::AdtId, - f: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let name = match id.0 { - AdtId::StructId(it) => self.0.struct_signature(it).name.clone(), - AdtId::UnionId(it) => self.0.union_signature(it).name.clone(), - AdtId::EnumId(it) => self.0.enum_signature(it).name.clone(), - }; - name.display(self.0, Edition::LATEST).fmt(f)?; - Ok(()) - } - - pub(crate) fn debug_trait_id( - &self, - id: chalk_db::TraitId, - f: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let trait_: hir_def::TraitId = from_chalk_trait_id(id); - let trait_data = self.0.trait_signature(trait_); - trait_data.name.display(self.0, Edition::LATEST).fmt(f)?; - Ok(()) - } - - pub(crate) fn debug_assoc_type_id( - &self, - id: chalk_db::AssocTypeId, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let type_alias: TypeAliasId = from_assoc_type_id(id); - let type_alias_data = self.0.type_alias_signature(type_alias); - let trait_ = match type_alias.lookup(self.0).container { - ItemContainerId::TraitId(t) => t, - _ => panic!("associated type not in trait"), - }; - let trait_data = self.0.trait_signature(trait_); - write!( - fmt, - "{}::{}", - trait_data.name.display(self.0, Edition::LATEST), - type_alias_data.name.display(self.0, Edition::LATEST) - )?; - Ok(()) - } - - pub(crate) fn debug_projection_ty( - &self, - projection_ty: &chalk_ir::ProjectionTy, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let type_alias = from_assoc_type_id(projection_ty.associated_ty_id); - let type_alias_data = self.0.type_alias_signature(type_alias); - let trait_ = match type_alias.lookup(self.0).container { - ItemContainerId::TraitId(t) => t, - _ => panic!("associated type not in trait"), - }; - let trait_name = &self.0.trait_signature(trait_).name; - let trait_ref = projection_ty.trait_ref(self.0); - let trait_params = trait_ref.substitution.as_slice(Interner); - let self_ty = trait_ref.self_type_parameter(Interner); - write!(fmt, "<{self_ty:?} as {}", trait_name.display(self.0, Edition::LATEST))?; - if trait_params.len() > 1 { - write!( - fmt, - "<{}>", - trait_params[1..].iter().format_with(", ", |x, f| f(&format_args!("{x:?}"))), - )?; - } - write!(fmt, ">::{}", type_alias_data.name.display(self.0, Edition::LATEST))?; - - let proj_params = &projection_ty.substitution.as_slice(Interner)[trait_params.len()..]; - if !proj_params.is_empty() { - write!( - fmt, - "<{}>", - proj_params.iter().format_with(", ", |x, f| f(&format_args!("{x:?}"))), - )?; - } - - Ok(()) - } - - pub(crate) fn debug_fn_def_id( - &self, - fn_def_id: chalk_ir::FnDefId, - fmt: &mut fmt::Formatter<'_>, - ) -> Result<(), fmt::Error> { - let def: CallableDefId = from_chalk(self.0, fn_def_id); - let name = match def { - CallableDefId::FunctionId(ff) => self.0.function_signature(ff).name.clone(), - CallableDefId::StructId(s) => self.0.struct_signature(s).name.clone(), - CallableDefId::EnumVariantId(e) => { - let loc = e.lookup(self.0); - loc.parent.enum_variants(self.0).variants[loc.index as usize].1.clone() - } - }; - match def { - CallableDefId::FunctionId(_) => { - write!(fmt, "{{fn {}}}", name.display(self.0, Edition::LATEST)) - } - CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => { - write!(fmt, "{{ctor {}}}", name.display(self.0, Edition::LATEST)) - } - } - } -} - -mod unsafe_tls { - use super::DebugContext; - use crate::db::HirDatabase; - use scoped_tls::scoped_thread_local; - - scoped_thread_local!(static PROGRAM: DebugContext<'_>); - - pub(crate) fn with_current_program( - op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R, - ) -> R { - if PROGRAM.is_set() { PROGRAM.with(|prog| op(Some(prog))) } else { op(None) } - } - - #[allow(dead_code)] - pub(crate) fn set_current_program(p: &dyn HirDatabase, op: OP) -> R - where - OP: FnOnce() -> R, - { - let ctx = DebugContext(p); - // we're transmuting the lifetime in the DebugContext to static. This is - // fine because we only keep the reference for the lifetime of this - // function, *and* the only way to access the context is through - // `with_current_program`, which hides the lifetime through the `for` - // type. - let static_p: &DebugContext<'static> = - unsafe { std::mem::transmute::<&DebugContext<'_>, &DebugContext<'static>>(&ctx) }; - PROGRAM.set(static_p, op) - } -} 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 35c8a197f52c..7f6d4ff17f9f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -3,33 +3,26 @@ use core::fmt; use std::hash::Hash; -use chalk_ir::{DebruijnIndex, GoalData, fold::TypeFoldable}; - use base_db::Crate; use hir_def::{BlockId, TraitId, lang_item::LangItem}; use hir_expand::name::Name; use intern::sym; use rustc_next_trait_solver::solve::{HasChanged, SolverDelegateEvalExt}; use rustc_type_ir::{ - InferCtxtLike, TypingMode, - inherent::{IntoKind, SliceLike, Span as _}, + TypingMode, + inherent::{IntoKind, Span as _}, solve::Certainty, }; -use span::Edition; use triomphe::Arc; use crate::{ - AliasEq, AliasTy, Canonical, DomainGoal, Goal, InEnvironment, Interner, ProjectionTyExt, - TraitRefExt, TyKind, WhereClause, db::HirDatabase, next_solver::{ - DbInterner, GenericArg, ParamEnv, Predicate, SolverContext, Span, + Canonical, DbInterner, GenericArgs, Goal, ParamEnv, Predicate, SolverContext, Span, Ty, + TyKind, infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause}, - mapping::{ChalkToNextSolver, convert_canonical_args_for_result}, obligation_ctxt::ObligationCtxt, - util::mini_canonicalize, }, - utils::UnevaluatedConstEvaluatorFolder, }; /// A set of clauses that we assume to be true. E.g. if we are inside this function: @@ -42,7 +35,7 @@ pub struct TraitEnvironment<'db> { pub krate: Crate, pub block: Option, // FIXME make this a BTreeMap - traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>, + traits_from_clauses: Box<[(Ty<'db>, TraitId)]>, pub env: ParamEnv<'db>, } @@ -59,7 +52,7 @@ impl<'db> TraitEnvironment<'db> { pub fn new( krate: Crate, block: Option, - traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>, + traits_from_clauses: Box<[(Ty<'db>, TraitId)]>, env: ParamEnv<'db>, ) -> Arc { Arc::new(TraitEnvironment { krate, block, traits_from_clauses, env }) @@ -70,10 +63,7 @@ impl<'db> TraitEnvironment<'db> { Arc::make_mut(this).block = Some(block); } - pub fn traits_in_scope_from_clauses( - &self, - ty: crate::next_solver::Ty<'db>, - ) -> impl Iterator + '_ { + pub fn traits_in_scope_from_clauses(&self, ty: Ty<'db>) -> impl Iterator + '_ { self.traits_from_clauses .iter() .filter_map(move |(self_ty, trait_id)| (*self_ty == ty).then_some(*trait_id)) @@ -83,92 +73,19 @@ impl<'db> TraitEnvironment<'db> { /// This should be used in `hir` only. pub fn structurally_normalize_ty<'db>( infcx: &InferCtxt<'db>, - ty: crate::next_solver::Ty<'db>, + ty: Ty<'db>, env: Arc>, -) -> crate::next_solver::Ty<'db> { - let crate::next_solver::TyKind::Alias(..) = ty.kind() else { return ty }; +) -> Ty<'db> { + let 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) } -fn identity_subst( - binders: chalk_ir::CanonicalVarKinds, -) -> chalk_ir::Canonical> { - let identity_subst = chalk_ir::Substitution::from_iter( - Interner, - binders.iter(Interner).enumerate().map(|(index, c)| { - let index_db = chalk_ir::BoundVar::new(DebruijnIndex::INNERMOST, index); - match &c.kind { - chalk_ir::VariableKind::Ty(_) => { - chalk_ir::GenericArgData::Ty(TyKind::BoundVar(index_db).intern(Interner)) - .intern(Interner) - } - chalk_ir::VariableKind::Lifetime => chalk_ir::GenericArgData::Lifetime( - chalk_ir::LifetimeData::BoundVar(index_db).intern(Interner), - ) - .intern(Interner), - chalk_ir::VariableKind::Const(ty) => chalk_ir::GenericArgData::Const( - chalk_ir::ConstData { - ty: ty.clone(), - value: chalk_ir::ConstValue::BoundVar(index_db), - } - .intern(Interner), - ) - .intern(Interner), - } - }), - ); - chalk_ir::Canonical { binders, value: identity_subst } -} - -fn solve_nextsolver<'db>( - db: &'db dyn HirDatabase, - krate: Crate, - block: Option, - goal: &chalk_ir::UCanonical>>, -) -> Result< - (HasChanged, Certainty, rustc_type_ir::Canonical, Vec>>), - rustc_type_ir::solve::NoSolution, -> { - // FIXME: should use analysis_in_body, but that needs GenericDefId::Block - let context = SolverContext( - DbInterner::new_with(db, Some(krate), block) - .infer_ctxt() - .build(TypingMode::non_body_analysis()), - ); - - match goal.canonical.value.goal.data(Interner) { - // FIXME: args here should be...what? not empty - GoalData::All(goals) if goals.is_empty(Interner) => { - return Ok((HasChanged::No, Certainty::Yes, mini_canonicalize(context, vec![]))); - } - _ => {} - } - - let goal = goal.canonical.to_nextsolver(context.cx()); - tracing::info!(?goal); - - let (goal, var_values) = context.instantiate_canonical(&goal); - tracing::info!(?var_values); - - let res = context.evaluate_root_goal(goal, Span::dummy(), None); - - let vars = - var_values.var_values.iter().map(|g| context.0.resolve_vars_if_possible(g)).collect(); - let canonical_var_values = mini_canonicalize(context, vars); - - let res = res.map(|r| (r.has_changed, r.certainty, canonical_var_values)); - - tracing::debug!("solve_nextsolver({:?}) => {:?}", goal, res); - - res -} - #[derive(Clone, Debug, PartialEq)] pub enum NextTraitSolveResult { - Certain(chalk_ir::Canonical>), - Uncertain(chalk_ir::Canonical>), + Certain, + Uncertain, NoSolution, } @@ -178,75 +95,17 @@ impl NextTraitSolveResult { } pub fn certain(&self) -> bool { - matches!(self, NextTraitSolveResult::Certain(..)) + matches!(self, NextTraitSolveResult::Certain) } pub fn uncertain(&self) -> bool { - matches!(self, NextTraitSolveResult::Uncertain(..)) - } -} - -pub fn next_trait_solve( - db: &dyn HirDatabase, - krate: Crate, - block: Option, - goal: Canonical>, -) -> NextTraitSolveResult { - let detail = match &goal.value.goal.data(Interner) { - GoalData::DomainGoal(DomainGoal::Holds(WhereClause::Implemented(it))) => { - db.trait_signature(it.hir_trait_id()).name.display(db, Edition::LATEST).to_string() - } - GoalData::DomainGoal(DomainGoal::Holds(WhereClause::AliasEq(_))) => "alias_eq".to_owned(), - _ => "??".to_owned(), - }; - let _p = tracing::info_span!("next_trait_solve", ?detail).entered(); - tracing::info!("next_trait_solve({:?})", goal.value.goal); - - if let GoalData::DomainGoal(DomainGoal::Holds(WhereClause::AliasEq(AliasEq { - alias: AliasTy::Projection(projection_ty), - .. - }))) = &goal.value.goal.data(Interner) - && let TyKind::BoundVar(_) = projection_ty.self_type_parameter(db).kind(Interner) - { - // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible - // FIXME - return NextTraitSolveResult::Uncertain(identity_subst(goal.binders.clone())); - } - - // Chalk see `UnevaluatedConst` as a unique concrete value, but we see it as an alias for another const. So - // we should get rid of it when talking to chalk. - let goal = goal - .try_fold_with(&mut UnevaluatedConstEvaluatorFolder { db }, DebruijnIndex::INNERMOST) - .unwrap(); - - // We currently don't deal with universes (I think / hope they're not yet - // relevant for our use cases?) - let u_canonical = chalk_ir::UCanonical { canonical: goal, universes: 1 }; - tracing::info!(?u_canonical); - - let next_solver_res = solve_nextsolver(db, krate, block, &u_canonical); - - match next_solver_res { - Err(_) => NextTraitSolveResult::NoSolution, - Ok((_, Certainty::Yes, args)) => NextTraitSolveResult::Certain( - convert_canonical_args_for_result(DbInterner::new_with(db, Some(krate), block), args), - ), - Ok((_, Certainty::Maybe { .. }, args)) => { - let subst = convert_canonical_args_for_result( - DbInterner::new_with(db, Some(krate), block), - args, - ); - NextTraitSolveResult::Uncertain(chalk_ir::Canonical { - binders: subst.binders, - value: subst.value.subst, - }) - } + matches!(self, NextTraitSolveResult::Uncertain) } } pub fn next_trait_solve_canonical_in_ctxt<'db>( infer_ctxt: &InferCtxt<'db>, - goal: crate::next_solver::Canonical<'db, crate::next_solver::Goal<'db, Predicate<'db>>>, + goal: Canonical<'db, Goal<'db, Predicate<'db>>>, ) -> NextTraitSolveResult { let context = SolverContext(infer_ctxt.clone()); @@ -257,33 +116,21 @@ pub fn next_trait_solve_canonical_in_ctxt<'db>( let res = context.evaluate_root_goal(goal, Span::dummy(), None); - let vars = - var_values.var_values.iter().map(|g| context.0.resolve_vars_if_possible(g)).collect(); - let canonical_var_values = mini_canonicalize(context, vars); - - let res = res.map(|r| (r.has_changed, r.certainty, canonical_var_values)); + let res = res.map(|r| (r.has_changed, r.certainty)); tracing::debug!("solve_nextsolver({:?}) => {:?}", goal, res); match res { Err(_) => NextTraitSolveResult::NoSolution, - Ok((_, Certainty::Yes, args)) => NextTraitSolveResult::Certain( - convert_canonical_args_for_result(infer_ctxt.interner, args), - ), - Ok((_, Certainty::Maybe { .. }, args)) => { - let subst = convert_canonical_args_for_result(infer_ctxt.interner, args); - NextTraitSolveResult::Uncertain(chalk_ir::Canonical { - binders: subst.binders, - value: subst.value.subst, - }) - } + Ok((_, Certainty::Yes)) => NextTraitSolveResult::Certain, + Ok((_, Certainty::Maybe { .. })) => NextTraitSolveResult::Uncertain, } } /// Solve a trait goal using next trait solver. pub fn next_trait_solve_in_ctxt<'db, 'a>( infer_ctxt: &'a InferCtxt<'db>, - goal: crate::next_solver::Goal<'db, crate::next_solver::Predicate<'db>>, + goal: Goal<'db, Predicate<'db>>, ) -> Result<(HasChanged, Certainty), rustc_type_ir::solve::NoSolution> { tracing::info!(?goal); @@ -377,7 +224,7 @@ impl FnTrait { /// This should not be used in `hir-ty`, only in `hir`. pub fn implements_trait_unique<'db>( - ty: crate::next_solver::Ty<'db>, + ty: Ty<'db>, db: &'db dyn HirDatabase, env: Arc>, trait_: TraitId, @@ -392,7 +239,7 @@ pub fn implements_trait_unique_with_args<'db>( db: &'db dyn HirDatabase, env: Arc>, trait_: TraitId, - args: crate::next_solver::GenericArgs<'db>, + args: GenericArgs<'db>, ) -> bool { implements_trait_unique_impl(db, env, trait_, &mut |_| args) } @@ -401,7 +248,7 @@ 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>, + create_args: &mut dyn FnMut(&InferCtxt<'db>) -> GenericArgs<'db>, ) -> bool { let interner = DbInterner::new_with(db, Some(env.krate), env.block); // FIXME(next-solver): I believe this should be `PostAnalysis`. @@ -409,7 +256,7 @@ fn implements_trait_unique_impl<'db>( 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 goal = 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-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 15359922c80e..ca5e33fe6ad0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -1,40 +1,30 @@ //! Helper functions for working with def, which don't need to be a separate //! query, but can't be computed directly from `*Data` (ie, which need a `db`). -use std::{cell::LazyCell, iter}; +use std::cell::LazyCell; use base_db::{ Crate, target::{self, TargetData}, }; -use chalk_ir::{DebruijnIndex, fold::FallibleTypeFolder}; use hir_def::{ - EnumId, EnumVariantId, FunctionId, Lookup, TraitId, TypeAliasId, TypeOrConstParamId, + EnumId, EnumVariantId, FunctionId, Lookup, TraitId, db::DefDatabase, hir::generics::WherePredicate, lang_item::LangItem, resolver::{HasResolver, TypeNs}, type_ref::{TraitBoundModifier, TypeRef}, }; -use hir_expand::name::Name; use intern::sym; use rustc_abi::TargetDataLayout; -use rustc_hash::FxHashSet; -use rustc_type_ir::inherent::{IntoKind, SliceLike}; use smallvec::{SmallVec, smallvec}; use span::Edition; use crate::{ - ChalkTraitId, Const, ConstScalar, Interner, TargetFeatures, TraitRef, TraitRefExt, - consteval::unknown_const, + TargetFeatures, db::HirDatabase, layout::{Layout, TagEncoding}, mir::pad16, - next_solver::{ - DbInterner, - mapping::{ChalkToNextSolver, NextSolverToChalk, convert_args_for_result}, - }, - to_chalk_trait_id, }; pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator + '_ { @@ -75,49 +65,6 @@ pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[Trai result } -/// Given a trait ref (`Self: Trait`), builds all the implied trait refs for -/// super traits. The original trait ref will be included. So the difference to -/// `all_super_traits` is that we keep track of type parameters; for example if -/// we have `Self: Trait` and `Trait: OtherTrait` we'll get -/// `Self: OtherTrait`. -pub(super) fn all_super_trait_refs( - db: &dyn HirDatabase, - trait_ref: TraitRef, - cb: impl FnMut(TraitRef) -> Option, -) -> Option { - let seen = iter::once(trait_ref.trait_id).collect(); - SuperTraits { db, seen, stack: vec![trait_ref] }.find_map(cb) -} - -struct SuperTraits<'a> { - db: &'a dyn HirDatabase, - stack: Vec, - seen: FxHashSet, -} - -impl SuperTraits<'_> { - fn elaborate(&mut self, trait_ref: &TraitRef) { - direct_super_trait_refs(self.db, trait_ref, |trait_ref| { - if !self.seen.contains(&trait_ref.trait_id) { - self.stack.push(trait_ref); - } - }); - } -} - -impl Iterator for SuperTraits<'_> { - type Item = TraitRef; - - fn next(&mut self) -> Option { - if let Some(next) = self.stack.pop() { - self.elaborate(&next); - Some(next) - } else { - None - } - } -} - fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) { let resolver = LazyCell::new(|| trait_.resolver(db)); let (generic_params, store) = db.generic_params_and_store(trait_.into()); @@ -148,49 +95,6 @@ fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut( .for_each(cb); } -fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef, cb: impl FnMut(TraitRef)) { - let interner = DbInterner::new_with(db, None, None); - let generic_params = db.generic_params(trait_ref.hir_trait_id().into()); - let trait_self = match generic_params.trait_self_param() { - Some(p) => TypeOrConstParamId { parent: trait_ref.hir_trait_id().into(), local_id: p }, - None => return, - }; - let trait_ref_args: crate::next_solver::GenericArgs<'_> = - trait_ref.substitution.to_nextsolver(interner); - db.generic_predicates_for_param_ns(trait_self.parent, trait_self, None) - .iter() - .filter_map(|pred| { - let pred = pred.kind(); - // FIXME: how to correctly handle higher-ranked bounds here? - let pred = pred.no_bound_vars().expect("FIXME unexpected higher-ranked trait bound"); - match pred { - rustc_type_ir::ClauseKind::Trait(t) => { - let t = - rustc_type_ir::EarlyBinder::bind(t).instantiate(interner, trait_ref_args); - let trait_id = to_chalk_trait_id(t.def_id().0); - - let substitution = - convert_args_for_result(interner, t.trait_ref.args.as_slice()); - let tr = chalk_ir::TraitRef { trait_id, substitution }; - Some(tr) - } - _ => None, - } - }) - .for_each(cb); -} - -pub(super) fn associated_type_by_name_including_super_traits( - db: &dyn HirDatabase, - trait_ref: TraitRef, - name: &Name, -) -> Option<(TraitRef, TypeAliasId)> { - all_super_trait_refs(db, trait_ref, |t| { - let assoc_type = t.hir_trait_id().trait_items(db).associated_type_by_name(name)?; - Some((t, assoc_type)) - }) -} - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Unsafety { Safe, @@ -263,41 +167,6 @@ pub fn is_fn_unsafe_to_call( } } -pub(crate) struct UnevaluatedConstEvaluatorFolder<'a> { - pub(crate) db: &'a dyn HirDatabase, -} - -impl FallibleTypeFolder for UnevaluatedConstEvaluatorFolder<'_> { - type Error = (); - - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { - self - } - - fn interner(&self) -> Interner { - Interner - } - - fn try_fold_const( - &mut self, - constant: Const, - _outer_binder: DebruijnIndex, - ) -> Result { - if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value - && let ConstScalar::UnevaluatedConst(id, subst) = &c.interned - { - let interner = DbInterner::conjure(); - if let Ok(eval) = self.db.const_eval(*id, subst.to_nextsolver(interner), None) { - return Ok(eval.to_chalk(interner)); - } else { - return Ok(unknown_const(constant.data(Interner).ty.to_nextsolver(interner)) - .to_chalk(interner)); - } - } - Ok(constant) - } -} - pub(crate) fn detect_variant_from_bytes<'a>( layout: &'a Layout, db: &dyn HirDatabase, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index 46898ddeec12..b57bf03f2472 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -128,7 +128,7 @@ impl<'db> Context<'db> { GenericDefId::AdtId(adt) => { let db = self.db; let mut add_constraints_from_variant = |variant| { - for (_, field) in db.field_types_ns(variant).iter() { + for (_, field) in db.field_types(variant).iter() { self.add_constraints_from_ty( field.instantiate_identity(), Variance::Covariant, diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index b31bb248e839..d61c2eca8347 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir/src/display.rs @@ -484,7 +484,7 @@ impl<'db> HirDisplay<'db> for TypeParam { let param_data = ¶ms[self.id.local_id()]; let krate = self.id.parent().krate(f.db).id; let ty = self.ty(f.db).ty; - let predicates = f.db.generic_predicates_ns(self.id.parent()); + let predicates = f.db.generic_predicates(self.id.parent()); let predicates = predicates .instantiate_identity() .into_iter() diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 78b4533a94b0..48eafb0bd4c6 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1271,7 +1271,7 @@ impl<'db> InstantiatedField<'db> { let interner = DbInterner::new_with(db, Some(krate.base()), None); let var_id = self.inner.parent.into(); - let field = db.field_types_ns(var_id)[self.inner.id]; + let field = db.field_types(var_id)[self.inner.id]; let ty = field.instantiate(interner, self.args); TypeNs::new(db, var_id, ty) } @@ -1350,7 +1350,7 @@ impl Field { /// context of the field definition. pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> TypeNs<'db> { let var_id = self.parent.into(); - let ty = db.field_types_ns(var_id)[self.id].skip_binder(); + let ty = db.field_types(var_id)[self.id].skip_binder(); TypeNs::new(db, var_id, ty) } @@ -1368,7 +1368,7 @@ impl Field { }; let interner = DbInterner::new_with(db, None, None); let args = generic_args_from_tys(interner, def_id.into(), generics.map(|ty| ty.ty)); - let ty = db.field_types_ns(var_id)[self.id].instantiate(interner, args); + let ty = db.field_types(var_id)[self.id].instantiate(interner, args); Type::new(db, var_id, ty) } @@ -3693,7 +3693,7 @@ impl GenericDef { }; expr_store_diagnostics(db, acc, &source_map); - push_ty_diagnostics(db, acc, db.generic_defaults_ns_with_diagnostics(def).1, &source_map); + push_ty_diagnostics(db, acc, db.generic_defaults_with_diagnostics(def).1, &source_map); push_ty_diagnostics( db, acc, @@ -4192,7 +4192,7 @@ impl TypeParam { /// parameter, not additional bounds that might be added e.g. by a method if /// the parameter comes from an impl! pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec { - db.generic_predicates_for_param_ns(self.id.parent(), self.id.into(), None) + db.generic_predicates_for_param(self.id.parent(), self.id.into(), None) .iter() .filter_map(|pred| match &pred.kind().skip_binder() { ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)), @@ -4282,7 +4282,7 @@ impl ConstParam { 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_ns(id.parent); + let defaults = db.generic_defaults(id.parent); let ty = defaults.get(local_idx)?; // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. Some(ty.instantiate_identity()) @@ -4883,7 +4883,7 @@ impl<'db> Type<'db> { if variant_data.fields().is_empty() { vec![] } else { - let field_types = self.interner.db().field_types_ns(id); + let field_types = self.interner.db().field_types(id); variant_data .fields() .iter() @@ -5216,7 +5216,7 @@ impl<'db> Type<'db> { _ => return Vec::new(), }; - db.field_types_ns(variant_id) + db.field_types(variant_id) .iter() .map(|(local_id, ty)| { let def = Field { parent: variant_id.into(), id: local_id }; @@ -6450,7 +6450,7 @@ fn generic_args_from_tys<'db>( fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) -> bool { let params = db.generic_params(generic_def); - let defaults = db.generic_defaults_ns(generic_def); + let defaults = db.generic_defaults(generic_def); params .iter_type_or_consts() .filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_))) 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 8d2ba7e604e7..15eab14b88df 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -712,8 +712,7 @@ impl<'db> SourceAnalyzer<'db> { 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_ns(variant).get(field.local_id)?).instantiate(interner, subst); + let field_ty = (*db.field_types(variant).get(field.local_id)?).instantiate(interner, subst); Some(( field.into(), local, @@ -735,8 +734,7 @@ 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 field_ty = - (*db.field_types_ns(variant).get(field.local_id)?).instantiate(interner, subst); + let field_ty = (*db.field_types(variant).get(field.local_id)?).instantiate(interner, subst); Some(( field.into(), Type::new_with_resolver(db, &self.resolver, field_ty), @@ -802,7 +800,7 @@ impl<'db> SourceAnalyzer<'db> { |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); + let field_types = db.field_types(variant); *container = Either::Right(field_types[field].instantiate(interner, subst)); let generic_def = match variant { VariantId::EnumVariantId(it) => it.loc(db).parent.into(), @@ -1255,7 +1253,7 @@ impl<'db> SourceAnalyzer<'db> { missing_fields: Vec, ) -> Vec<(Field, Type<'db>)> { let interner = DbInterner::new_with(db, None, None); - let field_types = db.field_types_ns(variant); + let field_types = db.field_types(variant); missing_fields .into_iter() diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index df3dc53f7c03..91fb4d0a6715 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -9393,7 +9393,7 @@ fn main(a$0: T) {} *a* ```rust - a: T + a: T ``` ---