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