Skip to content

Commit d6e48fd

Browse files
committed
Cleanup opaque_type computation a bit
1 parent 7510100 commit d6e48fd

File tree

1 file changed

+59
-49
lines changed

1 file changed

+59
-49
lines changed

compiler/rustc_hir_typeck/src/opaque_types.rs

Lines changed: 59 additions & 49 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_concrete_opaque_types(&opaque_types, true);
37-
self.apply_computed_concrete_opaque_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_concrete_opaque_types(&opaque_types, false);
62-
self.apply_computed_concrete_opaque_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,66 @@ 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 = self
154+
.typeck_results
155+
.borrow_mut()
156+
.concrete_opaque_types
157+
.insert(def_id, hidden_type);
158+
159+
// We do want to insert opaque types the first pass, because
160+
// we want to equate them. So, the second pass (where we
161+
// report errors) may have a hidden type inserted.
162+
if first_pass {
163+
assert!(prev.is_none());
164+
}
165+
}
166+
UsageKind::HasError(guar) => {
167+
self.typeck_results
168+
.borrow_mut()
169+
.concrete_opaque_types
170+
.insert(def_id, OpaqueHiddenType::new_error(self.tcx, guar));
171+
}
172+
_ => {}
173+
}
174+
131175
// If this the first pass (`try_handle_opaque_type_uses_next`),
132176
// then do not report any errors.
133177
if first_pass {
134178
continue;
135179
}
136180

137181
let guar = match usage_kind {
182+
UsageKind::HasDefiningUse(_) | UsageKind::HasError(_) => continue,
138183
UsageKind::None => {
139184
if let Some(guar) = self.tainted_by_errors() {
140185
guar
@@ -171,7 +216,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
171216
.emit()
172217
}
173218
}
174-
UsageKind::HasDefiningUse => continue,
175219
};
176220

177221
self.typeck_results
@@ -182,11 +226,11 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
182226
}
183227
}
184228

229+
#[tracing::instrument(skip(self), ret)]
185230
fn consider_opaque_type_use(
186231
&mut self,
187232
opaque_type_key: OpaqueTypeKey<'tcx>,
188233
hidden_type: OpaqueHiddenType<'tcx>,
189-
first_pass: bool,
190234
) -> UsageKind<'tcx> {
191235
if let Err(err) = opaque_type_has_defining_use_args(
192236
&self,
@@ -196,11 +240,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
196240
) {
197241
match err {
198242
NonDefiningUseReason::Tainted(guar) => {
199-
self.typeck_results.borrow_mut().concrete_opaque_types.insert(
200-
opaque_type_key.def_id,
201-
OpaqueHiddenType::new_error(self.tcx, guar),
202-
);
203-
return UsageKind::HasDefiningUse;
243+
return UsageKind::HasError(guar);
204244
}
205245
_ => return UsageKind::NonDefiningUse(opaque_type_key, hidden_type),
206246
};
@@ -228,37 +268,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
228268
self.tcx,
229269
DefiningScopeKind::HirTypeck,
230270
);
231-
232-
let prev = self
233-
.typeck_results
234-
.borrow_mut()
235-
.concrete_opaque_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_computed_concrete_opaque_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) =
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-
}
261-
}
271+
UsageKind::HasDefiningUse(hidden_type)
262272
}
263273

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

0 commit comments

Comments
 (0)