Skip to content

Commit 5693ef8

Browse files
jackh726lcnr
authored andcommitted
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 cfdf14c commit 5693ef8

File tree

2 files changed

+56
-7
lines changed

2 files changed

+56
-7
lines changed

compiler/rustc_hir_typeck/src/lib.rs

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

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

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

compiler/rustc_hir_typeck/src/opaque_types.rs

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,29 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
2222
/// inference variables.
2323
///
2424
/// 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_definition_site_hidden_types(&opaque_types, true);
37+
self.apply_definition_site_hidden_types(&opaque_types);
38+
}
39+
40+
/// This takes all the opaque type uses during HIR typeck. It first computes
41+
/// the concrete hidden type by iterating over all defining uses.
42+
///
43+
/// A use during HIR typeck is defining if all non-lifetime arguments are
44+
/// unique generic parameters and the hidden type does not reference any
45+
/// inference variables.
46+
///
47+
/// It then uses these defining uses to guide inference for all other uses.
2548
#[instrument(level = "debug", skip(self))]
2649
pub(super) fn handle_opaque_type_uses_next(&mut self) {
2750
// We clone the opaques instead of stealing them here as they are still used for
@@ -35,7 +58,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
3558
}
3659
debug!(?opaque_types);
3760

38-
self.compute_definition_site_hidden_types(&opaque_types);
61+
self.compute_definition_site_hidden_types(&opaque_types, false);
3962
self.apply_definition_site_hidden_types(&opaque_types);
4063
}
4164
}
@@ -74,6 +97,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
7497
fn compute_definition_site_hidden_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
.hidden_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,10 +250,12 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
209250
) {
210251
let tcx = self.tcx;
211252
for &(key, hidden_type) in opaque_types {
212-
let expected = *self.typeck_results.borrow_mut().hidden_types.get(&key.def_id).unwrap();
213-
214-
let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
215-
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) = self.typeck_results.borrow_mut().hidden_types.get(&key.def_id) {
256+
let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
257+
self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
258+
}
216259
}
217260
}
218261

0 commit comments

Comments
 (0)