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