Skip to content

Commit e1df397

Browse files
authored
Rollup merge of rust-lang#131599 - compiler-errors:storage, r=lcnr
Shallowly match opaque key in storage Using a full eq on the key *and* the hidden type means that in cases where we first ambiguously register a `?t` hidden type then constrain that `?t` to be a type that doesn't actually satisfy its bounds, we end up with bogus entries in the opaque type storage. We should commit to the type in the storage if it's registered. r? lcnr
2 parents b9e083f + 470e9fa commit e1df397

File tree

2 files changed

+42
-43
lines changed

2 files changed

+42
-43
lines changed

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

+17-34
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use derive_where::derive_where;
44
#[cfg(feature = "nightly")]
55
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
66
use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack};
7+
use rustc_type_ir::fast_reject::DeepRejectCtxt;
78
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
89
use rustc_type_ir::inherent::*;
910
use rustc_type_ir::relate::Relate;
@@ -18,9 +19,9 @@ use crate::delegate::SolverDelegate;
1819
use crate::solve::inspect::{self, ProofTreeBuilder};
1920
use crate::solve::search_graph::SearchGraph;
2021
use crate::solve::{
21-
CanonicalInput, CanonicalResponse, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind,
22-
GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData,
23-
QueryResult, SolverMode,
22+
CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource,
23+
HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult,
24+
SolverMode,
2425
};
2526

2627
pub(super) mod canonical;
@@ -987,40 +988,22 @@ where
987988

988989
// Do something for each opaque/hidden pair defined with `def_id` in the
989990
// current inference context.
990-
pub(super) fn unify_existing_opaque_tys(
991+
pub(super) fn probe_existing_opaque_ty(
991992
&mut self,
992-
param_env: I::ParamEnv,
993993
key: ty::OpaqueTypeKey<I>,
994-
ty: I::Ty,
995-
) -> Vec<CanonicalResponse<I>> {
996-
// FIXME: Super inefficient to be cloning this...
997-
let opaques = self.delegate.clone_opaque_types_for_query_response();
998-
999-
let mut values = vec![];
1000-
for (candidate_key, candidate_ty) in opaques {
1001-
if candidate_key.def_id != key.def_id {
1002-
continue;
1003-
}
1004-
values.extend(
1005-
self.probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup {
1006-
result: *result,
1007-
})
1008-
.enter(|ecx| {
1009-
for (a, b) in std::iter::zip(candidate_key.args.iter(), key.args.iter()) {
1010-
ecx.eq(param_env, a, b)?;
1011-
}
1012-
ecx.eq(param_env, candidate_ty, ty)?;
1013-
ecx.add_item_bounds_for_hidden_type(
1014-
candidate_key.def_id.into(),
1015-
candidate_key.args,
1016-
param_env,
1017-
candidate_ty,
1018-
);
1019-
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
1020-
}),
994+
) -> Option<(ty::OpaqueTypeKey<I>, I::Ty)> {
995+
let mut matching =
996+
self.delegate.clone_opaque_types_for_query_response().into_iter().filter(
997+
|(candidate_key, _)| {
998+
candidate_key.def_id == key.def_id
999+
&& DeepRejectCtxt::relate_rigid_rigid(self.cx())
1000+
.args_may_unify(candidate_key.args, key.args)
1001+
},
10211002
);
1022-
}
1023-
values
1003+
let first = matching.next();
1004+
let second = matching.next();
1005+
assert_eq!(second, None);
1006+
first
10241007
}
10251008

10261009
// Try to evaluate a const, or return `None` if the const is too generic.

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

+25-9
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use rustc_type_ir::inherent::*;
77
use rustc_type_ir::{self as ty, Interner};
88

99
use crate::delegate::SolverDelegate;
10-
use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode};
10+
use crate::solve::{
11+
Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode, inspect,
12+
};
1113

1214
impl<D, I> EvalCtxt<'_, D>
1315
where
@@ -52,14 +54,28 @@ where
5254
//
5355
// If that fails, we insert `expected` as a new hidden type instead of
5456
// eagerly emitting an error.
55-
let matches =
56-
self.unify_existing_opaque_tys(goal.param_env, opaque_type_key, expected);
57-
if !matches.is_empty() {
58-
if let Some(response) = self.try_merge_responses(&matches) {
59-
return Ok(response);
60-
} else {
61-
return self.flounder(&matches);
62-
}
57+
let existing = self.probe_existing_opaque_ty(opaque_type_key);
58+
if let Some((candidate_key, candidate_ty)) = existing {
59+
return self
60+
.probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup {
61+
result: *result,
62+
})
63+
.enter(|ecx| {
64+
for (a, b) in std::iter::zip(
65+
candidate_key.args.iter(),
66+
opaque_type_key.args.iter(),
67+
) {
68+
ecx.eq(goal.param_env, a, b)?;
69+
}
70+
ecx.eq(goal.param_env, candidate_ty, expected)?;
71+
ecx.add_item_bounds_for_hidden_type(
72+
candidate_key.def_id.into(),
73+
candidate_key.args,
74+
goal.param_env,
75+
candidate_ty,
76+
);
77+
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
78+
});
6379
}
6480

6581
// Otherwise, define a new opaque type

0 commit comments

Comments
 (0)