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};
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.infcx.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 alias_ty @ ty::AliasTy {
183 kind: kind @ (ty::Projection { def_id } | ty::Opaque { def_id }),
184 ..
185 },
186 ) = *consider_ty.kind()
187 {
188 if tcx.is_conditionally_const(def_id) {
189 for clause in elaborate(
190 tcx,
191 tcx.explicit_implied_const_bounds(def_id)
192 .iter_instantiated_copied(tcx, alias_ty.args)
193 .map(|(trait_ref, _)| {
194 trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness)
195 }),
196 ) {
197 let bound_clause = clause.kind();
198 let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
199 {
::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")
200 };
201 let data = bound_clause.rebind(data);
202 if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
203 continue;
204 }
205
206 if !drcx.args_may_unify(
207 obligation.predicate.trait_ref.args,
208 data.skip_binder().trait_ref.args,
209 ) {
210 continue;
211 }
212
213 let is_match = infcx
214 .probe(|_| match_candidate(selcx, obligation, data, true, |_, _| {}).is_ok());
215
216 if is_match {
217 if candidate.is_some() {
218 return Err(EvaluationFailure::Ambiguous);
219 } else {
220 candidate = Some((data, alias_ty));
221 }
222 }
223 }
224 }
225
226 if !#[allow(non_exhaustive_omitted_patterns)] match kind {
ty::Projection { .. } => true,
_ => false,
}matches!(kind, ty::Projection { .. }) {
227 break;
228 }
229
230 consider_ty = alias_ty.self_ty();
231 }
232
233 if let Some((data, alias_ty)) = candidate {
234 Ok(match_candidate(selcx, obligation, data, true, |selcx, nested| {
235 let const_conditions = normalize_with_depth_to(
238 selcx,
239 obligation.param_env,
240 obligation.cause.clone(),
241 obligation.recursion_depth,
242 tcx.const_conditions(alias_ty.kind.def_id()).instantiate(tcx, alias_ty.args),
243 nested,
244 );
245 nested.extend(const_conditions.into_iter().map(|(trait_ref, _)| {
246 obligation
247 .with(tcx, trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness))
248 }));
249 })
250 .expect("candidate matched before, so it should match again"))
251 } else {
252 Err(EvaluationFailure::NoSolution)
253 }
254}
255
256fn evaluate_host_effect_from_item_bounds<'tcx>(
259 selcx: &mut SelectionContext<'_, 'tcx>,
260 obligation: &HostEffectObligation<'tcx>,
261) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
262 let infcx = selcx.infcx;
263 let tcx = infcx.tcx;
264 let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
265 let mut candidate = None;
266
267 let mut consider_ty = obligation.predicate.self_ty();
268 while let ty::Alias(
269 alias_ty @ ty::AliasTy {
270 kind: kind @ (ty::Projection { def_id } | ty::Opaque { def_id }),
271 ..
272 },
273 ) = *consider_ty.kind()
274 {
275 for clause in tcx.item_bounds(def_id).iter_instantiated(tcx, alias_ty.args) {
276 let bound_clause = clause.kind();
277 let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
278 continue;
279 };
280 let data = bound_clause.rebind(data);
281 if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
282 continue;
283 }
284
285 if !drcx.args_may_unify(
286 obligation.predicate.trait_ref.args,
287 data.skip_binder().trait_ref.args,
288 ) {
289 continue;
290 }
291
292 let is_match =
293 infcx.probe(|_| match_candidate(selcx, obligation, data, true, |_, _| {}).is_ok());
294
295 if is_match {
296 if candidate.is_some() {
297 return Err(EvaluationFailure::Ambiguous);
298 } else {
299 candidate = Some(data);
300 }
301 }
302 }
303
304 if !#[allow(non_exhaustive_omitted_patterns)] match kind {
ty::Projection { .. } => true,
_ => false,
}matches!(kind, ty::Projection { .. }) {
305 break;
306 }
307
308 consider_ty = alias_ty.self_ty();
309 }
310
311 if let Some(data) = candidate {
312 Ok(match_candidate(selcx, obligation, data, true, |_, _| {})
313 .expect("candidate matched before, so it should match again"))
314 } else {
315 Err(EvaluationFailure::NoSolution)
316 }
317}
318
319fn evaluate_host_effect_from_builtin_impls<'tcx>(
320 selcx: &mut SelectionContext<'_, 'tcx>,
321 obligation: &HostEffectObligation<'tcx>,
322) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
323 match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
324 Some(LangItem::Copy | LangItem::Clone) => {
325 evaluate_host_effect_for_copy_clone_goal(selcx, obligation)
326 }
327 Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
328 Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => {
329 evaluate_host_effect_for_fn_goal(selcx, obligation)
330 }
331 _ => Err(EvaluationFailure::NoSolution),
332 }
333}
334
335fn evaluate_host_effect_for_copy_clone_goal<'tcx>(
336 selcx: &mut SelectionContext<'_, 'tcx>,
337 obligation: &HostEffectObligation<'tcx>,
338) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
339 let tcx = selcx.tcx();
340 let self_ty = obligation.predicate.self_ty();
341 let constituent_tys = match *self_ty.kind() {
342 ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(::alloc::vec::Vec::new()vec![])),
344
345 ty::Uint(_)
347 | ty::Int(_)
348 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
349 | ty::Bool
350 | ty::Float(_)
351 | ty::Char
352 | ty::RawPtr(..)
353 | ty::Never
354 | ty::Ref(_, _, ty::Mutability::Not)
355 | ty::Array(..) => Err(EvaluationFailure::NoSolution),
356
357 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])),
360
361 ty::Dynamic(..)
362 | ty::Str
363 | ty::Slice(_)
364 | ty::Foreign(..)
365 | ty::Ref(_, _, ty::Mutability::Mut)
366 | ty::Adt(_, _)
367 | ty::Alias(_)
368 | ty::Param(_)
369 | ty::Placeholder(..) => Err(EvaluationFailure::NoSolution),
370
371 ty::Bound(..)
372 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
373 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
374 }
375
376 ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
378
379 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()])),
381
382 ty::CoroutineClosure(_, args) => {
384 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()]))
385 }
386
387 ty::Coroutine(def_id, args) => {
390 if selcx.should_stall_coroutine(def_id) {
391 return Err(EvaluationFailure::Ambiguous);
392 }
393 match tcx.coroutine_movability(def_id) {
394 ty::Movability::Static => Err(EvaluationFailure::NoSolution),
395 ty::Movability::Movable => {
396 if tcx.features().coroutine_clone() {
397 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![
398 args.as_coroutine().tupled_upvars_ty(),
399 Ty::new_coroutine_witness_for_coroutine(tcx, def_id, args),
400 ]))
401 } else {
402 Err(EvaluationFailure::NoSolution)
403 }
404 }
405 }
406 }
407
408 ty::UnsafeBinder(_) => Err(EvaluationFailure::NoSolution),
409
410 ty::CoroutineWitness(def_id, args) => Ok(tcx
412 .coroutine_hidden_types(def_id)
413 .instantiate(tcx, args)
414 .map_bound(|bound| bound.types.to_vec())),
415 }?;
416
417 Ok(constituent_tys
418 .iter()
419 .map(|ty| {
420 obligation.with(
421 tcx,
422 ty.map_bound(|ty| ty::TraitRef::new(tcx, obligation.predicate.def_id(), [ty]))
423 .to_host_effect_clause(tcx, obligation.predicate.constness),
424 )
425 })
426 .collect())
427}
428
429fn evaluate_host_effect_for_destruct_goal<'tcx>(
431 selcx: &mut SelectionContext<'_, 'tcx>,
432 obligation: &HostEffectObligation<'tcx>,
433) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
434 let tcx = selcx.tcx();
435 let destruct_def_id = tcx.require_lang_item(LangItem::Destruct, obligation.cause.span);
436 let self_ty = obligation.predicate.self_ty();
437
438 let const_conditions = match *self_ty.kind() {
439 ty::Adt(adt_def, _) if adt_def.is_manually_drop() => ::thin_vec::ThinVec::new()thin_vec![],
441
442 ty::Adt(adt_def, args) => {
445 let mut const_conditions: ThinVec<_> = adt_def
446 .all_fields()
447 .map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
448 .collect();
449 match adt_def.destructor(tcx).map(|dtor| tcx.constness(dtor.did)) {
450 Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
452 Some(hir::Constness::Const) => {
454 let drop_def_id = tcx.require_lang_item(LangItem::Drop, obligation.cause.span);
455 let drop_trait_ref = ty::TraitRef::new(tcx, drop_def_id, [self_ty]);
456 const_conditions.push(drop_trait_ref);
457 }
458 None => {}
460 }
461 const_conditions
462 }
463
464 ty::Array(ty, _) | ty::Pat(ty, _) | ty::Slice(ty) => {
465 {
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])]
466 }
467
468 ty::Tuple(tys) => {
469 tys.iter().map(|field_ty| ty::TraitRef::new(tcx, destruct_def_id, [field_ty])).collect()
470 }
471
472 ty::Bool
474 | ty::Char
475 | ty::Int(..)
476 | ty::Uint(..)
477 | ty::Float(..)
478 | ty::Str
479 | ty::RawPtr(..)
480 | ty::Ref(..)
481 | ty::FnDef(..)
482 | ty::FnPtr(..)
483 | ty::Never
484 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
485 | ty::Error(_) => ::thin_vec::ThinVec::new()thin_vec![],
486
487 ty::Closure(_, args) => {
489 let closure_args = args.as_closure();
490 {
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()])]
491 }
492
493 ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(_, _) => {
496 return Err(EvaluationFailure::NoSolution);
497 }
498
499 ty::UnsafeBinder(_) => return Err(EvaluationFailure::NoSolution),
502
503 ty::Dynamic(..) | ty::Param(_) | ty::Alias(..) | ty::Placeholder(_) | ty::Foreign(_) => {
504 return Err(EvaluationFailure::NoSolution);
505 }
506
507 ty::Bound(..)
508 | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
509 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
510 }
511 };
512
513 Ok(const_conditions
514 .into_iter()
515 .map(|trait_ref| {
516 obligation.with(
517 tcx,
518 ty::Binder::dummy(trait_ref)
519 .to_host_effect_clause(tcx, obligation.predicate.constness),
520 )
521 })
522 .collect())
523}
524
525fn evaluate_host_effect_for_fn_goal<'tcx>(
527 selcx: &mut SelectionContext<'_, 'tcx>,
528 obligation: &HostEffectObligation<'tcx>,
529) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
530 let tcx = selcx.tcx();
531 let self_ty = obligation.predicate.self_ty();
532
533 let (def, args) = match *self_ty.kind() {
534 ty::FnDef(def, args) => (def, args),
535
536 ty::FnPtr(..) => return Err(EvaluationFailure::NoSolution),
538
539 ty::CoroutineClosure(_, _) => return Err(EvaluationFailure::NoSolution),
542
543 ty::Closure(def, args) => {
544 let sig =
546 args.as_closure().sig().no_bound_vars().ok_or(EvaluationFailure::NoSolution)?;
547 (
548 def,
549 tcx.mk_args_from_iter(
550 [ty::GenericArg::from(*sig.inputs().get(0).unwrap()), sig.output().into()]
551 .into_iter(),
552 ),
553 )
554 }
555
556 _ => return Err(EvaluationFailure::NoSolution),
558 };
559
560 match tcx.constness(def) {
561 hir::Constness::Const => Ok(tcx
562 .const_conditions(def)
563 .instantiate(tcx, args)
564 .into_iter()
565 .map(|(c, span)| {
566 let code = ObligationCauseCode::WhereClause(def, span);
567 let cause =
568 ObligationCause::new(obligation.cause.span, obligation.cause.body_id, code);
569 Obligation::new(
570 tcx,
571 cause,
572 obligation.param_env,
573 c.to_host_effect_clause(tcx, obligation.predicate.constness),
574 )
575 })
576 .collect()),
577 hir::Constness::NotConst => Err(EvaluationFailure::NoSolution),
578 }
579}
580
581fn evaluate_host_effect_from_selection_candidate<'tcx>(
582 selcx: &mut SelectionContext<'_, 'tcx>,
583 obligation: &HostEffectObligation<'tcx>,
584) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
585 let tcx = selcx.tcx();
586 selcx.infcx.commit_if_ok(|_| {
587 match selcx.select(&obligation.with(tcx, obligation.predicate.trait_ref)) {
588 Ok(None) => Err(EvaluationFailure::Ambiguous),
589 Err(_) => Err(EvaluationFailure::NoSolution),
590 Ok(Some(source)) => match source {
591 ImplSource::UserDefined(impl_) => {
592 if tcx.impl_trait_header(impl_.impl_def_id).constness != hir::Constness::Const {
593 return Err(EvaluationFailure::NoSolution);
594 }
595
596 let mut nested = impl_.nested;
597 nested.extend(
598 tcx.const_conditions(impl_.impl_def_id)
599 .instantiate(tcx, impl_.args)
600 .into_iter()
601 .map(|(trait_ref, span)| {
602 Obligation::new(
603 tcx,
604 obligation.cause.clone().derived_host_cause(
605 ty::Binder::dummy(obligation.predicate),
606 |derived| {
607 ObligationCauseCode::ImplDerivedHost(Box::new(
608 ImplDerivedHostCause {
609 derived,
610 impl_def_id: impl_.impl_def_id,
611 span,
612 },
613 ))
614 },
615 ),
616 obligation.param_env,
617 trait_ref
618 .to_host_effect_clause(tcx, obligation.predicate.constness),
619 )
620 }),
621 );
622
623 Ok(nested)
624 }
625 _ => Err(EvaluationFailure::NoSolution),
626 },
627 }
628 })
629}
630
631fn evaluate_host_effect_from_trait_alias<'tcx>(
632 selcx: &mut SelectionContext<'_, 'tcx>,
633 obligation: &HostEffectObligation<'tcx>,
634) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
635 let tcx = selcx.tcx();
636 let def_id = obligation.predicate.def_id();
637 if !tcx.trait_is_alias(def_id) {
638 return Err(EvaluationFailure::NoSolution);
639 }
640
641 Ok(tcx
642 .const_conditions(def_id)
643 .instantiate(tcx, obligation.predicate.trait_ref.args)
644 .into_iter()
645 .map(|(trait_ref, span)| {
646 Obligation::new(
647 tcx,
648 obligation.cause.clone().derived_host_cause(
649 ty::Binder::dummy(obligation.predicate),
650 |derived| {
651 ObligationCauseCode::ImplDerivedHost(Box::new(ImplDerivedHostCause {
652 derived,
653 impl_def_id: def_id,
654 span,
655 }))
656 },
657 ),
658 obligation.param_env,
659 trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness),
660 )
661 })
662 .collect())
663}