1use rustc_hir::{self as hir, LangItem};
2use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
3use rustc_infer::traits::{
4 ImplDerivedHostCause, ImplSource, Obligation, ObligationCause, ObligationCauseCode,
5 PredicateObligation,
6};
7use rustc_middle::span_bug;
8use rustc_middle::traits::query::NoSolution;
9use rustc_middle::ty::elaborate::elaborate;
10use rustc_middle::ty::fast_reject::DeepRejectCtxt;
11use rustc_middle::ty::{self, Ty, Unnormalized};
12use thin_vec::{ThinVec, thin_vec};
13
14use super::SelectionContext;
15use super::normalize::normalize_with_depth_to;
16
17pub type HostEffectObligation<'tcx> = Obligation<'tcx, ty::HostEffectPredicate<'tcx>>;
18
19pub enum EvaluationFailure {
20 Ambiguous,
21 NoSolution,
22}
23
24pub fn evaluate_host_effect_obligation<'tcx>(
25 selcx: &mut SelectionContext<'_, 'tcx>,
26 obligation: &HostEffectObligation<'tcx>,
27) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
28 if selcx.typing_mode().is_coherence() {
29 ::rustc_middle::util::bug::span_bug_fmt(obligation.cause.span,
format_args!("should not select host obligation in old solver in intercrate mode"));span_bug!(
30 obligation.cause.span,
31 "should not select host obligation in old solver in intercrate mode"
32 );
33 }
34
35 let ref obligation = selcx.infcx.resolve_vars_if_possible(obligation.clone());
36
37 if obligation.predicate.self_ty().is_ty_var() {
39 return Err(EvaluationFailure::Ambiguous);
40 }
41
42 match evaluate_host_effect_from_bounds(selcx, obligation) {
43 Ok(result) => return Ok(result),
44 Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
45 Err(EvaluationFailure::NoSolution) => {}
46 }
47
48 match evaluate_host_effect_from_conditionally_const_item_bounds(selcx, obligation) {
49 Ok(result) => return Ok(result),
50 Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
51 Err(EvaluationFailure::NoSolution) => {}
52 }
53
54 match evaluate_host_effect_from_item_bounds(selcx, obligation) {
55 Ok(result) => return Ok(result),
56 Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
57 Err(EvaluationFailure::NoSolution) => {}
58 }
59
60 match evaluate_host_effect_from_builtin_impls(selcx, obligation) {
61 Ok(result) => return Ok(result),
62 Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
63 Err(EvaluationFailure::NoSolution) => {}
64 }
65
66 match evaluate_host_effect_from_selection_candidate(selcx, obligation) {
67 Ok(result) => return Ok(result),
68 Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
69 Err(EvaluationFailure::NoSolution) => {}
70 }
71
72 match evaluate_host_effect_from_trait_alias(selcx, obligation) {
73 Ok(result) => return Ok(result),
74 Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
75 Err(EvaluationFailure::NoSolution) => {}
76 }
77
78 Err(EvaluationFailure::NoSolution)
79}
80
81fn match_candidate<'tcx>(
82 selcx: &mut SelectionContext<'_, 'tcx>,
83 obligation: &HostEffectObligation<'tcx>,
84 candidate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
85 candidate_is_unnormalized: bool,
86 more_nested: impl FnOnce(&mut SelectionContext<'_, 'tcx>, &mut ThinVec<PredicateObligation<'tcx>>),
87) -> Result<ThinVec<PredicateObligation<'tcx>>, NoSolution> {
88 if !candidate.skip_binder().constness.satisfies(obligation.predicate.constness) {
89 return Err(NoSolution);
90 }
91
92 let mut candidate = selcx.infcx.instantiate_binder_with_fresh_vars(
93 obligation.cause.span,
94 BoundRegionConversionTime::HigherRankedType,
95 candidate,
96 );
97
98 let mut nested = ::thin_vec::ThinVec::new()thin_vec![];
99
100 if candidate_is_unnormalized {
102 candidate = normalize_with_depth_to(
103 selcx,
104 obligation.param_env,
105 obligation.cause.clone(),
106 obligation.recursion_depth,
107 candidate,
108 &mut nested,
109 );
110 }
111
112 nested.extend(
113 selcx
114 .infcx
115 .at(&obligation.cause, obligation.param_env)
116 .eq(DefineOpaqueTypes::Yes, obligation.predicate.trait_ref, candidate.trait_ref)?
117 .into_obligations(),
118 );
119
120 more_nested(selcx, &mut nested);
121
122 Ok(nested)
123}
124
125fn evaluate_host_effect_from_bounds<'tcx>(
126 selcx: &mut SelectionContext<'_, 'tcx>,
127 obligation: &HostEffectObligation<'tcx>,
128) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
129 let infcx = selcx.infcx;
130 let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
131 let mut candidate = None;
132
133 for clause in obligation.param_env.caller_bounds() {
134 let bound_clause = clause.kind();
135 let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
136 continue;
137 };
138 let data = bound_clause.rebind(data);
139 if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
140 continue;
141 }
142
143 if !drcx
144 .args_may_unify(obligation.predicate.trait_ref.args, data.skip_binder().trait_ref.args)
145 {
146 continue;
147 }
148
149 let is_match =
150 infcx.probe(|_| match_candidate(selcx, obligation, data, false, |_, _| {}).is_ok());
151
152 if is_match {
153 if candidate.is_some() {
154 return Err(EvaluationFailure::Ambiguous);
155 } else {
156 candidate = Some(data);
157 }
158 }
159 }
160
161 if let Some(data) = candidate {
162 Ok(match_candidate(selcx, obligation, data, false, |_, _| {})
163 .expect("candidate matched before, so it should match again"))
164 } else {
165 Err(EvaluationFailure::NoSolution)
166 }
167}
168
169fn evaluate_host_effect_from_conditionally_const_item_bounds<'tcx>(
172 selcx: &mut SelectionContext<'_, 'tcx>,
173 obligation: &HostEffectObligation<'tcx>,
174) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
175 let infcx = selcx.infcx;
176 let tcx = infcx.tcx;
177 let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
178 let mut candidate = None;
179
180 let mut consider_ty = obligation.predicate.self_ty();
181 while let ty::Alias(
182 _,
183 alias_ty @ ty::AliasTy {
184 kind: kind @ (ty::Projection { def_id } | ty::Opaque { def_id }),
185 ..
186 },
187 ) = *consider_ty.kind()
188 {
189 if tcx.is_conditionally_const(def_id) {
190 for clause in elaborate(
191 tcx,
192 tcx.explicit_implied_const_bounds(def_id)
193 .iter_instantiated_copied(tcx, alias_ty.args)
194 .map(Unnormalized::skip_norm_wip)
195 .map(|(trait_ref, _)| {
196 trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness)
197 }),
198 ) {
199 let bound_clause = clause.kind();
200 let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
201 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("should not elaborate non-HostEffect from HostEffect")));
}unreachable!("should not elaborate non-HostEffect from HostEffect")
202 };
203 let data = bound_clause.rebind(data);
204 if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
205 continue;
206 }
207
208 if !drcx.args_may_unify(
209 obligation.predicate.trait_ref.args,
210 data.skip_binder().trait_ref.args,
211 ) {
212 continue;
213 }
214
215 let is_match = infcx
216 .probe(|_| match_candidate(selcx, obligation, data, true, |_, _| {}).is_ok());
217
218 if is_match {
219 if candidate.is_some() {
220 return Err(EvaluationFailure::Ambiguous);
221 } else {
222 candidate = Some((data, alias_ty, def_id));
223 }
224 }
225 }
226 }
227
228 if !#[allow(non_exhaustive_omitted_patterns)] match kind {
ty::Projection { .. } => true,
_ => false,
}matches!(kind, ty::Projection { .. }) {
229 break;
230 }
231
232 consider_ty = alias_ty.self_ty();
233 }
234
235 if let Some((data, alias_ty, def_id)) = candidate {
236 Ok(match_candidate(selcx, obligation, data, true, |selcx, nested| {
237 let const_conditions = tcx.const_conditions(def_id).instantiate(tcx, alias_ty.args);
240 let const_conditions: Vec<_> = const_conditions
241 .into_iter()
242 .map(|(trait_ref, span)| {
243 let trait_ref = normalize_with_depth_to(
244 selcx,
245 obligation.param_env,
246 obligation.cause.clone(),
247 obligation.recursion_depth,
248 trait_ref.skip_norm_wip(),
249 nested,
250 );
251 (trait_ref, span)
252 })
253 .collect();
254 nested.extend(const_conditions.into_iter().map(|(trait_ref, _)| {
255 obligation
256 .with(tcx, trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness))
257 }));
258 })
259 .expect("candidate matched before, so it should match again"))
260 } else {
261 Err(EvaluationFailure::NoSolution)
262 }
263}
264
265fn evaluate_host_effect_from_item_bounds<'tcx>(
268 selcx: &mut SelectionContext<'_, 'tcx>,
269 obligation: &HostEffectObligation<'tcx>,
270) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
271 let infcx = selcx.infcx;
272 let tcx = infcx.tcx;
273 let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
274 let mut candidate = None;
275
276 let mut consider_ty = obligation.predicate.self_ty();
277 while let ty::Alias(
278 _,
279 alias_ty @ ty::AliasTy {
280 kind: kind @ (ty::Projection { def_id } | ty::Opaque { def_id }),
281 ..
282 },
283 ) = *consider_ty.kind()
284 {
285 for clause in tcx
286 .item_bounds(def_id)
287 .iter_instantiated(tcx, alias_ty.args)
288 .map(Unnormalized::skip_norm_wip)
289 {
290 let bound_clause = clause.kind();
291 let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
292 continue;
293 };
294 let data = bound_clause.rebind(data);
295 if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
296 continue;
297 }
298
299 if !drcx.args_may_unify(
300 obligation.predicate.trait_ref.args,
301 data.skip_binder().trait_ref.args,
302 ) {
303 continue;
304 }
305
306 let is_match =
307 infcx.probe(|_| match_candidate(selcx, obligation, data, true, |_, _| {}).is_ok());
308
309 if is_match {
310 if candidate.is_some() {
311 return Err(EvaluationFailure::Ambiguous);
312 } else {
313 candidate = Some(data);
314 }
315 }
316 }
317
318 if !#[allow(non_exhaustive_omitted_patterns)] match kind {
ty::Projection { .. } => true,
_ => false,
}matches!(kind, ty::Projection { .. }) {
319 break;
320 }
321
322 consider_ty = alias_ty.self_ty();
323 }
324
325 if let Some(data) = candidate {
326 Ok(match_candidate(selcx, obligation, data, true, |_, _| {})
327 .expect("candidate matched before, so it should match again"))
328 } else {
329 Err(EvaluationFailure::NoSolution)
330 }
331}
332
333fn evaluate_host_effect_from_builtin_impls<'tcx>(
334 selcx: &mut SelectionContext<'_, 'tcx>,
335 obligation: &HostEffectObligation<'tcx>,
336) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
337 match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
338 Some(LangItem::Copy | LangItem::Clone) => {
339 evaluate_host_effect_for_copy_clone_goal(selcx, obligation)
340 }
341 Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
342 Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => {
343 evaluate_host_effect_for_fn_goal(selcx, obligation)
344 }
345 _ => Err(EvaluationFailure::NoSolution),
346 }
347}
348
349fn evaluate_host_effect_for_copy_clone_goal<'tcx>(
350 selcx: &mut SelectionContext<'_, 'tcx>,
351 obligation: &HostEffectObligation<'tcx>,
352) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
353 let tcx = selcx.tcx();
354 let self_ty = obligation.predicate.self_ty();
355 let constituent_tys = match *self_ty.kind() {
356 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(::alloc::vec::Vec::new()vec![])),
358
359 ty::Uint(_)
361 | ty::Int(_)
362 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
363 | ty::Bool
364 | ty::Float(_)
365 | ty::Char
366 | ty::RawPtr(..)
367 | ty::Never
368 | ty::Ref(_, _, ty::Mutability::Not)
369 | ty::Array(..) => Err(EvaluationFailure::NoSolution),
370
371 ty::Pat(ty, ..) => Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ty]))vec![ty])),
374
375 ty::Dynamic(..)
376 | ty::Str
377 | ty::Slice(_)
378 | ty::Foreign(..)
379 | ty::Ref(_, _, ty::Mutability::Mut)
380 | ty::Adt(_, _)
381 | ty::Alias(_, _)
382 | ty::Param(_)
383 | ty::Placeholder(..) => Err(EvaluationFailure::NoSolution),
384
385 ty::Bound(..)
386 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
387 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
388 }
389
390 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
392
393 ty::Closure(_, args) => Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[args.as_closure().tupled_upvars_ty()]))vec![args.as_closure().tupled_upvars_ty()])),
395
396 ty::CoroutineClosure(_, args) => {
398 Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[args.as_coroutine_closure().tupled_upvars_ty()]))vec![args.as_coroutine_closure().tupled_upvars_ty()]))
399 }
400
401 ty::Coroutine(def_id, args) => {
404 if selcx.should_stall_coroutine(def_id) {
405 return Err(EvaluationFailure::Ambiguous);
406 }
407 match tcx.coroutine_movability(def_id) {
408 ty::Movability::Static => Err(EvaluationFailure::NoSolution),
409 ty::Movability::Movable => {
410 if tcx.features().coroutine_clone() {
411 Ok(ty::Binder::dummy(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[args.as_coroutine().tupled_upvars_ty(),
Ty::new_coroutine_witness_for_coroutine(tcx, def_id, args)]))vec![
412 args.as_coroutine().tupled_upvars_ty(),
413 Ty::new_coroutine_witness_for_coroutine(tcx, def_id, args),
414 ]))
415 } else {
416 Err(EvaluationFailure::NoSolution)
417 }
418 }
419 }
420 }
421
422 ty::UnsafeBinder(_) => Err(EvaluationFailure::NoSolution),
423
424 ty::CoroutineWitness(def_id, args) => Ok(tcx
426 .coroutine_hidden_types(def_id)
427 .instantiate(tcx, args)
428 .skip_norm_wip()
429 .map_bound(|bound| bound.types.to_vec())),
430 }?;
431
432 Ok(constituent_tys
433 .iter()
434 .map(|ty| {
435 obligation.with(
436 tcx,
437 ty.map_bound(|ty| ty::TraitRef::new(tcx, obligation.predicate.def_id(), [ty]))
438 .to_host_effect_clause(tcx, obligation.predicate.constness),
439 )
440 })
441 .collect())
442}
443
444fn evaluate_host_effect_for_destruct_goal<'tcx>(
446 selcx: &mut SelectionContext<'_, 'tcx>,
447 obligation: &HostEffectObligation<'tcx>,
448) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
449 let tcx = selcx.tcx();
450 let destruct_def_id = tcx.require_lang_item(LangItem::Destruct, obligation.cause.span);
451 let self_ty = obligation.predicate.self_ty();
452
453 let const_conditions = match *self_ty.kind() {
454 ty::Adt(adt_def, _) if adt_def.is_manually_drop() => ::thin_vec::ThinVec::new()thin_vec![],
456
457 ty::Adt(adt_def, args) => {
460 let mut const_conditions: ThinVec<_> = adt_def
461 .all_fields()
462 .map(|field| {
463 ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args).skip_norm_wip()])
464 })
465 .collect();
466 match adt_def.destructor(tcx).map(|dtor| tcx.constness(dtor.did)) {
467 Some(hir::Constness::Const { always: true }) => {
::core::panicking::panic_fmt(format_args!("not yet implemented: {0}",
format_args!("FIXME(comptime)")));
}todo!("FIXME(comptime)"),
468 Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
470 Some(hir::Constness::Const { always: false }) => {
472 let drop_def_id = tcx.require_lang_item(LangItem::Drop, obligation.cause.span);
473 let drop_trait_ref = ty::TraitRef::new(tcx, drop_def_id, [self_ty]);
474 const_conditions.push(drop_trait_ref);
475 }
476 None => {}
478 }
479 const_conditions
480 }
481
482 ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
483 {
let len = [()].len();
let mut vec = ::thin_vec::ThinVec::with_capacity(len);
vec.push(ty::TraitRef::new(tcx, destruct_def_id, [ty]));
vec
}thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [ty])]
484 }
485
486 ty::Tuple(tys) => {
487 tys.iter().map(|field_ty| ty::TraitRef::new(tcx, destruct_def_id, [field_ty])).collect()
488 }
489
490 ty::Bool
492 | ty::Char
493 | ty::Int(..)
494 | ty::Uint(..)
495 | ty::Float(..)
496 | ty::Str
497 | ty::RawPtr(..)
498 | ty::Ref(..)
499 | ty::FnDef(..)
500 | ty::FnPtr(..)
501 | ty::Never
502 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
503 | ty::Error(_) => ::thin_vec::ThinVec::new()thin_vec![],
504
505 ty::Closure(_, args) => {
507 let closure_args = args.as_closure();
508 {
let len = [()].len();
let mut vec = ::thin_vec::ThinVec::with_capacity(len);
vec.push(ty::TraitRef::new(tcx, destruct_def_id,
[closure_args.tupled_upvars_ty()]));
vec
}thin_vec![ty::TraitRef::new(tcx, destruct_def_id, [closure_args.tupled_upvars_ty()])]
509 }
510
511 ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
514 return Err(EvaluationFailure::NoSolution);
515 }
516
517 ty::UnsafeBinder(_) => return Err(EvaluationFailure::NoSolution),
520
521 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
522 return Err(EvaluationFailure::NoSolution);
523 }
524
525 ty::Bound(..)
526 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
527 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
528 }
529 };
530
531 Ok(const_conditions
532 .into_iter()
533 .map(|trait_ref| {
534 obligation.with(
535 tcx,
536 ty::Binder::dummy(trait_ref)
537 .to_host_effect_clause(tcx, obligation.predicate.constness),
538 )
539 })
540 .collect())
541}
542
543fn evaluate_host_effect_for_fn_goal<'tcx>(
545 selcx: &mut SelectionContext<'_, 'tcx>,
546 obligation: &HostEffectObligation<'tcx>,
547) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
548 let tcx = selcx.tcx();
549 let self_ty = obligation.predicate.self_ty();
550
551 let (def, args) = match *self_ty.kind() {
552 ty::FnDef(def, args) => (def, args),
553
554 ty::FnPtr(..) => return Err(EvaluationFailure::NoSolution),
556
557 ty::CoroutineClosure(_, _) => return Err(EvaluationFailure::NoSolution),
560
561 ty::Closure(def, args) => (def, args),
562
563 _ => return Err(EvaluationFailure::NoSolution),
565 };
566
567 match tcx.constness(def) {
568 hir::Constness::Const { always: true } => Err(EvaluationFailure::NoSolution),
570 hir::Constness::Const { always: false } => Ok(tcx
571 .const_conditions(def)
572 .instantiate(tcx, args)
573 .into_iter()
574 .map(|(c, span)| {
575 let code = ObligationCauseCode::WhereClause(def, span);
576 let cause =
577 ObligationCause::new(obligation.cause.span, obligation.cause.body_def_id, code);
578 Obligation::new(
579 tcx,
580 cause,
581 obligation.param_env,
582 c.to_host_effect_clause(tcx, obligation.predicate.constness).skip_norm_wip(),
583 )
584 })
585 .collect()),
586 hir::Constness::NotConst => Err(EvaluationFailure::NoSolution),
587 }
588}
589
590fn evaluate_host_effect_from_selection_candidate<'tcx>(
591 selcx: &mut SelectionContext<'_, 'tcx>,
592 obligation: &HostEffectObligation<'tcx>,
593) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
594 let tcx = selcx.tcx();
595 selcx.infcx.commit_if_ok(|_| {
596 match selcx.select(&obligation.with(tcx, obligation.predicate.trait_ref)) {
597 Ok(None) => Err(EvaluationFailure::Ambiguous),
598 Err(_) => Err(EvaluationFailure::NoSolution),
599 Ok(Some(source)) => match source {
600 ImplSource::UserDefined(impl_) => {
601 match tcx.impl_trait_header(impl_.impl_def_id).constness {
602 rustc_hir::Constness::Const { always } => {
603 if always {
604 ::core::panicking::panic("not yet implemented")todo!()
605 }
606 }
607 rustc_hir::Constness::NotConst => {
608 return Err(EvaluationFailure::NoSolution);
609 }
610 }
611
612 let mut nested = impl_.nested;
613 nested.extend(
614 tcx.const_conditions(impl_.impl_def_id)
615 .instantiate(tcx, impl_.args)
616 .into_iter()
617 .map(|(trait_ref, span)| {
618 Obligation::new(
619 tcx,
620 obligation.cause.clone().derived_host_cause(
621 ty::Binder::dummy(obligation.predicate),
622 |derived| {
623 ObligationCauseCode::ImplDerivedHost(Box::new(
624 ImplDerivedHostCause {
625 derived,
626 impl_def_id: impl_.impl_def_id,
627 span,
628 },
629 ))
630 },
631 ),
632 obligation.param_env,
633 trait_ref
634 .to_host_effect_clause(tcx, obligation.predicate.constness)
635 .skip_norm_wip(),
636 )
637 }),
638 );
639
640 Ok(nested)
641 }
642 _ => Err(EvaluationFailure::NoSolution),
643 },
644 }
645 })
646}
647
648fn evaluate_host_effect_from_trait_alias<'tcx>(
649 selcx: &mut SelectionContext<'_, 'tcx>,
650 obligation: &HostEffectObligation<'tcx>,
651) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
652 let tcx = selcx.tcx();
653 let def_id = obligation.predicate.def_id();
654 if !tcx.trait_is_alias(def_id) {
655 return Err(EvaluationFailure::NoSolution);
656 }
657
658 Ok(tcx
659 .const_conditions(def_id)
660 .instantiate(tcx, obligation.predicate.trait_ref.args)
661 .into_iter()
662 .map(|(trait_ref, span)| {
663 Obligation::new(
664 tcx,
665 obligation.cause.clone().derived_host_cause(
666 ty::Binder::dummy(obligation.predicate),
667 |derived| {
668 ObligationCauseCode::ImplDerivedHost(Box::new(ImplDerivedHostCause {
669 derived,
670 impl_def_id: def_id,
671 span,
672 }))
673 },
674 ),
675 obligation.param_env,
676 trait_ref
677 .to_host_effect_clause(tcx, obligation.predicate.constness)
678 .skip_norm_wip(),
679 )
680 })
681 .collect())
682}