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 _guar: I::ErrorGuaranteed,
195 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
196 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
197 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
198 }
199
200 fn consider_auto_trait_candidate(
201 ecx: &mut EvalCtxt<'_, D>,
202 _goal: Goal<I, Self>,
203 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
204 ecx.cx().delay_bug("auto traits are never const");
205 Err(NoSolution.into())
206 }
207
208 fn consider_trait_alias_candidate(
209 ecx: &mut EvalCtxt<'_, D>,
210 goal: Goal<I, Self>,
211 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
212 let cx = ecx.cx();
213
214 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
215 let where_clause_bounds = cx
216 .predicates_of(goal.predicate.def_id().into())
217 .iter_instantiated(cx, goal.predicate.trait_ref.args)
218 .map(Unnormalized::skip_norm_wip)
219 .map(|p| goal.with(cx, p));
220
221 let const_conditions = cx
222 .const_conditions(goal.predicate.def_id().into())
223 .iter_instantiated(cx, goal.predicate.trait_ref.args)
224 .map(|bound_trait_ref| {
225 goal.with(
226 cx,
227 bound_trait_ref
228 .to_host_effect_clause(cx, goal.predicate.constness)
229 .skip_norm_wip(),
230 )
231 });
232 ecx.add_goals(GoalSource::Misc, where_clause_bounds);
238 ecx.add_goals(GoalSource::Misc, const_conditions);
239 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
240 })
241 }
242
243 fn consider_builtin_sizedness_candidates(
244 _ecx: &mut EvalCtxt<'_, D>,
245 _goal: Goal<I, Self>,
246 _sizedness: SizedTraitKind,
247 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
248 {
::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")
249 }
250
251 fn consider_builtin_copy_clone_candidate(
252 ecx: &mut EvalCtxt<'_, D>,
253 goal: Goal<I, Self>,
254 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
255 let cx = ecx.cx();
256
257 let self_ty = goal.predicate.self_ty();
258 let constituent_tys =
259 structural_traits::instantiate_constituent_tys_for_copy_clone_trait(ecx, self_ty)?;
260
261 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
262 ecx.enter_forall_with_assumptions(constituent_tys, goal.param_env, |ecx, tys| {
263 ecx.add_goals(
264 GoalSource::ImplWhereBound,
265 tys.into_iter().map(|ty| {
266 goal.with(
267 cx,
268 ty::ClauseKind::HostEffect(
269 goal.predicate.with_replaced_self_ty(cx, ty),
270 ),
271 )
272 }),
273 );
274 });
275
276 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
277 })
278 }
279
280 fn consider_builtin_fn_ptr_trait_candidate(
281 _ecx: &mut EvalCtxt<'_, D>,
282 _goal: Goal<I, Self>,
283 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
284 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("Fn* are not yet const")));
}todo!("Fn* are not yet const")
285 }
286
287 x;#[instrument(level = "trace", skip_all, ret)]
288 fn consider_builtin_fn_trait_candidates(
289 ecx: &mut EvalCtxt<'_, D>,
290 goal: Goal<I, Self>,
291 _kind: rustc_type_ir::ClosureKind,
292 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
293 let cx = ecx.cx();
294
295 let self_ty = goal.predicate.self_ty();
296 let (inputs_and_output, def_id, args) =
297 structural_traits::extract_fn_def_from_const_callable(cx, self_ty)?;
298 let (inputs, output) = ecx.instantiate_binder_with_infer(inputs_and_output);
299
300 let output_is_sized_pred =
303 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
304 let requirements = cx
305 .const_conditions(def_id)
306 .iter_instantiated(cx, args)
307 .map(|trait_ref| {
308 (
309 GoalSource::ImplWhereBound,
310 goal.with(
311 cx,
312 trait_ref
313 .to_host_effect_clause(cx, goal.predicate.constness)
314 .skip_norm_wip(),
315 ),
316 )
317 })
318 .chain([(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))]);
319
320 let pred = ty::Binder::dummy(ty::TraitRef::new(
321 cx,
322 goal.predicate.def_id(),
323 [goal.predicate.self_ty(), inputs],
324 ))
325 .to_host_effect_clause(cx, goal.predicate.constness);
326
327 Self::probe_and_consider_implied_clause(
328 ecx,
329 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
330 goal,
331 pred,
332 requirements,
333 )
334 .map_err(Into::into)
335 }
336
337 fn consider_builtin_async_fn_trait_candidates(
338 _ecx: &mut EvalCtxt<'_, D>,
339 _goal: Goal<I, Self>,
340 _kind: rustc_type_ir::ClosureKind,
341 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
342 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("AsyncFn* are not yet const")));
}todo!("AsyncFn* are not yet const")
343 }
344
345 fn consider_builtin_async_fn_kind_helper_candidate(
346 _ecx: &mut EvalCtxt<'_, D>,
347 _goal: Goal<I, Self>,
348 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
349 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("AsyncFnKindHelper is not const")));
}unreachable!("AsyncFnKindHelper is not const")
350 }
351
352 fn consider_builtin_tuple_candidate(
353 _ecx: &mut EvalCtxt<'_, D>,
354 _goal: Goal<I, Self>,
355 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
356 {
::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")
357 }
358
359 fn consider_builtin_pointee_candidate(
360 _ecx: &mut EvalCtxt<'_, D>,
361 _goal: Goal<I, Self>,
362 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
363 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Pointee is not const")));
}unreachable!("Pointee is not const")
364 }
365
366 fn consider_builtin_future_candidate(
367 _ecx: &mut EvalCtxt<'_, D>,
368 _goal: Goal<I, Self>,
369 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
370 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Future is not const")));
}unreachable!("Future is not const")
371 }
372
373 fn consider_builtin_iterator_candidate(
374 _ecx: &mut EvalCtxt<'_, D>,
375 _goal: Goal<I, Self>,
376 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
377 {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("Iterator is not yet const")));
}todo!("Iterator is not yet const")
378 }
379
380 fn consider_builtin_fused_iterator_candidate(
381 _ecx: &mut EvalCtxt<'_, D>,
382 _goal: Goal<I, Self>,
383 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
384 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("FusedIterator is not const")));
}unreachable!("FusedIterator is not const")
385 }
386
387 fn consider_builtin_async_iterator_candidate(
388 _ecx: &mut EvalCtxt<'_, D>,
389 _goal: Goal<I, Self>,
390 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
391 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("AsyncIterator is not const")));
}unreachable!("AsyncIterator is not const")
392 }
393
394 fn consider_builtin_coroutine_candidate(
395 _ecx: &mut EvalCtxt<'_, D>,
396 _goal: Goal<I, Self>,
397 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
398 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Coroutine is not const")));
}unreachable!("Coroutine is not const")
399 }
400
401 fn consider_builtin_discriminant_kind_candidate(
402 _ecx: &mut EvalCtxt<'_, D>,
403 _goal: Goal<I, Self>,
404 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
405 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("DiscriminantKind is not const")));
}unreachable!("DiscriminantKind is not const")
406 }
407
408 fn consider_builtin_destruct_candidate(
409 ecx: &mut EvalCtxt<'_, D>,
410 goal: Goal<I, Self>,
411 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
412 let cx = ecx.cx();
413
414 let self_ty = goal.predicate.self_ty();
415 let const_conditions = structural_traits::const_conditions_for_destruct(cx, self_ty)?;
416
417 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
418 ecx.add_goals(
419 GoalSource::AliasBoundConstCondition,
420 const_conditions.into_iter().map(|trait_ref| {
421 goal.with(
422 cx,
423 ty::Binder::dummy(trait_ref)
424 .to_host_effect_clause(cx, goal.predicate.constness),
425 )
426 }),
427 );
428 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
429 })
430 }
431
432 fn consider_builtin_transmute_candidate(
433 _ecx: &mut EvalCtxt<'_, D>,
434 _goal: Goal<I, Self>,
435 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
436 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("TransmuteFrom is not const")));
}unreachable!("TransmuteFrom is not const")
437 }
438
439 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
440 _ecx: &mut EvalCtxt<'_, D>,
441 _goal: Goal<I, Self>,
442 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
443 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("BikeshedGuaranteedNoDrop is not const")));
};unreachable!("BikeshedGuaranteedNoDrop is not const");
444 }
445
446 fn consider_structural_builtin_unsize_candidates(
447 _ecx: &mut EvalCtxt<'_, D>,
448 _goal: Goal<I, Self>,
449 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
450 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Unsize is not const")));
}unreachable!("Unsize is not const")
451 }
452
453 fn consider_builtin_field_candidate(
454 _ecx: &mut EvalCtxt<'_, D>,
455 _goal: Goal<<D as SolverDelegate>::Interner, Self>,
456 ) -> Result<Candidate<<D as SolverDelegate>::Interner>, NoSolutionOrRerunNonErased> {
457 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Field is not const")));
}unreachable!("Field is not const")
458 }
459}
460
461impl<D, I> EvalCtxt<'_, D>
462where
463 D: SolverDelegate<Interner = I>,
464 I: Interner,
465{
466 #[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(466u32),
::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))]
467 pub(super) fn compute_host_effect_goal(
468 &mut self,
469 goal: Goal<I, ty::HostEffectPredicate<I>>,
470 ) -> QueryResultOrRerunNonErased<I> {
471 let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
472 let trait_goal: Goal<I, ty::TraitPredicate<I>> =
473 goal.with(ecx.cx(), goal.predicate.trait_ref);
474 ecx.compute_trait_goal(trait_goal).map_err(Into::into)
475 })?;
476 self.assemble_and_merge_candidates(
477 proven_via,
478 goal,
479 |_ecx| None,
480 |_ecx| Err(NoSolution.into()),
481 )
482 }
483}