1use rustc_type_ir::data_structures::IndexSet;
4use rustc_type_ir::fast_reject::DeepRejectCtxt;
5use rustc_type_ir::inherent::*;
6use rustc_type_ir::lang_items::SolverTraitLangItem;
7use rustc_type_ir::solve::{
8 AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, ExternalConstraintsData, MaybeInfo,
9 NoSolutionOrRerunNonErased, OpaqueTypesJank, QueryResultOrRerunNonErased, RerunNonErased,
10 RerunReason, RerunResultExt, SizedTraitKind,
11};
12use rustc_type_ir::{
13 self as ty, ClausePolarity, ExistentialPredicate, FieldInfo, Interner, MayBeErased, Movability,
14 Region, TraitClause, TraitRef, TypeVisitableExt as _, TypingMode, Unnormalized, Upcast as _,
15 elaborate,
16};
17use tracing::{debug, instrument, trace, warn};
18
19use crate::delegate::SolverDelegate;
20use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
21use crate::solve::assembly::{
22 self, AllowInferenceConstraints, AssembleCandidatesFrom, Candidate, FailedCandidateInfo,
23};
24use crate::solve::inspect::ProbeKind;
25use crate::solve::{
26 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
27 MergeCandidateInfo, NoSolution, ParamEnvSource, StalledOnCoroutines, flatten_answer_tree,
28 has_only_region_constraints,
29};
30
31impl<D, I> assembly::GoalKind<D> for TraitClause<I>
32where
33 D: SolverDelegate<Interner = I>,
34 I: Interner,
35{
36 fn self_ty(self) -> I::Ty {
37 self.self_ty()
38 }
39
40 fn trait_ref(self, _: I) -> ty::TraitRef<I> {
41 self.trait_ref
42 }
43
44 fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self {
45 self.with_replaced_self_ty(cx, self_ty)
46 }
47
48 fn trait_def_id(self, _: I) -> I::TraitId {
49 self.def_id()
50 }
51
52 fn consider_additional_alias_assumptions(
53 _ecx: &mut EvalCtxt<'_, D>,
54 _goal: Goal<I, Self>,
55 _alias_ty: ty::AliasTy<I>,
56 ) -> Vec<Candidate<I>> {
57 ::alloc::vec::Vec::new()vec![]
58 }
59
60 fn consider_impl_candidate(
61 ecx: &mut EvalCtxt<'_, D>,
62 goal: Goal<I, TraitClause<I>>,
63 goal_trait_ref: TraitRef<I>,
64 impl_def_id: I::ImplId,
65 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
66 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
67 let cx = ecx.cx();
68
69 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
70 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
71 .args_may_unify(goal_trait_ref.args, impl_trait_ref.skip_binder().args)
72 {
73 return Err(NoSolution.into());
74 }
75
76 if cx.impl_is_default(impl_def_id) {
80 return Err(NoSolution.into());
81 }
82
83 match (cx.impl_polarity(impl_def_id), goal.predicate.polarity) {
84 (ty::ImplPolarity::Positive, ty::ClausePolarity::Positive)
86 | (ty::ImplPolarity::Negative, ty::ClausePolarity::Negative) => {}
87
88 (ty::ImplPolarity::Positive, ty::ClausePolarity::Negative)
90 | (ty::ImplPolarity::Negative, ty::ClausePolarity::Positive) => {
91 return Err(NoSolution.into());
92 }
93 }
94
95 if ecx.typing_mode().is_reflection() && !cx.is_fully_generic_for_reflection(impl_def_id) {
96 return Err(NoSolution.into());
97 }
98
99 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
100 let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
101 ecx.record_impl_args(impl_args);
102 let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
103
104 ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
105 let where_clause_bounds = cx
106 .clauses_of(impl_def_id.into())
107 .iter_instantiated(cx, impl_args)
108 .map(Unnormalized::skip_norm_wip)
109 .map(|clause| goal.with(cx, clause));
110 ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds)?;
111
112 ecx.add_goals(
116 GoalSource::Misc,
117 cx.impl_super_outlives(impl_def_id)
118 .iter_instantiated(cx, impl_args)
119 .map(Unnormalized::skip_norm_wip)
120 .map(|pred| goal.with(cx, pred)),
121 )?;
122
123 then(ecx)
124 })
125 }
126
127 fn consider_error_guaranteed_candidate(
128 ecx: &mut EvalCtxt<'_, D>,
129 _goal: Goal<I, Self>,
130 _guar: I::ErrorGuaranteed,
131 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
132 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
133 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
134 }
135
136 fn fast_reject_assumption(
137 ecx: &mut EvalCtxt<'_, D>,
138 goal: Goal<I, Self>,
139 goal_lang_item: Option<SolverTraitLangItem>,
140 assumption: I::Clause,
141 ) -> Result<(), NoSolution> {
142 fn trait_def_id_matches<I: Interner>(
143 cx: I,
144 clause_def_id: I::TraitId,
145 goal_def_id: I::TraitId,
146 polarity: ClausePolarity,
147 goal_lang_item: Option<SolverTraitLangItem>,
148 ) -> bool {
149 clause_def_id == goal_def_id
150 || (polarity == ClausePolarity::Positive
155 && goal_lang_item == Some(SolverTraitLangItem::MetaSized)
156 && cx.is_trait_lang_item(clause_def_id, SolverTraitLangItem::Sized))
157 }
158
159 if let Some(trait_clause) = assumption.as_trait_clause()
160 && trait_clause.polarity() == goal.predicate.polarity
161 && trait_def_id_matches(
162 ecx.cx(),
163 trait_clause.def_id(),
164 goal.predicate.def_id(),
165 goal.predicate.polarity,
166 goal_lang_item,
167 )
168 && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
169 goal.predicate.trait_ref.args,
170 trait_clause.skip_binder().trait_ref.args,
171 )
172 {
173 return Ok(());
174 } else {
175 Err(NoSolution)
176 }
177 }
178
179 fn match_assumption(
180 ecx: &mut EvalCtxt<'_, D>,
181 goal: Goal<I, Self>,
182 assumption: I::Clause,
183 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
184 ) -> QueryResultOrRerunNonErased<I> {
185 let trait_clause = assumption.as_trait_clause().unwrap();
186
187 if ecx.cx().is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::MetaSized)
193 && ecx.cx().is_trait_lang_item(trait_clause.def_id(), SolverTraitLangItem::Sized)
194 {
195 let meta_sized_clause =
196 trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id());
197 return Self::match_assumption(ecx, goal, meta_sized_clause, then);
198 }
199
200 let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
201 ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?;
202
203 then(ecx)
204 }
205
206 fn consider_auto_trait_candidate(
207 ecx: &mut EvalCtxt<'_, D>,
208 goal: Goal<I, Self>,
209 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
210 let cx = ecx.cx();
211 if goal.predicate.polarity != ty::ClausePolarity::Positive {
212 return Err(NoSolution.into());
213 }
214
215 if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) {
216 return result;
217 }
218
219 if cx.trait_is_unsafe(goal.predicate.def_id())
222 && goal.predicate.self_ty().has_unsafe_fields()
223 {
224 return Err(NoSolution.into());
225 }
226
227 if let ty::Alias(is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) =
243 goal.predicate.self_ty().kind()
244 {
245 if true {
if !(is_rigid == ty::IsRigid::Yes) {
::core::panicking::panic("assertion failed: is_rigid == ty::IsRigid::Yes")
};
};debug_assert!(is_rigid == ty::IsRigid::Yes);
246 return ecx.consider_auto_trait_candidate_for_opaque_ty(goal, def_id, args);
247 }
248
249 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
251 return cand;
252 }
253
254 ecx.probe_and_evaluate_goal_for_constituent_tys(
255 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
256 goal,
257 structural_traits::instantiate_constituent_tys_for_auto_trait,
258 )
259 }
260
261 fn consider_trait_alias_candidate(
262 ecx: &mut EvalCtxt<'_, D>,
263 goal: Goal<I, Self>,
264 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
265 if goal.predicate.polarity != ty::ClausePolarity::Positive {
266 return Err(NoSolution.into());
267 }
268
269 let cx = ecx.cx();
270
271 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
272 let nested_obligations = cx
273 .clauses_of(goal.predicate.def_id().into())
274 .iter_instantiated(cx, goal.predicate.trait_ref.args)
275 .map(Unnormalized::skip_norm_wip)
276 .map(|c| goal.with(cx, c));
277 ecx.add_goals(GoalSource::Misc, nested_obligations)?;
283 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
284 })
285 }
286
287 fn consider_builtin_sizedness_candidates(
288 ecx: &mut EvalCtxt<'_, D>,
289 goal: Goal<I, Self>,
290 sizedness: SizedTraitKind,
291 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
292 if goal.predicate.polarity != ty::ClausePolarity::Positive {
293 return Err(NoSolution.into());
294 }
295
296 ecx.probe_and_evaluate_goal_for_constituent_tys(
297 CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
298 goal,
299 |ecx, ty| {
300 structural_traits::instantiate_constituent_tys_for_sizedness_trait(
301 ecx, sizedness, ty,
302 )
303 },
304 )
305 }
306
307 fn consider_builtin_copy_clone_candidate(
308 ecx: &mut EvalCtxt<'_, D>,
309 goal: Goal<I, Self>,
310 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
311 if goal.predicate.polarity != ty::ClausePolarity::Positive {
312 return Err(NoSolution.into());
313 }
314
315 if let Some(cand) = ecx.try_stall_coroutine(goal.predicate.self_ty()) {
317 return cand;
318 }
319
320 ecx.probe_and_evaluate_goal_for_constituent_tys(
321 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
322 goal,
323 structural_traits::instantiate_constituent_tys_for_copy_clone_trait,
324 )
325 }
326
327 fn consider_builtin_fn_ptr_trait_candidate(
328 ecx: &mut EvalCtxt<'_, D>,
329 goal: Goal<I, Self>,
330 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
331 let self_ty = goal.predicate.self_ty();
332 match goal.predicate.polarity {
333 ty::ClausePolarity::Positive => {
335 if self_ty.is_fn_ptr() {
336 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
337 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
338 })
339 } else {
340 Err(NoSolution.into())
341 }
342 }
343 ty::ClausePolarity::Negative => {
345 if !self_ty.is_fn_ptr() && self_ty.is_known_rigid() {
348 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
349 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
350 })
351 } else {
352 Err(NoSolution.into())
353 }
354 }
355 }
356 }
357
358 fn consider_builtin_fn_trait_candidates(
359 ecx: &mut EvalCtxt<'_, D>,
360 goal: Goal<I, Self>,
361 goal_kind: ty::ClosureKind,
362 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
363 if goal.predicate.polarity != ty::ClausePolarity::Positive {
364 return Err(NoSolution.into());
365 }
366
367 let cx = ecx.cx();
368 let Some(tupled_inputs_and_output) =
369 structural_traits::extract_tupled_inputs_and_output_from_callable(
370 cx,
371 goal.predicate.self_ty(),
372 goal_kind,
373 )?
374 else {
375 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
376 };
377 let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
378
379 let output_is_sized_pred =
382 ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]);
383
384 let pred =
385 ty::TraitRef::new(cx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
386 .upcast(cx);
387 Self::probe_and_consider_implied_clause(
388 ecx,
389 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
390 goal,
391 pred,
392 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
393 )
394 }
395
396 fn consider_builtin_async_fn_trait_candidates(
397 ecx: &mut EvalCtxt<'_, D>,
398 goal: Goal<I, Self>,
399 goal_kind: ty::ClosureKind,
400 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
401 if goal.predicate.polarity != ty::ClausePolarity::Positive {
402 return Err(NoSolution.into());
403 }
404
405 let cx = ecx.cx();
406 let (tupled_inputs_and_output_and_coroutine, nested_preds) =
407 structural_traits::extract_tupled_inputs_and_output_from_async_callable(
408 cx,
409 goal.predicate.self_ty(),
410 goal_kind,
411 Region::new_static(cx),
413 )?;
414 let AsyncCallableRelevantTypes {
415 tupled_inputs_ty,
416 output_coroutine_ty,
417 coroutine_return_ty: _,
418 } = ecx.instantiate_binder_with_infer(tupled_inputs_and_output_and_coroutine);
419
420 let output_is_sized_pred = ty::TraitRef::new(
423 cx,
424 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
425 [output_coroutine_ty],
426 );
427
428 let pred = ty::TraitRef::new(
429 cx,
430 goal.predicate.def_id(),
431 [goal.predicate.self_ty(), tupled_inputs_ty],
432 )
433 .upcast(cx);
434 Self::probe_and_consider_implied_clause(
435 ecx,
436 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
437 goal,
438 pred,
439 [goal.with(cx, output_is_sized_pred)]
440 .into_iter()
441 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
442 .map(|goal| (GoalSource::ImplWhereBound, goal)),
443 )
444 }
445
446 fn consider_builtin_async_fn_kind_helper_candidate(
447 ecx: &mut EvalCtxt<'_, D>,
448 goal: Goal<I, Self>,
449 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
450 let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
451 ::core::panicking::panic("explicit panic");panic!();
452 };
453
454 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
455 return Err(NoSolution.into());
457 };
458 let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap();
459 if closure_kind.extends(goal_kind) {
460 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
461 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
462 } else {
463 Err(NoSolution.into())
464 }
465 }
466
467 fn consider_builtin_tuple_candidate(
474 ecx: &mut EvalCtxt<'_, D>,
475 goal: Goal<I, Self>,
476 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
477 if goal.predicate.polarity != ty::ClausePolarity::Positive {
478 return Err(NoSolution.into());
479 }
480
481 if let ty::Tuple(..) = goal.predicate.self_ty().kind() {
482 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
483 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
484 } else {
485 Err(NoSolution.into())
486 }
487 }
488
489 fn consider_builtin_pointee_candidate(
490 ecx: &mut EvalCtxt<'_, D>,
491 goal: Goal<I, Self>,
492 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
493 if goal.predicate.polarity != ty::ClausePolarity::Positive {
494 return Err(NoSolution.into());
495 }
496
497 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
498 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
499 }
500
501 fn consider_builtin_future_candidate(
502 ecx: &mut EvalCtxt<'_, D>,
503 goal: Goal<I, Self>,
504 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
505 if goal.predicate.polarity != ty::ClausePolarity::Positive {
506 return Err(NoSolution.into());
507 }
508
509 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
510 return Err(NoSolution.into());
511 };
512
513 let cx = ecx.cx();
515 if !cx.coroutine_is_async(def_id) {
516 return Err(NoSolution.into());
517 }
518
519 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
523 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
524 }
525
526 fn consider_builtin_iterator_candidate(
527 ecx: &mut EvalCtxt<'_, D>,
528 goal: Goal<I, Self>,
529 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
530 if goal.predicate.polarity != ty::ClausePolarity::Positive {
531 return Err(NoSolution.into());
532 }
533
534 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
535 return Err(NoSolution.into());
536 };
537
538 let cx = ecx.cx();
540 if !cx.coroutine_is_gen(def_id) {
541 return Err(NoSolution.into());
542 }
543
544 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
548 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
549 }
550
551 fn consider_builtin_fused_iterator_candidate(
552 ecx: &mut EvalCtxt<'_, D>,
553 goal: Goal<I, Self>,
554 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
555 if goal.predicate.polarity != ty::ClausePolarity::Positive {
556 return Err(NoSolution.into());
557 }
558
559 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
560 return Err(NoSolution.into());
561 };
562
563 let cx = ecx.cx();
565 if !cx.coroutine_is_gen(def_id) {
566 return Err(NoSolution.into());
567 }
568
569 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
571 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
572 }
573
574 fn consider_builtin_async_iterator_candidate(
575 ecx: &mut EvalCtxt<'_, D>,
576 goal: Goal<I, Self>,
577 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
578 if goal.predicate.polarity != ty::ClausePolarity::Positive {
579 return Err(NoSolution.into());
580 }
581
582 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
583 return Err(NoSolution.into());
584 };
585
586 let cx = ecx.cx();
588 if !cx.coroutine_is_async_gen(def_id) {
589 return Err(NoSolution.into());
590 }
591
592 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
596 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
597 }
598
599 fn consider_builtin_coroutine_candidate(
600 ecx: &mut EvalCtxt<'_, D>,
601 goal: Goal<I, Self>,
602 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
603 if goal.predicate.polarity != ty::ClausePolarity::Positive {
604 return Err(NoSolution.into());
605 }
606
607 let self_ty = goal.predicate.self_ty();
608 let ty::Coroutine(def_id, args) = self_ty.kind() else {
609 return Err(NoSolution.into());
610 };
611
612 let cx = ecx.cx();
614 if !cx.is_general_coroutine(def_id) {
615 return Err(NoSolution.into());
616 }
617
618 let coroutine = args.as_coroutine();
619 Self::probe_and_consider_implied_clause(
620 ecx,
621 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
622 goal,
623 ty::TraitRef::new(cx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
624 .upcast(cx),
625 [],
628 )
629 }
630
631 fn consider_builtin_discriminant_kind_candidate(
632 ecx: &mut EvalCtxt<'_, D>,
633 goal: Goal<I, Self>,
634 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
635 if goal.predicate.polarity != ty::ClausePolarity::Positive {
636 return Err(NoSolution.into());
637 }
638
639 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
641 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
642 }
643
644 fn consider_builtin_destruct_candidate(
645 ecx: &mut EvalCtxt<'_, D>,
646 goal: Goal<I, Self>,
647 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
648 if goal.predicate.polarity != ty::ClausePolarity::Positive {
649 return Err(NoSolution.into());
650 }
651
652 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
655 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
656 }
657
658 fn consider_builtin_transmute_candidate(
659 ecx: &mut EvalCtxt<'_, D>,
660 goal: Goal<I, Self>,
661 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
662 use rustc_type_ir::transmute::Answer;
663
664 if goal.predicate.polarity != ty::ClausePolarity::Positive {
665 return Err(NoSolution.into());
666 }
667
668 if goal.predicate.has_non_region_placeholders() {
670 return Err(NoSolution.into());
671 }
672
673 if goal.has_non_region_infer() {
676 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
677 }
678
679 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(
680 |ecx| -> Result<_, NoSolutionOrRerunNonErased> {
681 let assume = ecx.structurally_normalize_const(
682 goal.param_env,
683 goal.predicate.trait_ref.args.const_at(2),
684 )?;
685
686 let answer = ecx.is_transmutable(
687 goal.predicate.trait_ref.args.type_at(0),
688 goal.predicate.trait_ref.args.type_at(1),
689 assume,
690 )?;
691
692 let certainty = match answer {
693 Answer::No(_) => return Err(NoSolution.into()),
694 Answer::Yes => Certainty::Yes,
695 Answer::If(cond) => {
696 let tcx = ecx.cx();
697 ecx.add_goals(
698 GoalSource::Misc,
699 flatten_answer_tree(tcx, goal.predicate, cond)
700 .into_iter()
701 .map(|predicate| Goal::new(tcx, goal.param_env, predicate)),
702 )?;
703
704 Certainty::Yes
705 }
706 };
707
708 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
709 },
710 )
711 }
712
713 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
726 ecx: &mut EvalCtxt<'_, D>,
727 goal: Goal<I, Self>,
728 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
729 if goal.predicate.polarity != ty::ClausePolarity::Positive {
730 return Err(NoSolution.into());
731 }
732
733 let cx = ecx.cx();
734 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
735 let ty = goal.predicate.self_ty();
736 match ty.kind() {
737 ty::Ref(..) => {}
739 ty::Adt(def, _) if def.is_manually_drop() => {}
741 ty::Tuple(tys) => {
744 ecx.add_goals(
745 GoalSource::ImplWhereBound,
746 tys.iter().map(|elem_ty| {
747 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty]))
748 }),
749 )?;
750 }
751 ty::Array(elem_ty, _) => {
752 ecx.add_goal(
753 GoalSource::ImplWhereBound,
754 goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])),
755 )?;
756 }
757
758 ty::FnDef(..)
762 | ty::FnPtr(..)
763 | ty::Error(_)
764 | ty::Uint(_)
765 | ty::Int(_)
766 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
767 | ty::Bool
768 | ty::Float(_)
769 | ty::Char
770 | ty::RawPtr(..)
771 | ty::Never
772 | ty::Pat(..)
773 | ty::Dynamic(..)
774 | ty::Str
775 | ty::Slice(_)
776 | ty::Foreign(..)
777 | ty::Adt(..)
778 | ty::Alias(..)
779 | ty::Param(_)
780 | ty::Placeholder(..)
781 | ty::Closure(..)
782 | ty::CoroutineClosure(..)
783 | ty::Coroutine(..)
784 | ty::UnsafeBinder(_)
785 | ty::CoroutineWitness(..) => {
786 ecx.add_goal(
787 GoalSource::ImplWhereBound,
788 goal.with(
789 cx,
790 ty::TraitRef::new(
791 cx,
792 cx.require_trait_lang_item(SolverTraitLangItem::Copy),
793 [ty],
794 ),
795 ),
796 )?;
797 }
798
799 ty::Bound(..)
800 | ty::Infer(
801 ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
802 ) => {
803 { ::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`", ty)); }panic!("unexpected type `{ty:?}`")
804 }
805 }
806
807 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
808 })
809 }
810
811 fn consider_structural_builtin_unsize_candidates(
819 ecx: &mut EvalCtxt<'_, D>,
820 goal: Goal<I, Self>,
821 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
822 if goal.predicate.polarity != ty::ClausePolarity::Positive {
823 return Ok(::alloc::vec::Vec::new()vec![]);
824 }
825
826 let result = ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(
827 |ecx| -> Result<Vec<Candidate<I>>, NoSolutionOrRerunNonErased> {
828 let a_ty = goal.predicate.self_ty();
829 let b_ty = ecx.structurally_normalize_ty(
832 goal.param_env,
833 goal.predicate.trait_ref.args.type_at(1),
834 )?;
835
836 let goal = goal.with(ecx.cx(), (a_ty, b_ty));
837 match (a_ty.kind(), b_ty.kind()) {
838 (ty::Infer(ty::TyVar(..)), ..) => {
::core::panicking::panic_fmt(format_args!("unexpected infer {0:?} {1:?}",
a_ty, b_ty));
}panic!("unexpected infer {a_ty:?} {b_ty:?}"),
839
840 (_, ty::Infer(ty::TyVar(..))) => {
841 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS)?]))vec![ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS)?])
842 }
843
844 (ty::Dynamic(a_data, a_region), ty::Dynamic(b_data, b_region)) => Ok(ecx
846 .consider_builtin_dyn_upcast_candidates(
847 goal, a_data, a_region, b_data, b_region,
848 )),
849
850 (_, ty::Dynamic(b_region, b_data)) => Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region,
b_data)?]))vec![
852 ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data)?,
853 ]),
854
855 (ty::Array(a_elem_ty, ..), ty::Slice(b_elem_ty)) => {
857 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty)?]))vec![ecx.consider_builtin_array_unsize(goal, a_elem_ty, b_elem_ty)?])
858 }
859
860 (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args))
862 if a_def.is_struct() && a_def == b_def =>
863 {
864 Ok(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args)?]))vec![ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args)?])
865 }
866
867 _ => Err(NoSolution.into()),
868 }
869 },
870 );
871
872 match result.map_err_to_rerun()? {
873 Ok(resp) => Ok(resp),
874 Err(NoSolution) => Ok(::alloc::vec::Vec::new()vec![]),
875 }
876 }
877
878 fn consider_builtin_try_as_dyn_candidate(
879 ecx: &mut EvalCtxt<'_, D>,
880 goal: Goal<I, Self>,
881 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
882 if goal.predicate.polarity != ty::ClausePolarity::Positive {
883 return Err(NoSolution.into());
884 }
885 let cx = ecx.cx();
886
887 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
888 let self_ty = goal.predicate.self_ty();
889 let ty_lifetime = goal.predicate.trait_ref.args.region_at(1);
890 match self_ty.kind() {
891 ty::Dynamic(bounds, lifetime) => {
892 for bound in bounds.iter() {
893 match bound.skip_binder() {
894 ExistentialPredicate::Trait(_) => {}
895 ExistentialPredicate::Projection(_) => return Err(NoSolution.into()),
897 ExistentialPredicate::AutoTrait(_) => {}
900 }
901 }
902 ecx.add_goal(
903 GoalSource::Misc,
904 goal.with(cx, ty::OutlivesClause(ty_lifetime, lifetime)),
905 )?;
906 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
907 }
908
909 ty::Bound(..)
910 | ty::Infer(
911 ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
912 ) => {
913 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
914 }
915
916 _ => Err(NoSolution.into()),
917 }
918 })
919 }
920
921 fn consider_builtin_field_candidate(
922 ecx: &mut EvalCtxt<'_, D>,
923 goal: Goal<I, Self>,
924 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
925 if goal.predicate.polarity != ty::ClausePolarity::Positive {
926 return Err(NoSolution.into());
927 }
928
929 let ty::Adt(def, args) = goal.predicate.self_ty().kind() else {
930 return Err(NoSolution.into());
931 };
932
933 let Some(FieldInfo { base, ty, .. }) = def.field_representing_type_info(ecx.cx(), args)
934 else {
935 return Err(NoSolution.into());
936 };
937
938 match base.kind() {
939 ty::Adt(def, _) if def.is_struct() && !def.is_packed() => {}
940 ty::Adt(..) => return Err(NoSolution.into()),
941 ty::Tuple(..) => {}
942 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
943 }
944
945 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
946 let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized);
947
948 ecx.add_goal(
956 GoalSource::ImplWhereBound,
957 Goal {
958 param_env: goal.param_env,
959 predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()),
960 },
961 )?;
962 ecx.add_goal(
963 GoalSource::ImplWhereBound,
964 Goal {
965 param_env: goal.param_env,
966 predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()),
967 },
968 )?;
969
970 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
971 })
972 }
973}
974
975#[inline(always)]
981fn trait_predicate_with_def_id<I: Interner>(
982 cx: I,
983 clause: ty::Binder<I, ty::TraitClause<I>>,
984 did: I::TraitId,
985) -> I::Clause {
986 clause
987 .map_bound(|c| TraitClause {
988 trait_ref: TraitRef::new_from_args(cx, did, c.trait_ref.args),
989 polarity: c.polarity,
990 })
991 .upcast(cx)
992}
993
994impl<D, I> EvalCtxt<'_, D>
995where
996 D: SolverDelegate<Interner = I>,
997 I: Interner,
998{
999 fn consider_builtin_dyn_upcast_candidates(
1009 &mut self,
1010 goal: Goal<I, (I::Ty, I::Ty)>,
1011 a_data: I::BoundExistentialPredicates,
1012 a_region: Region<I>,
1013 b_data: I::BoundExistentialPredicates,
1014 b_region: Region<I>,
1015 ) -> Vec<Candidate<I>> {
1016 let cx = self.cx();
1017 let Goal { predicate: (a_ty, _b_ty), .. } = goal;
1018
1019 let mut responses = ::alloc::vec::Vec::new()vec![];
1020 let b_principal_def_id = b_data.principal_def_id();
1023 if a_data.principal_def_id() == b_principal_def_id || b_principal_def_id.is_none() {
1024 responses.extend(self.consider_builtin_upcast_to_principal(
1025 goal,
1026 CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
1027 a_data,
1028 a_region,
1029 b_data,
1030 b_region,
1031 a_data.principal(),
1032 ));
1033 } else if let Some(a_principal) = a_data.principal() {
1034 for (idx, new_a_principal) in
1035 elaborate::supertraits(self.cx(), a_principal.with_self_ty(cx, a_ty))
1036 .enumerate()
1037 .skip(1)
1038 {
1039 responses.extend(self.consider_builtin_upcast_to_principal(
1040 goal,
1041 CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting(idx)),
1042 a_data,
1043 a_region,
1044 b_data,
1045 b_region,
1046 Some(new_a_principal.map_bound(|trait_ref| {
1047 ty::ExistentialTraitRef::erase_self_ty(cx, trait_ref)
1048 })),
1049 ));
1050 }
1051 }
1052
1053 responses
1054 }
1055
1056 fn consider_builtin_unsize_to_dyn_candidate(
1057 &mut self,
1058 goal: Goal<I, (I::Ty, I::Ty)>,
1059 b_data: I::BoundExistentialPredicates,
1060 b_region: Region<I>,
1061 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1062 let cx = self.cx();
1063 let Goal { predicate: (a_ty, _), .. } = goal;
1064
1065 if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
1067 return Err(NoSolution.into());
1068 }
1069
1070 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1071 ecx.add_goals(
1074 GoalSource::ImplWhereBound,
1075 b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))),
1076 )?;
1077
1078 ecx.add_goal(
1080 GoalSource::ImplWhereBound,
1081 goal.with(
1082 cx,
1083 ty::TraitRef::new(
1084 cx,
1085 cx.require_trait_lang_item(SolverTraitLangItem::Sized),
1086 [a_ty],
1087 ),
1088 ),
1089 )?;
1090
1091 ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesClause(a_ty, b_region)))?;
1093 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1094 })
1095 }
1096
1097 fn consider_builtin_upcast_to_principal(
1098 &mut self,
1099 goal: Goal<I, (I::Ty, I::Ty)>,
1100 source: CandidateSource<I>,
1101 a_data: I::BoundExistentialPredicates,
1102 a_region: Region<I>,
1103 b_data: I::BoundExistentialPredicates,
1104 b_region: Region<I>,
1105 upcast_principal: Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>,
1106 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1107 let param_env = goal.param_env;
1108
1109 let a_auto_traits: IndexSet<I::TraitId> = a_data
1113 .auto_traits()
1114 .into_iter()
1115 .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| {
1116 self.cx()
1117 .supertrait_def_ids(principal_def_id)
1118 .filter(|def_id| self.cx().trait_is_auto(*def_id))
1119 }))
1120 .collect();
1121
1122 let projection_may_match =
1127 |ecx: &mut EvalCtxt<'_, D>,
1128 source_projection: ty::Binder<I, ty::ExistentialProjection<I>>,
1129 target_projection: ty::Binder<I, ty::ExistentialProjection<I>>|
1130 -> Result<bool, RerunNonErased> {
1131 if source_projection.item_def_id() != target_projection.item_def_id() {
1132 return Ok(false);
1133 }
1134 match ecx.probe(|_| ProbeKind::ProjectionCompatibility).enter(|ecx| {
1135 let target_projection = ecx.deeply_resolve_ignoring_regions(target_projection);
1136 ecx.enter_forall_with_assumptions(
1137 target_projection,
1138 param_env,
1139 |ecx, target_projection| {
1140 let source_projection =
1141 ecx.instantiate_binder_with_infer(source_projection);
1142 ecx.eq(param_env, source_projection, target_projection)?;
1143 ecx.try_evaluate_added_goals()
1144 },
1145 )
1146 }) {
1147 Ok(_) => Ok(true),
1148 Err(NoSolutionOrRerunNonErased::NoSolution(_)) => Ok(false),
1149 Err(NoSolutionOrRerunNonErased::RerunNonErased(rerun)) => Err(rerun),
1150 }
1151 };
1152
1153 self.probe_trait_candidate(source).enter(|ecx| {
1154 for bound in b_data.iter() {
1155 match bound.skip_binder() {
1156 ty::ExistentialPredicate::Trait(target_principal) => {
1159 let source_principal = upcast_principal.unwrap();
1160 let target_principal = bound.rebind(target_principal);
1161 let target_principal =
1163 ecx.deeply_resolve_ignoring_regions(target_principal);
1164 ecx.enter_forall_with_assumptions(
1165 target_principal,
1166 param_env,
1167 |ecx, target_principal| {
1168 let source_principal =
1169 ecx.instantiate_binder_with_infer(source_principal);
1170 ecx.eq(param_env, source_principal, target_principal)?;
1171 ecx.try_evaluate_added_goals()
1172 },
1173 )?;
1174 }
1175 ty::ExistentialPredicate::Projection(target_projection) => {
1181 let target_projection = bound.rebind(target_projection);
1182 let mut matching_projection = None;
1183 for source_projection in a_data.projection_bounds() {
1184 if projection_may_match(ecx, source_projection, target_projection)? {
1185 if matching_projection.is_some() {
1186 return ecx.evaluate_added_goals_and_make_canonical_response(
1187 Certainty::AMBIGUOUS,
1188 );
1189 }
1190 matching_projection = Some(source_projection);
1191 }
1192 }
1193 let Some(matching) = matching_projection else {
1194 return Err(NoSolution.into());
1195 };
1196
1197 let target_projection =
1199 ecx.deeply_resolve_ignoring_regions(target_projection);
1200 ecx.enter_forall_with_assumptions(
1201 target_projection,
1202 param_env,
1203 |ecx, target_projection| {
1204 let source_projection = ecx.instantiate_binder_with_infer(matching);
1205 ecx.eq(param_env, source_projection, target_projection)?;
1206 ecx.try_evaluate_added_goals()
1207 },
1208 )?;
1209 }
1210 ty::ExistentialPredicate::AutoTrait(def_id) => {
1212 if !a_auto_traits.contains(&def_id) {
1213 return Err(NoSolution.into());
1214 }
1215 }
1216 }
1217 }
1218
1219 ecx.add_goal(
1221 GoalSource::ImplWhereBound,
1222 Goal::new(ecx.cx(), param_env, ty::OutlivesClause(a_region, b_region)),
1223 )?;
1224
1225 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1226 })
1227 }
1228
1229 fn consider_builtin_array_unsize(
1238 &mut self,
1239 goal: Goal<I, (I::Ty, I::Ty)>,
1240 a_elem_ty: I::Ty,
1241 b_elem_ty: I::Ty,
1242 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1243 self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
1244 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1245 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1246 }
1247
1248 fn consider_builtin_struct_unsize(
1262 &mut self,
1263 goal: Goal<I, (I::Ty, I::Ty)>,
1264 def: I::AdtDef,
1265 a_args: I::GenericArgs,
1266 b_args: I::GenericArgs,
1267 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1268 let cx = self.cx();
1269 let Goal { predicate: (_a_ty, b_ty), .. } = goal;
1270
1271 let unsizing_params = cx.unsizing_params_for_adt(def.def_id());
1272 if unsizing_params.is_empty() {
1275 return Err(NoSolution.into());
1276 }
1277
1278 let tail_field_ty = def.struct_tail_ty(cx).unwrap();
1279
1280 let a_tail_ty = tail_field_ty.instantiate(cx, a_args).skip_norm_wip();
1281 let b_tail_ty = tail_field_ty.instantiate(cx, b_args).skip_norm_wip();
1282
1283 let new_a_args = cx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| {
1287 if unsizing_params.contains(i as u32) { b_args.get(i).unwrap() } else { a }
1288 }));
1289 let unsized_a_ty = Ty::new_adt(cx, def, new_a_args);
1290
1291 self.eq(goal.param_env, unsized_a_ty, b_ty)?;
1294 self.add_goal(
1295 GoalSource::ImplWhereBound,
1296 goal.with(
1297 cx,
1298 ty::TraitRef::new(
1299 cx,
1300 cx.require_trait_lang_item(SolverTraitLangItem::Unsize),
1301 [a_tail_ty, b_tail_ty],
1302 ),
1303 ),
1304 )?;
1305 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
1306 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1307 }
1308
1309 fn consider_auto_trait_candidate_for_opaque_ty(
1310 &mut self,
1311 goal: Goal<I, TraitClause<I>>,
1312 def_id: I::OpaqueTyId,
1313 args: I::GenericArgs,
1314 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1315 let cx = self.cx();
1316 let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc);
1317
1318 for item_bound in cx.item_self_bounds(def_id.into()).skip_binder() {
1319 if item_bound.as_trait_clause().is_some_and(|b| b.def_id() == goal.predicate.def_id()) {
1320 return Err(NoSolution.into());
1321 }
1322 }
1323
1324 let candidate = self.probe_trait_candidate(source).enter(|ecx| {
1325 let hidden_ty = cx.type_of(def_id.into()).instantiate(cx, args).skip_norm_wip();
1326 ecx.add_goal(
1327 GoalSource::ImplWhereBound,
1328 goal.with(cx, goal.predicate.with_replaced_self_ty(cx, hidden_ty)),
1329 )?;
1330 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1331 })?;
1332
1333 if !candidate.result.value.is_identity_modulo_regions() {
1336 return self.forced_ambiguity(MaybeInfo::AMBIGUOUS);
1337 }
1338
1339 let ExternalConstraintsData {
1340 region_constraints: _,
1341 ref opaque_types,
1342 ref normalization_nested_goals,
1343 } = *candidate.result.value.external_constraints;
1344 if true {
if !normalization_nested_goals.is_empty() {
::core::panicking::panic("assertion failed: normalization_nested_goals.is_empty()")
};
};debug_assert!(normalization_nested_goals.is_empty());
1345
1346 if !opaque_types.is_empty() {
1351 let typing_mode = self.typing_mode();
1352
1353 match typing_mode {
1354 TypingMode::PostTypeckUntilBorrowck { .. } => {}
1358 TypingMode::Typeck { .. } => {
1361 return self.forced_ambiguity(MaybeInfo::AMBIGUOUS);
1362 }
1363 TypingMode::Coherence
1365 | TypingMode::PostBorrowck { .. }
1366 | TypingMode::Reflection
1367 | TypingMode::PostAnalysis
1368 | TypingMode::Codegen
1369 | TypingMode::ErasedNotCoherence(MayBeErased) => {
1370 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("we never add new uses to opaque types in typing mode {0:?}",
typing_mode)));
};unreachable!(
1371 "we never add new uses to opaque types in typing mode {typing_mode:?}"
1372 );
1373 }
1374 }
1375 }
1376
1377 Ok(candidate)
1378 }
1379
1380 fn disqualify_auto_trait_candidate_due_to_possible_impl(
1385 &mut self,
1386 goal: Goal<I, TraitClause<I>>,
1387 ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1388 let self_ty = goal.predicate.self_ty();
1389 let check_impls = || {
1390 let mut disqualifying_impl = None;
1391 self.cx().for_each_relevant_impl(goal.predicate.trait_ref, |impl_def_id| {
1392 disqualifying_impl = Some(impl_def_id);
1393 });
1394 if let Some(def_id) = disqualifying_impl {
1395 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs:1395",
"rustc_next_trait_solver::solve::trait_goals",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
::tracing_core::__macro_support::Option::Some(1395u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("goal")
}> =
::tracing::__macro_support::FieldName::new("goal");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("disqualified auto-trait implementation")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};trace!(?def_id, ?goal, "disqualified auto-trait implementation");
1396 return Some(Err(NoSolution.into()));
1399 } else {
1400 None
1401 }
1402 };
1403
1404 match self_ty.kind() {
1405 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
1411 Some(self.forced_ambiguity(MaybeInfo::AMBIGUOUS))
1412 }
1413
1414 ty::Foreign(..) if self.cx().is_default_trait(goal.predicate.def_id()) => check_impls(),
1417
1418 ty::Dynamic(..)
1421 | ty::Param(..)
1422 | ty::Foreign(..)
1423 | ty::Alias(
1424 ty::IsRigid::Yes,
1425 ty::AliasTy {
1426 kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. },
1427 ..
1428 },
1429 )
1430 | ty::Placeholder(..) => Some(Err(NoSolution.into())),
1431
1432 ty::Coroutine(def_id, _)
1436 if self
1437 .cx()
1438 .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
1439 {
1440 match self.cx().coroutine_movability(def_id) {
1441 Movability::Static => Some(Err(NoSolution.into())),
1442 Movability::Movable => Some(
1443 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
1444 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1445 }),
1446 ),
1447 }
1448 }
1449
1450 ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => None,
1455
1456 ty::Bool
1463 | ty::Char
1464 | ty::Int(_)
1465 | ty::Uint(_)
1466 | ty::Float(_)
1467 | ty::Str
1468 | ty::Array(_, _)
1469 | ty::Pat(_, _)
1470 | ty::Slice(_)
1471 | ty::RawPtr(_, _)
1472 | ty::Ref(_, _, _)
1473 | ty::FnDef(_, _)
1474 | ty::FnPtr(..)
1475 | ty::Closure(..)
1476 | ty::CoroutineClosure(..)
1477 | ty::Coroutine(_, _)
1478 | ty::CoroutineWitness(..)
1479 | ty::Never
1480 | ty::Tuple(_)
1481 | ty::Adt(_, _)
1482 | ty::UnsafeBinder(_) => check_impls(),
1483 ty::Error(_) => None,
1484
1485 ty::Infer(_) | ty::Alias(ty::IsRigid::No, _) | ty::Bound(_, _) => {
1486 {
::core::panicking::panic_fmt(format_args!("unexpected type `{0:?}`",
self_ty));
}panic!("unexpected type `{self_ty:?}`")
1487 }
1488 }
1489 }
1490
1491 fn probe_and_evaluate_goal_for_constituent_tys(
1496 &mut self,
1497 source: CandidateSource<I>,
1498 goal: Goal<I, TraitClause<I>>,
1499 constituent_tys: impl Fn(
1500 &EvalCtxt<'_, D>,
1501 I::Ty,
1502 ) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
1503 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
1504 self.probe_trait_candidate(source).enter(|ecx| {
1505 let goals = ecx.enter_forall_with_assumptions(
1506 constituent_tys(ecx, goal.predicate.self_ty())?,
1507 goal.param_env,
1508 |ecx, tys| {
1509 tys.into_iter()
1510 .map(|ty| {
1511 goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty))
1512 })
1513 .collect::<Vec<_>>()
1514 },
1515 );
1516 ecx.add_goals(GoalSource::ImplWhereBound, goals)?;
1517 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1518 })
1519 }
1520}
1521
1522#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TraitGoalProvenVia {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
TraitGoalProvenVia::Misc => "Misc",
TraitGoalProvenVia::ParamEnv => "ParamEnv",
TraitGoalProvenVia::AliasBound => "AliasBound",
})
}
}Debug, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TraitGoalProvenVia { }
#[automatically_derived]
impl ::core::clone::Clone for TraitGoalProvenVia {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for TraitGoalProvenVia { }Copy)]
1533pub(super) enum TraitGoalProvenVia {
1534 Misc,
1540 ParamEnv,
1541 AliasBound,
1542}
1543
1544impl<D, I> EvalCtxt<'_, D>
1545where
1546 D: SolverDelegate<Interner = I>,
1547 I: Interner,
1548{
1549 pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Candidate<I>>) {
1562 if self.typing_mode().is_coherence() {
1563 return;
1564 }
1565
1566 if candidates
1567 .iter()
1568 .find(|c| {
1569 #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)) => true,
_ => false,
}matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)))
1570 })
1571 .is_some_and(|c| has_only_region_constraints(c.result))
1572 {
1573 candidates.retain(|c| {
1574 if #[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::Impl(_) => true,
_ => false,
}matches!(c.source, CandidateSource::Impl(_)) {
1575 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs:1575",
"rustc_next_trait_solver::solve::trait_goals",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
::tracing_core::__macro_support::Option::Some(1575u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("c")
}> =
::tracing::__macro_support::FieldName::new("c");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("unsoundly dropping impl in favor of builtin dyn-candidate")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&c)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?c, "unsoundly dropping impl in favor of builtin dyn-candidate");
1576 false
1577 } else {
1578 true
1579 }
1580 });
1581 }
1582 }
1583
1584 {}
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("try_merge_impl_candidates",
"rustc_next_trait_solver::solve::trait_goals",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
::tracing_core::__macro_support::Option::Some(1591u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("trait_def_id")
}> =
::tracing::__macro_support::FieldName::new("trait_def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("candidates")
}> =
::tracing::__macro_support::FieldName::new("candidates");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&candidates)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[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:
Option<CanonicalResponse<I>> = loop {};
return __tracing_attr_fake_return;
}
{
let is_marker = self.cx().trait_is_marker(trait_def_id);
let all_builtin =
candidates.iter().all(|candidate|
#[allow(non_exhaustive_omitted_patterns)] match candidate.source
{
CandidateSource::BuiltinImpl(_) => true,
_ => false,
});
if is_marker || all_builtin {
self.try_merge_candidates(candidates).map(|(response, _)|
response)
} else if candidates.len() > 1 {
None
} else {
candidates.first().map(|candidate| candidate.result)
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs:1591",
"rustc_next_trait_solver::solve::trait_goals",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
::tracing_core::__macro_support::Option::Some(1591u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x;#[instrument(level = "trace", skip(self), ret)]
1592 fn try_merge_impl_candidates(
1593 &mut self,
1594 trait_def_id: I::TraitId,
1595 candidates: &[Candidate<I>],
1596 ) -> Option<CanonicalResponse<I>> {
1597 let is_marker = self.cx().trait_is_marker(trait_def_id);
1598 let all_builtin = candidates
1599 .iter()
1600 .all(|candidate| matches!(candidate.source, CandidateSource::BuiltinImpl(_)));
1601
1602 if is_marker || all_builtin {
1603 self.try_merge_candidates(candidates).map(|(response, _)| response)
1604 } else if candidates.len() > 1 {
1605 None
1606 } else {
1607 candidates.first().map(|candidate| candidate.result)
1608 }
1609 }
1610
1611 fn merge_candidates_or_bail_with_ambiguity(
1612 &mut self,
1613 candidates: &[Candidate<I>],
1614 proven_via: TraitGoalProvenVia,
1615 ) -> (CanonicalResponse<I>, Option<TraitGoalProvenVia>) {
1616 if let Some((response, _)) = self.try_merge_candidates(candidates) {
1617 (response, Some(proven_via))
1618 } else {
1619 (self.bail_with_ambiguity(candidates), None)
1620 }
1621 }
1622
1623 fn merge_impl_candidates_or_bail_with_ambiguity(
1624 &mut self,
1625 trait_def_id: I::TraitId,
1626 candidates: &[Candidate<I>],
1627 ) -> (CanonicalResponse<I>, Option<TraitGoalProvenVia>) {
1628 if true {
if !candidates.iter().all(|c|
#[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::Impl(_) | CandidateSource::BuiltinImpl(_)
=> true,
_ => false,
}) {
::core::panicking::panic("assertion failed: candidates.iter().all(|c|\n matches!(c.source, CandidateSource::Impl(_) |\n CandidateSource::BuiltinImpl(_)))")
};
};debug_assert!(candidates.iter().all(|c| matches!(
1629 c.source,
1630 CandidateSource::Impl(_) | CandidateSource::BuiltinImpl(_)
1631 )));
1632 match self.try_merge_impl_candidates(trait_def_id, candidates) {
1633 Some(response) => (response, Some(TraitGoalProvenVia::Misc)),
1634 None => (self.bail_with_ambiguity(candidates), None),
1635 }
1636 }
1637
1638 {}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::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("merge_trait_candidates",
"rustc_next_trait_solver::solve::trait_goals",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
::tracing_core::__macro_support::Option::Some(1638u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("trait_def_id")
}> =
::tracing::__macro_support::FieldName::new("trait_def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("candidates")
}> =
::tracing::__macro_support::FieldName::new("candidates");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("failed_candidate_info")
}> =
::tracing::__macro_support::FieldName::new("failed_candidate_info");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&candidates)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&failed_candidate_info)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[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:
Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>),
NoSolution> = loop {};
return __tracing_attr_fake_return;
}
{
if candidates.is_empty() { return Err(NoSolution); }
let candidate_preference_mode =
CandidatePreferenceMode::compute(self.cx(), trait_def_id);
if self.typing_mode().is_coherence() {
return Ok(match self.try_merge_impl_candidates(trait_def_id,
&candidates) {
Some(response) =>
(response, Some(TraitGoalProvenVia::Misc)),
None => (self.bail_with_ambiguity(&candidates), None),
});
}
let mut trivial_builtin_impls =
candidates.iter().filter(|c|
{
#[allow(non_exhaustive_omitted_patterns)]
match c.source {
CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial) =>
true,
_ => false,
}
});
if let Some(candidate) = trivial_builtin_impls.next() {
if !trivial_builtin_impls.next().is_none() {
::core::panicking::panic("assertion failed: trivial_builtin_impls.next().is_none()")
};
return Ok((candidate.result,
Some(TraitGoalProvenVia::Misc)));
}
if #[allow(non_exhaustive_omitted_patterns)] match candidate_preference_mode
{
CandidatePreferenceMode::Marker => true,
_ => false,
} &&
candidates.iter().any(|c|
{
#[allow(non_exhaustive_omitted_patterns)]
match c.source {
CandidateSource::AliasBound(AliasBoundKind::SelfBounds) =>
true,
_ => false,
}
}) {
let alias_bounds: Vec<_> =
candidates.extract_if(..,
|c|
#[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::AliasBound(..) => true,
_ => false,
}).collect();
return Ok(self.merge_candidates_or_bail_with_ambiguity(&alias_bounds,
TraitGoalProvenVia::AliasBound));
}
let has_non_global_where_bounds =
candidates.iter().any(|c|
#[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::ParamEnv(ParamEnvSource::NonGlobal) =>
true,
_ => false,
});
if has_non_global_where_bounds {
let where_bounds: Vec<_> =
candidates.extract_if(..,
|c|
#[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::ParamEnv(_) => true,
_ => false,
}).collect();
let Some((response, info)) =
self.try_merge_candidates(&where_bounds) else {
return Ok((self.bail_with_ambiguity(&where_bounds), None));
};
match info {
MergeCandidateInfo::AlwaysApplicable(i) => {
for (j, c) in where_bounds.into_iter().enumerate() {
if i != j {
self.ignore_candidate_head_usages(c.head_usages)
}
}
self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
}
MergeCandidateInfo::EqualResponse => {}
}
return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
}
if candidates.iter().any(|c|
#[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::AliasBound(_) => true,
_ => false,
}) {
let alias_bounds: Vec<_> =
candidates.extract_if(..,
|c|
#[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::AliasBound(_) => true,
_ => false,
}).collect();
return Ok(self.merge_candidates_or_bail_with_ambiguity(&alias_bounds,
TraitGoalProvenVia::AliasBound));
}
self.filter_specialized_impls(AllowInferenceConstraints::No,
&mut candidates);
self.unsound_prefer_builtin_dyn_impl(&mut candidates);
let only_global_where_bounds =
candidates.iter().all(|c|
#[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::ParamEnv(ParamEnvSource::Global) => true,
_ => false,
});
if only_global_where_bounds {
Ok(self.merge_candidates_or_bail_with_ambiguity(&candidates,
TraitGoalProvenVia::ParamEnv))
} else {
candidates.retain(|c|
!#[allow(non_exhaustive_omitted_patterns)] match c.source {
CandidateSource::ParamEnv(ParamEnvSource::Global) => true,
_ => false,
});
Ok(self.merge_impl_candidates_or_bail_with_ambiguity(trait_def_id,
&candidates))
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs:1638",
"rustc_next_trait_solver::solve::trait_goals",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
::tracing_core::__macro_support::Option::Some(1638u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x;#[instrument(level = "debug", skip(self), ret)]
1639 pub(super) fn merge_trait_candidates(
1640 &mut self,
1641 trait_def_id: I::TraitId,
1642 mut candidates: Vec<Candidate<I>>,
1643 failed_candidate_info: FailedCandidateInfo,
1644 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1645 if candidates.is_empty() {
1646 return Err(NoSolution);
1647 }
1648
1649 let candidate_preference_mode = CandidatePreferenceMode::compute(self.cx(), trait_def_id);
1650 if self.typing_mode().is_coherence() {
1651 return Ok(match self.try_merge_impl_candidates(trait_def_id, &candidates) {
1652 Some(response) => (response, Some(TraitGoalProvenVia::Misc)),
1653 None => (self.bail_with_ambiguity(&candidates), None),
1654 });
1655 }
1656
1657 let mut trivial_builtin_impls = candidates.iter().filter(|c| {
1662 matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))
1663 });
1664 if let Some(candidate) = trivial_builtin_impls.next() {
1665 assert!(trivial_builtin_impls.next().is_none());
1668 return Ok((candidate.result, Some(TraitGoalProvenVia::Misc)));
1669 }
1670
1671 if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker)
1674 && candidates.iter().any(|c| {
1675 matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds))
1676 })
1677 {
1678 let alias_bounds: Vec<_> = candidates
1679 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..)))
1680 .collect();
1681 return Ok(self.merge_candidates_or_bail_with_ambiguity(
1682 &alias_bounds,
1683 TraitGoalProvenVia::AliasBound,
1684 ));
1685 }
1686
1687 let has_non_global_where_bounds = candidates
1690 .iter()
1691 .any(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal)));
1692 if has_non_global_where_bounds {
1693 let where_bounds: Vec<_> = candidates
1694 .extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
1695 .collect();
1696 let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
1697 return Ok((self.bail_with_ambiguity(&where_bounds), None));
1698 };
1699 match info {
1700 MergeCandidateInfo::AlwaysApplicable(i) => {
1716 for (j, c) in where_bounds.into_iter().enumerate() {
1717 if i != j {
1718 self.ignore_candidate_head_usages(c.head_usages)
1719 }
1720 }
1721 self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
1725 }
1726 MergeCandidateInfo::EqualResponse => {}
1727 }
1728 return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
1729 }
1730
1731 if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) {
1733 let alias_bounds: Vec<_> = candidates
1734 .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_)))
1735 .collect();
1736 return Ok(self.merge_candidates_or_bail_with_ambiguity(
1737 &alias_bounds,
1738 TraitGoalProvenVia::AliasBound,
1739 ));
1740 }
1741
1742 self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
1743 self.unsound_prefer_builtin_dyn_impl(&mut candidates);
1744
1745 let only_global_where_bounds = candidates
1750 .iter()
1751 .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)));
1752 if only_global_where_bounds {
1753 Ok(self
1754 .merge_candidates_or_bail_with_ambiguity(&candidates, TraitGoalProvenVia::ParamEnv))
1755 } else {
1756 candidates
1757 .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global)));
1758 Ok(self.merge_impl_candidates_or_bail_with_ambiguity(trait_def_id, &candidates))
1759 }
1760 }
1761
1762 {}
#[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_trait_goal",
"rustc_next_trait_solver::solve::trait_goals",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/b6eeb93c992027a03e1fd120b6652546396b142c/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs"),
::tracing_core::__macro_support::Option::Some(1762u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::solve::trait_goals"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("goal")
}> =
::tracing::__macro_support::FieldName::new("goal");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&goal)
as &dyn ::tracing::field::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:
Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>),
NoSolutionOrRerunNonErased> = loop {};
return __tracing_attr_fake_return;
}
{
let (candidates, failed_candidate_info) =
self.assemble_and_evaluate_candidates(goal,
AssembleCandidatesFrom::All)?;
self.merge_trait_candidates(goal.predicate.def_id(), candidates,
failed_candidate_info).map_err(Into::into)
}
}
}#[instrument(level = "trace", skip(self))]
1763 pub(super) fn compute_trait_goal(
1764 &mut self,
1765 goal: Goal<I, TraitClause<I>>,
1766 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolutionOrRerunNonErased>
1767 {
1768 let (candidates, failed_candidate_info) =
1769 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All)?;
1770 self.merge_trait_candidates(goal.predicate.def_id(), candidates, failed_candidate_info)
1771 .map_err(Into::into)
1772 }
1773
1774 fn try_stall_coroutine(
1775 &mut self,
1776 self_ty: I::Ty,
1777 ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
1778 if let ty::Coroutine(def_id, _) = self_ty.kind() {
1779 match self.typing_mode() {
1780 TypingMode::Typeck { defining_opaque_types_and_generators: stalled_generators } => {
1781 if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
1782 {
1783 return Some(self.forced_ambiguity(MaybeInfo {
1784 cause: MaybeCause::Ambiguity,
1785 opaque_types_jank: OpaqueTypesJank::AllGood,
1786 stalled_on_coroutines: StalledOnCoroutines::Yes,
1787 }));
1788 }
1789 }
1790 TypingMode::ErasedNotCoherence(MayBeErased) => {
1791 return Some(
1793 match self.opaque_accesses.rerun_always(RerunReason::TryStallCoroutine) {
1794 Err(e) => Err(e.into()),
1795 },
1796 );
1797 }
1798 TypingMode::Coherence
1799 | TypingMode::PostAnalysis
1800 | TypingMode::Reflection
1801 | TypingMode::Codegen
1802 | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ }
1803 | TypingMode::PostBorrowck { defined_opaque_types: _ } => {}
1804 }
1805 }
1806
1807 None
1808 }
1809}