Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/solver.rs')
| -rw-r--r-- | crates/hir-ty/src/next_solver/solver.rs | 91 |
1 files changed, 69 insertions, 22 deletions
diff --git a/crates/hir-ty/src/next_solver/solver.rs b/crates/hir-ty/src/next_solver/solver.rs index 487d164f86..7b96b4008f 100644 --- a/crates/hir-ty/src/next_solver/solver.rs +++ b/crates/hir-ty/src/next_solver/solver.rs @@ -2,17 +2,22 @@ use hir_def::{AssocItemId, GeneralConstId}; use rustc_next_trait_solver::delegate::SolverDelegate; -use rustc_type_ir::GenericArgKind; -use rustc_type_ir::lang_items::SolverTraitLangItem; use rustc_type_ir::{ - InferCtxtLike, Interner, PredicatePolarity, TypeFlags, TypeVisitableExt, - inherent::{IntoKind, Term as _, Ty as _}, + AliasTyKind, GenericArgKind, InferCtxtLike, Interner, PredicatePolarity, TypeFlags, + TypeVisitableExt, + inherent::{IntoKind, SliceLike, Term as _, Ty as _}, + lang_items::SolverTraitLangItem, solve::{Certainty, NoSolution}, }; +use tracing::debug; -use crate::next_solver::{CanonicalVarKind, ImplIdWrapper}; -use crate::next_solver::{ - ClauseKind, CoercePredicate, PredicateKind, SubtypePredicate, util::sizedness_fast_path, +use crate::{ + ImplTraitId, + next_solver::{ + AliasTy, CanonicalVarKind, Clause, ClauseKind, CoercePredicate, GenericArgs, ImplIdWrapper, + ParamEnv, Predicate, PredicateKind, SubtypePredicate, Ty, TyKind, fold::fold_tys, + util::sizedness_fast_path, + }, }; use super::{ @@ -76,7 +81,7 @@ impl<'db> SolverDelegate for SolverContext<'db> { fn well_formed_goals( &self, - _param_env: <Self::Interner as rustc_type_ir::Interner>::ParamEnv, + _param_env: ParamEnv<'db>, _arg: <Self::Interner as rustc_type_ir::Interner>::Term, ) -> Option< Vec< @@ -125,18 +130,60 @@ impl<'db> SolverDelegate for SolverContext<'db> { fn add_item_bounds_for_hidden_type( &self, - _def_id: <Self::Interner as rustc_type_ir::Interner>::DefId, - _args: <Self::Interner as rustc_type_ir::Interner>::GenericArgs, - _param_env: <Self::Interner as rustc_type_ir::Interner>::ParamEnv, - _hidden_ty: <Self::Interner as rustc_type_ir::Interner>::Ty, - _goals: &mut Vec< - rustc_type_ir::solve::Goal< - Self::Interner, - <Self::Interner as rustc_type_ir::Interner>::Predicate, - >, - >, + def_id: SolverDefId, + args: GenericArgs<'db>, + param_env: ParamEnv<'db>, + hidden_ty: Ty<'db>, + goals: &mut Vec<Goal<'db, Predicate<'db>>>, ) { - unimplemented!() + let interner = self.interner; + let opaque_id = def_id.expect_opaque_ty(); + // Require that the hidden type is well-formed. We have to + // make sure we wf-check the hidden type to fix #114728. + // + // However, we don't check that all types are well-formed. + // We only do so for types provided by the user or if they are + // "used", e.g. for method selection. + // + // This means we never check the wf requirements of the hidden + // type during MIR borrowck, causing us to infer the wrong + // lifetime for its member constraints which then results in + // unexpected region errors. + goals.push(Goal::new(interner, param_env, ClauseKind::WellFormed(hidden_ty.into()))); + + let replace_opaques_in = |clause: Clause<'db>| { + fold_tys(interner, clause, |ty| match ty.kind() { + // Replace all other mentions of the same opaque type with the hidden type, + // as the bounds must hold on the hidden type after all. + TyKind::Alias( + AliasTyKind::Opaque, + AliasTy { def_id: def_id2, args: args2, .. }, + ) if def_id == def_id2 && args == args2 => hidden_ty, + _ => ty, + }) + }; + + let db = interner.db; + let (opaques_table, opaque_idx) = match opaque_id.loc(db) { + ImplTraitId::ReturnTypeImplTrait(func, opaque_idx) => { + (db.return_type_impl_traits(func), opaque_idx) + } + ImplTraitId::TypeAliasImplTrait(type_alias, opaque_idx) => { + (db.type_alias_impl_traits(type_alias), opaque_idx) + } + }; + let item_bounds = opaques_table + .as_deref() + .unwrap() + .as_ref() + .map_bound(|table| &table.impl_traits[opaque_idx].predicates); + for predicate in item_bounds.iter_instantiated_copied(interner, args.as_slice()) { + let predicate = replace_opaques_in(predicate); + + // Require that the predicate holds for the concrete type. + debug!(?predicate); + goals.push(Goal::new(interner, param_env, predicate)); + } } fn fetch_eligible_assoc_item( @@ -190,8 +237,8 @@ impl<'db> SolverDelegate for SolverContext<'db> { fn is_transmutable( &self, - _dst: <Self::Interner as rustc_type_ir::Interner>::Ty, - _src: <Self::Interner as rustc_type_ir::Interner>::Ty, + _dst: Ty<'db>, + _src: Ty<'db>, _assume: <Self::Interner as rustc_type_ir::Interner>::Const, ) -> Result<Certainty, NoSolution> { unimplemented!() @@ -199,7 +246,7 @@ impl<'db> SolverDelegate for SolverContext<'db> { fn evaluate_const( &self, - _param_env: <Self::Interner as rustc_type_ir::Interner>::ParamEnv, + _param_env: ParamEnv<'db>, uv: rustc_type_ir::UnevaluatedConst<Self::Interner>, ) -> Option<<Self::Interner as rustc_type_ir::Interner>::Const> { let c = match uv.def { |