1use hir_def::{AssocItemId, GeneralConstId, TypeAliasId};
4use rustc_next_trait_solver::delegate::SolverDelegate;
5use rustc_type_ir::lang_items::SolverTraitLangItem;
6use rustc_type_ir::{
7 InferCtxtLike, Interner, PredicatePolarity, TypeFlags, TypeVisitableExt, UniverseIndex,
8 inherent::{IntoKind, SliceLike, Span as _, Term as _, Ty as _},
9 solve::{Certainty, NoSolution},
10};
11
12use crate::{
13 TraitRefExt,
14 db::HirDatabase,
15 next_solver::{
16 ClauseKind, CoercePredicate, PredicateKind, SubtypePredicate,
17 mapping::{ChalkToNextSolver, convert_args_for_result},
18 util::sizedness_fast_path,
19 },
20};
21
22use super::{
23 Canonical, CanonicalVarValues, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
24 ParamEnv, Predicate, SolverDefId, Span, Ty, UnevaluatedConst,
25 infer::{DbInternerInferExt, InferCtxt, canonical::instantiate::CanonicalExt},
26};
27
28pub type Goal<'db, P> = rustc_type_ir::solve::Goal<DbInterner<'db>, P>;
29
30#[repr(transparent)]
31pub(crate) struct SolverContext<'db>(pub(crate) InferCtxt<'db>);
32
33impl<'a, 'db> From<&'a InferCtxt<'db>> for &'a SolverContext<'db> {
34 fn from(infcx: &'a InferCtxt<'db>) -> Self {
35 unsafe { std::mem::transmute(infcx) }
37 }
38}
39
40impl<'db> std::ops::Deref for SolverContext<'db> {
41 type Target = InferCtxt<'db>;
42
43 fn deref(&self) -> &Self::Target {
44 &self.0
45 }
46}
47
48impl<'db> SolverDelegate for SolverContext<'db> {
49 type Interner = DbInterner<'db>;
50 type Infcx = InferCtxt<'db>;
51
52 fn cx(&self) -> Self::Interner {
53 self.0.interner
54 }
55
56 fn build_with_canonical<V>(
57 cx: Self::Interner,
58 canonical: &rustc_type_ir::CanonicalQueryInput<Self::Interner, V>,
59 ) -> (Self, V, rustc_type_ir::CanonicalVarValues<Self::Interner>)
60 where
61 V: rustc_type_ir::TypeFoldable<Self::Interner>,
62 {
63 let (infcx, value, vars) = cx.infer_ctxt().build_with_canonical(canonical);
64 (SolverContext(infcx), value, vars)
65 }
66
67 fn fresh_var_for_kind_with_span(
68 &self,
69 arg: <Self::Interner as rustc_type_ir::Interner>::GenericArg,
70 span: <Self::Interner as rustc_type_ir::Interner>::Span,
71 ) -> <Self::Interner as rustc_type_ir::Interner>::GenericArg {
72 unimplemented!()
73 }
74
75 fn leak_check(
76 &self,
77 max_input_universe: rustc_type_ir::UniverseIndex,
78 ) -> Result<(), NoSolution> {
79 Ok(())
80 }
81
82 fn well_formed_goals(
83 &self,
84 param_env: <Self::Interner as rustc_type_ir::Interner>::ParamEnv,
85 arg: <Self::Interner as rustc_type_ir::Interner>::Term,
86 ) -> Option<
87 Vec<
88 rustc_type_ir::solve::Goal<
89 Self::Interner,
90 <Self::Interner as rustc_type_ir::Interner>::Predicate,
91 >,
92 >,
93 > {
94 unimplemented!()
95 }
96
97 fn make_deduplicated_outlives_constraints(
98 &self,
99 ) -> Vec<
100 rustc_type_ir::OutlivesPredicate<
101 Self::Interner,
102 <Self::Interner as rustc_type_ir::Interner>::GenericArg,
103 >,
104 > {
105 vec![]
107 }
108
109 fn instantiate_canonical<V>(
110 &self,
111 canonical: rustc_type_ir::Canonical<Self::Interner, V>,
112 values: rustc_type_ir::CanonicalVarValues<Self::Interner>,
113 ) -> V
114 where
115 V: rustc_type_ir::TypeFoldable<Self::Interner>,
116 {
117 canonical.instantiate(self.cx(), &values)
118 }
119
120 fn instantiate_canonical_var_with_infer(
121 &self,
122 cv_info: rustc_type_ir::CanonicalVarKind<Self::Interner>,
123 _span: <Self::Interner as rustc_type_ir::Interner>::Span,
124 universe_map: impl Fn(rustc_type_ir::UniverseIndex) -> rustc_type_ir::UniverseIndex,
125 ) -> <Self::Interner as rustc_type_ir::Interner>::GenericArg {
126 self.0.instantiate_canonical_var(cv_info, universe_map)
127 }
128
129 fn add_item_bounds_for_hidden_type(
130 &self,
131 def_id: <Self::Interner as rustc_type_ir::Interner>::DefId,
132 args: <Self::Interner as rustc_type_ir::Interner>::GenericArgs,
133 param_env: <Self::Interner as rustc_type_ir::Interner>::ParamEnv,
134 hidden_ty: <Self::Interner as rustc_type_ir::Interner>::Ty,
135 goals: &mut Vec<
136 rustc_type_ir::solve::Goal<
137 Self::Interner,
138 <Self::Interner as rustc_type_ir::Interner>::Predicate,
139 >,
140 >,
141 ) {
142 unimplemented!()
143 }
144
145 fn fetch_eligible_assoc_item(
146 &self,
147 goal_trait_ref: rustc_type_ir::TraitRef<Self::Interner>,
148 trait_assoc_def_id: <Self::Interner as rustc_type_ir::Interner>::DefId,
149 impl_def_id: <Self::Interner as rustc_type_ir::Interner>::DefId,
150 ) -> Result<Option<<Self::Interner as rustc_type_ir::Interner>::DefId>, ErrorGuaranteed> {
151 let impl_id = match impl_def_id {
152 SolverDefId::ImplId(id) => id,
153 _ => panic!("Unexpected SolverDefId"),
154 };
155 let trait_assoc_id = match trait_assoc_def_id {
156 SolverDefId::TypeAliasId(id) => id,
157 _ => panic!("Unexpected SolverDefId"),
158 };
159 let trait_ref = self
160 .0
161 .interner
162 .db()
163 .impl_trait(impl_id)
164 .expect("invalid impl passed to next-solver")
166 .into_value_and_skipped_binders()
167 .0;
168 let trait_ = trait_ref.hir_trait_id();
169 let trait_data = trait_.trait_items(self.0.interner.db());
170 let id =
171 impl_id.impl_items(self.0.interner.db()).items.iter().find_map(|item| -> Option<_> {
172 match item {
173 (_, AssocItemId::TypeAliasId(type_alias)) => {
174 let name = &self.0.interner.db().type_alias_signature(*type_alias).name;
175 let found_trait_assoc_id = trait_data.associated_type_by_name(name)?;
176 (found_trait_assoc_id == trait_assoc_id).then_some(*type_alias)
177 }
178 _ => None,
179 }
180 });
181 Ok(id.map(SolverDefId::TypeAliasId))
182 }
183
184 fn is_transmutable(
185 &self,
186 dst: <Self::Interner as rustc_type_ir::Interner>::Ty,
187 src: <Self::Interner as rustc_type_ir::Interner>::Ty,
188 assume: <Self::Interner as rustc_type_ir::Interner>::Const,
189 ) -> Result<Certainty, NoSolution> {
190 unimplemented!()
191 }
192
193 fn evaluate_const(
194 &self,
195 param_env: <Self::Interner as rustc_type_ir::Interner>::ParamEnv,
196 uv: rustc_type_ir::UnevaluatedConst<Self::Interner>,
197 ) -> Option<<Self::Interner as rustc_type_ir::Interner>::Const> {
198 let c = match uv.def {
199 SolverDefId::ConstId(c) => GeneralConstId::ConstId(c),
200 SolverDefId::StaticId(c) => GeneralConstId::StaticId(c),
201 _ => unreachable!(),
202 };
203 let subst = convert_args_for_result(self.interner, uv.args.as_slice());
204 let ec = self.cx().db.const_eval(c, subst, None).ok()?;
205 Some(ec.to_nextsolver(self.interner))
206 }
207
208 fn compute_goal_fast_path(
209 &self,
210 goal: rustc_type_ir::solve::Goal<
211 Self::Interner,
212 <Self::Interner as rustc_type_ir::Interner>::Predicate,
213 >,
214 span: <Self::Interner as rustc_type_ir::Interner>::Span,
215 ) -> Option<Certainty> {
216 if let Some(trait_pred) = goal.predicate.as_trait_clause() {
217 if self.shallow_resolve(trait_pred.self_ty().skip_binder()).is_ty_var()
218 && self.inner.borrow_mut().opaque_types().is_empty()
223 {
224 return Some(Certainty::AMBIGUOUS);
225 }
226
227 if trait_pred.polarity() == PredicatePolarity::Positive {
228 match self.0.cx().as_trait_lang_item(trait_pred.def_id()) {
229 Some(SolverTraitLangItem::Sized) | Some(SolverTraitLangItem::MetaSized) => {
230 let predicate = self.resolve_vars_if_possible(goal.predicate);
231 if sizedness_fast_path(self.cx(), predicate, goal.param_env) {
232 return Some(Certainty::Yes);
233 }
234 }
235 Some(SolverTraitLangItem::Copy | SolverTraitLangItem::Clone) => {
236 let self_ty =
237 self.resolve_vars_if_possible(trait_pred.self_ty().skip_binder());
238 if !self_ty
244 .has_type_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_INFER)
245 && self_ty.is_trivially_pure_clone_copy()
246 {
247 return Some(Certainty::Yes);
248 }
249 }
250 _ => {}
251 }
252 }
253 }
254
255 let pred = goal.predicate.kind();
256 match pred.no_bound_vars()? {
257 PredicateKind::Clause(ClauseKind::RegionOutlives(outlives)) => Some(Certainty::Yes),
258 PredicateKind::Clause(ClauseKind::TypeOutlives(outlives)) => Some(Certainty::Yes),
259 PredicateKind::Subtype(SubtypePredicate { a, b, .. })
260 | PredicateKind::Coerce(CoercePredicate { a, b }) => {
261 if self.shallow_resolve(a).is_ty_var() && self.shallow_resolve(b).is_ty_var() {
262 Some(Certainty::AMBIGUOUS)
266 } else {
267 None
268 }
269 }
270 PredicateKind::Clause(ClauseKind::ConstArgHasType(ct, _)) => {
271 if self.shallow_resolve_const(ct).is_ct_infer() {
272 Some(Certainty::AMBIGUOUS)
273 } else {
274 None
275 }
276 }
277 PredicateKind::Clause(ClauseKind::WellFormed(arg)) => {
278 if arg.is_trivially_wf(self.interner) {
279 Some(Certainty::Yes)
280 } else if arg.is_infer() {
281 Some(Certainty::AMBIGUOUS)
282 } else {
283 None
284 }
285 }
286 _ => None,
287 }
288 }
289}