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 | 191 |
1 files changed, 116 insertions, 75 deletions
diff --git a/crates/hir-ty/src/next_solver/solver.rs b/crates/hir-ty/src/next_solver/solver.rs index 946e57e6cb..b5ed770e16 100644 --- a/crates/hir-ty/src/next_solver/solver.rs +++ b/crates/hir-ty/src/next_solver/solver.rs @@ -1,29 +1,24 @@ //! Defining `SolverContext` for next-trait-solver. -use hir_def::{AssocItemId, GeneralConstId, TypeAliasId}; +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, UniverseIndex, - inherent::{IntoKind, SliceLike, Span as _, 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::mapping::NextSolverToChalk; -use crate::next_solver::{CanonicalVarKind, ImplIdWrapper}; -use crate::{ - TraitRefExt, - db::HirDatabase, - next_solver::{ - ClauseKind, CoercePredicate, PredicateKind, SubtypePredicate, mapping::ChalkToNextSolver, - util::sizedness_fast_path, - }, +use crate::next_solver::{ + AliasTy, CanonicalVarKind, Clause, ClauseKind, CoercePredicate, GenericArgs, ImplIdWrapper, + ParamEnv, Predicate, PredicateKind, SubtypePredicate, Ty, TyKind, fold::fold_tys, + util::sizedness_fast_path, }; use super::{ - Canonical, CanonicalVarValues, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, - ParamEnv, Predicate, SolverDefId, Span, Ty, UnevaluatedConst, + DbInterner, ErrorGuaranteed, GenericArg, SolverDefId, Span, infer::{DbInternerInferExt, InferCtxt, canonical::instantiate::CanonicalExt}, }; @@ -66,7 +61,7 @@ impl<'db> SolverDelegate for SolverContext<'db> { (SolverContext(infcx), value, vars) } - fn fresh_var_for_kind_with_span(&self, arg: GenericArg<'db>, span: Span) -> GenericArg<'db> { + fn fresh_var_for_kind_with_span(&self, arg: GenericArg<'db>, _span: Span) -> GenericArg<'db> { match arg.kind() { GenericArgKind::Lifetime(_) => self.next_region_var().into(), GenericArgKind::Type(_) => self.next_ty_var().into(), @@ -76,15 +71,15 @@ impl<'db> SolverDelegate for SolverContext<'db> { fn leak_check( &self, - max_input_universe: rustc_type_ir::UniverseIndex, + _max_input_universe: rustc_type_ir::UniverseIndex, ) -> Result<(), NoSolution> { Ok(()) } fn well_formed_goals( &self, - param_env: <Self::Interner as rustc_type_ir::Interner>::ParamEnv, - arg: <Self::Interner as rustc_type_ir::Interner>::Term, + _param_env: ParamEnv<'db>, + _arg: <Self::Interner as rustc_type_ir::Interner>::Term, ) -> Option< Vec< rustc_type_ir::solve::Goal< @@ -123,7 +118,7 @@ impl<'db> SolverDelegate for SolverContext<'db> { fn instantiate_canonical_var( &self, kind: CanonicalVarKind<'db>, - span: <Self::Interner as Interner>::Span, + _span: <Self::Interner as Interner>::Span, var_values: &[GenericArg<'db>], universe_map: impl Fn(rustc_type_ir::UniverseIndex) -> rustc_type_ir::UniverseIndex, ) -> GenericArg<'db> { @@ -132,77 +127,123 @@ 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 item_bounds = opaque_id.predicates(interner.db); + 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( &self, - goal_trait_ref: rustc_type_ir::TraitRef<Self::Interner>, - trait_assoc_def_id: <Self::Interner as rustc_type_ir::Interner>::DefId, + _goal_trait_ref: rustc_type_ir::TraitRef<Self::Interner>, + trait_assoc_def_id: SolverDefId, impl_id: ImplIdWrapper, - ) -> Result<Option<<Self::Interner as rustc_type_ir::Interner>::DefId>, ErrorGuaranteed> { - let trait_assoc_id = match trait_assoc_def_id { - SolverDefId::TypeAliasId(id) => id, + ) -> Result<Option<SolverDefId>, ErrorGuaranteed> { + let impl_items = impl_id.0.impl_items(self.0.interner.db()); + let id = match trait_assoc_def_id { + SolverDefId::TypeAliasId(trait_assoc_id) => { + let trait_assoc_data = self.0.interner.db.type_alias_signature(trait_assoc_id); + impl_items + .items + .iter() + .find_map(|(impl_assoc_name, impl_assoc_id)| { + if let AssocItemId::TypeAliasId(impl_assoc_id) = *impl_assoc_id + && *impl_assoc_name == trait_assoc_data.name + { + Some(impl_assoc_id) + } else { + None + } + }) + .map(SolverDefId::TypeAliasId) + } + SolverDefId::ConstId(trait_assoc_id) => { + let trait_assoc_data = self.0.interner.db.const_signature(trait_assoc_id); + let trait_assoc_name = trait_assoc_data + .name + .as_ref() + .expect("unnamed consts should not get passed to the solver"); + impl_items + .items + .iter() + .find_map(|(impl_assoc_name, impl_assoc_id)| { + if let AssocItemId::ConstId(impl_assoc_id) = *impl_assoc_id + && impl_assoc_name == trait_assoc_name + { + Some(impl_assoc_id) + } else { + None + } + }) + .map(SolverDefId::ConstId) + } _ => panic!("Unexpected SolverDefId"), }; - let trait_ref = self - .0 - .interner - .db() - .impl_trait(impl_id.0) - // ImplIds for impls where the trait ref can't be resolved should never reach solver - .expect("invalid impl passed to next-solver") - .into_value_and_skipped_binders() - .0; - let trait_ = trait_ref.hir_trait_id(); - let trait_data = trait_.trait_items(self.0.interner.db()); - let id = - impl_id.0.impl_items(self.0.interner.db()).items.iter().find_map(|item| -> Option<_> { - match item { - (_, AssocItemId::TypeAliasId(type_alias)) => { - let name = &self.0.interner.db().type_alias_signature(*type_alias).name; - let found_trait_assoc_id = trait_data.associated_type_by_name(name)?; - (found_trait_assoc_id == trait_assoc_id).then_some(*type_alias) - } - _ => None, - } - }); - Ok(id.map(SolverDefId::TypeAliasId)) + Ok(id) } fn is_transmutable( &self, - dst: <Self::Interner as rustc_type_ir::Interner>::Ty, - src: <Self::Interner as rustc_type_ir::Interner>::Ty, - assume: <Self::Interner as rustc_type_ir::Interner>::Const, + _dst: Ty<'db>, + _src: Ty<'db>, + _assume: <Self::Interner as rustc_type_ir::Interner>::Const, ) -> Result<Certainty, NoSolution> { unimplemented!() } 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 { - SolverDefId::ConstId(c) => GeneralConstId::ConstId(c), - SolverDefId::StaticId(c) => GeneralConstId::StaticId(c), - _ => unreachable!(), - }; - let subst = uv.args.to_chalk(self.interner); - let ec = self.cx().db.const_eval(c, subst, None).ok()?; - Some(ec.to_nextsolver(self.interner)) + match uv.def.0 { + GeneralConstId::ConstId(c) => { + let subst = uv.args; + let ec = self.cx().db.const_eval(c, subst, None).ok()?; + Some(ec) + } + GeneralConstId::StaticId(c) => { + let ec = self.cx().db.const_eval_static(c).ok()?; + Some(ec) + } + } } fn compute_goal_fast_path( @@ -211,7 +252,7 @@ impl<'db> SolverDelegate for SolverContext<'db> { Self::Interner, <Self::Interner as rustc_type_ir::Interner>::Predicate, >, - span: <Self::Interner as rustc_type_ir::Interner>::Span, + _span: <Self::Interner as rustc_type_ir::Interner>::Span, ) -> Option<Certainty> { if let Some(trait_pred) = goal.predicate.as_trait_clause() { if self.shallow_resolve(trait_pred.self_ty().skip_binder()).is_ty_var() @@ -254,8 +295,8 @@ impl<'db> SolverDelegate for SolverContext<'db> { let pred = goal.predicate.kind(); match pred.no_bound_vars()? { - PredicateKind::Clause(ClauseKind::RegionOutlives(outlives)) => Some(Certainty::Yes), - PredicateKind::Clause(ClauseKind::TypeOutlives(outlives)) => Some(Certainty::Yes), + PredicateKind::Clause(ClauseKind::RegionOutlives(_outlives)) => Some(Certainty::Yes), + PredicateKind::Clause(ClauseKind::TypeOutlives(_outlives)) => Some(Certainty::Yes), PredicateKind::Subtype(SubtypePredicate { a, b, .. }) | PredicateKind::Coerce(CoercePredicate { a, b }) => { if self.shallow_resolve(a).is_ty_var() && self.shallow_resolve(b).is_ty_var() { |