Skip to content

Commit 22e7a5a

Browse files
committed
consistently return OpaquesAccessed from probes to signal why they error
1 parent ef84b07 commit 22e7a5a

5 files changed

Lines changed: 58 additions & 22 deletions

File tree

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use derive_where::derive_where;
99
use rustc_type_ir::inherent::*;
1010
use rustc_type_ir::lang_items::SolverTraitLangItem;
1111
use rustc_type_ir::search_graph::CandidateHeadUsages;
12-
use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind};
12+
use rustc_type_ir::solve::{AliasBoundKind, NoSolutionOrOpaquesAccessed, SizedTraitKind};
1313
use rustc_type_ir::{
1414
self as ty, AliasTy, Interner, MayBeErased, TypeFlags, TypeFoldable, TypeFolder,
1515
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
@@ -161,7 +161,7 @@ where
161161
})
162162
});
163163

164-
match result {
164+
match result.map_err(Into::into) {
165165
Ok(result) => Ok(Candidate { source: source.get(), result, head_usages }),
166166
Err(NoSolution) => Err(head_usages),
167167
}
@@ -683,7 +683,7 @@ where
683683
goal: Goal<I, G>,
684684
candidates: &mut Vec<Candidate<I>>,
685685
) {
686-
let _res = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
686+
let res = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
687687
ecx.assemble_alias_bound_candidates_recur(
688688
goal.predicate.self_ty(),
689689
goal,
@@ -692,9 +692,14 @@ where
692692
);
693693
Ok(())
694694
});
695+
695696
// always returns Ok
696-
// TODO: separate path for probes erroring because of accessing opaques
697-
// assert!(res.is_ok());
697+
match res {
698+
Ok(_) | Err(NoSolutionOrOpaquesAccessed::OpaquesAccessed) => {}
699+
Err(NoSolutionOrOpaquesAccessed::NoSolution(NoSolution)) => {
700+
unreachable!()
701+
}
702+
}
698703
}
699704

700705
/// For some deeply nested `<T>::A::B::C::D` rigid associated type,

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::marker::PhantomData;
22

33
use rustc_type_ir::search_graph::CandidateHeadUsages;
4-
use rustc_type_ir::solve::{AccessedOpaques, CanonicalResponse};
4+
use rustc_type_ir::solve::{AccessedOpaques, CanonicalResponse, NoSolutionOrOpaquesAccessed};
55
use rustc_type_ir::{InferCtxtLike, Interner};
66
use tracing::{instrument, warn};
77

@@ -31,11 +31,11 @@ where
3131
pub(in crate::solve) fn enter_single_candidate(
3232
self,
3333
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolution>,
34-
) -> (Result<T, NoSolution>, CandidateHeadUsages) {
34+
) -> (Result<T, NoSolutionOrOpaquesAccessed>, CandidateHeadUsages) {
3535
let mut candidate_usages = CandidateHeadUsages::default();
3636

3737
if self.ecx.opaque_accesses.should_bail() {
38-
return (Err(NoSolution), candidate_usages);
38+
return (Err(NoSolutionOrOpaquesAccessed::OpaquesAccessed), candidate_usages);
3939
}
4040

4141
self.ecx.search_graph.enter_single_candidate();
@@ -50,27 +50,27 @@ where
5050
pub(in crate::solve) fn enter(
5151
self,
5252
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolution>,
53-
) -> Result<T, NoSolution> {
53+
) -> Result<T, NoSolutionOrOpaquesAccessed> {
5454
let nested_goals = self.ecx.nested_goals.clone();
5555
self.enter_inner(f, nested_goals)
5656
}
5757

5858
pub(in crate::solve) fn enter_without_propagated_nested_goals(
5959
self,
6060
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolution>,
61-
) -> Result<T, NoSolution> {
61+
) -> Result<T, NoSolutionOrOpaquesAccessed> {
6262
self.enter_inner(f, Default::default())
6363
}
6464

6565
pub(in crate::solve) fn enter_inner(
6666
self,
6767
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> Result<T, NoSolution>,
6868
propagated_nested_goals: Vec<(GoalSource, Goal<I, I::Predicate>, Option<GoalStalledOn<I>>)>,
69-
) -> Result<T, NoSolution> {
69+
) -> Result<T, NoSolutionOrOpaquesAccessed> {
7070
let ProbeCtxt { ecx: outer, probe_kind, _result } = self;
7171

7272
if outer.opaque_accesses.should_bail() {
73-
return Err(NoSolution);
73+
return Err(NoSolutionOrOpaquesAccessed::OpaquesAccessed);
7474
}
7575

7676
let delegate = outer.delegate;
@@ -103,7 +103,7 @@ where
103103

104104
outer.opaque_accesses.update(nested.opaque_accesses);
105105

106-
r
106+
r.map_err(Into::into)
107107
}
108108
}
109109

@@ -128,7 +128,7 @@ where
128128
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> QueryResult<I>,
129129
) -> Result<Candidate<I>, NoSolution> {
130130
let (result, head_usages) = self.cx.enter_single_candidate(f);
131-
result.map(|result| Candidate { source: self.source, result, head_usages })
131+
Ok(Candidate { source: self.source, result: result?, head_usages })
132132
}
133133
}
134134

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,17 @@ where
7676
None
7777
},
7878
|ecx| {
79-
ecx.probe(|&result| ProbeKind::RigidAlias { result }).enter(|this| {
80-
this.structurally_instantiate_normalizes_to_term(
81-
goal,
82-
goal.predicate.alias,
83-
);
84-
this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
85-
})
79+
ecx.probe(|&result| ProbeKind::RigidAlias { result })
80+
.enter(|this| {
81+
this.structurally_instantiate_normalizes_to_term(
82+
goal,
83+
goal.predicate.alias,
84+
);
85+
this.evaluate_added_goals_and_make_canonical_response(
86+
Certainty::Yes,
87+
)
88+
})
89+
.map_err(Into::into)
8690
},
8791
)
8892
}

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ where
854854
},
855855
);
856856

857-
match result {
857+
match result.map_err(Into::into) {
858858
Ok(resp) => resp,
859859
Err(NoSolution) => vec![],
860860
}

compiler/rustc_type_ir/src/solve/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,33 @@ pub type QueryResult<I> = Result<CanonicalResponse<I>, NoSolution>;
3232
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
3333
pub struct NoSolution;
3434

35+
pub 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,
44+
}
45+
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..
48+
impl From<NoSolutionOrOpaquesAccessed> for NoSolution {
49+
fn from(
50+
(NoSolutionOrOpaquesAccessed::NoSolution(_) | NoSolutionOrOpaquesAccessed::OpaquesAccessed): NoSolutionOrOpaquesAccessed,
51+
) -> Self {
52+
NoSolution
53+
}
54+
}
55+
56+
impl From<NoSolution> for NoSolutionOrOpaquesAccessed {
57+
fn from(value: NoSolution) -> Self {
58+
Self::NoSolution(value)
59+
}
60+
}
61+
3562
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
3663
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)]
3764
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]

0 commit comments

Comments
 (0)