1use rustc_type_ir::fast_reject::DeepRejectCtxt;
5use rustc_type_ir::inherent::*;
6use rustc_type_ir::lang_items::SolverTraitLangItem;
7use rustc_type_ir::solve::inspect::ProbeKind;
8use rustc_type_ir::solve::{
9 AliasBoundKind, NoSolutionOrRerunNonErased, QueryResultOrRerunNonErased, RerunNonErased,
10 SizedTraitKind,
11};
12use rustc_type_ir::{self as ty, Interner, Unnormalized, elaborate};
13use tracing::instrument;
14
15use super::assembly::{Candidate, structural_traits};
16use crate::delegate::SolverDelegate;
17use crate::solve::{
18 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution, assembly,
19};
20
21impl<D, I> assembly::GoalKind<D> for ty::HostEffectPredicate<I>
22where
23 D: SolverDelegate<Interner = I>,
24 I: Interner,
25{
26 fn self_ty(self) -> I::Ty {
27 self.self_ty()
28 }
29
30 fn trait_ref(self, _: I) -> ty::TraitRef<I> {
31 self.trait_ref
32 }
33
34 fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
35 self.with_replaced_self_ty(cx, self_ty)
36 }
37
38 fn trait_def_id(self, _: I) -> I::TraitId {
39 self.def_id()
40 }
41
42 fn fast_reject_assumption(
43 ecx: &mut EvalCtxt<'_, D>,
44 goal: Goal<I, Self>,
45 assumption: I::Clause,
46 ) -> Result<(), NoSolution> {
47 if let Some(host_clause) = assumption.as_host_effect_clause()
48 && host_clause.def_id() == goal.predicate.def_id()
49 && host_clause.constness().satisfies(goal.predicate.constness)
50 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
51 goal.predicate.trait_ref.args,
52 host_clause.skip_binder().trait_ref.args,
53 )
54 {
55 Ok(())
56 } else {
57 Err(NoSolution)
58 }
59 }
60
61 fn match_assumption(
62 ecx: &mut EvalCtxt<'_, D>,
63 goal: Goal<I, Self>,
64 assumption: I::Clause,
65 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
66 ) -> QueryResultOrRerunNonErased<I> {
67 let host_clause = assumption.as_host_effect_clause().unwrap();
68
69 let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause);
70 ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;
71
72 then(ecx)
73 }
74
75 fn consider_additional_alias_assumptions(
82 ecx: &mut EvalCtxt<'_, D>,
83 goal: Goal<I, Self>,
84 alias_ty: ty::AliasTy<I>,
85 ) -> Vec<Candidate<I>> {
86 let cx = ecx.cx();
87 let mut candidates = ::alloc::vec::Vec::new()vec![];
88
89 if !ecx.cx().alias_has_const_conditions(alias_ty.kind.def_id()) {
90 return ::alloc::vec::Vec::new()vec![];
91 }
92
93 for clause in elaborate::elaborate(
94 cx,
95 cx.explicit_implied_const_bounds(alias_ty.kind.def_id())
96 .iter_instantiated(cx, alias_ty.args)
97 .map(|trait_ref| {
98 trait_ref.to_host_effect_clause(cx, goal.predicate.constness).skip_norm_wip()
99 }),
100 ) {
101 candidates.extend(Self::probe_and_match_goal_against_assumption(
102 ecx,
103 CandidateSource::AliasBound(AliasBoundKind::SelfBounds),
104 goal,
105 clause,
106 |ecx| {
107 ecx.add_goals(
109 GoalSource::AliasBoundConstCondition,
110 cx.const_conditions(alias_ty.kind.def_id())
111 .iter_instantiated(cx, alias_ty.args)
112 .map(|trait_ref| {
113 goal.with(
114 cx,
115 trait_ref
116 .to_host_effect_clause(cx, goal.predicate.constness)
117 .skip_norm_wip(),
118 )
119 }),
120 );
121 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
122 },
123 ));
124 }
125
126 candidates
127 }
128
129 fn consider_impl_candidate(
130 ecx: &mut EvalCtxt<'_, D>,
131 goal: Goal<I, Self>,
132 impl_def_id: I::ImplId,
133 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
134 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
135 let cx = ecx.cx();
136
137 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
138 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
139 .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
140 {
141 return Err(NoSolution.into());
142 }
143
144 let impl_polarity = cx.impl_polarity(impl_def_id);
145 let certainty = match impl_polarity {
146 ty::ImplPolarity::Negative => return Err(NoSolution.into()),
147 ty::ImplPolarity::Reservation => {
148 if ecx.typing_mode().is_coherence() {
149 Certainty::AMBIGUOUS
150 } else {
151 return Err(NoSolution.into());
152 }
153 }
154 ty::ImplPolarity::Positive => Certainty::Yes,
155 };
156
157 if !cx.impl_is_const(impl_def_id) {
158 return Err(NoSolution.into());
159 }
160
161 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
162 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
163 ecx.record_impl_args(impl_args);
164 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
165
166 ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
167 let where_clause_bounds = cx
168 .predicates_of(impl_def_id.into())
169 .iter_instantiated(cx, impl_args)
170 .map(Unnormalized::skip_norm_wip)
171 .map(|pred| goal.with(cx, pred));
172 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
173
174 let const_conditions = cx
176 .const_conditions(impl_def_id.into())
177 .iter_instantiated(cx, impl_args)
178 .map(|bound_trait_ref| {
179 goal.with(
180 cx,
181 bound_trait_ref
182 .to_host_effect_clause(cx, goal.predicate.constness)
183 .skip_norm_wip(),
184 )
185 });
186 ecx.add_goals(GoalSource::ImplWhereBound, const_conditions);
187
188 then(ecx, certainty)
189 })
190 }
191
192 fn consider_error_guaranteed_candidate(
193 ecx: &mut EvalCtxt<'_, D>,
194 _goal: Goal<I, Self>,
195 _guar: I::ErrorGuaranteed,
196 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
197 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
198 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
199 }
200
201 fn consider_auto_trait_candidate(
202 ecx: &mut EvalCtxt<'_, D>,
203 _goal: Goal<I, Self>,
204 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
205 ecx.cx().delay_bug("auto traits are never const");
206 Err(NoSolution.into())
207 }
208
209 fn consider_trait_alias_candidate(
210 ecx: &mut EvalCtxt<'_, D>,
211 goal: Goal<I, Self>,
212 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
213 let cx = ecx.cx();
214
215 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
216 let where_clause_bounds = cx
217 .predicates_of(goal.predicate.def_id().into())
218 .iter_instantiated(cx, goal.predicate.trait_ref.args)
219 .map(Unnormalized::skip_norm_wip)
220 .map(|p| goal.with(cx, p));
221
222 let const_conditions = cx
223 .const_conditions(goal.predicate.def_id().into())
224 .iter_instantiated(cx, goal.predicate.trait_ref.args)
225 .map(|bound_trait_ref| {
226 goal.with(
227 cx,
228 bound_trait_ref
229 .to_host_effect_clause(cx, goal.predicate.constness)
230 .skip_norm_wip(),
231 )
232 });
233 ecx.add_goals(GoalSource::Misc, where_clause_bounds);
239 ecx.add_goals(GoalSource::Misc, const_conditions);
240 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
241 })
242 }
243
244 fn consider_builtin_sizedness_candidates(
245 _ecx: &mut EvalCtxt<'_, D>,
246 _goal: Goal<I, Self>,
247 _sizedness: SizedTraitKind,
248 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
249 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Sized/MetaSized is never const")));
}unreachable!("Sized/MetaSized is never const")
250 }
251
252 fn consider_builtin_copy_clone_candidate(
253 ecx: &mut EvalCtxt<'_, D>,
254 goal: Goal<I, Self>,
255 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
256 let cx = ecx.cx();
257
258 let self_ty = goal.predicate.self_ty();
259 let constituent_tys =
260 structural_traits::instantiate_constituent_tys_for_copy_clone_trait(ecx, self_ty)?;
261
262 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
263 ecx.enter_forall_with_assumptions(constituent_tys, goal.param_env, |ecx, tys| {
264 ecx.add_goals(
265 GoalSource::ImplWhereBound,
266 tys.into_iter().map(|ty| {
267 goal.with(
268 cx,
269 ty::ClauseKind::HostEffect(
270 goal.predicate.with_replaced_self_ty(cx, ty),
271 ),
272 )
273 }),
274 );
275 });
276
277 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
278 })
279 }
280
281 fn consider_builtin_fn_ptr_trait_candidate(
282 _ecx: &mut EvalCtxt<'_, D>,
283 _goal: Goal<I, Self>,
284 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
285 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("Fn* are not yet const")));
}todo!("Fn* are not yet const")
286 }
287
288 x;#[instrument(level = "trace", skip_all, ret)]
289 fn consider_builtin_fn_trait_candidates(
290 ecx: &mut EvalCtxt<'_, D>,
291 goal: Goal<I, Self>,
292 _kind: rustc_type_ir::ClosureKind,
293 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
294 let cx = ecx.cx();
295
296 let self_ty = goal.predicate.self_ty();
297 let (inputs_and_output, def_id, args) =
298 structural_traits::extract_fn_def_from_const_callable(cx, self_ty)?;
299 let (inputs, output) = ecx.instantiate_binder_with_infer(inputs_and_output);
300
301 let output_is_sized_pred =
304 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
305 let requirements = cx
306 .const_conditions(def_id)
307 .iter_instantiated(cx, args)
308 .map(|trait_ref| {
309 (
310 GoalSource::ImplWhereBound,
311 goal.with(
312 cx,
313 trait_ref
314 .to_host_effect_clause(cx, goal.predicate.constness)
315 .skip_norm_wip(),
316 ),
317 )
318 })
319 .chain([(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))]);
320
321 let pred = ty::Binder::dummy(ty::TraitRef::new(
322 cx,
323 goal.predicate.def_id(),
324 [goal.predicate.self_ty(), inputs],
325 ))
326 .to_host_effect_clause(cx, goal.predicate.constness);
327
328 Self::probe_and_consider_implied_clause(
329 ecx,
330 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
331 goal,
332 pred,
333 requirements,
334 )
335 .map_err(Into::into)
336 }
337
338 fn consider_builtin_async_fn_trait_candidates(
339 _ecx: &mut EvalCtxt<'_, D>,
340 _goal: Goal<I, Self>,
341 _kind: rustc_type_ir::ClosureKind,
342 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
343 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("AsyncFn* are not yet const")));
}todo!("AsyncFn* are not yet const")
344 }
345
346 fn consider_builtin_async_fn_kind_helper_candidate(
347 _ecx: &mut EvalCtxt<'_, D>,
348 _goal: Goal<I, Self>,
349 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
350 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("AsyncFnKindHelper is not const")));
}unreachable!("AsyncFnKindHelper is not const")
351 }
352
353 fn consider_builtin_tuple_candidate(
354 _ecx: &mut EvalCtxt<'_, D>,
355 _goal: Goal<I, Self>,
356 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
357 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Tuple trait is not const")));
}unreachable!("Tuple trait is not const")
358 }
359
360 fn consider_builtin_pointee_candidate(
361 _ecx: &mut EvalCtxt<'_, D>,
362 _goal: Goal<I, Self>,
363 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
364 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Pointee is not const")));
}unreachable!("Pointee is not const")
365 }
366
367 fn consider_builtin_future_candidate(
368 _ecx: &mut EvalCtxt<'_, D>,
369 _goal: Goal<I, Self>,
370 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
371 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Future is not const")));
}unreachable!("Future is not const")
372 }
373
374 fn consider_builtin_iterator_candidate(
375 _ecx: &mut EvalCtxt<'_, D>,
376 _goal: Goal<I, Self>,
377 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
378 Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution))
379 }
380
381 fn consider_builtin_fused_iterator_candidate(
382 _ecx: &mut EvalCtxt<'_, D>,
383 _goal: Goal<I, Self>,
384 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
385 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("FusedIterator is not const")));
}unreachable!("FusedIterator is not const")
386 }
387
388 fn consider_builtin_async_iterator_candidate(
389 _ecx: &mut EvalCtxt<'_, D>,
390 _goal: Goal<I, Self>,
391 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
392 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("AsyncIterator is not const")));
}unreachable!("AsyncIterator is not const")
393 }
394
395 fn consider_builtin_coroutine_candidate(
396 _ecx: &mut EvalCtxt<'_, D>,
397 _goal: Goal<I, Self>,
398 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
399 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Coroutine is not const")));
}unreachable!("Coroutine is not const")
400 }
401
402 fn consider_builtin_discriminant_kind_candidate(
403 _ecx: &mut EvalCtxt<'_, D>,
404 _goal: Goal<I, Self>,
405 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
406 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("DiscriminantKind is not const")));
}unreachable!("DiscriminantKind is not const")
407 }
408
409 fn consider_builtin_destruct_candidate(
410 ecx: &mut EvalCtxt<'_, D>,
411 goal: Goal<I, Self>,
412 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
413 let cx = ecx.cx();
414
415 let self_ty = goal.predicate.self_ty();
416 let const_conditions = structural_traits::const_conditions_for_destruct(cx, self_ty)?;
417
418 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
419 ecx.add_goals(
420 GoalSource::AliasBoundConstCondition,
421 const_conditions.into_iter().map(|trait_ref| {
422 goal.with(
423 cx,
424 ty::Binder::dummy(trait_ref)
425 .to_host_effect_clause(cx, goal.predicate.constness),
426 )
427 }),
428 );
429 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
430 })
431 }
432
433 fn consider_builtin_transmute_candidate(
434 _ecx: &mut EvalCtxt<'_, D>,
435 _goal: Goal<I, Self>,
436 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
437 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("TransmuteFrom is not const")));
}unreachable!("TransmuteFrom is not const")
438 }
439
440 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
441 _ecx: &mut EvalCtxt<'_, D>,
442 _goal: Goal<I, Self>,
443 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
444 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("BikeshedGuaranteedNoDrop is not const")));
};unreachable!("BikeshedGuaranteedNoDrop is not const");
445 }
446
447 fn consider_structural_builtin_unsize_candidates(
448 _ecx: &mut EvalCtxt<'_, D>,
449 _goal: Goal<I, Self>,
450 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
451 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Unsize is not const")));
}unreachable!("Unsize is not const")
452 }
453
454 fn consider_builtin_field_candidate(
455 _ecx: &mut EvalCtxt<'_, D>,
456 _goal: Goal<<D as SolverDelegate>::Interner, Self>,
457 ) -> Result<Candidate<<D as SolverDelegate>::Interner>, NoSolutionOrRerunNonErased> {
458 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Field is not const")));
}unreachable!("Field is not const")
459 }
460}
461
462impl<D, I> EvalCtxt<'_, D>
463where
464 D: SolverDelegate<Interner = I>,
465 I: Interner,
466{
467 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("compute_host_effect_goal",
"rustc_next_trait_solver::solve::effect_goals",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_next_trait_solver/src/solve/effect_goals.rs"),
::tracing_core::__macro_support::Option::Some(467u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::effect_goals"),
::tracing_core::field::FieldSet::new(&["goal"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: QueryResultOrRerunNonErased<I> =
loop {};
return __tracing_attr_fake_return;
}
{
let (_, proven_via) =
self.probe(|_|
ProbeKind::ShadowedEnvProbing).enter(|ecx|
{
let trait_goal: Goal<I, ty::TraitPredicate<I>> =
goal.with(ecx.cx(), goal.predicate.trait_ref);
ecx.compute_trait_goal(trait_goal).map_err(Into::into)
})?;
self.assemble_and_merge_candidates(proven_via, goal, |_ecx| None,
|_ecx| Err(NoSolution.into()))
}
}
}#[instrument(level = "trace", skip(self))]
468 pub(super) fn compute_host_effect_goal(
469 &mut self,
470 goal: Goal<I, ty::HostEffectPredicate<I>>,
471 ) -> QueryResultOrRerunNonErased<I> {
472 let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
473 let trait_goal: Goal<I, ty::TraitPredicate<I>> =
474 goal.with(ecx.cx(), goal.predicate.trait_ref);
475 ecx.compute_trait_goal(trait_goal).map_err(Into::into)
476 })?;
477 self.assemble_and_merge_candidates(
478 proven_via,
479 goal,
480 |_ecx| None,
481 |_ecx| Err(NoSolution.into()),
482 )
483 }
484}