Skip to content

Commit 14449f1

Browse files
committed
When computing opaque types in the next solver, take an initial pass pre-fallback where we equate hidden types but do not report errors
1 parent 1372123 commit 14449f1

File tree

2 files changed

+58
-8
lines changed

2 files changed

+58
-8
lines changed

compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,12 @@ fn typeck_with_inspect<'tcx>(
218218
// the future.
219219
fcx.check_repeat_exprs();
220220

221+
// We need to handle opaque types before emitting ambiguity errors as applying
222+
// defining uses may guide type inference.
223+
if fcx.next_trait_solver() {
224+
fcx.try_handle_opaque_type_uses_next();
225+
}
226+
221227
fcx.type_inference_fallback();
222228

223229
// Even though coercion casts provide type hints, we check casts after fallback for

compiler/rustc_hir_typeck/src/opaque_types.rs

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,29 @@ use tracing::{debug, instrument};
1414
use crate::FnCtxt;
1515

1616
impl<'tcx> FnCtxt<'_, 'tcx> {
17+
/// This takes all the opaque type uses during HIR typeck. It first computes
18+
/// the concrete hidden type by iterating over all defining uses.
19+
///
20+
/// A use during HIR typeck is defining if all non-lifetime arguments are
21+
/// unique generic parameters and the hidden type does not reference any
22+
/// inference variables.
23+
///
24+
/// It then uses these defining uses to guide inference for all other uses.
25+
///
26+
/// Unlike `handle_opaque_type_uses_next`, this does not report errors.
27+
pub(super) fn try_handle_opaque_type_uses_next(&mut self) {
28+
// We clone the opaques instead of stealing them here as they are still used for
29+
// normalization in the next generation trait solver.
30+
let mut opaque_types: Vec<_> = self.infcx.clone_opaque_types();
31+
for entry in &mut opaque_types {
32+
*entry = self.resolve_vars_if_possible(*entry);
33+
}
34+
debug!(?opaque_types);
35+
36+
self.compute_concrete_opaque_types(&opaque_types, true);
37+
self.apply_computed_concrete_opaque_types(&opaque_types);
38+
}
39+
1740
/// This takes all the opaque type uses during HIR typeck. It first computes
1841
/// the concrete hidden type by iterating over all defining uses.
1942
///
@@ -35,7 +58,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
3558
}
3659
debug!(?opaque_types);
3760

38-
self.compute_concrete_opaque_types(&opaque_types);
61+
self.compute_concrete_opaque_types(&opaque_types, false);
3962
self.apply_computed_concrete_opaque_types(&opaque_types);
4063
}
4164
}
@@ -74,6 +97,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
7497
fn compute_concrete_opaque_types(
7598
&mut self,
7699
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
100+
first_pass: bool,
77101
) {
78102
let tcx = self.tcx;
79103
let TypingMode::Analysis { defining_opaque_types_and_generators } = self.typing_mode()
@@ -94,12 +118,22 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
94118
continue;
95119
}
96120

97-
usage_kind.merge(self.consider_opaque_type_use(opaque_type_key, hidden_type));
121+
usage_kind.merge(self.consider_opaque_type_use(
122+
opaque_type_key,
123+
hidden_type,
124+
first_pass,
125+
));
98126
if let UsageKind::HasDefiningUse = usage_kind {
99127
break;
100128
}
101129
}
102130

131+
// If this the first pass (`try_handle_opaque_type_uses_next`),
132+
// then do not report any errors.
133+
if first_pass {
134+
continue;
135+
}
136+
103137
let guar = match usage_kind {
104138
UsageKind::None => {
105139
if let Some(guar) = self.tainted_by_errors() {
@@ -152,6 +186,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
152186
&mut self,
153187
opaque_type_key: OpaqueTypeKey<'tcx>,
154188
hidden_type: OpaqueHiddenType<'tcx>,
189+
first_pass: bool,
155190
) -> UsageKind<'tcx> {
156191
if let Err(err) = opaque_type_has_defining_use_args(
157192
&self,
@@ -199,7 +234,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
199234
.borrow_mut()
200235
.concrete_opaque_types
201236
.insert(opaque_type_key.def_id, hidden_type);
202-
assert!(prev.is_none());
237+
238+
// We do want to insert opaque types the first pass, because we want to
239+
// equate them. So, the second pass (where we report errors) will have
240+
// a hidden type inserted.
241+
if first_pass {
242+
assert!(prev.is_none());
243+
}
203244
UsageKind::HasDefiningUse
204245
}
205246

@@ -209,11 +250,14 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
209250
) {
210251
let tcx = self.tcx;
211252
for &(key, hidden_type) in opaque_types {
212-
let expected =
213-
*self.typeck_results.borrow_mut().concrete_opaque_types.get(&key.def_id).unwrap();
214-
215-
let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
216-
self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
253+
// On the first pass to this function, some opaque types may not
254+
// have a hidden type assigned.
255+
if let Some(expected) =
256+
self.typeck_results.borrow_mut().concrete_opaque_types.get(&key.def_id)
257+
{
258+
let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
259+
self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
260+
}
217261
}
218262
}
219263

0 commit comments

Comments
 (0)