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 let def_id = match alias_ty.kind {
90 ty::AliasTyKind::Projection { def_id } => def_id.into(),
91 ty::AliasTyKind::Inherent { def_id } => def_id.into(),
92 ty::AliasTyKind::Opaque { def_id } => def_id.into(),
93 ty::AliasTyKind::Free { def_id } => def_id.into(),
94 };
95
96 if !ecx.cx().alias_has_const_conditions(def_id) {
97 return ::alloc::vec::Vec::new()vec![];
98 }
99
100 for clause in elaborate::elaborate(
101 cx,
102 cx.explicit_implied_const_bounds(def_id).iter_instantiated(cx, alias_ty.args).map(
103 |trait_ref| {
104 trait_ref.to_host_effect_clause(cx, goal.predicate.constness).skip_norm_wip()
105 },
106 ),
107 ) {
108 candidates.extend(Self::probe_and_match_goal_against_assumption(
109 ecx,
110 CandidateSource::AliasBound(AliasBoundKind::SelfBounds),
111 goal,
112 clause,
113 |ecx| {
114 ecx.add_goals(
116 GoalSource::AliasBoundConstCondition,
117 cx.const_conditions(def_id).iter_instantiated(cx, alias_ty.args).map(
118 |trait_ref| {
119 goal.with(
120 cx,
121 trait_ref
122 .to_host_effect_clause(cx, goal.predicate.constness)
123 .skip_norm_wip(),
124 )
125 },
126 ),
127 );
128 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
129 },
130 ));
131 }
132
133 candidates
134 }
135
136 fn consider_impl_candidate(
137 ecx: &mut EvalCtxt<'_, D>,
138 goal: Goal<I, Self>,
139 impl_def_id: I::ImplId,
140 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
141 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
142 let cx = ecx.cx();
143
144 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
145 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
146 .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
147 {
148 return Err(NoSolution.into());
149 }
150
151 let impl_polarity = cx.impl_polarity(impl_def_id);
152 let certainty = match impl_polarity {
153 ty::ImplPolarity::Negative => return Err(NoSolution.into()),
154 ty::ImplPolarity::Reservation => {
155 if ecx.typing_mode().is_coherence() {
156 Certainty::AMBIGUOUS
157 } else {
158 return Err(NoSolution.into());
159 }
160 }
161 ty::ImplPolarity::Positive => Certainty::Yes,
162 };
163
164 if !cx.impl_is_const(impl_def_id) {
165 return Err(NoSolution.into());
166 }
167
168 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
169 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
170 ecx.record_impl_args(impl_args);
171 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
172
173 ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
174 let where_clause_bounds = cx
175 .predicates_of(impl_def_id.into())
176 .iter_instantiated(cx, impl_args)
177 .map(Unnormalized::skip_norm_wip)
178 .map(|pred| goal.with(cx, pred));
179 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
180
181 let const_conditions = cx
183 .const_conditions(impl_def_id.into())
184 .iter_instantiated(cx, impl_args)
185 .map(|bound_trait_ref| {
186 goal.with(
187 cx,
188 bound_trait_ref
189 .to_host_effect_clause(cx, goal.predicate.constness)
190 .skip_norm_wip(),
191 )
192 });
193 ecx.add_goals(GoalSource::ImplWhereBound, const_conditions);
194
195 then(ecx, certainty)
196 })
197 }
198
199 fn consider_error_guaranteed_candidate(
200 ecx: &mut EvalCtxt<'_, D>,
201 _goal: Goal<I, Self>,
202 _guar: I::ErrorGuaranteed,
203 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
204 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
205 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
206 }
207
208 fn consider_auto_trait_candidate(
209 ecx: &mut EvalCtxt<'_, D>,
210 _goal: Goal<I, Self>,
211 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
212 ecx.cx().delay_bug("auto traits are never const");
213 Err(NoSolution.into())
214 }
215
216 fn consider_trait_alias_candidate(
217 ecx: &mut EvalCtxt<'_, D>,
218 goal: Goal<I, Self>,
219 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
220 let cx = ecx.cx();
221
222 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
223 let where_clause_bounds = cx
224 .predicates_of(goal.predicate.def_id().into())
225 .iter_instantiated(cx, goal.predicate.trait_ref.args)
226 .map(Unnormalized::skip_norm_wip)
227 .map(|p| goal.with(cx, p));
228
229 let const_conditions = cx
230 .const_conditions(goal.predicate.def_id().into())
231 .iter_instantiated(cx, goal.predicate.trait_ref.args)
232 .map(|bound_trait_ref| {
233 goal.with(
234 cx,
235 bound_trait_ref
236 .to_host_effect_clause(cx, goal.predicate.constness)
237 .skip_norm_wip(),
238 )
239 });
240 ecx.add_goals(GoalSource::Misc, where_clause_bounds);
246 ecx.add_goals(GoalSource::Misc, const_conditions);
247 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
248 })
249 }
250
251 fn consider_builtin_sizedness_candidates(
252 _ecx: &mut EvalCtxt<'_, D>,
253 _goal: Goal<I, Self>,
254 _sizedness: SizedTraitKind,
255 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
256 {
::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")
257 }
258
259 fn consider_builtin_copy_clone_candidate(
260 ecx: &mut EvalCtxt<'_, D>,
261 goal: Goal<I, Self>,
262 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
263 let cx = ecx.cx();
264
265 let self_ty = goal.predicate.self_ty();
266 let constituent_tys =
267 structural_traits::instantiate_constituent_tys_for_copy_clone_trait(ecx, self_ty)?;
268
269 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
270 ecx.enter_forall_with_assumptions(constituent_tys, goal.param_env, |ecx, tys| {
271 ecx.add_goals(
272 GoalSource::ImplWhereBound,
273 tys.into_iter().map(|ty| {
274 goal.with(
275 cx,
276 ty::ClauseKind::HostEffect(
277 goal.predicate.with_replaced_self_ty(cx, ty),
278 ),
279 )
280 }),
281 );
282 });
283
284 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
285 })
286 }
287
288 fn consider_builtin_fn_ptr_trait_candidate(
289 _ecx: &mut EvalCtxt<'_, D>,
290 _goal: Goal<I, Self>,
291 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
292 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("Fn* are not yet const")));
}todo!("Fn* are not yet const")
293 }
294
295 x;#[instrument(level = "trace", skip_all, ret)]
296 fn consider_builtin_fn_trait_candidates(
297 ecx: &mut EvalCtxt<'_, D>,
298 goal: Goal<I, Self>,
299 _kind: rustc_type_ir::ClosureKind,
300 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
301 let cx = ecx.cx();
302
303 let self_ty = goal.predicate.self_ty();
304 let (inputs_and_output, def_id, args) =
305 structural_traits::extract_fn_def_from_const_callable(cx, self_ty)?;
306 let (inputs, output) = ecx.instantiate_binder_with_infer(inputs_and_output);
307
308 let output_is_sized_pred =
311 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
312 let requirements = cx
313 .const_conditions(def_id)
314 .iter_instantiated(cx, args)
315 .map(|trait_ref| {
316 (
317 GoalSource::ImplWhereBound,
318 goal.with(
319 cx,
320 trait_ref
321 .to_host_effect_clause(cx, goal.predicate.constness)
322 .skip_norm_wip(),
323 ),
324 )
325 })
326 .chain([(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))]);
327
328 let pred = ty::Binder::dummy(ty::TraitRef::new(
329 cx,
330 goal.predicate.def_id(),
331 [goal.predicate.self_ty(), inputs],
332 ))
333 .to_host_effect_clause(cx, goal.predicate.constness);
334
335 Self::probe_and_consider_implied_clause(
336 ecx,
337 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
338 goal,
339 pred,
340 requirements,
341 )
342 .map_err(Into::into)
343 }
344
345 fn consider_builtin_async_fn_trait_candidates(
346 _ecx: &mut EvalCtxt<'_, D>,
347 _goal: Goal<I, Self>,
348 _kind: rustc_type_ir::ClosureKind,
349 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
350 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("AsyncFn* are not yet const")));
}todo!("AsyncFn* are not yet const")
351 }
352
353 fn consider_builtin_async_fn_kind_helper_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!("AsyncFnKindHelper is not const")));
}unreachable!("AsyncFnKindHelper is not const")
358 }
359
360 fn consider_builtin_tuple_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!("Tuple trait is not const")));
}unreachable!("Tuple trait is not const")
365 }
366
367 fn consider_builtin_pointee_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!("Pointee is not const")));
}unreachable!("Pointee is not const")
372 }
373
374 fn consider_builtin_future_candidate(
375 _ecx: &mut EvalCtxt<'_, D>,
376 _goal: Goal<I, Self>,
377 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
378 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Future is not const")));
}unreachable!("Future is not const")
379 }
380
381 fn consider_builtin_iterator_candidate(
382 _ecx: &mut EvalCtxt<'_, D>,
383 _goal: Goal<I, Self>,
384 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
385 Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution))
386 }
387
388 fn consider_builtin_fused_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!("FusedIterator is not const")));
}unreachable!("FusedIterator is not const")
393 }
394
395 fn consider_builtin_async_iterator_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!("AsyncIterator is not const")));
}unreachable!("AsyncIterator is not const")
400 }
401
402 fn consider_builtin_coroutine_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!("Coroutine is not const")));
}unreachable!("Coroutine is not const")
407 }
408
409 fn consider_builtin_discriminant_kind_candidate(
410 _ecx: &mut EvalCtxt<'_, D>,
411 _goal: Goal<I, Self>,
412 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
413 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("DiscriminantKind is not const")));
}unreachable!("DiscriminantKind is not const")
414 }
415
416 fn consider_builtin_destruct_candidate(
417 ecx: &mut EvalCtxt<'_, D>,
418 goal: Goal<I, Self>,
419 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
420 let cx = ecx.cx();
421
422 let self_ty = goal.predicate.self_ty();
423 let const_conditions = structural_traits::const_conditions_for_destruct(cx, self_ty)?;
424
425 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
426 ecx.add_goals(
427 GoalSource::AliasBoundConstCondition,
428 const_conditions.into_iter().map(|trait_ref| {
429 goal.with(
430 cx,
431 ty::Binder::dummy(trait_ref)
432 .to_host_effect_clause(cx, goal.predicate.constness),
433 )
434 }),
435 );
436 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
437 })
438 }
439
440 fn consider_builtin_transmute_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!("TransmuteFrom is not const")));
}unreachable!("TransmuteFrom is not const")
445 }
446
447 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
448 _ecx: &mut EvalCtxt<'_, D>,
449 _goal: Goal<I, Self>,
450 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
451 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("BikeshedGuaranteedNoDrop is not const")));
};unreachable!("BikeshedGuaranteedNoDrop is not const");
452 }
453
454 fn consider_structural_builtin_unsize_candidates(
455 _ecx: &mut EvalCtxt<'_, D>,
456 _goal: Goal<I, Self>,
457 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
458 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Unsize is not const")));
}unreachable!("Unsize is not const")
459 }
460
461 fn consider_builtin_field_candidate(
462 _ecx: &mut EvalCtxt<'_, D>,
463 _goal: Goal<<D as SolverDelegate>::Interner, Self>,
464 ) -> Result<Candidate<<D as SolverDelegate>::Interner>, NoSolutionOrRerunNonErased> {
465 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Field is not const")));
}unreachable!("Field is not const")
466 }
467}
468
469impl<D, I> EvalCtxt<'_, D>
470where
471 D: SolverDelegate<Interner = I>,
472 I: Interner,
473{
474 #[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(474u32),
::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))]
475 pub(super) fn compute_host_effect_goal(
476 &mut self,
477 goal: Goal<I, ty::HostEffectPredicate<I>>,
478 ) -> QueryResultOrRerunNonErased<I> {
479 let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
480 let trait_goal: Goal<I, ty::TraitPredicate<I>> =
481 goal.with(ecx.cx(), goal.predicate.trait_ref);
482 ecx.compute_trait_goal(trait_goal).map_err(Into::into)
483 })?;
484 self.assemble_and_merge_candidates(
485 proven_via,
486 goal,
487 |_ecx| None,
488 |_ecx| Err(NoSolution.into()),
489 )
490 }
491}