Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/traits.rs')
| -rw-r--r-- | crates/hir-ty/src/traits.rs | 97 |
1 files changed, 87 insertions, 10 deletions
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs index 8ac152341e..cd125f3af8 100644 --- a/crates/hir-ty/src/traits.rs +++ b/crates/hir-ty/src/traits.rs @@ -12,7 +12,7 @@ use intern::sym; use rustc_next_trait_solver::solve::{HasChanged, SolverDelegateEvalExt}; use rustc_type_ir::{ InferCtxtLike, TypingMode, - inherent::{SliceLike, Span as _}, + inherent::{IntoKind, SliceLike, Span as _, Ty as _}, solve::Certainty, }; use span::Edition; @@ -23,11 +23,12 @@ use crate::{ AliasEq, AliasTy, Canonical, DomainGoal, Goal, InEnvironment, Interner, ProjectionTy, ProjectionTyExt, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause, db::HirDatabase, - infer::unify::InferenceTable, + from_assoc_type_id, next_solver::{ DbInterner, GenericArg, ParamEnv, Predicate, SolverContext, Span, - infer::{DbInternerInferExt, InferCtxt}, - mapping::{ChalkToNextSolver, convert_canonical_args_for_result}, + infer::{DbInternerInferExt, InferCtxt, traits::ObligationCause}, + mapping::{ChalkToNextSolver, NextSolverToChalk, convert_canonical_args_for_result}, + obligation_ctxt::ObligationCtxt, util::mini_canonicalize, }, utils::UnevaluatedConstEvaluatorFolder, @@ -43,7 +44,7 @@ pub struct TraitEnvironment<'db> { pub krate: Crate, pub block: Option<BlockId>, // FIXME make this a BTreeMap - traits_from_clauses: Box<[(Ty, TraitId)]>, + traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>, pub env: ParamEnv<'db>, } @@ -60,7 +61,7 @@ impl<'db> TraitEnvironment<'db> { pub fn new( krate: Crate, block: Option<BlockId>, - traits_from_clauses: Box<[(Ty, TraitId)]>, + traits_from_clauses: Box<[(crate::next_solver::Ty<'db>, TraitId)]>, env: ParamEnv<'db>, ) -> Arc<Self> { Arc::new(TraitEnvironment { krate, block, traits_from_clauses, env }) @@ -71,13 +72,28 @@ impl<'db> TraitEnvironment<'db> { Arc::make_mut(this).block = Some(block); } - pub fn traits_in_scope_from_clauses(&self, ty: Ty) -> impl Iterator<Item = TraitId> + '_ { + pub fn traits_in_scope_from_clauses( + &self, + ty: crate::next_solver::Ty<'db>, + ) -> impl Iterator<Item = TraitId> + '_ { self.traits_from_clauses .iter() .filter_map(move |(self_ty, trait_id)| (*self_ty == ty).then_some(*trait_id)) } } +/// This should be used in `hir` only. +pub fn structurally_normalize_ty<'db>( + infcx: &InferCtxt<'db>, + ty: crate::next_solver::Ty<'db>, + env: Arc<TraitEnvironment<'db>>, +) -> crate::next_solver::Ty<'db> { + let crate::next_solver::TyKind::Alias(..) = ty.kind() else { return ty }; + let mut ocx = ObligationCtxt::new(infcx); + let ty = ocx.structurally_normalize_ty(&ObligationCause::dummy(), env.env, ty).unwrap_or(ty); + ty.replace_infer_with_error(infcx.interner) +} + pub(crate) fn normalize_projection_query<'db>( db: &'db dyn HirDatabase, projection: ProjectionTy, @@ -93,9 +109,30 @@ pub(crate) fn normalize_projection_query<'db>( return TyKind::Error.intern(Interner); } - let mut table = InferenceTable::new(db, env); - let ty = table.normalize_projection_ty(projection); - table.resolve_completely(ty) + let interner = DbInterner::new_with(db, Some(env.krate), env.block); + // FIXME(next-solver): I believe this should use `PostAnalysis` (this is only used for IDE things), + // but this causes some bug because of our incorrect impl of `type_of_opaque_hir_typeck()` for TAIT + // and async blocks. + let infcx = interner.infer_ctxt().build(TypingMode::Analysis { + defining_opaque_types_and_generators: crate::next_solver::SolverDefIds::new_from_iter( + interner, + [], + ), + }); + let alias_ty = crate::next_solver::Ty::new_alias( + interner, + rustc_type_ir::AliasTyKind::Projection, + crate::next_solver::AliasTy::new( + interner, + from_assoc_type_id(projection.associated_ty_id).into(), + <crate::Substitution as ChalkToNextSolver<crate::next_solver::GenericArgs<'_>>>::to_nextsolver(&projection.substitution, interner), + ), + ); + let mut ctxt = crate::next_solver::obligation_ctxt::ObligationCtxt::new(&infcx); + let normalized = ctxt + .structurally_normalize_ty(&ObligationCause::dummy(), env.env, alias_ty) + .unwrap_or(alias_ty); + normalized.replace_infer_with_error(interner).to_chalk(interner) } fn identity_subst( @@ -419,3 +456,43 @@ impl FnTrait { self.lang_item().resolve_trait(db, krate) } } + +/// This should not be used in `hir-ty`, only in `hir`. +pub fn implements_trait_unique<'db>( + ty: crate::next_solver::Ty<'db>, + db: &'db dyn HirDatabase, + env: Arc<TraitEnvironment<'db>>, + trait_: TraitId, +) -> bool { + implements_trait_unique_impl(db, env, trait_, &mut |infcx| { + infcx.fill_rest_fresh_args(trait_.into(), [ty.into()]) + }) +} + +/// This should not be used in `hir-ty`, only in `hir`. +pub fn implements_trait_unique_with_args<'db>( + db: &'db dyn HirDatabase, + env: Arc<TraitEnvironment<'db>>, + trait_: TraitId, + args: crate::next_solver::GenericArgs<'db>, +) -> bool { + implements_trait_unique_impl(db, env, trait_, &mut |_| args) +} + +fn implements_trait_unique_impl<'db>( + db: &'db dyn HirDatabase, + env: Arc<TraitEnvironment<'db>>, + trait_: TraitId, + create_args: &mut dyn FnMut(&InferCtxt<'db>) -> crate::next_solver::GenericArgs<'db>, +) -> bool { + let interner = DbInterner::new_with(db, Some(env.krate), env.block); + // FIXME(next-solver): I believe this should be `PostAnalysis`. + let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); + + let args = create_args(&infcx); + let trait_ref = rustc_type_ir::TraitRef::new_from_args(interner, trait_.into(), args); + let goal = crate::next_solver::Goal::new(interner, env.env, trait_ref); + + let result = crate::traits::next_trait_solve_in_ctxt(&infcx, goal); + matches!(result, Ok((_, Certainty::Yes))) +} |