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