Skip to content

Commit 9a5cef1

Browse files
committed
Cleanup opaque_type computation a bit
1 parent db3c9b6 commit 9a5cef1

File tree

1 file changed

+56
-47
lines changed

1 file changed

+56
-47
lines changed

compiler/rustc_hir_typeck/src/opaque_types.rs

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_middle::ty::{
44
self, DefiningScopeKind, EarlyBinder, OpaqueHiddenType, OpaqueTypeKey, TypeVisitableExt,
55
TypingMode,
66
};
7+
use rustc_span::ErrorGuaranteed;
78
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
89
use rustc_trait_selection::opaque_types::{
910
NonDefiningUseReason, opaque_type_has_defining_use_args, report_item_does_not_constrain_error,
@@ -24,6 +25,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
2425
/// It then uses these defining uses to guide inference for all other uses.
2526
///
2627
/// Unlike `handle_opaque_type_uses_next`, this does not report errors.
28+
#[instrument(level = "debug", skip(self))]
2729
pub(super) fn try_handle_opaque_type_uses_next(&mut self) {
2830
// We clone the opaques instead of stealing them here as they are still used for
2931
// normalization in the next generation trait solver.
@@ -34,7 +36,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
3436
debug!(?opaque_types);
3537

3638
self.compute_definition_site_hidden_types(&opaque_types, true);
37-
self.apply_definition_site_hidden_types(&opaque_types);
3839
}
3940

4041
/// This takes all the opaque type uses during HIR typeck. It first computes
@@ -59,22 +60,29 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
5960
debug!(?opaque_types);
6061

6162
self.compute_definition_site_hidden_types(&opaque_types, false);
62-
self.apply_definition_site_hidden_types(&opaque_types);
6363
}
6464
}
6565

