authorbors <bors@rust-lang.org> 2026-05-08 14:56:56 UTC
committerbors <bors@rust-lang.org> 2026-05-08 14:56:56 UTC
log8068e2fc9afa8c888336b12db01987be768785f9
tree32d63ab35a6b7818f9e08e2cc5c21ac5c5d38d25
parentf2b291d902bfde7d7f209fc3a64908134bcef201
parent01cccf92dca30d28746597f6f06e6af2f832ba92

Auto merge of #156324 - JonathanBrouwer:rollup-HKA8242, r=JonathanBrouwer

Rollup of 4 pull requests Successful merges: - rust-lang/rust#156246 (Introduce a `RerunNonErased` error type mirroring `NoSolution`, to better track when we're bailing) - rust-lang/rust#156038 (turn `compute_goal_fast_path` into a single match) - rust-lang/rust#156291 (Treat MSVC "performing full link" message as informational) - rust-lang/rust#156301 (Avoid ICE when suggesting as_ref for ill-typed closure receivers)

28 files changed, 879 insertions(+), 518 deletions(-)

compiler/rustc_ast_ir/src/visit.rs+23
......@@ -41,6 +41,29 @@ impl<T> VisitorResult for ControlFlow<T> {
4141 }
4242}
4343
44impl<E> VisitorResult for Result<(), E> {
45 type Residual = E;
46
47 fn output() -> Self {
48 Ok(())
49 }
50 fn from_residual(residual: Self::Residual) -> Self {
51 Err(residual)
52 }
53 fn from_branch(b: ControlFlow<Self::Residual>) -> Self {
54 match b {
55 ControlFlow::Continue(()) => Ok(()),
56 ControlFlow::Break(e) => Err(e),
57 }
58 }
59 fn branch(self) -> ControlFlow<Self::Residual> {
60 match self {
61 Ok(()) => ControlFlow::Continue(()),
62 Err(e) => ControlFlow::Break(e),
63 }
64 }
65}
66
4467#[macro_export]
4568macro_rules! try_visit {
4669 ($e:expr) => {
compiler/rustc_codegen_ssa/src/back/link.rs+5
......@@ -754,10 +754,15 @@ fn report_linker_output(sess: &Session, levels: CodegenLintLevels, stdout: &[u8]
754754 escaped_stdout = for_each(&stdout, |line, output| {
755755 // Hide some progress messages from link.exe that we don't care about.
756756 // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146
757 // When incremental linking is enabled and an .ilk exists, but its associated .exe is
758 // missing, link.exe prints the path of the missing .exe followed by:
759 let ilk_but_no_exe =
760 "not found or not built by the last incremental link; performing full link";
757761 let trimmed = line.trim_start();
758762 if trimmed.starts_with("Creating library")
759763 || trimmed.starts_with("Generating code")
760764 || trimmed.starts_with("Finished generating code")
765 || trimmed.ends_with(ilk_but_no_exe)
761766 {
762767 linker_info += line;
763768 linker_info += "\r\n";
compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs+1-1
......@@ -2787,7 +2787,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27872787 return None;
27882788 };
27892789
2790 let self_ty = self.typeck_results.borrow().expr_ty(receiver);
2790 let self_ty = self.typeck_results.borrow().expr_ty_opt(receiver)?;
27912791 let name = method_path.ident.name;
27922792 let is_as_ref_able = match self_ty.peel_refs().kind() {
27932793 ty::Adt(def, _) => {
compiler/rustc_middle/src/ty/context/impl_interner.rs+33-10
......@@ -1,5 +1,6 @@
11//! Implementation of [`rustc_type_ir::Interner`] for [`TyCtxt`].
22
3use std::ops::ControlFlow;
34use std::{debug_assert_matches, fmt};
45
56use rustc_errors::ErrorGuaranteed;
......@@ -9,7 +10,9 @@ use rustc_hir::def_id::{DefId, LocalDefId};
910use rustc_hir::lang_items::LangItem;
1011use rustc_span::{DUMMY_SP, Span, Symbol};
1112use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem};
12use rustc_type_ir::{CollectAndApply, Interner, TypeFoldable, Unnormalized, search_graph};
13use rustc_type_ir::{
14 CollectAndApply, Interner, TypeFoldable, Unnormalized, VisitorResult, search_graph,
15};
1316
1417use crate::dep_graph::{DepKind, DepNodeIndex};
1518use crate::infer::canonical::CanonicalVarKinds;
......@@ -522,20 +525,31 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
522525 // This implementation is a bit different from `TyCtxt::for_each_relevant_impl`,
523526 // since we want to skip over blanket impls for non-rigid aliases, and also we
524527 // only want to consider types that *actually* unify with float/int vars.
525 fn for_each_relevant_impl(
528 fn for_each_relevant_impl<R: VisitorResult>(
526529 self,
527530 trait_def_id: DefId,
528531 self_ty: Ty<'tcx>,
529 mut f: impl FnMut(DefId),
530 ) {
532 mut f: impl FnMut(DefId) -> R,
533 ) -> R {
534 macro_rules! ret {
535 ($e: expr) => {
536 match $e.branch() {
537 ControlFlow::Break(b) => return R::from_residual(b),
538 ControlFlow::Continue(()) => {}
539 }
540 };
541 }
542
531543 let tcx = self;
532544 let trait_impls = tcx.trait_impls_of(trait_def_id);
533545 let mut consider_impls_for_simplified_type = |simp| {
534546 if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) {
535547 for &impl_def_id in impls_for_type {
536 f(impl_def_id);
548 ret!(f(impl_def_id))
537549 }
538550 }
551
552 R::output()
539553 };
540554
541555 match self_ty.kind() {
......@@ -566,7 +580,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
566580 self_ty,
567581 ty::fast_reject::TreatParams::AsRigid,
568582 ) {
569 consider_impls_for_simplified_type(simp);
583 ret!(consider_impls_for_simplified_type(simp));
570584 }
571585 }
572586
......@@ -595,7 +609,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
595609 ty::SimplifiedType::Uint(Usize),
596610 ];
597611 for simp in possible_integers {
598 consider_impls_for_simplified_type(simp);
612 ret!(consider_impls_for_simplified_type(simp));
599613 }
600614 }
601615
......@@ -610,7 +624,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
610624 ];
611625
612626 for simp in possible_floats {
613 consider_impls_for_simplified_type(simp);
627 ret!(consider_impls_for_simplified_type(simp));
614628 }
615629 }
616630
......@@ -634,11 +648,20 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
634648 #[allow(rustc::usage_of_type_ir_traits)]
635649 self.for_each_blanket_impl(trait_def_id, f)
636650 }
637 fn for_each_blanket_impl(self, trait_def_id: DefId, mut f: impl FnMut(DefId)) {
651 fn for_each_blanket_impl<R: VisitorResult>(
652 self,
653 trait_def_id: DefId,
654 mut f: impl FnMut(DefId) -> R,
655 ) -> R {
638656 let trait_impls = self.trait_impls_of(trait_def_id);
639657 for &impl_def_id in trait_impls.blanket_impls() {
640 f(impl_def_id);
658 match f(impl_def_id).branch() {
659 ControlFlow::Break(b) => return R::from_residual(b),
660 ControlFlow::Continue(()) => {}
661 }
641662 }
663
664 R::output()
642665 }
643666
644667 fn has_item_definition(self, def_id: DefId) -> bool {
compiler/rustc_next_trait_solver/src/solve/alias_relate.rs+3-3
......@@ -16,12 +16,12 @@
1616//! relate them structurally.
1717
1818use rustc_type_ir::inherent::*;
19use rustc_type_ir::solve::GoalSource;
19use rustc_type_ir::solve::{GoalSource, QueryResultOrRerunNonErased};
2020use rustc_type_ir::{self as ty, Interner};
2121use tracing::{instrument, trace};
2222
2323use crate::delegate::SolverDelegate;
24use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult};
24use crate::solve::{Certainty, EvalCtxt, Goal};
2525
2626impl<D, I> EvalCtxt<'_, D>
2727where
......@@ -32,7 +32,7 @@ where
3232 pub(super) fn compute_alias_relate_goal(
3333 &mut self,
3434 goal: Goal<I, (I::Term, I::Term, ty::AliasRelationDirection)>,
35 ) -> QueryResult<I> {
35 ) -> QueryResultOrRerunNonErased<I> {
3636 let cx = self.cx();
3737 let Goal { param_env, predicate: (lhs, rhs, direction) } = goal;
3838
compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs+123-92
......@@ -10,8 +10,8 @@ use rustc_type_ir::inherent::*;
1010use rustc_type_ir::lang_items::SolverTraitLangItem;
1111use rustc_type_ir::search_graph::CandidateHeadUsages;
1212use rustc_type_ir::solve::{
13 AliasBoundKind, MaybeInfo, NoSolutionOrOpaquesAccessed, RerunReason, SizedTraitKind,
14 StalledOnCoroutines,
13 AliasBoundKind, MaybeInfo, NoSolutionOrRerunNonErased, QueryResultOrRerunNonErased,
14 RerunNonErased, RerunReason, RerunResultExt, SizedTraitKind, StalledOnCoroutines,
1515};
1616use rustc_type_ir::{
1717 self as ty, AliasTy, Interner, MayBeErased, TypeFlags, TypeFoldable, TypeFolder,
......@@ -65,7 +65,7 @@ where
6565 goal: Goal<I, Self>,
6666 assumption: I::Clause,
6767 requirements: impl IntoIterator<Item = (GoalSource, Goal<I, I::Predicate>)>,
68 ) -> Result<Candidate<I>, NoSolution> {
68 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
6969 Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| {
7070 for (nested_source, goal) in requirements {
7171 ecx.add_goal(nested_source, goal);
......@@ -84,7 +84,7 @@ where
8484 source: CandidateSource<I>,
8585 goal: Goal<I, Self>,
8686 assumption: I::Clause,
87 ) -> Result<Candidate<I>, NoSolution> {
87 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
8888 Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
8989 let cx = ecx.cx();
9090 let ty::Dynamic(bounds, _) = goal.predicate.self_ty().kind() else {
......@@ -136,10 +136,10 @@ where
136136 ecx: &mut EvalCtxt<'_, D>,
137137 goal: Goal<I, Self>,
138138 assumption: I::Clause,
139 ) -> Result<Candidate<I>, CandidateHeadUsages> {
139 ) -> Result<Result<Candidate<I>, CandidateHeadUsages>, RerunNonErased> {
140140 match Self::fast_reject_assumption(ecx, goal, assumption) {
141141 Ok(()) => {}
142 Err(NoSolution) => return Err(CandidateHeadUsages::default()),
142 Err(NoSolution) => return Ok(Err(CandidateHeadUsages::default())),
143143 }
144144
145145 // Dealing with `ParamEnv` candidates is a bit of a mess as we need to lazily
......@@ -155,19 +155,25 @@ where
155155 result: *result,
156156 })
157157 .enter_single_candidate(|ecx| {
158 Self::match_assumption(ecx, goal, assumption, |ecx| {
159 ecx.try_evaluate_added_goals()?;
160 let (src, certainty) =
161 ecx.characterize_param_env_assumption(goal.param_env, assumption)?;
162 source.set(src);
163 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
164 })
158 Self::match_assumption(
159 ecx,
160 goal,
161 assumption,
162 |ecx| -> Result<_, NoSolutionOrRerunNonErased> {
163 ecx.try_evaluate_added_goals()?;
164 let (src, certainty) =
165 ecx.characterize_param_env_assumption(goal.param_env, assumption)?;
166 source.set(src);
167 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
168 },
169 )
170 .map_err(Into::into)
165171 });
166172
167 match result.map_err(Into::into) {
173 Ok(match result.map_err_to_rerun()? {
168174 Ok(result) => Ok(Candidate { source: source.get(), result, head_usages }),
169175 Err(NoSolution) => Err(head_usages),
170 }
176 })
171177 }
172178
173179 /// Try equating an assumption predicate against a goal's predicate. If it
......@@ -179,8 +185,8 @@ where
179185 source: CandidateSource<I>,
180186 goal: Goal<I, Self>,
181187 assumption: I::Clause,
182 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
183 ) -> Result<Candidate<I>, NoSolution> {
188 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
189 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
184190 Self::fast_reject_assumption(ecx, goal, assumption)?;
185191
186192 ecx.probe_trait_candidate(source)
......@@ -200,15 +206,15 @@ where
200206 ecx: &mut EvalCtxt<'_, D>,
201207 goal: Goal<I, Self>,
202208 assumption: I::Clause,
203 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
204 ) -> QueryResult<I>;
209 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
210 ) -> QueryResultOrRerunNonErased<I>;
205211
206212 fn consider_impl_candidate(
207213 ecx: &mut EvalCtxt<'_, D>,
208214 goal: Goal<I, Self>,
209215 impl_def_id: I::ImplId,
210 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
211 ) -> Result<Candidate<I>, NoSolution>;
216 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
217 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
212218
213219 /// If the predicate contained an error, we want to avoid emitting unnecessary trait
214220 /// errors but still want to emit errors for other trait goals. We have some special
......@@ -219,7 +225,7 @@ where
219225 fn consider_error_guaranteed_candidate(
220226 ecx: &mut EvalCtxt<'_, D>,
221227 guar: I::ErrorGuaranteed,
222 ) -> Result<Candidate<I>, NoSolution>;
228 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
223229
224230 /// A type implements an `auto trait` if its components do as well.
225231 ///
......@@ -228,13 +234,13 @@ where
228234 fn consider_auto_trait_candidate(
229235 ecx: &mut EvalCtxt<'_, D>,
230236 goal: Goal<I, Self>,
231 ) -> Result<Candidate<I>, NoSolution>;
237 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
232238
233239 /// A trait alias holds if the RHS traits and `where` clauses hold.
234240 fn consider_trait_alias_candidate(
235241 ecx: &mut EvalCtxt<'_, D>,
236242 goal: Goal<I, Self>,
237 ) -> Result<Candidate<I>, NoSolution>;
243 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
238244
239245 /// A type is `Sized` if its tail component is `Sized` and a type is `MetaSized` if its tail
240246 /// component is `MetaSized`.
......@@ -245,7 +251,7 @@ where
245251 ecx: &mut EvalCtxt<'_, D>,
246252 goal: Goal<I, Self>,
247253 sizedness: SizedTraitKind,
248 ) -> Result<Candidate<I>, NoSolution>;
254 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
249255
250256 /// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
251257 ///
......@@ -254,13 +260,13 @@ where
254260 fn consider_builtin_copy_clone_candidate(
255261 ecx: &mut EvalCtxt<'_, D>,
256262 goal: Goal<I, Self>,
257 ) -> Result<Candidate<I>, NoSolution>;
263 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
258264
259265 /// A type is a `FnPtr` if it is of `FnPtr` type.
260266 fn consider_builtin_fn_ptr_trait_candidate(
261267 ecx: &mut EvalCtxt<'_, D>,
262268 goal: Goal<I, Self>,
263 ) -> Result<Candidate<I>, NoSolution>;
269 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
264270
265271 /// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
266272 /// family of traits where `A` is given by the signature of the type.
......@@ -268,7 +274,7 @@ where
268274 ecx: &mut EvalCtxt<'_, D>,
269275 goal: Goal<I, Self>,
270276 kind: ty::ClosureKind,
271 ) -> Result<Candidate<I>, NoSolution>;
277 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
272278
273279 /// An async closure is known to implement the `AsyncFn<A>` family of traits
274280 /// where `A` is given by the signature of the type.
......@@ -276,7 +282,7 @@ where
276282 ecx: &mut EvalCtxt<'_, D>,
277283 goal: Goal<I, Self>,
278284 kind: ty::ClosureKind,
279 ) -> Result<Candidate<I>, NoSolution>;
285 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
280286
281287 /// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which
282288 /// is used internally to delay computation for async closures until after
......@@ -284,13 +290,13 @@ where
284290 fn consider_builtin_async_fn_kind_helper_candidate(
285291 ecx: &mut EvalCtxt<'_, D>,
286292 goal: Goal<I, Self>,
287 ) -> Result<Candidate<I>, NoSolution>;
293 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
288294
289295 /// `Tuple` is implemented if the `Self` type is a tuple.
290296 fn consider_builtin_tuple_candidate(
291297 ecx: &mut EvalCtxt<'_, D>,
292298 goal: Goal<I, Self>,
293 ) -> Result<Candidate<I>, NoSolution>;
299 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
294300
295301 /// `Pointee` is always implemented.
296302 ///
......@@ -300,7 +306,7 @@ where
300306 fn consider_builtin_pointee_candidate(
301307 ecx: &mut EvalCtxt<'_, D>,
302308 goal: Goal<I, Self>,
303 ) -> Result<Candidate<I>, NoSolution>;
309 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
304310
305311 /// A coroutine (that comes from an `async` desugaring) is known to implement
306312 /// `Future<Output = O>`, where `O` is given by the coroutine's return type
......@@ -308,7 +314,7 @@ where
308314 fn consider_builtin_future_candidate(
309315 ecx: &mut EvalCtxt<'_, D>,
310316 goal: Goal<I, Self>,
311 ) -> Result<Candidate<I>, NoSolution>;
317 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
312318
313319 /// A coroutine (that comes from a `gen` desugaring) is known to implement
314320 /// `Iterator<Item = O>`, where `O` is given by the generator's yield type
......@@ -316,19 +322,19 @@ where
316322 fn consider_builtin_iterator_candidate(
317323 ecx: &mut EvalCtxt<'_, D>,
318324 goal: Goal<I, Self>,
319 ) -> Result<Candidate<I>, NoSolution>;
325 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
320326
321327 /// A coroutine (that comes from a `gen` desugaring) is known to implement
322328 /// `FusedIterator`
323329 fn consider_builtin_fused_iterator_candidate(
324330 ecx: &mut EvalCtxt<'_, D>,
325331 goal: Goal<I, Self>,
326 ) -> Result<Candidate<I>, NoSolution>;
332 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
327333
328334 fn consider_builtin_async_iterator_candidate(
329335 ecx: &mut EvalCtxt<'_, D>,
330336 goal: Goal<I, Self>,
331 ) -> Result<Candidate<I>, NoSolution>;
337 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
332338
333339 /// A coroutine (that doesn't come from an `async` or `gen` desugaring) is known to
334340 /// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield,
......@@ -336,27 +342,27 @@ where
336342 fn consider_builtin_coroutine_candidate(
337343 ecx: &mut EvalCtxt<'_, D>,
338344 goal: Goal<I, Self>,
339 ) -> Result<Candidate<I>, NoSolution>;
345 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
340346
341347 fn consider_builtin_discriminant_kind_candidate(
342348 ecx: &mut EvalCtxt<'_, D>,
343349 goal: Goal<I, Self>,
344 ) -> Result<Candidate<I>, NoSolution>;
350 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
345351
346352 fn consider_builtin_destruct_candidate(
347353 ecx: &mut EvalCtxt<'_, D>,
348354 goal: Goal<I, Self>,
349 ) -> Result<Candidate<I>, NoSolution>;
355 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
350356
351357 fn consider_builtin_transmute_candidate(
352358 ecx: &mut EvalCtxt<'_, D>,
353359 goal: Goal<I, Self>,
354 ) -> Result<Candidate<I>, NoSolution>;
360 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
355361
356362 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
357363 ecx: &mut EvalCtxt<'_, D>,
358364 goal: Goal<I, Self>,
359 ) -> Result<Candidate<I>, NoSolution>;
365 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
360366
361367 /// Consider (possibly several) candidates to upcast or unsize a type to another
362368 /// type, excluding the coercion of a sized type into a `dyn Trait`.
......@@ -368,12 +374,12 @@ where
368374 fn consider_structural_builtin_unsize_candidates(
369375 ecx: &mut EvalCtxt<'_, D>,
370376 goal: Goal<I, Self>,
371 ) -> Vec<Candidate<I>>;
377 ) -> Result<Vec<Candidate<I>>, RerunNonErased>;
372378
373379 fn consider_builtin_field_candidate(
374380 ecx: &mut EvalCtxt<'_, D>,
375381 goal: Goal<I, Self>,
376 ) -> Result<Candidate<I>, NoSolution>;
382 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased>;
377383}
378384
379385/// Allows callers of `assemble_and_evaluate_candidates` to choose whether to limit
......@@ -425,14 +431,14 @@ where
425431 &mut self,
426432 goal: Goal<I, G>,
427433 assemble_from: AssembleCandidatesFrom,
428 ) -> (Vec<Candidate<I>>, FailedCandidateInfo) {
434 ) -> Result<(Vec<Candidate<I>>, FailedCandidateInfo), RerunNonErased> {
429435 let mut candidates = vec![];
430436 let mut failed_candidate_info =
431437 FailedCandidateInfo { param_env_head_usages: CandidateHeadUsages::default() };
432438 let Ok(normalized_self_ty) =
433439 self.structurally_normalize_ty(goal.param_env, goal.predicate.self_ty())
434440 else {
435 return (candidates, failed_candidate_info);
441 return Ok((candidates, failed_candidate_info));
436442 };
437443
438444 let goal: Goal<I, G> = goal
......@@ -440,8 +446,8 @@ where
440446
441447 if normalized_self_ty.is_ty_var() {
442448 debug!("self type has been normalized to infer");
443 self.try_assemble_bounds_via_registered_opaques(goal, assemble_from, &mut candidates);
444 return (candidates, failed_candidate_info);
449 self.try_assemble_bounds_via_registered_opaques(goal, assemble_from, &mut candidates)?;
450 return Ok((candidates, failed_candidate_info));
445451 }
446452
447453 // Vars that show up in the rest of the goal substs may have been constrained by
......@@ -452,15 +458,15 @@ where
452458 && let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal)
453459 {
454460 candidates.push(candidate);
455 return (candidates, failed_candidate_info);
461 return Ok((candidates, failed_candidate_info));
456462 }
457463
458 self.assemble_alias_bound_candidates(goal, &mut candidates);
459 self.assemble_param_env_candidates(goal, &mut candidates, &mut failed_candidate_info);
464 self.assemble_alias_bound_candidates(goal, &mut candidates)?;
465 self.assemble_param_env_candidates(goal, &mut candidates, &mut failed_candidate_info)?;
460466
461467 match assemble_from {
462468 AssembleCandidatesFrom::All => {
463 self.assemble_builtin_impl_candidates(goal, &mut candidates);
469 self.assemble_builtin_impl_candidates(goal, &mut candidates)?;
464470 // For performance we only assemble impls if there are no candidates
465471 // which would shadow them. This is necessary to avoid hangs in rayon,
466472 // see trait-system-refactor-initiative#109 for more details.
......@@ -487,7 +493,7 @@ where
487493 }),
488494 };
489495 if assemble_impls {
490 self.assemble_impl_candidates(goal, &mut candidates);
496 self.assemble_impl_candidates(goal, &mut candidates)?;
491497 self.assemble_object_bound_candidates(goal, &mut candidates);
492498 }
493499 }
......@@ -503,13 +509,13 @@ where
503509 }
504510 }
505511
506 (candidates, failed_candidate_info)
512 Ok((candidates, failed_candidate_info))
507513 }
508514
509515 pub(super) fn forced_ambiguity(
510516 &mut self,
511517 maybe: MaybeInfo,
512 ) -> Result<Candidate<I>, NoSolution> {
518 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
513519 // This may fail if `try_evaluate_added_goals` overflows because it
514520 // fails to reach a fixpoint but ends up getting an error after
515521 // running for some additional step.
......@@ -529,26 +535,30 @@ where
529535 &mut self,
530536 goal: Goal<I, G>,
531537 candidates: &mut Vec<Candidate<I>>,
532 ) {
538 ) -> Result<(), RerunNonErased> {
533539 let cx = self.cx();
534540 cx.for_each_relevant_impl(
535541 goal.predicate.trait_def_id(cx),
536542 goal.predicate.self_ty(),
537 |impl_def_id| {
543 |impl_def_id| -> Result<_, _> {
538544 // For every `default impl`, there's always a non-default `impl`
539545 // that will *also* apply. There's no reason to register a candidate
540546 // for this impl, since it is *not* proof that the trait goal holds.
541547 if cx.impl_is_default(impl_def_id) {
542 return;
548 return Ok(());
543549 }
544550 match G::consider_impl_candidate(self, goal, impl_def_id, |ecx, certainty| {
545551 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
546 }) {
552 })
553 .map_err_to_rerun()?
554 {
547555 Ok(candidate) => candidates.push(candidate),
548 Err(NoSolution) => (),
556 Err(NoSolution) => {}
549557 }
558
559 Ok(())
550560 },
551 );
561 )
552562 }
553563
554564 #[instrument(level = "trace", skip_all)]
......@@ -556,7 +566,7 @@ where
556566 &mut self,
557567 goal: Goal<I, G>,
558568 candidates: &mut Vec<Candidate<I>>,
559 ) {
569 ) -> Result<(), RerunNonErased> {
560570 let cx = self.cx();
561571 let trait_def_id = goal.predicate.trait_def_id(cx);
562572
......@@ -653,7 +663,7 @@ where
653663 G::consider_builtin_bikeshed_guaranteed_no_drop_candidate(self, goal)
654664 }
655665 Some(SolverTraitLangItem::Field) => G::consider_builtin_field_candidate(self, goal),
656 _ => Err(NoSolution),
666 _ => Err(NoSolution.into()),
657667 }
658668 };
659669
......@@ -662,8 +672,10 @@ where
662672 // There may be multiple unsize candidates for a trait with several supertraits:
663673 // `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
664674 if cx.is_trait_lang_item(trait_def_id, SolverTraitLangItem::Unsize) {
665 candidates.extend(G::consider_structural_builtin_unsize_candidates(self, goal));
675 candidates.extend(G::consider_structural_builtin_unsize_candidates(self, goal)?);
666676 }
677
678 Ok(())
667679 }
668680
669681 #[instrument(level = "trace", skip_all)]
......@@ -672,15 +684,17 @@ where
672684 goal: Goal<I, G>,
673685 candidates: &mut Vec<Candidate<I>>,
674686 failed_candidate_info: &mut FailedCandidateInfo,
675 ) {
687 ) -> Result<(), RerunNonErased> {
676688 for assumption in goal.param_env.caller_bounds().iter() {
677 match G::probe_and_consider_param_env_candidate(self, goal, assumption) {
689 match G::probe_and_consider_param_env_candidate(self, goal, assumption)? {
678690 Ok(candidate) => candidates.push(candidate),
679691 Err(head_usages) => {
680692 failed_candidate_info.param_env_head_usages.merge_usages(head_usages)
681693 }
682694 }
683695 }
696
697 Ok(())
684698 }
685699
686700 #[instrument(level = "trace", skip_all)]
......@@ -688,21 +702,22 @@ where
688702 &mut self,
689703 goal: Goal<I, G>,
690704 candidates: &mut Vec<Candidate<I>>,
691 ) {
705 ) -> Result<(), RerunNonErased> {
692706 let res = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
693707 ecx.assemble_alias_bound_candidates_recur(
694708 goal.predicate.self_ty(),
695709 goal,
696710 candidates,
697711 AliasBoundKind::SelfBounds,
698 );
712 )?;
699713 Ok(())
700714 });
701715
702716 // always returns Ok
703717 match res {
704 Ok(_) | Err(NoSolutionOrOpaquesAccessed::OpaquesAccessed) => {}
705 Err(NoSolutionOrOpaquesAccessed::NoSolution(NoSolution)) => {
718 Ok(_) => Ok(()),
719 Err(NoSolutionOrRerunNonErased::RerunNonErased(e)) => Err(e),
720 Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) => {
706721 unreachable!()
707722 }
708723 }
......@@ -723,7 +738,7 @@ where
723738 goal: Goal<I, G>,
724739 candidates: &mut Vec<Candidate<I>>,
725740 consider_self_bounds: AliasBoundKind,
726 ) {
741 ) -> Result<(), RerunNonErased> {
727742 let alias_ty = match self_ty.kind() {
728743 ty::Bool
729744 | ty::Char
......@@ -751,7 +766,7 @@ where
751766 | ty::Param(_)
752767 | ty::Placeholder(..)
753768 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
754 | ty::Error(_) => return,
769 | ty::Error(_) => return Ok(()),
755770 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Bound(..) => {
756771 panic!("unexpected self type for `{goal:?}`")
757772 }
......@@ -769,7 +784,7 @@ where
769784 head_usages: CandidateHeadUsages::default(),
770785 });
771786 }
772 return;
787 return Ok(());
773788 }
774789
775790 ty::Alias(
......@@ -777,7 +792,7 @@ where
777792 ) => alias_ty,
778793 ty::Alias(AliasTy { kind: ty::Inherent { .. } | ty::Free { .. }, .. }) => {
779794 self.cx().delay_bug(format!("could not normalize {self_ty:?}, it is not WF"));
780 return;
795 return Ok(());
781796 }
782797 };
783798
......@@ -819,7 +834,7 @@ where
819834 candidates.extend(G::consider_additional_alias_assumptions(self, goal, alias_ty));
820835
821836 if !matches!(alias_ty.kind, ty::Projection { .. }) {
822 return;
837 return Ok(());
823838 }
824839
825840 // Recurse on the self type of the projection.
......@@ -830,7 +845,8 @@ where
830845 candidates,
831846 AliasBoundKind::NonSelfBounds,
832847 ),
833 Err(NoSolution) => {}
848 Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) => Ok(()),
849 Err(NoSolutionOrRerunNonErased::RerunNonErased(e)) => Err(e),
834850 }
835851 }
836852
......@@ -932,12 +948,12 @@ where
932948 fn consider_coherence_unknowable_candidate<G: GoalKind<D>>(
933949 &mut self,
934950 goal: Goal<I, G>,
935 ) -> Result<Candidate<I>, NoSolution> {
951 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
936952 self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter(|ecx| {
937953 let cx = ecx.cx();
938954 let trait_ref = goal.predicate.trait_ref(cx);
939955 if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? {
940 Err(NoSolution)
956 Err(NoSolution.into())
941957 } else {
942958 // While the trait bound itself may be unknowable, we may be able to
943959 // prove that a super trait is not implemented. For this, we recursively
......@@ -1032,7 +1048,7 @@ where
10321048 goal: Goal<I, G>,
10331049 assemble_from: AssembleCandidatesFrom,
10341050 candidates: &mut Vec<Candidate<I>>,
1035 ) {
1051 ) -> Result<(), RerunNonErased> {
10361052 let self_ty = goal.predicate.self_ty();
10371053 // We only use this hack during HIR typeck.
10381054 let opaque_types = match self.typing_mode() {
......@@ -1043,14 +1059,14 @@ where
10431059 | TypingMode::PostAnalysis => vec![],
10441060 TypingMode::ErasedNotCoherence(MayBeErased) => {
10451061 self.opaque_accesses
1046 .rerun_if_any_opaque_has_infer_as_hidden_type(RerunReason::SelfTyInfer);
1062 .rerun_if_any_opaque_has_infer_as_hidden_type(RerunReason::SelfTyInfer)?;
10471063 Vec::new()
10481064 }
10491065 };
10501066
10511067 if opaque_types.is_empty() {
10521068 candidates.extend(self.forced_ambiguity(MaybeInfo::AMBIGUOUS));
1053 return;
1069 return Ok(());
10541070 }
10551071
10561072 for &alias_ty in &opaque_types {
......@@ -1115,7 +1131,7 @@ where
11151131 // that will *also* apply. There's no reason to register a candidate
11161132 // for this impl, since it is *not* proof that the trait goal holds.
11171133 if cx.impl_is_default(impl_def_id) {
1118 return;
1134 return Ok(());
11191135 }
11201136
11211137 match G::consider_impl_candidate(self, goal, impl_def_id, |ecx, certainty| {
......@@ -1129,13 +1145,17 @@ where
11291145 // FIXME(trait-system-refactor-initiative#229): This isn't
11301146 // perfect yet as it still allows us to incorrectly constrain
11311147 // other inference variables.
1132 Err(NoSolution)
1148 Err(NoSolution.into())
11331149 }
1134 }) {
1150 })
1151 .map_err_to_rerun()?
1152 {
11351153 Ok(candidate) => candidates.push(candidate),
1136 Err(NoSolution) => (),
1154 Err(NoSolution) => {}
11371155 }
1138 });
1156
1157 Ok(())
1158 })?;
11391159 }
11401160
11411161 if candidates.is_empty() {
......@@ -1150,6 +1170,8 @@ where
11501170 this.evaluate_added_goals_and_make_canonical_response(certainty)
11511171 }));
11521172 }
1173
1174 Ok(())
11531175 }
11541176
11551177 /// Assemble and merge candidates for goals which are related to an underlying trait
......@@ -1187,9 +1209,18 @@ where
11871209 &mut self,
11881210 proven_via: Option<TraitGoalProvenVia>,
11891211 goal: Goal<I, G>,
1190 inject_forced_ambiguity_candidate: impl FnOnce(&mut EvalCtxt<'_, D>) -> Option<QueryResult<I>>,
1191 inject_normalize_to_rigid_candidate: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
1192 ) -> QueryResult<I> {
1212 inject_forced_ambiguity_candidate: impl FnOnce(
1213 &mut EvalCtxt<'_, D>,
1214 ) -> Option<
1215 Result<CanonicalResponse<I>, NoSolutionOrRerunNonErased>,
1216 >,
1217 inject_normalize_to_rigid_candidate: impl FnOnce(
1218 &mut EvalCtxt<'_, D>,
1219 ) -> Result<
1220 CanonicalResponse<I>,
1221 NoSolutionOrRerunNonErased,
1222 >,
1223 ) -> QueryResultOrRerunNonErased<I> {
11931224 let Some(proven_via) = proven_via else {
11941225 // We don't care about overflow. If proving the trait goal overflowed, then
11951226 // it's enough to report an overflow error for that, we don't also have to
......@@ -1206,7 +1237,7 @@ where
12061237 // still need to consider alias-bounds for normalization, see
12071238 // `tests/ui/next-solver/alias-bound-shadowed-by-env.rs`.
12081239 let (mut candidates, _) = self
1209 .assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::EnvAndBounds);
1240 .assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::EnvAndBounds)?;
12101241 debug!(?candidates);
12111242
12121243 // If the trait goal has been proven by using the environment, we want to treat
......@@ -1230,12 +1261,12 @@ where
12301261 if let Some((response, _)) = self.try_merge_candidates(&candidates) {
12311262 Ok(response)
12321263 } else {
1233 self.flounder(&candidates)
1264 self.flounder(&candidates).map_err(Into::into)
12341265 }
12351266 }
12361267 TraitGoalProvenVia::Misc => {
12371268 let (mut candidates, _) =
1238 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
1269 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All)?;
12391270
12401271 // Prefer "orphaned" param-env normalization predicates, which are used
12411272 // (for example, and ideally only) when proving item bounds for an impl.
......@@ -1252,7 +1283,7 @@ where
12521283 if let Some((response, _)) = self.try_merge_candidates(&candidates) {
12531284 Ok(response)
12541285 } else {
1255 self.flounder(&candidates)
1286 self.flounder(&candidates).map_err(Into::into)
12561287 }
12571288 }
12581289 }
compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs+1-1
......@@ -970,7 +970,7 @@ where
970970 && self
971971 .ecx
972972 .probe(|_| ProbeKind::ProjectionCompatibility)
973 .enter_without_propagated_nested_goals(|ecx| -> Result<_, NoSolution> {
973 .enter_without_propagated_nested_goals(|ecx| {
974974 let source_projection = ecx.instantiate_binder_with_infer(source_projection);
975975 ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
976976 ecx.try_evaluate_added_goals()
compiler/rustc_next_trait_solver/src/solve/effect_goals.rs+45-37
......@@ -5,15 +5,17 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt;
55use rustc_type_ir::inherent::*;
66use rustc_type_ir::lang_items::SolverTraitLangItem;
77use rustc_type_ir::solve::inspect::ProbeKind;
8use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind};
8use rustc_type_ir::solve::{
9 AliasBoundKind, NoSolutionOrRerunNonErased, QueryResultOrRerunNonErased, RerunNonErased,
10 SizedTraitKind,
11};
912use rustc_type_ir::{self as ty, Interner, Unnormalized, elaborate};
1013use tracing::instrument;
1114
1215use super::assembly::{Candidate, structural_traits};
1316use crate::delegate::SolverDelegate;
1417use crate::solve::{
15 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution,
16 QueryResult, assembly,
18 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution, assembly,
1719};
1820
1921impl<D, I> assembly::GoalKind<D> for ty::HostEffectPredicate<I>
......@@ -60,8 +62,8 @@ where
6062 ecx: &mut EvalCtxt<'_, D>,
6163 goal: Goal<I, Self>,
6264 assumption: I::Clause,
63 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
64 ) -> QueryResult<I> {
65 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
66 ) -> QueryResultOrRerunNonErased<I> {
6567 let host_clause = assumption.as_host_effect_clause().unwrap();
6668
6769 let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause);
......@@ -128,32 +130,32 @@ where
128130 ecx: &mut EvalCtxt<'_, D>,
129131 goal: Goal<I, Self>,
130132 impl_def_id: I::ImplId,
131 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
132 ) -> Result<Candidate<I>, NoSolution> {
133 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
134 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
133135 let cx = ecx.cx();
134136
135137 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
136138 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
137139 .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
138140 {
139 return Err(NoSolution);
141 return Err(NoSolution.into());
140142 }
141143
142144 let impl_polarity = cx.impl_polarity(impl_def_id);
143145 let certainty = match impl_polarity {
144 ty::ImplPolarity::Negative => return Err(NoSolution),
146 ty::ImplPolarity::Negative => return Err(NoSolution.into()),
145147 ty::ImplPolarity::Reservation => {
146148 if ecx.typing_mode().is_coherence() {
147149 Certainty::AMBIGUOUS
148150 } else {
149 return Err(NoSolution);
151 return Err(NoSolution.into());
150152 }
151153 }
152154 ty::ImplPolarity::Positive => Certainty::Yes,
153155 };
154156
155157 if !cx.impl_is_const(impl_def_id) {
156 return Err(NoSolution);
158 return Err(NoSolution.into());
157159 }
158160
159161 ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
......@@ -190,7 +192,7 @@ where
190192 fn consider_error_guaranteed_candidate(
191193 ecx: &mut EvalCtxt<'_, D>,
192194 _guar: I::ErrorGuaranteed,
193 ) -> Result<Candidate<I>, NoSolution> {
195 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
194196 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
195197 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
196198 }
......@@ -198,15 +200,15 @@ where
198200 fn consider_auto_trait_candidate(
199201 ecx: &mut EvalCtxt<'_, D>,
200202 _goal: Goal<I, Self>,
201 ) -> Result<Candidate<I>, NoSolution> {
203 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
202204 ecx.cx().delay_bug("auto traits are never const");
203 Err(NoSolution)
205 Err(NoSolution.into())
204206 }
205207
206208 fn consider_trait_alias_candidate(
207209 ecx: &mut EvalCtxt<'_, D>,
208210 goal: Goal<I, Self>,
209 ) -> Result<Candidate<I>, NoSolution> {
211 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
210212 let cx = ecx.cx();
211213
212214 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
......@@ -242,14 +244,14 @@ where
242244 _ecx: &mut EvalCtxt<'_, D>,
243245 _goal: Goal<I, Self>,
244246 _sizedness: SizedTraitKind,
245 ) -> Result<Candidate<I>, NoSolution> {
247 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
246248 unreachable!("Sized/MetaSized is never const")
247249 }
248250
249251 fn consider_builtin_copy_clone_candidate(
250252 ecx: &mut EvalCtxt<'_, D>,
251253 goal: Goal<I, Self>,
252 ) -> Result<Candidate<I>, NoSolution> {
254 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
253255 let cx = ecx.cx();
254256
255257 let self_ty = goal.predicate.self_ty();
......@@ -278,7 +280,7 @@ where
278280 fn consider_builtin_fn_ptr_trait_candidate(
279281 _ecx: &mut EvalCtxt<'_, D>,
280282 _goal: Goal<I, Self>,
281 ) -> Result<Candidate<I>, NoSolution> {
283 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
282284 todo!("Fn* are not yet const")
283285 }
284286
......@@ -287,7 +289,7 @@ where
287289 ecx: &mut EvalCtxt<'_, D>,
288290 goal: Goal<I, Self>,
289291 _kind: rustc_type_ir::ClosureKind,
290 ) -> Result<Candidate<I>, NoSolution> {
292 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
291293 let cx = ecx.cx();
292294
293295 let self_ty = goal.predicate.self_ty();
......@@ -329,83 +331,84 @@ where
329331 pred,
330332 requirements,
331333 )
334 .map_err(Into::into)
332335 }
333336
334337 fn consider_builtin_async_fn_trait_candidates(
335338 _ecx: &mut EvalCtxt<'_, D>,
336339 _goal: Goal<I, Self>,
337340 _kind: rustc_type_ir::ClosureKind,
338 ) -> Result<Candidate<I>, NoSolution> {
341 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
339342 todo!("AsyncFn* are not yet const")
340343 }
341344
342345 fn consider_builtin_async_fn_kind_helper_candidate(
343346 _ecx: &mut EvalCtxt<'_, D>,
344347 _goal: Goal<I, Self>,
345 ) -> Result<Candidate<I>, NoSolution> {
348 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
346349 unreachable!("AsyncFnKindHelper is not const")
347350 }
348351
349352 fn consider_builtin_tuple_candidate(
350353 _ecx: &mut EvalCtxt<'_, D>,
351354 _goal: Goal<I, Self>,
352 ) -> Result<Candidate<I>, NoSolution> {
355 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
353356 unreachable!("Tuple trait is not const")
354357 }
355358
356359 fn consider_builtin_pointee_candidate(
357360 _ecx: &mut EvalCtxt<'_, D>,
358361 _goal: Goal<I, Self>,
359 ) -> Result<Candidate<I>, NoSolution> {
362 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
360363 unreachable!("Pointee is not const")
361364 }
362365
363366 fn consider_builtin_future_candidate(
364367 _ecx: &mut EvalCtxt<'_, D>,
365368 _goal: Goal<I, Self>,
366 ) -> Result<Candidate<I>, NoSolution> {
369 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
367370 unreachable!("Future is not const")
368371 }
369372
370373 fn consider_builtin_iterator_candidate(
371374 _ecx: &mut EvalCtxt<'_, D>,
372375 _goal: Goal<I, Self>,
373 ) -> Result<Candidate<I>, NoSolution> {
376 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
374377 todo!("Iterator is not yet const")
375378 }
376379
377380 fn consider_builtin_fused_iterator_candidate(
378381 _ecx: &mut EvalCtxt<'_, D>,
379382 _goal: Goal<I, Self>,
380 ) -> Result<Candidate<I>, NoSolution> {
383 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
381384 unreachable!("FusedIterator is not const")
382385 }
383386
384387 fn consider_builtin_async_iterator_candidate(
385388 _ecx: &mut EvalCtxt<'_, D>,
386389 _goal: Goal<I, Self>,
387 ) -> Result<Candidate<I>, NoSolution> {
390 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
388391 unreachable!("AsyncIterator is not const")
389392 }
390393
391394 fn consider_builtin_coroutine_candidate(
392395 _ecx: &mut EvalCtxt<'_, D>,
393396 _goal: Goal<I, Self>,
394 ) -> Result<Candidate<I>, NoSolution> {
397 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
395398 unreachable!("Coroutine is not const")
396399 }
397400
398401 fn consider_builtin_discriminant_kind_candidate(
399402 _ecx: &mut EvalCtxt<'_, D>,
400403 _goal: Goal<I, Self>,
401 ) -> Result<Candidate<I>, NoSolution> {
404 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
402405 unreachable!("DiscriminantKind is not const")
403406 }
404407
405408 fn consider_builtin_destruct_candidate(
406409 ecx: &mut EvalCtxt<'_, D>,
407410 goal: Goal<I, Self>,
408 ) -> Result<Candidate<I>, NoSolution> {
411 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
409412 let cx = ecx.cx();
410413
411414 let self_ty = goal.predicate.self_ty();
......@@ -429,28 +432,28 @@ where
429432 fn consider_builtin_transmute_candidate(
430433 _ecx: &mut EvalCtxt<'_, D>,
431434 _goal: Goal<I, Self>,
432 ) -> Result<Candidate<I>, NoSolution> {
435 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
433436 unreachable!("TransmuteFrom is not const")
434437 }
435438
436439 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
437440 _ecx: &mut EvalCtxt<'_, D>,
438441 _goal: Goal<I, Self>,
439 ) -> Result<Candidate<I>, NoSolution> {
442 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
440443 unreachable!("BikeshedGuaranteedNoDrop is not const");
441444 }
442445
443446 fn consider_structural_builtin_unsize_candidates(
444447 _ecx: &mut EvalCtxt<'_, D>,
445448 _goal: Goal<I, Self>,
446 ) -> Vec<Candidate<I>> {
449 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
447450 unreachable!("Unsize is not const")
448451 }
449452
450453 fn consider_builtin_field_candidate(
451454 _ecx: &mut EvalCtxt<'_, D>,
452455 _goal: Goal<<D as SolverDelegate>::Interner, Self>,
453 ) -> Result<Candidate<<D as SolverDelegate>::Interner>, NoSolution> {
456 ) -> Result<Candidate<<D as SolverDelegate>::Interner>, NoSolutionOrRerunNonErased> {
454457 unreachable!("Field is not const")
455458 }
456459}
......@@ -464,12 +467,17 @@ where
464467 pub(super) fn compute_host_effect_goal(
465468 &mut self,
466469 goal: Goal<I, ty::HostEffectPredicate<I>>,
467 ) -> QueryResult<I> {
470 ) -> QueryResultOrRerunNonErased<I> {
468471 let (_, proven_via) = self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
469472 let trait_goal: Goal<I, ty::TraitPredicate<I>> =
470473 goal.with(ecx.cx(), goal.predicate.trait_ref);
471 ecx.compute_trait_goal(trait_goal)
474 ecx.compute_trait_goal(trait_goal).map_err(Into::into)
472475 })?;
473 self.assemble_and_merge_candidates(proven_via, goal, |_ecx| None, |_ecx| Err(NoSolution))
476 self.assemble_and_merge_candidates(
477 proven_via,
478 goal,
479 |_ecx| None,
480 |_ecx| Err(NoSolution.into()),
481 )
474482 }
475483}
compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs+119-79
......@@ -9,8 +9,9 @@ use rustc_type_ir::relate::Relate;
99use rustc_type_ir::relate::solver_relating::RelateExt;
1010use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind};
1111use rustc_type_ir::solve::{
12 AccessedOpaques, FetchEligibleAssocItemResponse, MaybeInfo, OpaqueTypesJank, RerunCondition,
13 RerunReason, SmallCopyList,
12 AccessedOpaques, FetchEligibleAssocItemResponse, MaybeInfo, NoSolutionOrRerunNonErased,
13 OpaqueTypesJank, QueryResultOrRerunNonErased, RerunCondition, RerunNonErased, RerunReason,
14 RerunResultExt, SmallCopyList,
1415};
1516use rustc_type_ir::{
1617 self as ty, CanonicalVarValues, ClauseKind, InferCtxtLike, Interner, MayBeErased,
......@@ -214,9 +215,17 @@ where
214215 span: I::Span,
215216 stalled_on: Option<GoalStalledOn<I>>,
216217 ) -> Result<GoalEvaluation<I>, NoSolution> {
217 EvalCtxt::enter_root(self, self.cx().recursion_limit(), span, |ecx| {
218 let result = EvalCtxt::enter_root(self, self.cx().recursion_limit(), span, |ecx| {
218219 ecx.evaluate_goal(GoalSource::Misc, goal, stalled_on)
219 })
220 });
221
222 match result {
223 Ok(i) => Ok(i),
224 Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) => Err(NoSolution),
225 Err(NoSolutionOrRerunNonErased::RerunNonErased(_)) => {
226 unreachable!("this never happens at the root, we're never in erased mode here");
227 }
228 }
220229 }
221230
222231 #[instrument(level = "debug", skip(self), ret)]
......@@ -371,7 +380,10 @@ where
371380 search_graph: &'a mut SearchGraph<D>,
372381 canonical_input: CanonicalInput<I>,
373382 proof_tree_builder: &mut inspect::ProofTreeBuilder<D>,
374 f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> Result<T, NoSolution>,
383 f: impl FnOnce(
384 &mut EvalCtxt<'_, D>,
385 Goal<I, I::Predicate>,
386 ) -> Result<T, NoSolutionOrRerunNonErased>,
375387 ) -> (Result<T, NoSolution>, AccessedOpaques<I>) {
376388 let (ref delegate, input, var_values) = D::build_with_canonical(cx, &canonical_input);
377389 for (key, ty) in input.predefined_opaques_in_body.iter() {
......@@ -427,7 +439,19 @@ where
427439 // FIXME: Could we make `build_with_canonical` into `enter_with_canonical` and call this at the end?
428440 delegate.reset_opaque_types();
429441
430 (result, ecx.opaque_accesses)
442 let opaque_accesses = ecx.opaque_accesses;
443 (
444 match result {
445 Ok(i) => Ok(i),
446 Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) => Err(NoSolution),
447 Err(NoSolutionOrRerunNonErased::RerunNonErased(_)) => {
448 // check th t the opaque_accesses state mirrors the result we got.
449 assert!(opaque_accesses.should_bail().is_err());
450 Err(NoSolution)
451 }
452 },
453 opaque_accesses,
454 )
431455 }
432456
433457 pub(super) fn ignore_candidate_head_usages(&mut self, usages: CandidateHeadUsages) {
......@@ -441,7 +465,7 @@ where
441465 source: GoalSource,
442466 goal: Goal<I, I::Predicate>,
443467 stalled_on: Option<GoalStalledOn<I>>,
444 ) -> Result<GoalEvaluation<I>, NoSolution> {
468 ) -> Result<GoalEvaluation<I>, NoSolutionOrRerunNonErased> {
445469 let (normalization_nested_goals, goal_evaluation) =
446470 self.evaluate_goal_raw(source, goal, stalled_on)?;
447471 assert!(normalization_nested_goals.is_empty());
......@@ -460,7 +484,7 @@ where
460484 source: GoalSource,
461485 goal: Goal<I, I::Predicate>,
462486 stalled_on: Option<GoalStalledOn<I>>,
463 ) -> Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolution> {
487 ) -> Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolutionOrRerunNonErased> {
464488 // If we have run this goal before, and it was stalled, check that any of the goal's
465489 // args have changed. Otherwise, we don't need to re-run the goal because it'll remain
466490 // stalled, since it'll canonicalize the same way and evaluation is pure.
......@@ -532,9 +556,7 @@ where
532556
533557 if skip_erased_attempt {
534558 if typing_mode.is_erased_not_coherence() {
535 self.opaque_accesses.rerun_always(RerunReason::SkipErasedAttempt);
536 // FIXME(#155443): We should differentiate between `NoSolution` and force rerun here.
537 return Err(NoSolution);
559 match self.opaque_accesses.rerun_always(RerunReason::SkipErasedAttempt)? {}
538560 } else {
539561 debug!("running in original typing mode");
540562 }
......@@ -566,7 +588,7 @@ where
566588 break 'retry_canonicalize (canonical_result, orig_values, canonical_goal);
567589 }
568590 RerunDecision::EagerlyPropagateToParent => {
569 self.opaque_accesses.update(accessed_opaques);
591 self.opaque_accesses.update(accessed_opaques)?;
570592 break 'retry_canonicalize (canonical_result, orig_values, canonical_goal);
571593 }
572594 }
......@@ -590,7 +612,16 @@ where
590612 };
591613
592614 debug!(?result);
593 let response = result?;
615 let response = match result {
616 Ok(response) => {
617 debug!("success");
618 response
619 }
620 Err(NoSolution) => {
621 debug!("normal failure");
622 return Err(NoSolution.into());
623 }
624 };
594625
595626 drop(tracing_span);
596627
......@@ -786,72 +817,81 @@ where
786817 res
787818 }
788819
789 pub(super) fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
820 pub(super) fn compute_goal(
821 &mut self,
822 goal: Goal<I, I::Predicate>,
823 ) -> QueryResultOrRerunNonErased<I> {
790824 let Goal { param_env, predicate } = goal;
791825 let kind = predicate.kind();
792 self.enter_forall(kind, |ecx, kind| match kind {
793 ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
794 ecx.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r)
795 }
796 ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
797 ecx.compute_host_effect_goal(Goal { param_env, predicate })
798 }
799 ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => {
800 ecx.compute_projection_goal(Goal { param_env, predicate })
801 }
802 ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => {
803 ecx.compute_type_outlives_goal(Goal { param_env, predicate })
804 }
805 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => {
806 ecx.compute_region_outlives_goal(Goal { param_env, predicate })
807 }
808 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
809 ecx.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })
810 }
811 ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
812 ecx.compute_unstable_feature_goal(param_env, symbol)
813 }
814 ty::PredicateKind::Subtype(predicate) => {
815 ecx.compute_subtype_goal(Goal { param_env, predicate })
816 }
817 ty::PredicateKind::Coerce(predicate) => {
818 ecx.compute_coerce_goal(Goal { param_env, predicate })
819 }
820 ty::PredicateKind::DynCompatible(trait_def_id) => {
821 ecx.compute_dyn_compatible_goal(trait_def_id)
822 }
823 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
824 ecx.compute_well_formed_goal(Goal { param_env, predicate: term })
825 }
826 ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
827 ecx.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })
828 }
829 ty::PredicateKind::ConstEquate(_, _) => {
830 panic!("ConstEquate should not be emitted when `-Znext-solver` is active")
831 }
832 ty::PredicateKind::NormalizesTo(predicate) => {
833 ecx.compute_normalizes_to_goal(Goal { param_env, predicate })
834 }
835 ty::PredicateKind::AliasRelate(lhs, rhs, direction) => {
836 ecx.compute_alias_relate_goal(Goal { param_env, predicate: (lhs, rhs, direction) })
837 }
838 ty::PredicateKind::Ambiguous => {
839 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
840 }
826 self.enter_forall(kind, |ecx, kind| {
827 Ok(match kind {
828 ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
829 ecx.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r)?
830 }
831 ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
832 ecx.compute_host_effect_goal(Goal { param_env, predicate })?
833 }
834 ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) => {
835 ecx.compute_projection_goal(Goal { param_env, predicate })?
836 }
837 ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(predicate)) => {
838 ecx.compute_type_outlives_goal(Goal { param_env, predicate })?
839 }
840 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(predicate)) => {
841 ecx.compute_region_outlives_goal(Goal { param_env, predicate })?
842 }
843 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
844 ecx.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })?
845 }
846 ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
847 ecx.compute_unstable_feature_goal(param_env, symbol)?
848 }
849 ty::PredicateKind::Subtype(predicate) => {
850 ecx.compute_subtype_goal(Goal { param_env, predicate })?
851 }
852 ty::PredicateKind::Coerce(predicate) => {
853 ecx.compute_coerce_goal(Goal { param_env, predicate })?
854 }
855 ty::PredicateKind::DynCompatible(trait_def_id) => {
856 ecx.compute_dyn_compatible_goal(trait_def_id)?
857 }
858 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
859 ecx.compute_well_formed_goal(Goal { param_env, predicate: term })?
860 }
861 ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
862 ecx.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })?
863 }
864 ty::PredicateKind::ConstEquate(_, _) => {
865 panic!("ConstEquate should not be emitted when `-Znext-solver` is active")
866 }
867 ty::PredicateKind::NormalizesTo(predicate) => {
868 ecx.compute_normalizes_to_goal(Goal { param_env, predicate })?
869 }
870 ty::PredicateKind::AliasRelate(lhs, rhs, direction) => ecx
871 .compute_alias_relate_goal(Goal {
872 param_env,
873 predicate: (lhs, rhs, direction),
874 })?,
875 ty::PredicateKind::Ambiguous => {
876 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)?
877 }
878 })
841879 })
842880 }
843881
844882 // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning
845883 // the certainty of all the goals.
846884 #[instrument(level = "trace", skip(self))]
847 pub(super) fn try_evaluate_added_goals(&mut self) -> Result<Certainty, NoSolution> {
885 pub(super) fn try_evaluate_added_goals(
886 &mut self,
887 ) -> Result<Certainty, NoSolutionOrRerunNonErased> {
848888 for _ in 0..FIXPOINT_STEP_LIMIT {
849 match self.evaluate_added_goals_step() {
889 match self.evaluate_added_goals_step().map_err_to_rerun()? {
850890 Ok(None) => {}
851891 Ok(Some(cert)) => return Ok(cert),
852892 Err(NoSolution) => {
853893 self.tainted = Err(NoSolution);
854 return Err(NoSolution);
894 return Err(NoSolution.into());
855895 }
856896 }
857897 }
......@@ -863,7 +903,9 @@ where
863903 /// Iterate over all added goals: returning `Ok(Some(_))` in case we can stop rerunning.
864904 ///
865905 /// Goals for the next step get directly added to the nested goals of the `EvalCtxt`.
866 fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution> {
906 fn evaluate_added_goals_step(
907 &mut self,
908 ) -> Result<Option<Certainty>, NoSolutionOrRerunNonErased> {
867909 let cx = self.cx();
868910 // If this loop did not result in any progress, what's our final certainty.
869911 let mut unchanged_certainty = Some(Certainty::Yes);
......@@ -1347,7 +1389,7 @@ where
13471389 &mut self,
13481390 param_env: I::ParamEnv,
13491391 trait_ref: ty::TraitRef<I>,
1350 ) -> Result<bool, NoSolution> {
1392 ) -> Result<bool, NoSolutionOrRerunNonErased> {
13511393 let delegate = self.delegate;
13521394 let lazily_normalize_ty = |ty| self.structurally_normalize_ty(param_env, ty);
13531395 coherence::trait_ref_is_knowable(&**delegate, trait_ref, lazily_normalize_ty)
......@@ -1397,21 +1439,20 @@ where
13971439 &mut self,
13981440 param_env: I::ParamEnv,
13991441 uv: ty::UnevaluatedConst<I>,
1400 ) -> Option<I::Const> {
1442 ) -> Result<Option<I::Const>, RerunNonErased> {
14011443 if self.typing_mode().is_erased_not_coherence() {
1402 self.opaque_accesses.rerun_always(RerunReason::EvaluateConst);
1403 return None;
1444 self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)?;
14041445 }
14051446
1406 self.delegate.evaluate_const(param_env, uv)
1447 Ok(self.delegate.evaluate_const(param_env, uv))
14071448 }
14081449
14091450 pub(super) fn evaluate_const_and_instantiate_normalizes_to_term(
14101451 &mut self,
14111452 goal: Goal<I, ty::NormalizesTo<I>>,
14121453 uv: ty::UnevaluatedConst<I>,
1413 ) -> QueryResult<I> {
1414 match self.evaluate_const(goal.param_env, uv) {
1454 ) -> QueryResultOrRerunNonErased<I> {
1455 match self.evaluate_const(goal.param_env, uv)? {
14151456 Some(evaluated) => {
14161457 self.instantiate_normalizes_to_term(goal, evaluated.into());
14171458 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
......@@ -1465,13 +1506,12 @@ where
14651506 &mut self,
14661507 param_env: I::ParamEnv,
14671508 symbol: I::Symbol,
1468 ) -> bool {
1509 ) -> Result<bool, RerunNonErased> {
14691510 if self.typing_mode().is_erased_not_coherence() {
1470 self.opaque_accesses.rerun_always(RerunReason::MayUseUnstableFeature);
1471 return false;
1511 self.opaque_accesses.rerun_always(RerunReason::MayUseUnstableFeature)?;
14721512 }
14731513
1474 may_use_unstable_feature(&**self.delegate, param_env, symbol)
1514 Ok(may_use_unstable_feature(&**self.delegate, param_env, symbol))
14751515 }
14761516
14771517 pub(crate) fn opaques_with_sub_unified_hidden_type(
......@@ -1502,7 +1542,7 @@ where
15021542 pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
15031543 &mut self,
15041544 shallow_certainty: Certainty,
1505 ) -> QueryResult<I> {
1545 ) -> QueryResultOrRerunNonErased<I> {
15061546 self.inspect.make_canonical_response(shallow_certainty);
15071547
15081548 let goals_certainty = self.try_evaluate_added_goals()?;
compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs+24-18
......@@ -1,7 +1,9 @@
11use std::marker::PhantomData;
22
33use rustc_type_ir::search_graph::CandidateHeadUsages;
4use rustc_type_ir::solve::{AccessedOpaques, CanonicalResponse, NoSolutionOrOpaquesAccessed};
4use rustc_type_ir::solve::{
5 AccessedOpaques, CanonicalResponse, NoSolutionOrRerunNonErased, RerunResultExt,
6};
57use rustc_type_ir::{InferCtxtLike, Interner};
68use tracing::{instrument, warn};
79
......@@ -30,12 +32,12 @@ where
3032{
3133 pub(in crate::solve) fn enter_single_candidate(
3234 self,
33 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolution>,
34 ) -> (Result<T, NoSolutionOrOpaquesAccessed>, CandidateHeadUsages) {
35 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolutionOrRerunNonErased>,
36 ) -> (Result<T, NoSolutionOrRerunNonErased>, CandidateHeadUsages) {
3537 let mut candidate_usages = CandidateHeadUsages::default();
3638
37 if self.ecx.opaque_accesses.should_bail() {
38 return (Err(NoSolutionOrOpaquesAccessed::OpaquesAccessed), candidate_usages);
39 if let Err(e) = self.ecx.opaque_accesses.should_bail() {
40 return (Err(e.into()), candidate_usages);
3941 }
4042
4143 self.ecx.search_graph.enter_single_candidate();
......@@ -49,29 +51,27 @@ where
4951
5052 pub(in crate::solve) fn enter(
5153 self,
52 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolution>,
53 ) -> Result<T, NoSolutionOrOpaquesAccessed> {
54 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolutionOrRerunNonErased>,
55 ) -> Result<T, NoSolutionOrRerunNonErased> {
5456 let nested_goals = self.ecx.nested_goals.clone();
5557 self.enter_inner(f, nested_goals)
5658 }
5759
5860 pub(in crate::solve) fn enter_without_propagated_nested_goals(
5961 self,
60 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolution>,
61 ) -> Result<T, NoSolutionOrOpaquesAccessed> {
62 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolutionOrRerunNonErased>,
63 ) -> Result<T, NoSolutionOrRerunNonErased> {
6264 self.enter_inner(f, Default::default())
6365 }
6466
6567 pub(in crate::solve) fn enter_inner(
6668 self,
67 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolution>,
69 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolutionOrRerunNonErased>,
6870 propagated_nested_goals: Vec<(GoalSource, Goal<I, I::Predicate>, Option<GoalStalledOn<I>>)>,
69 ) -> Result<T, NoSolutionOrOpaquesAccessed> {
71 ) -> Result<T, NoSolutionOrRerunNonErased> {
7072 let ProbeCtxt { ecx: outer, probe_kind, _result } = self;
7173
72 if outer.opaque_accesses.should_bail() {
73 return Err(NoSolutionOrOpaquesAccessed::OpaquesAccessed);
74 }
74 outer.opaque_accesses.should_bail()?;
7575
7676 let delegate = outer.delegate;
7777 let max_input_universe = outer.max_input_universe;
......@@ -95,14 +95,20 @@ where
9595 nested.inspect.probe_final_state(delegate, max_input_universe);
9696 r
9797 });
98
99 outer.opaque_accesses.update(nested.opaque_accesses)?;
100
101 let r = match r.map_err_to_rerun()? {
102 Ok(i) => Ok(i),
103 Err(NoSolution) => Err(NoSolution),
104 };
105
98106 if !nested.inspect.is_noop() {
99107 let probe_kind = probe_kind(&r);
100108 nested.inspect.probe_kind(probe_kind);
101109 outer.inspect = nested.inspect.finish_probe();
102110 }
103111
104 outer.opaque_accesses.update(nested.opaque_accesses);
105
106112 r.map_err(Into::into)
107113 }
108114}
......@@ -125,8 +131,8 @@ where
125131 #[instrument(level = "debug", skip_all, fields(source = ?self.source))]
126132 pub(in crate::solve) fn enter(
127133 self,
128 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
129 ) -> Result<Candidate<I>, NoSolution> {
134 f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<CanonicalResponse<I>, NoSolutionOrRerunNonErased>,
135 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
130136 let (result, head_usages) = self.cx.enter_single_candidate(f);
131137 Ok(Candidate { source: self.source, result: result?, head_usages })
132138 }
compiler/rustc_next_trait_solver/src/solve/mod.rs+34-18
......@@ -89,7 +89,7 @@ where
8989 fn compute_type_outlives_goal(
9090 &mut self,
9191 goal: Goal<I, ty::OutlivesPredicate<I, I::Ty>>,
92 ) -> QueryResult<I> {
92 ) -> QueryResultOrRerunNonErased<I> {
9393 let ty::OutlivesPredicate(ty, lt) = goal.predicate;
9494 self.register_ty_outlives(ty, lt);
9595 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
......@@ -99,14 +99,17 @@ where
9999 fn compute_region_outlives_goal(
100100 &mut self,
101101 goal: Goal<I, ty::OutlivesPredicate<I, I::Region>>,
102 ) -> QueryResult<I> {
102 ) -> QueryResultOrRerunNonErased<I> {
103103 let ty::OutlivesPredicate(a, b) = goal.predicate;
104104 self.register_region_outlives(a, b, VisibleForLeakCheck::Yes);
105105 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
106106 }
107107
108108 #[instrument(level = "trace", skip(self))]
109 fn compute_coerce_goal(&mut self, goal: Goal<I, ty::CoercePredicate<I>>) -> QueryResult<I> {
109 fn compute_coerce_goal(
110 &mut self,
111 goal: Goal<I, ty::CoercePredicate<I>>,
112 ) -> QueryResultOrRerunNonErased<I> {
110113 self.compute_subtype_goal(Goal {
111114 param_env: goal.param_env,
112115 predicate: ty::SubtypePredicate {
......@@ -118,7 +121,10 @@ where
118121 }
119122
120123 #[instrument(level = "trace", skip(self))]
121 fn compute_subtype_goal(&mut self, goal: Goal<I, ty::SubtypePredicate<I>>) -> QueryResult<I> {
124 fn compute_subtype_goal(
125 &mut self,
126 goal: Goal<I, ty::SubtypePredicate<I>>,
127 ) -> QueryResultOrRerunNonErased<I> {
122128 match (goal.predicate.a.kind(), goal.predicate.b.kind()) {
123129 (ty::Infer(ty::TyVar(a_vid)), ty::Infer(ty::TyVar(b_vid))) => {
124130 self.sub_unify_ty_vids_raw(a_vid, b_vid);
......@@ -131,16 +137,22 @@ where
131137 }
132138 }
133139
134 fn compute_dyn_compatible_goal(&mut self, trait_def_id: I::TraitId) -> QueryResult<I> {
140 fn compute_dyn_compatible_goal(
141 &mut self,
142 trait_def_id: I::TraitId,
143 ) -> QueryResultOrRerunNonErased<I> {
135144 if self.cx().trait_is_dyn_compatible(trait_def_id) {
136145 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
137146 } else {
138 Err(NoSolution)
147 Err(NoSolution.into())
139148 }
140149 }
141150
142151 #[instrument(level = "trace", skip(self))]
143 fn compute_well_formed_goal(&mut self, goal: Goal<I, I::Term>) -> QueryResult<I> {
152 fn compute_well_formed_goal(
153 &mut self,
154 goal: Goal<I, I::Term>,
155 ) -> QueryResultOrRerunNonErased<I> {
144156 match self.well_formed_goals(goal.param_env, goal.predicate) {
145157 Some(goals) => {
146158 self.add_goals(GoalSource::Misc, goals);
......@@ -154,8 +166,8 @@ where
154166 &mut self,
155167 param_env: <I as Interner>::ParamEnv,
156168 symbol: <I as Interner>::Symbol,
157 ) -> QueryResult<I> {
158 if self.may_use_unstable_feature(param_env, symbol) {
169 ) -> QueryResultOrRerunNonErased<I> {
170 if self.may_use_unstable_feature(param_env, symbol)? {
159171 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
160172 } else {
161173 self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
......@@ -166,7 +178,7 @@ where
166178 fn compute_const_evaluatable_goal(
167179 &mut self,
168180 Goal { param_env, predicate: ct }: Goal<I, I::Const>,
169 ) -> QueryResult<I> {
181 ) -> QueryResultOrRerunNonErased<I> {
170182 match ct.kind() {
171183 ty::ConstKind::Unevaluated(uv) => {
172184 // We never return `NoSolution` here as `evaluate_const` emits an
......@@ -177,7 +189,7 @@ where
177189
178190 // FIXME(generic_const_exprs): Implement handling for generic
179191 // const expressions here.
180 if let Some(_normalized) = self.evaluate_const(param_env, uv) {
192 if let Some(_normalized) = self.evaluate_const(param_env, uv)? {
181193 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
182194 } else {
183195 self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
......@@ -203,16 +215,20 @@ where
203215 fn compute_const_arg_has_type_goal(
204216 &mut self,
205217 goal: Goal<I, (I::Const, I::Ty)>,
206 ) -> QueryResult<I> {
218 ) -> QueryResultOrRerunNonErased<I> {
207219 let (ct, ty) = goal.predicate;
208220 let ct = self.structurally_normalize_const(goal.param_env, ct)?;
209221
210222 let ct_ty = match ct.kind() {
211223 ty::ConstKind::Infer(_) => {
212 return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
224 return self
225 .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
226 .map_err(Into::into);
213227 }
214228 ty::ConstKind::Error(_) => {
215 return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
229 return self
230 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
231 .map_err(Into::into);
216232 }
217233 ty::ConstKind::Unevaluated(uv) => {
218234 self.cx().type_of(uv.def.into()).instantiate(self.cx(), uv.args).skip_norm_wip()
......@@ -231,7 +247,7 @@ where
231247 };
232248
233249 self.eq(goal.param_env, ct_ty, ty)?;
234 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
250 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into)
235251 }
236252}
237253
......@@ -308,7 +324,7 @@ where
308324 &mut self,
309325 param_env: I::ParamEnv,
310326 ty: I::Ty,
311 ) -> Result<I::Ty, NoSolution> {
327 ) -> Result<I::Ty, NoSolutionOrRerunNonErased> {
312328 self.structurally_normalize_term(param_env, ty.into()).map(|term| term.expect_ty())
313329 }
314330
......@@ -323,7 +339,7 @@ where
323339 &mut self,
324340 param_env: I::ParamEnv,
325341 ct: I::Const,
326 ) -> Result<I::Const, NoSolution> {
342 ) -> Result<I::Const, NoSolutionOrRerunNonErased> {
327343 self.structurally_normalize_term(param_env, ct.into()).map(|term| term.expect_const())
328344 }
329345
......@@ -335,7 +351,7 @@ where
335351 &mut self,
336352 param_env: I::ParamEnv,
337353 term: I::Term,
338 ) -> Result<I::Term, NoSolution> {
354 ) -> Result<I::Term, NoSolutionOrRerunNonErased> {
339355 if let Some(_) = term.to_alias_term(self.cx()) {
340356 let normalized_term = self.next_term_infer_of_kind(term);
341357 let alias_relate_goal = Goal::new(
compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs+3-2
......@@ -1,8 +1,9 @@
1use rustc_type_ir::solve::QueryResultOrRerunNonErased;
12use rustc_type_ir::{self as ty, Interner};
23use tracing::instrument;
34
45use crate::delegate::SolverDelegate;
5use crate::solve::{EvalCtxt, Goal, QueryResult};
6use crate::solve::{EvalCtxt, Goal};
67
78impl<D, I> EvalCtxt<'_, D>
89where
......@@ -14,7 +15,7 @@ where
1415 &mut self,
1516 goal: Goal<I, ty::NormalizesTo<I>>,
1617 def_id: I::UnevaluatedConstId,
17 ) -> QueryResult<I> {
18 ) -> QueryResultOrRerunNonErased<I> {
1819 let uv = goal.predicate.alias.expect_ct(self.cx());
1920 self.evaluate_const_and_instantiate_normalizes_to_term(goal, uv)
2021 }
compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs+3-2
......@@ -4,10 +4,11 @@
44//! Since a free alias is never ambiguous, this just computes the `type_of` of
55//! the alias and registers the where-clauses of the type alias.
66
7use rustc_type_ir::solve::QueryResultOrRerunNonErased;
78use rustc_type_ir::{self as ty, Interner, Unnormalized};
89
910use crate::delegate::SolverDelegate;
10use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult};
11use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource};
1112
1213impl<D, I> EvalCtxt<'_, D>
1314where
......@@ -17,7 +18,7 @@ where
1718 pub(super) fn normalize_free_alias(
1819 &mut self,
1920 goal: Goal<I, ty::NormalizesTo<I>>,
20 ) -> QueryResult<I> {
21 ) -> QueryResultOrRerunNonErased<I> {
2122 let cx = self.cx();
2223 let free_alias = goal.predicate.alias;
2324
compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs+3-2
......@@ -5,10 +5,11 @@
55//! 2. equate the self type, and
66//! 3. instantiate and register where clauses.
77
8use rustc_type_ir::solve::QueryResultOrRerunNonErased;
89use rustc_type_ir::{self as ty, Interner, Unnormalized};
910
1011use crate::delegate::SolverDelegate;
11use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult};
12use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource};
1213
1314impl<D, I> EvalCtxt<'_, D>
1415where
......@@ -19,7 +20,7 @@ where
1920 &mut self,
2021 goal: Goal<I, ty::NormalizesTo<I>>,
2122 def_id: I::InherentAssocTermId,
22 ) -> QueryResult<I> {
23 ) -> QueryResultOrRerunNonErased<I> {
2324 let cx = self.cx();
2425 let inherent = goal.predicate.alias;
2526
compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs+79-58
......@@ -6,7 +6,10 @@ mod opaque_types;
66use rustc_type_ir::fast_reject::DeepRejectCtxt;
77use rustc_type_ir::inherent::*;
88use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem};
9use rustc_type_ir::solve::{FetchEligibleAssocItemResponse, RerunReason};
9use rustc_type_ir::solve::{
10 FetchEligibleAssocItemResponse, NoSolutionOrRerunNonErased, QueryResultOrRerunNonErased,
11 RerunNonErased, RerunReason, RerunResultExt,
12};
1013use rustc_type_ir::{
1114 self as ty, FieldInfo, Interner, NormalizesTo, PredicateKind, Unnormalized, Upcast as _,
1215};
......@@ -18,7 +21,7 @@ use crate::solve::assembly::{self, Candidate};
1821use crate::solve::inspect::ProbeKind;
1922use crate::solve::{
2023 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeInfo,
21 NoSolution, QueryResult, SizedTraitKind,
24 NoSolution, SizedTraitKind,
2225};
2326
2427impl<D, I> EvalCtxt<'_, D>
......@@ -30,7 +33,7 @@ where
3033 pub(super) fn compute_normalizes_to_goal(
3134 &mut self,
3235 goal: Goal<I, NormalizesTo<I>>,
33 ) -> QueryResult<I> {
36 ) -> QueryResultOrRerunNonErased<I> {
3437 debug_assert!(self.term_is_fully_unconstrained(goal));
3538 match goal.predicate.alias.kind {
3639 ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } => {
......@@ -44,15 +47,18 @@ where
4447 }
4548 ty::AliasTermKind::OpaqueTy { def_id } => self.normalize_opaque_type(goal, def_id),
4649 ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } => {
47 self.normalize_free_alias(goal)
50 self.normalize_free_alias(goal).map_err(Into::into)
4851 }
4952 ty::AliasTermKind::UnevaluatedConst { def_id } => {
50 self.normalize_anon_const(goal, def_id)
53 self.normalize_anon_const(goal, def_id).map_err(Into::into)
5154 }
5255 }
5356 }
5457
55 fn normalize_associated_term(&mut self, goal: Goal<I, NormalizesTo<I>>) -> QueryResult<I> {
58 fn normalize_associated_term(
59 &mut self,
60 goal: Goal<I, NormalizesTo<I>>,
61 ) -> QueryResultOrRerunNonErased<I> {
5662 let cx = self.cx();
5763
5864 let trait_ref = goal.predicate.alias.trait_ref(cx);
......@@ -85,7 +91,12 @@ where
8591 ));
8692 }
8793 }
88 Err(NoSolution) => return Some(Err(NoSolution)),
94 Err(
95 e @ (NoSolutionOrRerunNonErased::NoSolution(NoSolution)
96 | NoSolutionOrRerunNonErased::RerunNonErased(_)),
97 ) => {
98 return Some(Err(e));
99 }
89100 }
90101 }
91102
......@@ -174,8 +185,8 @@ where
174185 ecx: &mut EvalCtxt<'_, D>,
175186 goal: Goal<I, Self>,
176187 assumption: I::Clause,
177 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
178 ) -> QueryResult<I> {
188 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
189 ) -> QueryResultOrRerunNonErased<I> {
179190 let cx = ecx.cx();
180191 let projection_pred = assumption.as_projection_clause().unwrap();
181192 let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred);
......@@ -204,7 +215,7 @@ where
204215 source: CandidateSource<I>,
205216 goal: Goal<I, Self>,
206217 assumption: I::Clause,
207 ) -> Result<Candidate<I>, NoSolution> {
218 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
208219 Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
209220 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
210221 })
......@@ -222,8 +233,8 @@ where
222233 ecx: &mut EvalCtxt<'_, D>,
223234 goal: Goal<I, NormalizesTo<I>>,
224235 impl_def_id: I::ImplId,
225 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
226 ) -> Result<Candidate<I>, NoSolution> {
236 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
237 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
227238 let cx = ecx.cx();
228239
229240 let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
......@@ -232,13 +243,13 @@ where
232243 goal.predicate.alias.trait_ref(cx).args,
233244 impl_trait_ref.skip_binder().args,
234245 ) {
235 return Err(NoSolution);
246 return Err(NoSolution.into());
236247 }
237248
238249 // We have to ignore negative impls when projecting.
239250 let impl_polarity = cx.impl_polarity(impl_def_id);
240251 match impl_polarity {
241 ty::ImplPolarity::Negative => return Err(NoSolution),
252 ty::ImplPolarity::Negative => return Err(NoSolution.into()),
242253 ty::ImplPolarity::Reservation => {
243254 unimplemented!("reservation impl for trait with assoc item: {:?}", goal)
244255 }
......@@ -307,7 +318,8 @@ where
307318 ty::TypingMode::Coherence => {
308319 ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous));
309320 return ecx
310 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
321 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
322 .map_err(Into::into);
311323 }
312324 // Outside of coherence, we treat the associated item as rigid instead.
313325 ty::TypingMode::Analysis { .. }
......@@ -319,14 +331,15 @@ where
319331 goal.predicate.alias,
320332 );
321333 return ecx
322 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
334 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
335 .map_err(Into::into);
323336 }
324337 };
325338 }
326339 FetchEligibleAssocItemResponse::Err(guar) => return error_response(ecx, guar),
327340 FetchEligibleAssocItemResponse::NotFoundBecauseErased => {
328 ecx.opaque_accesses.rerun_always(RerunReason::FetchEligibleAssocItem);
329 return Err(NoSolution);
341 ecx.opaque_accesses.rerun_always(RerunReason::FetchEligibleAssocItem)?;
342 return Err(NoSolution.into());
330343 }
331344 };
332345
......@@ -349,10 +362,10 @@ where
349362 // This is not the case here and we only prefer adding an ambiguous
350363 // nested goal for consistency.
351364 ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous));
352 return then(ecx, Certainty::Yes);
365 return then(ecx, Certainty::Yes).map_err(Into::into);
353366 } else {
354367 ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
355 return then(ecx, Certainty::Yes);
368 return then(ecx, Certainty::Yes).map_err(Into::into);
356369 }
357370 } else {
358371 return error_response(ecx, cx.delay_bug("missing item"));
......@@ -412,7 +425,7 @@ where
412425 };
413426
414427 ecx.instantiate_normalizes_to_term(goal, term);
415 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
428 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into)
416429 })
417430 }
418431
......@@ -421,22 +434,22 @@ where
421434 fn consider_error_guaranteed_candidate(
422435 _ecx: &mut EvalCtxt<'_, D>,
423436 _guar: I::ErrorGuaranteed,
424 ) -> Result<Candidate<I>, NoSolution> {
425 Err(NoSolution)
437 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
438 Err(NoSolution.into())
426439 }
427440
428441 fn consider_auto_trait_candidate(
429442 ecx: &mut EvalCtxt<'_, D>,
430443 _goal: Goal<I, Self>,
431 ) -> Result<Candidate<I>, NoSolution> {
444 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
432445 ecx.cx().delay_bug("associated types not allowed on auto traits");
433 Err(NoSolution)
446 Err(NoSolution.into())
434447 }
435448
436449 fn consider_trait_alias_candidate(
437450 _ecx: &mut EvalCtxt<'_, D>,
438451 goal: Goal<I, Self>,
439 ) -> Result<Candidate<I>, NoSolution> {
452 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
440453 panic!("trait aliases do not have associated types: {:?}", goal);
441454 }
442455
......@@ -444,21 +457,21 @@ where
444457 _ecx: &mut EvalCtxt<'_, D>,
445458 goal: Goal<I, Self>,
446459 _sizedness: SizedTraitKind,
447 ) -> Result<Candidate<I>, NoSolution> {
460 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
448461 panic!("`Sized`/`MetaSized` does not have an associated type: {:?}", goal);
449462 }
450463
451464 fn consider_builtin_copy_clone_candidate(
452465 _ecx: &mut EvalCtxt<'_, D>,
453466 goal: Goal<I, Self>,
454 ) -> Result<Candidate<I>, NoSolution> {
467 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
455468 panic!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
456469 }
457470
458471 fn consider_builtin_fn_ptr_trait_candidate(
459472 _ecx: &mut EvalCtxt<'_, D>,
460473 goal: Goal<I, Self>,
461 ) -> Result<Candidate<I>, NoSolution> {
474 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
462475 panic!("`FnPtr` does not have an associated type: {:?}", goal);
463476 }
464477
......@@ -466,7 +479,7 @@ where
466479 ecx: &mut EvalCtxt<'_, D>,
467480 goal: Goal<I, Self>,
468481 goal_kind: ty::ClosureKind,
469 ) -> Result<Candidate<I>, NoSolution> {
482 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
470483 let cx = ecx.cx();
471484 let Some(tupled_inputs_and_output) =
472485 structural_traits::extract_tupled_inputs_and_output_from_callable(
......@@ -501,13 +514,14 @@ where
501514 pred,
502515 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
503516 )
517 .map_err(Into::into)
504518 }
505519
506520 fn consider_builtin_async_fn_trait_candidates(
507521 ecx: &mut EvalCtxt<'_, D>,
508522 goal: Goal<I, Self>,
509523 goal_kind: ty::ClosureKind,
510 ) -> Result<Candidate<I>, NoSolution> {
524 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
511525 let cx = ecx.cx();
512526 let def_id = goal.predicate.def_id().try_into().unwrap();
513527
......@@ -590,7 +604,7 @@ where
590604 fn consider_builtin_async_fn_kind_helper_candidate(
591605 ecx: &mut EvalCtxt<'_, D>,
592606 goal: Goal<I, Self>,
593 ) -> Result<Candidate<I>, NoSolution> {
607 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
594608 let [
595609 closure_fn_kind_ty,
596610 goal_kind_ty,
......@@ -610,13 +624,13 @@ where
610624
611625 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
612626 // We don't need to worry about the self type being an infer var.
613 return Err(NoSolution);
627 return Err(NoSolution.into());
614628 };
615629 let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else {
616 return Err(NoSolution);
630 return Err(NoSolution.into());
617631 };
618632 if !closure_kind.extends(goal_kind) {
619 return Err(NoSolution);
633 return Err(NoSolution.into());
620634 }
621635
622636 let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
......@@ -637,14 +651,14 @@ where
637651 fn consider_builtin_tuple_candidate(
638652 _ecx: &mut EvalCtxt<'_, D>,
639653 goal: Goal<I, Self>,
640 ) -> Result<Candidate<I>, NoSolution> {
654 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
641655 panic!("`Tuple` does not have an associated type: {:?}", goal);
642656 }
643657
644658 fn consider_builtin_pointee_candidate(
645659 ecx: &mut EvalCtxt<'_, D>,
646660 goal: Goal<I, Self>,
647 ) -> Result<Candidate<I>, NoSolution> {
661 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
648662 let cx = ecx.cx();
649663 let metadata_def_id = cx.require_projection_lang_item(SolverProjectionLangItem::Metadata);
650664 assert_eq!(Into::<I::DefId>::into(metadata_def_id), goal.predicate.def_id());
......@@ -695,6 +709,12 @@ where
695709 ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into());
696710 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
697711 });
712
713 let alias_bound_result = match alias_bound_result.map_err_to_rerun()? {
714 Ok(i) => Ok(i),
715 Err(NoSolution) => Err(NoSolution),
716 };
717
698718 // In case the dummy alias-bound candidate does not apply, we instead treat this projection
699719 // as rigid.
700720 return alias_bound_result.or_else(|NoSolution| {
......@@ -744,16 +764,16 @@ where
744764 fn consider_builtin_future_candidate(
745765 ecx: &mut EvalCtxt<'_, D>,
746766 goal: Goal<I, Self>,
747 ) -> Result<Candidate<I>, NoSolution> {
767 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
748768 let self_ty = goal.predicate.self_ty();
749769 let ty::Coroutine(def_id, args) = self_ty.kind() else {
750 return Err(NoSolution);
770 return Err(NoSolution.into());
751771 };
752772
753773 // Coroutines are not futures unless they come from `async` desugaring
754774 let cx = ecx.cx();
755775 if !cx.coroutine_is_async(def_id) {
756 return Err(NoSolution);
776 return Err(NoSolution.into());
757777 }
758778
759779 let term = args.as_coroutine().return_ty().into();
......@@ -780,16 +800,16 @@ where
780800 fn consider_builtin_iterator_candidate(
781801 ecx: &mut EvalCtxt<'_, D>,
782802 goal: Goal<I, Self>,
783 ) -> Result<Candidate<I>, NoSolution> {
803 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
784804 let self_ty = goal.predicate.self_ty();
785805 let ty::Coroutine(def_id, args) = self_ty.kind() else {
786 return Err(NoSolution);
806 return Err(NoSolution.into());
787807 };
788808
789809 // Coroutines are not Iterators unless they come from `gen` desugaring
790810 let cx = ecx.cx();
791811 if !cx.coroutine_is_gen(def_id) {
792 return Err(NoSolution);
812 return Err(NoSolution.into());
793813 }
794814
795815 let term = args.as_coroutine().yield_ty().into();
......@@ -811,28 +831,29 @@ where
811831 // but that's already proven by the generator being WF.
812832 [],
813833 )
834 .map_err(Into::into)
814835 }
815836
816837 fn consider_builtin_fused_iterator_candidate(
817838 _ecx: &mut EvalCtxt<'_, D>,
818839 goal: Goal<I, Self>,
819 ) -> Result<Candidate<I>, NoSolution> {
840 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
820841 panic!("`FusedIterator` does not have an associated type: {:?}", goal);
821842 }
822843
823844 fn consider_builtin_async_iterator_candidate(
824845 ecx: &mut EvalCtxt<'_, D>,
825846 goal: Goal<I, Self>,
826 ) -> Result<Candidate<I>, NoSolution> {
847 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
827848 let self_ty = goal.predicate.self_ty();
828849 let ty::Coroutine(def_id, args) = self_ty.kind() else {
829 return Err(NoSolution);
850 return Err(NoSolution.into());
830851 };
831852
832853 // Coroutines are not AsyncIterators unless they come from `gen` desugaring
833854 let cx = ecx.cx();
834855 if !cx.coroutine_is_async_gen(def_id) {
835 return Err(NoSolution);
856 return Err(NoSolution.into());
836857 }
837858
838859 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
......@@ -859,16 +880,16 @@ where
859880 fn consider_builtin_coroutine_candidate(
860881 ecx: &mut EvalCtxt<'_, D>,
861882 goal: Goal<I, Self>,
862 ) -> Result<Candidate<I>, NoSolution> {
883 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
863884 let self_ty = goal.predicate.self_ty();
864885 let ty::Coroutine(def_id, args) = self_ty.kind() else {
865 return Err(NoSolution);
886 return Err(NoSolution.into());
866887 };
867888
868889 // `async`-desugared coroutines do not implement the coroutine trait
869890 let cx = ecx.cx();
870891 if !cx.is_general_coroutine(def_id) {
871 return Err(NoSolution);
892 return Err(NoSolution.into());
872893 }
873894
874895 let coroutine = args.as_coroutine();
......@@ -905,14 +926,14 @@ where
905926 fn consider_structural_builtin_unsize_candidates(
906927 _ecx: &mut EvalCtxt<'_, D>,
907928 goal: Goal<I, Self>,
908 ) -> Vec<Candidate<I>> {
929 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
909930 panic!("`Unsize` does not have an associated type: {:?}", goal);
910931 }
911932
912933 fn consider_builtin_discriminant_kind_candidate(
913934 ecx: &mut EvalCtxt<'_, D>,
914935 goal: Goal<I, Self>,
915 ) -> Result<Candidate<I>, NoSolution> {
936 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
916937 let self_ty = goal.predicate.self_ty();
917938 let discriminant_ty = match self_ty.kind() {
918939 ty::Bool
......@@ -971,35 +992,35 @@ where
971992 fn consider_builtin_destruct_candidate(
972993 _ecx: &mut EvalCtxt<'_, D>,
973994 goal: Goal<I, Self>,
974 ) -> Result<Candidate<I>, NoSolution> {
995 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
975996 panic!("`Destruct` does not have an associated type: {:?}", goal);
976997 }
977998
978999 fn consider_builtin_transmute_candidate(
9791000 _ecx: &mut EvalCtxt<'_, D>,
9801001 goal: Goal<I, Self>,
981 ) -> Result<Candidate<I>, NoSolution> {
1002 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
9821003 panic!("`TransmuteFrom` does not have an associated type: {:?}", goal)
9831004 }
9841005
9851006 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
9861007 _ecx: &mut EvalCtxt<'_, D>,
9871008 goal: Goal<I, Self>,
988 ) -> Result<Candidate<I>, NoSolution> {
1009 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
9891010 unreachable!("`BikeshedGuaranteedNoDrop` does not have an associated type: {:?}", goal)
9901011 }
9911012
9921013 fn consider_builtin_field_candidate(
9931014 ecx: &mut EvalCtxt<'_, D>,
9941015 goal: Goal<I, Self>,
995 ) -> Result<Candidate<I>, NoSolution> {
1016 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
9961017 let self_ty = goal.predicate.self_ty();
9971018 let ty::Adt(def, args) = self_ty.kind() else {
998 return Err(NoSolution);
1019 return Err(NoSolution.into());
9991020 };
10001021 let Some(FieldInfo { base, ty, .. }) = def.field_representing_type_info(ecx.cx(), args)
10011022 else {
1002 return Err(NoSolution);
1023 return Err(NoSolution.into());
10031024 };
10041025 let ty = match ecx.cx().as_projection_lang_item(goal.predicate.def_id().try_into().unwrap())
10051026 {
compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs+16-12
......@@ -2,11 +2,11 @@
22//! behaves differently depending on the current `TypingMode`.
33
44use rustc_type_ir::inherent::*;
5use rustc_type_ir::solve::{GoalSource, NoSolution, RerunReason};
5use rustc_type_ir::solve::{GoalSource, QueryResultOrRerunNonErased, RerunReason};
66use rustc_type_ir::{self as ty, Interner, MayBeErased, TypingMode, fold_regions};
77
88use crate::delegate::SolverDelegate;
9use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult};
9use crate::solve::{Certainty, EvalCtxt, Goal};
1010
1111impl<D, I> EvalCtxt<'_, D>
1212where
......@@ -18,7 +18,7 @@ where
1818 &mut self,
1919 goal: Goal<I, ty::NormalizesTo<I>>,
2020 def_id: I::OpaqueTyId,
21 ) -> QueryResult<I> {
21 ) -> QueryResultOrRerunNonErased<I> {
2222 let cx = self.cx();
2323 let opaque_ty = goal.predicate.alias;
2424 let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const");
......@@ -39,6 +39,7 @@ where
3939 // This can then allow nested goals to fail after we've constrained the `term`.
4040 self.add_goal(GoalSource::Misc, goal.with(cx, ty::PredicateKind::Ambiguous));
4141 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
42 .map_err(Into::into)
4243 }
4344 TypingMode::Analysis {
4445 defining_opaque_types_and_generators: defining_opaque_types,
......@@ -50,7 +51,9 @@ where
5051 else {
5152 // If we're not in the defining scope, treat the alias as rigid.
5253 self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
53 return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
54 return self
55 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
56 .map_err(Into::into);
5457 };
5558
5659 // We structurally normalize the args so that we're able to detect defining uses
......@@ -108,6 +111,7 @@ where
108111 expected,
109112 );
110113 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
114 .map_err(Into::into)
111115 }
112116 TypingMode::PostBorrowckAnalysis { defined_opaque_types } => {
113117 let Some(def_id) = opaque_ty
......@@ -116,7 +120,9 @@ where
116120 .filter(|&def_id| defined_opaque_types.contains(&def_id))
117121 else {
118122 self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
119 return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
123 return self
124 .evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
125 .map_err(Into::into);
120126 };
121127
122128 let actual =
......@@ -130,6 +136,7 @@ where
130136 });
131137 self.eq(goal.param_env, expected, actual)?;
132138 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
139 .map_err(Into::into)
133140 }
134141 TypingMode::PostAnalysis => {
135142 // FIXME: Add an assertion that opaque type storage is empty.
......@@ -137,6 +144,7 @@ where
137144 cx.type_of(def_id.into()).instantiate(cx, opaque_ty.args).skip_norm_wip();
138145 self.eq(goal.param_env, expected, actual)?;
139146 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
147 .map_err(Into::into)
140148 }
141149 TypingMode::ErasedNotCoherence(MayBeErased) => {
142150 let def_id = opaque_ty.def_id().as_local();
......@@ -151,20 +159,16 @@ where
151159 self.opaque_accesses.rerun_if_opaque_in_opaque_type_storage(
152160 RerunReason::NormalizeOpaqueType,
153161 def_id,
154 );
162 )?;
155163 } else {
156164 self.opaque_accesses
157 .rerun_if_in_post_analysis(RerunReason::NormalizeOpaqueTypeRemoteCrate);
158 }
159 if self.opaque_accesses.should_bail() {
160 // If we already accessed opaque types once, bail.
161 // We can't make it more precise
162 return Err(NoSolution);
165 .rerun_if_in_post_analysis(RerunReason::NormalizeOpaqueTypeRemoteCrate)?;
163166 }
164167
165168 // Always treat the opaque type as rigid.
166169 self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
167170 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
171 .map_err(Into::into)
168172 }
169173 }
170174 }
compiler/rustc_next_trait_solver/src/solve/project_goals.rs+3-2
......@@ -1,8 +1,9 @@
1use rustc_type_ir::solve::QueryResultOrRerunNonErased;
12use rustc_type_ir::{self as ty, Interner, ProjectionPredicate};
23use tracing::instrument;
34
45use crate::delegate::SolverDelegate;
5use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource, QueryResult};
6use crate::solve::{Certainty, EvalCtxt, Goal, GoalSource};
67
78impl<D, I> EvalCtxt<'_, D>
89where
......@@ -13,7 +14,7 @@ where
1314 pub(super) fn compute_projection_goal(
1415 &mut self,
1516 goal: Goal<I, ProjectionPredicate<I>>,
16 ) -> QueryResult<I> {
17 ) -> QueryResultOrRerunNonErased<I> {
1718 let cx = self.cx();
1819 let projection_term = goal.predicate.projection_term.to_term(cx);
1920 let goal = goal.with(
compiler/rustc_next_trait_solver/src/solve/search_graph.rs+15-2
......@@ -3,7 +3,9 @@ use std::marker::PhantomData;
33
44use rustc_type_ir::data_structures::ensure_sufficient_stack;
55use rustc_type_ir::search_graph::{self, PathKind};
6use rustc_type_ir::solve::{AccessedOpaques, CanonicalInput, Certainty, NoSolution, QueryResult};
6use rustc_type_ir::solve::{
7 AccessedOpaques, CanonicalInput, Certainty, NoSolution, NoSolutionOrRerunNonErased, QueryResult,
8};
79use rustc_type_ir::{Interner, MayBeErased, TypingMode};
810
911use crate::canonical::response_no_constraints_raw;
......@@ -139,8 +141,19 @@ where
139141 ensure_sufficient_stack(|| {
140142 EvalCtxt::enter_canonical(cx, search_graph, input, inspect, |ecx, goal| {
141143 let result = ecx.compute_goal(goal);
144
145 // if we're in `RerunNonErased`, don't even bother with inspect,
146 // and immediately return
147 let result = match result {
148 Ok(i) => Ok(i),
149 Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) => Err(NoSolution),
150 Err(NoSolutionOrRerunNonErased::RerunNonErased(e)) => {
151 return Err(e.into());
152 }
153 };
154
142155 ecx.inspect.query_result(result);
143 result
156 result.map_err(Into::into)
144157 })
145158 })
146159 }
compiler/rustc_next_trait_solver/src/solve/trait_goals.rs+129-113
......@@ -5,8 +5,9 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt;
55use rustc_type_ir::inherent::*;
66use rustc_type_ir::lang_items::SolverTraitLangItem;
77use rustc_type_ir::solve::{
8 AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, MaybeInfo, OpaqueTypesJank,
9 RerunReason, SizedTraitKind,
8 AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, MaybeInfo,
9 NoSolutionOrRerunNonErased, OpaqueTypesJank, QueryResultOrRerunNonErased, RerunNonErased,
10 RerunReason, RerunResultExt, SizedTraitKind,
1011};
1112use rustc_type_ir::{
1213 self as ty, FieldInfo, Interner, MayBeErased, Movability, PredicatePolarity, TraitPredicate,
......@@ -22,7 +23,7 @@ use crate::solve::assembly::{
2223use crate::solve::inspect::ProbeKind;
2324use crate::solve::{
2425 BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
25 MergeCandidateInfo, NoSolution, ParamEnvSource, QueryResult, StalledOnCoroutines,
26 MergeCandidateInfo, NoSolution, ParamEnvSource, StalledOnCoroutines,
2627 has_only_region_constraints,
2728};
2829
......@@ -59,15 +60,15 @@ where
5960 ecx: &mut EvalCtxt<'_, D>,
6061 goal: Goal<I, TraitPredicate<I>>,
6162 impl_def_id: I::ImplId,
62 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
63 ) -> Result<Candidate<I>, NoSolution> {
63 then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResultOrRerunNonErased<I>,
64 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
6465 let cx = ecx.cx();
6566
6667 let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
6768 if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
6869 .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
6970 {
70 return Err(NoSolution);
71 return Err(NoSolution.into());
7172 }
7273
7374 // An upper bound of the certainty of this goal, used to lower the certainty
......@@ -79,7 +80,7 @@ where
7980 if ecx.typing_mode().is_coherence() {
8081 Certainty::AMBIGUOUS
8182 } else {
82 return Err(NoSolution);
83 return Err(NoSolution.into());
8384 }
8485 }
8586
......@@ -90,7 +91,7 @@ where
9091 // Impl doesn't match polarity
9192 (ty::ImplPolarity::Positive, ty::PredicatePolarity::Negative)
9293 | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Positive) => {
93 return Err(NoSolution);
94 return Err(NoSolution.into());
9495 }
9596 };
9697
......@@ -118,14 +119,14 @@ where
118119 .map(|pred| goal.with(cx, pred)),
119120 );
120121
121 then(ecx, maximal_certainty)
122 then(ecx, maximal_certainty).map_err(Into::into)
122123 })
123124 }
124125
125126 fn consider_error_guaranteed_candidate(
126127 ecx: &mut EvalCtxt<'_, D>,
127128 _guar: I::ErrorGuaranteed,
128 ) -> Result<Candidate<I>, NoSolution> {
129 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
129130 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
130131 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
131132 }
......@@ -174,8 +175,8 @@ where
174175 ecx: &mut EvalCtxt<'_, D>,
175176 goal: Goal<I, Self>,
176177 assumption: I::Clause,
177 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
178 ) -> QueryResult<I> {
178 then: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResultOrRerunNonErased<I>,
179 ) -> QueryResultOrRerunNonErased<I> {
179180 let trait_clause = assumption.as_trait_clause().unwrap();
180181
181182 // PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so
......@@ -200,10 +201,10 @@ where
200201 fn consider_auto_trait_candidate(
201202 ecx: &mut EvalCtxt<'_, D>,
202203 goal: Goal<I, Self>,
203 ) -> Result<Candidate<I>, NoSolution> {
204 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
204205 let cx = ecx.cx();
205206 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
206 return Err(NoSolution);
207 return Err(NoSolution.into());
207208 }
208209
209210 if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) {
......@@ -215,7 +216,7 @@ where
215216 if cx.trait_is_unsafe(goal.predicate.def_id())
216217 && goal.predicate.self_ty().has_unsafe_fields()
217218 {
218 return Err(NoSolution);
219 return Err(NoSolution.into());
219220 }
220221
221222 // We leak the implemented auto traits of opaques outside of their defining scope.
......@@ -237,8 +238,8 @@ where
237238 goal.predicate.self_ty().kind()
238239 {
239240 if ecx.opaque_accesses.might_rerun() {
240 ecx.opaque_accesses.rerun_always(RerunReason::AutoTraitLeakage);
241 return Err(NoSolution);
241 ecx.opaque_accesses.rerun_always(RerunReason::AutoTraitLeakage)?;
242 return Err(NoSolution.into());
242243 }
243244
244245 debug_assert!(ecx.opaque_type_is_rigid(def_id));
......@@ -247,7 +248,7 @@ where
247248 .as_trait_clause()
248249 .is_some_and(|b| b.def_id() == goal.predicate.def_id())
249250 {
250 return Err(NoSolution);
251 return Err(NoSolution.into());
251252 }
252253 }
253254 }
......@@ -267,9 +268,9 @@ where
267268 fn consider_trait_alias_candidate(
268269 ecx: &mut EvalCtxt<'_, D>,
269270 goal: Goal<I, Self>,
270 ) -> Result<Candidate<I>, NoSolution> {
271 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
271272 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
272 return Err(NoSolution);
273 return Err(NoSolution.into());
273274 }
274275
275276 let cx = ecx.cx();
......@@ -294,9 +295,9 @@ where
294295 ecx: &mut EvalCtxt<'_, D>,
295296 goal: Goal<I, Self>,
296297 sizedness: SizedTraitKind,
297 ) -> Result<Candidate<I>, NoSolution> {
298 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
298299 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
299 return Err(NoSolution);
300 return Err(NoSolution.into());
300301 }
301302
302303 ecx.probe_and_evaluate_goal_for_constituent_tys(
......@@ -313,9 +314,9 @@ where
313314 fn consider_builtin_copy_clone_candidate(
314315 ecx: &mut EvalCtxt<'_, D>,
315316 goal: Goal<I, Self>,
316 ) -> Result<Candidate<I>, NoSolution> {
317 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
317318 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
318 return Err(NoSolution);
319 return Err(NoSolution.into());
319320 }
320321
321322 // We need to make sure to stall any coroutines we are inferring to avoid query cycles.
......@@ -333,7 +334,7 @@ where
333334 fn consider_builtin_fn_ptr_trait_candidate(
334335 ecx: &mut EvalCtxt<'_, D>,
335336 goal: Goal<I, Self>,
336 ) -> Result<Candidate<I>, NoSolution> {
337 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
337338 let self_ty = goal.predicate.self_ty();
338339 match goal.predicate.polarity {
339340 // impl FnPtr for FnPtr {}
......@@ -343,7 +344,7 @@ where
343344 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
344345 })
345346 } else {
346 Err(NoSolution)
347 Err(NoSolution.into())
347348 }
348349 }
349350 // impl !FnPtr for T where T != FnPtr && T is rigid {}
......@@ -355,7 +356,7 @@ where
355356 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
356357 })
357358 } else {
358 Err(NoSolution)
359 Err(NoSolution.into())
359360 }
360361 }
361362 }
......@@ -365,9 +366,9 @@ where
365366 ecx: &mut EvalCtxt<'_, D>,
366367 goal: Goal<I, Self>,
367368 goal_kind: ty::ClosureKind,
368 ) -> Result<Candidate<I>, NoSolution> {
369 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
369370 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
370 return Err(NoSolution);
371 return Err(NoSolution.into());
371372 }
372373
373374 let cx = ecx.cx();
......@@ -397,15 +398,16 @@ where
397398 pred,
398399 [(GoalSource::ImplWhereBound, goal.with(cx, output_is_sized_pred))],
399400 )
401 .map_err(Into::into)
400402 }
401403
402404 fn consider_builtin_async_fn_trait_candidates(
403405 ecx: &mut EvalCtxt<'_, D>,
404406 goal: Goal<I, Self>,
405407 goal_kind: ty::ClosureKind,
406 ) -> Result<Candidate<I>, NoSolution> {
408 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
407409 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
408 return Err(NoSolution);
410 return Err(NoSolution.into());
409411 }
410412
411413 let cx = ecx.cx();
......@@ -447,26 +449,27 @@ where
447449 .chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
448450 .map(|goal| (GoalSource::ImplWhereBound, goal)),
449451 )
452 .map_err(Into::into)
450453 }
451454
452455 fn consider_builtin_async_fn_kind_helper_candidate(
453456 ecx: &mut EvalCtxt<'_, D>,
454457 goal: Goal<I, Self>,
455 ) -> Result<Candidate<I>, NoSolution> {
458 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
456459 let [closure_fn_kind_ty, goal_kind_ty] = *goal.predicate.trait_ref.args.as_slice() else {
457460 panic!();
458461 };
459462
460463 let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else {
461464 // We don't need to worry about the self type being an infer var.
462 return Err(NoSolution);
465 return Err(NoSolution.into());
463466 };
464467 let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap();
465468 if closure_kind.extends(goal_kind) {
466469 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
467470 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
468471 } else {
469 Err(NoSolution)
472 Err(NoSolution.into())
470473 }
471474 }
472475
......@@ -479,25 +482,25 @@ where
479482 fn consider_builtin_tuple_candidate(
480483 ecx: &mut EvalCtxt<'_, D>,
481484 goal: Goal<I, Self>,
482 ) -> Result<Candidate<I>, NoSolution> {
485 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
483486 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
484 return Err(NoSolution);
487 return Err(NoSolution.into());
485488 }
486489
487490 if let ty::Tuple(..) = goal.predicate.self_ty().kind() {
488491 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
489492 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
490493 } else {
491 Err(NoSolution)
494 Err(NoSolution.into())
492495 }
493496 }
494497
495498 fn consider_builtin_pointee_candidate(
496499 ecx: &mut EvalCtxt<'_, D>,
497500 goal: Goal<I, Self>,
498 ) -> Result<Candidate<I>, NoSolution> {
501 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
499502 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
500 return Err(NoSolution);
503 return Err(NoSolution.into());
501504 }
502505
503506 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
......@@ -507,19 +510,19 @@ where
507510 fn consider_builtin_future_candidate(
508511 ecx: &mut EvalCtxt<'_, D>,
509512 goal: Goal<I, Self>,
510 ) -> Result<Candidate<I>, NoSolution> {
513 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
511514 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
512 return Err(NoSolution);
515 return Err(NoSolution.into());
513516 }
514517
515518 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
516 return Err(NoSolution);
519 return Err(NoSolution.into());
517520 };
518521
519522 // Coroutines are not futures unless they come from `async` desugaring
520523 let cx = ecx.cx();
521524 if !cx.coroutine_is_async(def_id) {
522 return Err(NoSolution);
525 return Err(NoSolution.into());
523526 }
524527
525528 // Async coroutine unconditionally implement `Future`
......@@ -532,19 +535,19 @@ where
532535 fn consider_builtin_iterator_candidate(
533536 ecx: &mut EvalCtxt<'_, D>,
534537 goal: Goal<I, Self>,
535 ) -> Result<Candidate<I>, NoSolution> {
538 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
536539 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
537 return Err(NoSolution);
540 return Err(NoSolution.into());
538541 }
539542
540543 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
541 return Err(NoSolution);
544 return Err(NoSolution.into());
542545 };
543546
544547 // Coroutines are not iterators unless they come from `gen` desugaring
545548 let cx = ecx.cx();
546549 if !cx.coroutine_is_gen(def_id) {
547 return Err(NoSolution);
550 return Err(NoSolution.into());
548551 }
549552
550553 // Gen coroutines unconditionally implement `Iterator`
......@@ -557,19 +560,19 @@ where
557560 fn consider_builtin_fused_iterator_candidate(
558561 ecx: &mut EvalCtxt<'_, D>,
559562 goal: Goal<I, Self>,
560 ) -> Result<Candidate<I>, NoSolution> {
563 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
561564 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
562 return Err(NoSolution);
565 return Err(NoSolution.into());
563566 }
564567
565568 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
566 return Err(NoSolution);
569 return Err(NoSolution.into());
567570 };
568571
569572 // Coroutines are not iterators unless they come from `gen` desugaring
570573 let cx = ecx.cx();
571574 if !cx.coroutine_is_gen(def_id) {
572 return Err(NoSolution);
575 return Err(NoSolution.into());
573576 }
574577
575578 // Gen coroutines unconditionally implement `FusedIterator`.
......@@ -580,19 +583,19 @@ where
580583 fn consider_builtin_async_iterator_candidate(
581584 ecx: &mut EvalCtxt<'_, D>,
582585 goal: Goal<I, Self>,
583 ) -> Result<Candidate<I>, NoSolution> {
586 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
584587 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
585 return Err(NoSolution);
588 return Err(NoSolution.into());
586589 }
587590
588591 let ty::Coroutine(def_id, _) = goal.predicate.self_ty().kind() else {
589 return Err(NoSolution);
592 return Err(NoSolution.into());
590593 };
591594
592595 // Coroutines are not iterators unless they come from `gen` desugaring
593596 let cx = ecx.cx();
594597 if !cx.coroutine_is_async_gen(def_id) {
595 return Err(NoSolution);
598 return Err(NoSolution.into());
596599 }
597600
598601 // Gen coroutines unconditionally implement `Iterator`
......@@ -605,20 +608,20 @@ where
605608 fn consider_builtin_coroutine_candidate(
606609 ecx: &mut EvalCtxt<'_, D>,
607610 goal: Goal<I, Self>,
608 ) -> Result<Candidate<I>, NoSolution> {
611 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
609612 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
610 return Err(NoSolution);
613 return Err(NoSolution.into());
611614 }
612615
613616 let self_ty = goal.predicate.self_ty();
614617 let ty::Coroutine(def_id, args) = self_ty.kind() else {
615 return Err(NoSolution);
618 return Err(NoSolution.into());
616619 };
617620
618621 // `async`-desugared coroutines do not implement the coroutine trait
619622 let cx = ecx.cx();
620623 if !cx.is_general_coroutine(def_id) {
621 return Err(NoSolution);
624 return Err(NoSolution.into());
622625 }
623626
624627 let coroutine = args.as_coroutine();
......@@ -637,9 +640,9 @@ where
637640 fn consider_builtin_discriminant_kind_candidate(
638641 ecx: &mut EvalCtxt<'_, D>,
639642 goal: Goal<I, Self>,
640 ) -> Result<Candidate<I>, NoSolution> {
643 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
641644 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
642 return Err(NoSolution);
645 return Err(NoSolution.into());
643646 }
644647
645648 // `DiscriminantKind` is automatically implemented for every type.
......@@ -650,9 +653,9 @@ where
650653 fn consider_builtin_destruct_candidate(
651654 ecx: &mut EvalCtxt<'_, D>,
652655 goal: Goal<I, Self>,
653 ) -> Result<Candidate<I>, NoSolution> {
656 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
654657 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
655 return Err(NoSolution);
658 return Err(NoSolution.into());
656659 }
657660
658661 // `Destruct` is automatically implemented for every type in
......@@ -664,14 +667,14 @@ where
664667 fn consider_builtin_transmute_candidate(
665668 ecx: &mut EvalCtxt<'_, D>,
666669 goal: Goal<I, Self>,
667 ) -> Result<Candidate<I>, NoSolution> {
670 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
668671 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
669 return Err(NoSolution);
672 return Err(NoSolution.into());
670673 }
671674
672675 // `rustc_transmute` does not have support for type or const params
673676 if goal.predicate.has_non_region_placeholders() {
674 return Err(NoSolution);
677 return Err(NoSolution.into());
675678 }
676679
677680 // Match the old solver by treating unresolved inference variables as
......@@ -680,19 +683,21 @@ where
680683 return ecx.forced_ambiguity(MaybeInfo::AMBIGUOUS);
681684 }
682685
683 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
684 let assume = ecx.structurally_normalize_const(
685 goal.param_env,
686 goal.predicate.trait_ref.args.const_at(2),
687 )?;
686 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(
687 |ecx| -> Result<_, NoSolutionOrRerunNonErased> {
688 let assume = ecx.structurally_normalize_const(
689 goal.param_env,
690 goal.predicate.trait_ref.args.const_at(2),
691 )?;
688692
689 let certainty = ecx.is_transmutable(
690 goal.predicate.trait_ref.args.type_at(0),
691 goal.predicate.trait_ref.args.type_at(1),
692 assume,
693 )?;
694 ecx.evaluate_added_goals_and_make_canonical_response(certainty)
695 })
693 let certainty = ecx.is_transmutable(
694 goal.predicate.trait_ref.args.type_at(0),
695 goal.predicate.trait_ref.args.type_at(1),
696 assume,
697 )?;
698 ecx.evaluate_added_goals_and_make_canonical_response(certainty).map_err(Into::into)
699 },
700 )
696701 }
697702
698703 /// NOTE: This is implemented as a built-in goal and not a set of impls like:
......@@ -710,9 +715,9 @@ where
710715 fn consider_builtin_bikeshed_guaranteed_no_drop_candidate(
711716 ecx: &mut EvalCtxt<'_, D>,
712717 goal: Goal<I, Self>,
713 ) -> Result<Candidate<I>, NoSolution> {
718 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
714719 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
715 return Err(NoSolution);
720 return Err(NoSolution.into());
716721 }
717722
718723 let cx = ecx.cx();
......@@ -803,13 +808,13 @@ where
803808 fn consider_structural_builtin_unsize_candidates(
804809 ecx: &mut EvalCtxt<'_, D>,
805810 goal: Goal<I, Self>,
806 ) -> Vec<Candidate<I>> {
811 ) -> Result<Vec<Candidate<I>>, RerunNonErased> {
807812 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
808 return vec![];
813 return Ok(vec![]);
809814 }
810815
811816 let result = ecx.probe(|_| ProbeKind::UnsizeAssembly).enter(
812 |ecx| -> Result<Vec<Candidate<I>>, NoSolution> {
817 |ecx| -> Result<Vec<Candidate<I>>, NoSolutionOrRerunNonErased> {
813818 let a_ty = goal.predicate.self_ty();
814819 // We need to normalize the b_ty since it's matched structurally
815820 // in the other functions below.
......@@ -849,23 +854,23 @@ where
849854 Ok(vec![ecx.consider_builtin_struct_unsize(goal, a_def, a_args, b_args)?])
850855 }
851856
852 _ => Err(NoSolution),
857 _ => Err(NoSolution.into()),
853858 }
854859 },
855860 );
856861
857 match result.map_err(Into::into) {
858 Ok(resp) => resp,
859 Err(NoSolution) => vec![],
862 match result.map_err_to_rerun()? {
863 Ok(resp) => Ok(resp),
864 Err(NoSolution) => Ok(vec![]),
860865 }
861866 }
862867
863868 fn consider_builtin_field_candidate(
864869 ecx: &mut EvalCtxt<'_, D>,
865870 goal: Goal<I, Self>,
866 ) -> Result<Candidate<I>, NoSolution> {
871 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
867872 if goal.predicate.polarity != ty::PredicatePolarity::Positive {
868 return Err(NoSolution);
873 return Err(NoSolution.into());
869874 }
870875 if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
871876 && let Some(FieldInfo { base, ty, .. }) =
......@@ -904,7 +909,7 @@ where
904909 ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
905910 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
906911 } else {
907 Err(NoSolution)
912 Err(NoSolution.into())
908913 }
909914 }
910915}
......@@ -995,13 +1000,13 @@ where
9951000 goal: Goal<I, (I::Ty, I::Ty)>,
9961001 b_data: I::BoundExistentialPredicates,
9971002 b_region: I::Region,
998 ) -> Result<Candidate<I>, NoSolution> {
1003 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
9991004 let cx = self.cx();
10001005 let Goal { predicate: (a_ty, _), .. } = goal;
10011006
10021007 // Can only unsize to an dyn-compatible trait.
10031008 if b_data.principal_def_id().is_some_and(|def_id| !cx.trait_is_dyn_compatible(def_id)) {
1004 return Err(NoSolution);
1009 return Err(NoSolution.into());
10051010 }
10061011
10071012 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
......@@ -1040,7 +1045,7 @@ where
10401045 b_data: I::BoundExistentialPredicates,
10411046 b_region: I::Region,
10421047 upcast_principal: Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>,
1043 ) -> Result<Candidate<I>, NoSolution> {
1048 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
10441049 let param_env = goal.param_env;
10451050
10461051 // We may upcast to auto traits that are either explicitly listed in
......@@ -1066,13 +1071,14 @@ where
10661071 source_projection.item_def_id() == target_projection.item_def_id()
10671072 && ecx
10681073 .probe(|_| ProbeKind::ProjectionCompatibility)
1069 .enter(|ecx| -> Result<_, NoSolution> {
1074 .enter(|ecx| {
10701075 ecx.enter_forall(target_projection, |ecx, target_projection| {
10711076 let source_projection =
10721077 ecx.instantiate_binder_with_infer(source_projection);
10731078 ecx.eq(param_env, source_projection, target_projection)?;
10741079 ecx.try_evaluate_added_goals()
10751080 })
1081 .map_err(Into::into)
10761082 })
10771083 .is_ok()
10781084 };
......@@ -1104,12 +1110,14 @@ where
11041110 projection_may_match(ecx, *source_projection, target_projection)
11051111 });
11061112 let Some(source_projection) = matching_projections.next() else {
1107 return Err(NoSolution);
1113 return Err(NoSolution.into());
11081114 };
11091115 if matching_projections.next().is_some() {
1110 return ecx.evaluate_added_goals_and_make_canonical_response(
1111 Certainty::AMBIGUOUS,
1112 );
1116 return ecx
1117 .evaluate_added_goals_and_make_canonical_response(
1118 Certainty::AMBIGUOUS,
1119 )
1120 .map_err(Into::into);
11131121 }
11141122 ecx.enter_forall(target_projection, |ecx, target_projection| {
11151123 let source_projection =
......@@ -1121,7 +1129,7 @@ where
11211129 // Check that b_ty's auto traits are present in a_ty's bounds.
11221130 ty::ExistentialPredicate::AutoTrait(def_id) => {
11231131 if !a_auto_traits.contains(&def_id) {
1124 return Err(NoSolution);
1132 return Err(NoSolution.into());
11251133 }
11261134 }
11271135 }
......@@ -1133,7 +1141,7 @@ where
11331141 Goal::new(ecx.cx(), param_env, ty::OutlivesPredicate(a_region, b_region)),
11341142 );
11351143
1136 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1144 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into)
11371145 })
11381146 }
11391147
......@@ -1150,7 +1158,7 @@ where
11501158 goal: Goal<I, (I::Ty, I::Ty)>,
11511159 a_elem_ty: I::Ty,
11521160 b_elem_ty: I::Ty,
1153 ) -> Result<Candidate<I>, NoSolution> {
1161 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
11541162 self.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
11551163 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
11561164 .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
......@@ -1175,7 +1183,7 @@ where
11751183 def: I::AdtDef,
11761184 a_args: I::GenericArgs,
11771185 b_args: I::GenericArgs,
1178 ) -> Result<Candidate<I>, NoSolution> {
1186 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
11791187 let cx = self.cx();
11801188 let Goal { predicate: (_a_ty, b_ty), .. } = goal;
11811189
......@@ -1183,7 +1191,7 @@ where
11831191 // We must be unsizing some type parameters. This also implies
11841192 // that the struct has a tail field.
11851193 if unsizing_params.is_empty() {
1186 return Err(NoSolution);
1194 return Err(NoSolution.into());
11871195 }
11881196
11891197 let tail_field_ty = def.struct_tail_ty(cx).unwrap();
......@@ -1224,7 +1232,7 @@ where
12241232 fn disqualify_auto_trait_candidate_due_to_possible_impl(
12251233 &mut self,
12261234 goal: Goal<I, TraitPredicate<I>>,
1227 ) -> Option<Result<Candidate<I>, NoSolution>> {
1235 ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
12281236 let self_ty = goal.predicate.self_ty();
12291237 let check_impls = || {
12301238 let mut disqualifying_impl = None;
......@@ -1239,7 +1247,7 @@ where
12391247 trace!(?def_id, ?goal, "disqualified auto-trait implementation");
12401248 // No need to actually consider the candidate here,
12411249 // since we do that in `consider_impl_candidate`.
1242 return Some(Err(NoSolution));
1250 return Some(Err(NoSolution.into()));
12431251 } else {
12441252 None
12451253 }
......@@ -1268,7 +1276,7 @@ where
12681276 kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. },
12691277 ..
12701278 })
1271 | ty::Placeholder(..) => Some(Err(NoSolution)),
1279 | ty::Placeholder(..) => Some(Err(NoSolution.into())),
12721280
12731281 ty::Infer(_) | ty::Bound(_, _) => panic!("unexpected type `{self_ty:?}`"),
12741282
......@@ -1281,7 +1289,7 @@ where
12811289 .is_trait_lang_item(goal.predicate.def_id(), SolverTraitLangItem::Unpin) =>
12821290 {
12831291 match self.cx().coroutine_movability(def_id) {
1284 Movability::Static => Some(Err(NoSolution)),
1292 Movability::Static => Some(Err(NoSolution.into())),
12851293 Movability::Movable => Some(
12861294 self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
12871295 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
......@@ -1339,7 +1347,7 @@ where
13391347 &EvalCtxt<'_, D>,
13401348 I::Ty,
13411349 ) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
1342 ) -> Result<Candidate<I>, NoSolution> {
1350 ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
13431351 self.probe_trait_candidate(source).enter(|ecx| {
13441352 let goals =
13451353 ecx.enter_forall(constituent_tys(ecx, goal.predicate.self_ty())?, |ecx, tys| {
......@@ -1548,15 +1556,20 @@ where
15481556 pub(super) fn compute_trait_goal(
15491557 &mut self,
15501558 goal: Goal<I, TraitPredicate<I>>,
1551 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolution> {
1559 ) -> Result<(CanonicalResponse<I>, Option<TraitGoalProvenVia>), NoSolutionOrRerunNonErased>
1560 {
15521561 let (candidates, failed_candidate_info) =
1553 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
1562 self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All)?;
15541563 let candidate_preference_mode =
15551564 CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id());
15561565 self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info)
1566 .map_err(Into::into)
15571567 }
15581568
1559 fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option<Result<Candidate<I>, NoSolution>> {
1569 fn try_stall_coroutine(
1570 &mut self,
1571 self_ty: I::Ty,
1572 ) -> Option<Result<Candidate<I>, NoSolutionOrRerunNonErased>> {
15601573 if let ty::Coroutine(def_id, _) = self_ty.kind() {
15611574 match self.typing_mode() {
15621575 TypingMode::Analysis {
......@@ -1573,8 +1586,11 @@ where
15731586 }
15741587 TypingMode::ErasedNotCoherence(MayBeErased) => {
15751588 // Trying to continue here isn't worth it.
1576 self.opaque_accesses.rerun_always(RerunReason::TryStallCoroutine);
1577 return Some(Err(NoSolution));
1589 return Some(
1590 match self.opaque_accesses.rerun_always(RerunReason::TryStallCoroutine) {
1591 Err(e) => Err(e.into()),
1592 },
1593 );
15781594 }
15791595 TypingMode::Coherence
15801596 | TypingMode::PostAnalysis
compiler/rustc_trait_selection/src/solve/delegate.rs+57-32
......@@ -13,7 +13,7 @@ use rustc_infer::traits::solve::{FetchEligibleAssocItemResponse, Goal};
1313use rustc_middle::traits::query::NoSolution;
1414use rustc_middle::traits::solve::Certainty;
1515use rustc_middle::ty::{
16 self, MayBeErased, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
16 self, MayBeErased, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt, TypingMode,
1717};
1818use rustc_span::{DUMMY_SP, Span};
1919
......@@ -73,51 +73,60 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
7373 goal: Goal<'tcx, ty::Predicate<'tcx>>,
7474 span: Span,
7575 ) -> Option<Certainty> {
76 if let Some(trait_pred) = goal.predicate.as_trait_clause() {
77 if self.shallow_resolve(trait_pred.self_ty().skip_binder()).is_ty_var()
76 let pred = goal.predicate.kind();
77 match pred.skip_binder() {
78 ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
79 let trait_pred = pred.rebind(trait_pred);
80
81 if self.shallow_resolve(trait_pred.self_ty().skip_binder()).is_ty_var()
7882 // We don't do this fast path when opaques are defined since we may
7983 // eventually use opaques to incompletely guide inference via ty var
8084 // self types.
8185 // FIXME: Properly consider opaques here.
8286 && self.known_no_opaque_types_in_storage()
83 {
84 return Some(Certainty::AMBIGUOUS);
85 }
86
87 if trait_pred.polarity() == ty::PredicatePolarity::Positive {
88 match self.0.tcx.as_lang_item(trait_pred.def_id()) {
89 Some(LangItem::Sized) | Some(LangItem::MetaSized) => {
90 let predicate = self.resolve_vars_if_possible(goal.predicate);
91 if sizedness_fast_path(self.tcx, predicate, goal.param_env) {
92 return Some(Certainty::Yes);
87 {
88 Some(Certainty::AMBIGUOUS)
89 } else if trait_pred.polarity() == ty::PredicatePolarity::Positive {
90 match self.0.tcx.as_lang_item(trait_pred.def_id()) {
91 Some(LangItem::Sized) | Some(LangItem::MetaSized) => {
92 let predicate = self.resolve_vars_if_possible(goal.predicate);
93 if sizedness_fast_path(self.tcx, predicate, goal.param_env) {
94 return Some(Certainty::Yes);
95 } else {
96 None
97 }
9398 }
94 }
95 Some(LangItem::Copy | LangItem::Clone) => {
96 let self_ty =
97 self.resolve_vars_if_possible(trait_pred.self_ty().skip_binder());
98 // Unlike `Sized` traits, which always prefer the built-in impl,
99 // `Copy`/`Clone` may be shadowed by a param-env candidate which
100 // could force a lifetime error or guide inference. While that's
101 // not generally desirable, it is observable, so for now let's
102 // ignore this fast path for types that have regions or infer.
103 if !self_ty
104 .has_type_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_INFER)
105 && self_ty.is_trivially_pure_clone_copy()
106 {
107 return Some(Certainty::Yes);
99 Some(LangItem::Copy | LangItem::Clone) => {
100 let self_ty =
101 self.resolve_vars_if_possible(trait_pred.self_ty().skip_binder());
102 // Unlike `Sized` traits, which always prefer the built-in impl,
103 // `Copy`/`Clone` may be shadowed by a param-env candidate which
104 // could force a lifetime error or guide inference. While that's
105 // not generally desirable, it is observable, so for now let's
106 // ignore this fast path for types that have regions or infer.
107 if !self_ty
108 .has_type_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_INFER)
109 && self_ty.is_trivially_pure_clone_copy()
110 {
111 return Some(Certainty::Yes);
112 } else {
113 None
114 }
108115 }
116 _ => None,
109117 }
110 _ => {}
118 } else {
119 None
111120 }
112121 }
113 }
114
115 let pred = goal.predicate.kind();
116 match pred.no_bound_vars()? {
117122 ty::PredicateKind::DynCompatible(def_id) if self.0.tcx.is_dyn_compatible(def_id) => {
118123 Some(Certainty::Yes)
119124 }
120125 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(outlives)) => {
126 if outlives.has_escaping_bound_vars() {
127 return None;
128 }
129
121130 self.0.sub_regions(
122131 SubregionOrigin::RelateRegionParamBound(span, None),
123132 outlives.1,
......@@ -127,6 +136,10 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
127136 Some(Certainty::Yes)
128137 }
129138 ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
139 if outlives.has_escaping_bound_vars() {
140 return None;
141 }
142
130143 self.0.register_type_outlives_constraint(
131144 outlives.0,
132145 outlives.1,
......@@ -137,6 +150,10 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
137150 }
138151 ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, .. })
139152 | ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
153 if a.has_escaping_bound_vars() || b.has_escaping_bound_vars() {
154 return None;
155 }
156
140157 match (self.shallow_resolve(a).kind(), self.shallow_resolve(b).kind()) {
141158 (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
142159 self.sub_unify_ty_vids_raw(a_vid, b_vid);
......@@ -146,6 +163,10 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
146163 }
147164 }
148165 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) => {
166 if ct.has_escaping_bound_vars() {
167 return None;
168 }
169
149170 if self.shallow_resolve_const(ct).is_ct_infer() {
150171 Some(Certainty::AMBIGUOUS)
151172 } else {
......@@ -153,6 +174,10 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
153174 }
154175 }
155176 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
177 if arg.has_escaping_bound_vars() {
178 return None;
179 }
180
156181 let arg = self.shallow_resolve_term(arg);
157182 if arg.is_trivially_wf(self.tcx) {
158183 Some(Certainty::Yes)
compiler/rustc_type_ir/src/interner.rs+9-4
......@@ -4,6 +4,7 @@ use std::hash::Hash;
44use std::ops::Deref;
55
66use rustc_ast_ir::Movability;
7use rustc_ast_ir::visit::VisitorResult;
78use rustc_index::bit_set::DenseBitSet;
89
910use crate::fold::TypeFoldable;
......@@ -401,13 +402,17 @@ pub trait Interner:
401402 def_id: Self::TraitId,
402403 ) -> impl IntoIterator<Item = Self::DefId>;
403404
404 fn for_each_relevant_impl(
405 fn for_each_relevant_impl<R: VisitorResult>(
405406 self,
406407 trait_def_id: Self::TraitId,
407408 self_ty: Self::Ty,
408 f: impl FnMut(Self::ImplId),
409 );
410 fn for_each_blanket_impl(self, trait_def_id: Self::TraitId, f: impl FnMut(Self::ImplId));
409 f: impl FnMut(Self::ImplId) -> R,
410 ) -> R;
411 fn for_each_blanket_impl<R: VisitorResult>(
412 self,
413 trait_def_id: Self::TraitId,
414 f: impl FnMut(Self::ImplId) -> R,
415 ) -> R;
411416
412417 fn has_item_definition(self, def_id: Self::ImplOrTraitAssocTermId) -> bool;
413418
compiler/rustc_type_ir/src/solve/mod.rs+56-30
......@@ -1,5 +1,6 @@
11pub mod inspect;
22
3use std::convert::Infallible;
34use std::fmt::Debug;
45use std::hash::Hash;
56
......@@ -27,38 +28,55 @@ pub type CanonicalResponse<I> = Canonical<I, Response<I>>;
2728/// having to worry about changes to currently used code. Once we've made progress on this
2829/// solver, merge the two responses again.
2930pub type QueryResult<I> = Result<CanonicalResponse<I>, NoSolution>;
31pub type QueryResultOrRerunNonErased<I> = Result<CanonicalResponse<I>, NoSolutionOrRerunNonErased>;
3032
3133#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
3234#[cfg_attr(feature = "nightly", derive(StableHash))]
3335pub struct NoSolution;
3436
35pub enum NoSolutionOrOpaquesAccessed {
36 NoSolution(NoSolution),
37 /// A bit like [`NoSolution`], but for functions that normally cannot fail *unless* they accessed
38 /// opaues. (See [`TypingMode::ErasedNotCoherence`]). Getting `OpaquesAccessed` doesn't mean there
39 /// truly is no solution. It just means that we want to bail out of the current query as fast as
40 /// possible, possibly by returning `NoSolution` if that's fastest. This is okay because when you get
41 /// `OpaquesAccessed` we're guaranteed that we're going to retry this query in the original typing
42 /// mode to get the correct answer.
43 OpaquesAccessed,
37pub trait RerunResultExt<T> {
38 fn map_err_to_rerun(self) -> Result<Result<T, NoSolution>, RerunNonErased>;
4439}
4540
46/// This conversion is sound, because even in we're in `OpaquesAccessed`,
47/// we're going to retry so `NoSolution` is a valid response to give..
48impl From<NoSolutionOrOpaquesAccessed> for NoSolution {
49 fn from(
50 (NoSolutionOrOpaquesAccessed::NoSolution(_) | NoSolutionOrOpaquesAccessed::OpaquesAccessed): NoSolutionOrOpaquesAccessed,
51 ) -> Self {
52 NoSolution
41impl<T> RerunResultExt<T> for Result<T, NoSolutionOrRerunNonErased> {
42 fn map_err_to_rerun(self) -> Result<Result<T, NoSolution>, RerunNonErased> {
43 match self {
44 Ok(i) => Ok(Ok(i)),
45 Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) => Ok(Err(NoSolution)),
46 Err(NoSolutionOrRerunNonErased::RerunNonErased(e)) => Err(e),
47 }
5348 }
5449}
5550
56impl From<NoSolution> for NoSolutionOrOpaquesAccessed {
51/// A bit like [`NoSolution`], but for functions that normally cannot fail *unless* they accessed
52/// opaues. (See [`TypingMode::ErasedNotCoherence`]). Getting `OpaquesAccessed` doesn't mean there
53/// truly is no solution. It just means that we want to bail out of the current query as fast as
54/// possible, possibly by returning `NoSolution` if that's fastest. This is okay because when you get
55/// `OpaquesAccessed` we're guaranteed that we're going to retry this query in the original typing
56/// mode to get the correct answer.
57#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
58#[cfg_attr(feature = "nightly", derive(StableHash))]
59pub struct RerunNonErased(());
60
61#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
62#[cfg_attr(feature = "nightly", derive(StableHash))]
63pub enum NoSolutionOrRerunNonErased {
64 NoSolution(NoSolution),
65 RerunNonErased(RerunNonErased),
66}
67
68impl From<NoSolution> for NoSolutionOrRerunNonErased {
5769 fn from(value: NoSolution) -> Self {
5870 Self::NoSolution(value)
5971 }
6072}
6173
74impl From<RerunNonErased> for NoSolutionOrRerunNonErased {
75 fn from(value: RerunNonErased) -> Self {
76 Self::RerunNonErased(value)
77 }
78}
79
6280#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
6381#[derive(TypeVisitable_Generic, TypeFoldable_Generic, GenericTypeVisitable)]
6482#[cfg_attr(feature = "nightly", derive(StableHash_NoContext))]
......@@ -216,13 +234,13 @@ impl<I: Interner> RerunCondition<I> {
216234 }
217235
218236 #[must_use]
219 fn should_bail(&self) -> bool {
237 fn should_bail(&self) -> Result<(), RerunNonErased> {
220238 match self {
221 Self::Always => true,
239 Self::Always => Err(RerunNonErased(())),
222240 Self::Never
223241 | Self::OpaqueInStorage(_)
224242 | Self::OpaqueInStorageOrAnyOpaqueHasInferAsHidden(_)
225 | Self::AnyOpaqueHasInferAsHidden => false,
243 | Self::AnyOpaqueHasInferAsHidden => Ok(()),
226244 }
227245 }
228246
......@@ -274,13 +292,15 @@ impl<I: Interner> Default for AccessedOpaques<I> {
274292}
275293
276294impl<I: Interner> AccessedOpaques<I> {
277 pub fn update(&mut self, other: Self) {
295 pub fn update(&mut self, other: Self) -> Result<(), RerunNonErased> {
278296 *self = Self {
279297 // prefer the newest reason
280298 reason: other.reason.or(self.reason),
281299 // merging accessed states can only result in MultipleOrUnknown
282300 rerun: self.rerun.merge(other.rerun),
283301 };
302
303 self.should_bail()
284304 }
285305
286306 #[must_use]
......@@ -289,41 +309,47 @@ impl<I: Interner> AccessedOpaques<I> {
289309 }
290310
291311 #[must_use]
292 pub fn should_bail(&self) -> bool {
312 pub fn should_bail(&self) -> Result<(), RerunNonErased> {
293313 self.rerun.should_bail()
294314 }
295315
296 pub fn rerun_always(&mut self, reason: RerunReason) {
316 pub fn rerun_always(&mut self, reason: RerunReason) -> Result<Infallible, RerunNonErased> {
297317 debug!("set rerun always");
298 self.update(AccessedOpaques { reason: Some(reason), rerun: RerunCondition::Always });
318 match self.update(AccessedOpaques { reason: Some(reason), rerun: RerunCondition::Always }) {
319 Ok(_) => unreachable!(),
320 Err(e) => Err(e),
321 }
299322 }
300323
301 pub fn rerun_if_in_post_analysis(&mut self, reason: RerunReason) {
324 pub fn rerun_if_in_post_analysis(&mut self, reason: RerunReason) -> Result<(), RerunNonErased> {
302325 debug!("set rerun if post analysis");
303326 self.update(AccessedOpaques {
304327 reason: Some(reason),
305328 rerun: RerunCondition::OpaqueInStorage(SmallCopyList::empty()),
306 });
329 })
307330 }
308331
309332 pub fn rerun_if_opaque_in_opaque_type_storage(
310333 &mut self,
311334 reason: RerunReason,
312335 defid: I::LocalDefId,
313 ) {
336 ) -> Result<(), RerunNonErased> {
314337 debug!("set rerun if opaque type {defid:?} in storage");
315338 self.update(AccessedOpaques {
316339 reason: Some(reason),
317340 rerun: RerunCondition::OpaqueInStorage(SmallCopyList::new(defid)),
318 });
341 })
319342 }
320343
321 pub fn rerun_if_any_opaque_has_infer_as_hidden_type(&mut self, reason: RerunReason) {
344 pub fn rerun_if_any_opaque_has_infer_as_hidden_type(
345 &mut self,
346 reason: RerunReason,
347 ) -> Result<(), RerunNonErased> {
322348 debug!("set rerun if any opaque in the storage has a hidden type that is an infer var");
323349 self.update(AccessedOpaques {
324350 reason: Some(reason),
325351 rerun: RerunCondition::AnyOpaqueHasInferAsHidden,
326 });
352 })
327353 }
328354}
329355
tests/run-make/msvc-incremental-full-link-info/main.rs created+1
......@@ -0,0 +1 @@
1fn main() {}
tests/run-make/msvc-incremental-full-link-info/rmake.rs created+47
......@@ -0,0 +1,47 @@
1//@ only-msvc
2//! Tests that the MSVC incremental linker's "performing full link" message is classified as
3//! `linker_info`, not `linker_messages`.
4//!
5//! The MSVC incremental linker prints this message to stdout when it finds a `.ilk` file for
6//! incremental linking but its associated `.exe` file is missing:
7//!
8//! ```
9//! LINK : ...\main.exe not found or not built by the last incremental link; performing full link
10//! ```
11
12use std::fs;
13
14use run_make_support::bare_rustc;
15
16fn incremental_rustc() -> run_make_support::Rustc {
17 let mut r = bare_rustc();
18 r.input("main.rs")
19 // Overrides `rust.lld=true` on CI.
20 .arg("-Clinker=link.exe")
21 .arg("-Clinker-flavor=msvc")
22 // Without this, Rust passes /OPT:REF to link.exe, which
23 // disables incremental linking entirely and suppresses the message.
24 .arg("-Clink-dead-code")
25 // /DEBUG is required: it implies /INCREMENTAL, which is what makes
26 // link.exe create the .ilk file and later emit the message.
27 .arg("-Cdebuginfo=2");
28 r
29}
30
31fn main() {
32 // First link: produces main.exe and main.ilk.
33 incremental_rustc().run();
34
35 // Delete the .exe but leave the .ilk.
36 fs::remove_file("main.exe").unwrap();
37
38 // Second link: link.exe finds the .ilk but not the .exe and emits the
39 // "performing full link" message on stdout.
40 let output = incremental_rustc()
41 .arg("-Dlinker_messages") // Fail if the message is misclassified.
42 .arg("-Wlinker_info")
43 .run();
44
45 // Verify the message was actually emitted and routed to linker_info.
46 output.assert_stderr_contains("performing full link");
47}
tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr+3
......@@ -16,6 +16,9 @@ help: the following other types implement trait `VisitorResult`
1616 ::: /rustc-dev/xyz/compiler/rustc_ast_ir/src/visit.rs:LL:COL
1717 |
1818 = note: `ControlFlow<T>`
19 ::: /rustc-dev/xyz/compiler/rustc_ast_ir/src/visit.rs:LL:COL
20 |
21 = note: `Result<(), E>`
1922note: required by a bound in `rustc_ast::visit::Visitor::Result`
2023 --> /rustc-dev/xyz/compiler/rustc_ast/src/visit.rs:LL:COL
2124 ::: /rustc-dev/xyz/compiler/rustc_ast/src/visit.rs:LL:COL
tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr+3
......@@ -17,6 +17,9 @@ LL | impl VisitorResult for () {
1717...
1818LL | impl<T> VisitorResult for ControlFlow<T> {
1919 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ControlFlow<T>`
20...
21LL | impl<E> VisitorResult for Result<(), E> {
22 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Result<(), E>`
2023note: required by a bound in `rustc_ast::visit::Visitor::Result`
2124 --> $COMPILER_DIR_REAL/rustc_ast/src/visit.rs:LL:COL
2225 |
tests/ui/closures/closure-arg-type-mismatch-method-receiver.rs created+13
......@@ -0,0 +1,13 @@
1// Regression test for https://github.com/rust-lang/rust/issues/156299.
2
3struct A;
4
5fn foo(_: &A) {}
6
7fn test_foo() {
8 (|a: A| foo(a)).bar();
9 //~^ ERROR mismatched types
10 //~| ERROR no method named `bar` found
11}
12
13fn main() {}
tests/ui/closures/closure-arg-type-mismatch-method-receiver.stderr created+28
......@@ -0,0 +1,28 @@
1error[E0308]: mismatched types
2 --> $DIR/closure-arg-type-mismatch-method-receiver.rs:8:17
3 |
4LL | (|a: A| foo(a)).bar();
5 | --- ^ expected `&A`, found `A`
6 | |
7 | arguments to this function are incorrect
8 |
9note: function defined here
10 --> $DIR/closure-arg-type-mismatch-method-receiver.rs:5:4
11 |
12LL | fn foo(_: &A) {}
13 | ^^^ -----
14help: consider borrowing here
15 |
16LL | (|a: A| foo(&a)).bar();
17 | +
18
19error[E0599]: no method named `bar` found for closure `{closure@$DIR/closure-arg-type-mismatch-method-receiver.rs:8:6: 8:12}` in the current scope
20 --> $DIR/closure-arg-type-mismatch-method-receiver.rs:8:21
21 |
22LL | (|a: A| foo(a)).bar();
23 | ^^^ method not found in `{closure@$DIR/closure-arg-type-mismatch-method-receiver.rs:8:6: 8:12}`
24
25error: aborting due to 2 previous errors
26
27Some errors have detailed explanations: E0308, E0599.
28For more information about an error, try `rustc --explain E0308`.