66+
#[derive(Copy, Clone, Debug)]
6667
enum UsageKind<'tcx> {
6768
None,
6869
NonDefiningUse(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>),
6970
UnconstrainedHiddenType(OpaqueHiddenType<'tcx>),
70-
HasDefiningUse,
71+
HasDefiningUse(OpaqueHiddenType<'tcx>),
72+
// `type_of_opaque_hir_typeck` reported an error
73+
HasError(ErrorGuaranteed),
7174
}
7275

7376
impl<'tcx> UsageKind<'tcx> {
7477
fn merge(&mut self, other: UsageKind<'tcx>) {
7578
match (&*self, &other) {
76-
(UsageKind::HasDefiningUse, _) | (_, UsageKind::None) => unreachable!(),
79+
(UsageKind::HasDefiningUse(_), _) | (_, UsageKind::None) => unreachable!(),
7780
(UsageKind::None, _) => *self = other,
81+
// If `type_of_opaque_hir_typeck` reported an error, then the hidden
82+
// type is an error, but we also want to still report errors for
83+
// remaining hidden types (really just normalization errors).
84+
(UsageKind::HasError(_), _) => {}
85+
(_, UsageKind::HasError(_)) => *self = other,
7886
// When mergining non-defining uses, prefer earlier ones. This means
7987
// the error happens as early as possible.
8088
(
@@ -87,7 +95,7 @@ impl<'tcx> UsageKind<'tcx> {
8795
// intended to be defining.
8896
(
8997
UsageKind::NonDefiningUse(..) | UsageKind::UnconstrainedHiddenType(..),
90-
UsageKind::UnconstrainedHiddenType(..) | UsageKind::HasDefiningUse,
98+
UsageKind::UnconstrainedHiddenType(..) | UsageKind::HasDefiningUse(_),
9199
) => *self = other,
92100
}
93101
}
@@ -112,29 +120,63 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
112120
_ => unreachable!("not opaque or generator: {def_id:?}"),
113121
}
114122

123+
// We do actually need to check this the second pass (we can't just
124+
// store this), because we can go from `UnconstrainedHiddenType` to
125+
// `HasDefiningUse` (because of fallback)
115126
let mut usage_kind = UsageKind::None;
116127
for &(opaque_type_key, hidden_type) in opaque_types {
117128
if opaque_type_key.def_id != def_id {
118129
continue;
119130
}
120131

121-
usage_kind.merge(self.consider_opaque_type_use(
122-
opaque_type_key,
123-
hidden_type,
124-
first_pass,
125-
));
126-
if let UsageKind::HasDefiningUse = usage_kind {
132+
usage_kind.merge(self.consider_opaque_type_use(opaque_type_key, hidden_type));
133+
134+
if let UsageKind::HasDefiningUse(..) = usage_kind {
127135
break;
128136
}
129137
}
130138

139+
if let UsageKind::HasDefiningUse(first_use) = usage_kind {
140+
for &(opaque_type_key, hidden_type) in opaque_types {
141+
if opaque_type_key.def_id != def_id {
142+
continue;
143+
}
144+
145+
let expected =
146+
EarlyBinder::bind(first_use.ty).instantiate(tcx, opaque_type_key.args);
147+
self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
148+
}
149+
}
150+
151+
match usage_kind {
152+
UsageKind::HasDefiningUse(hidden_type) => {
153+
let prev =
154+
self.typeck_results.borrow_mut().hidden_types.insert(def_id, hidden_type);
155+
156+
// We do want to insert opaque types the first pass, because
157+
// we want to equate them. So, the second pass (where we
158+
// report errors) may have a hidden type inserted.
159+
if first_pass {
160+
assert!(prev.is_none());
161+
}
162+
}
163+
UsageKind::HasError(guar) => {
164+
self.typeck_results
165+
.borrow_mut()
166+
.hidden_types
167+
.insert(def_id, OpaqueHiddenType::new_error(self.tcx, guar));
168+
}
169+
_ => {}
170+
}
171+
131172
// If this the first pass (`try_handle_opaque_type_uses_next`),
132173
// then do not report any errors.
133174
if first_pass {
134175
continue;
135176
}
136177

137178
let guar = match usage_kind {
179+
UsageKind::HasDefiningUse(_) | UsageKind::HasError(_) => continue,
138180
UsageKind::None => {
139181
if let Some(guar) = self.tainted_by_errors() {
140182
guar
@@ -171,7 +213,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
171213
.emit()
172214
}
173215
}
174-
UsageKind::HasDefiningUse => continue,
175216
};
176217

177218
self.typeck_results
@@ -182,11 +223,11 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
182223
}
183224
}
184225

226+
#[tracing::instrument(skip(self), ret)]
185227
fn consider_opaque_type_use(
186228
&mut self,
187229
opaque_type_key: OpaqueTypeKey<'tcx>,
188230
hidden_type: OpaqueHiddenType<'tcx>,
189-
first_pass: bool,
190231
) -> UsageKind<'tcx> {
191232
if let Err(err) = opaque_type_has_defining_use_args(
192233
&self,
@@ -196,11 +237,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
196237
) {
197238
match err {
198239
NonDefiningUseReason::Tainted(guar) => {
199-
self.typeck_results.borrow_mut().hidden_types.insert(
200-
opaque_type_key.def_id,
201-
OpaqueHiddenType::new_error(self.tcx, guar),
202-
);
203-
return UsageKind::HasDefiningUse;
240+
return UsageKind::HasError(guar);
204241
}
205242
_ => return UsageKind::NonDefiningUse(opaque_type_key, hidden_type),
206243
};
@@ -228,35 +265,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
228265
self.tcx,
229266
DefiningScopeKind::HirTypeck,
230267
);
231-
232-
let prev = self
233-
.typeck_results
234-
.borrow_mut()
235-
.hidden_types
236-
.insert(opaque_type_key.def_id, hidden_type);
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-
}
244-
UsageKind::HasDefiningUse
245-
}
246-
247-
fn apply_definition_site_hidden_types(
248-
&mut self,
249-
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
250-
) {
251-
let tcx = self.tcx;
252-
for &(key, hidden_type) in opaque_types {
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-
}
259-
}
268+
UsageKind::HasDefiningUse(hidden_type)
260269
}
261270

262271
/// We may in theory add further uses of an opaque after cloning the opaque

0 commit comments

Comments
 (0)