Skip to content

Commit d9b9f00

Browse files
committed
Infer opaque type regions in borrow checking
We want type checking for function bodies to ignore/erase regions. As such, we need to infer the regions in opaque types in borrow check instead.
1 parent 75ac0cc commit d9b9f00

File tree

4 files changed

+83
-3
lines changed

4 files changed

+83
-3
lines changed

src/librustc_mir/borrow_check/nll.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,11 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
282282
let (closure_region_requirements, nll_errors) =
283283
regioncx.solve(infcx, &body, def_id, polonius_output.clone());
284284

285+
let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values, body.span);
286+
285287
NllOutput {
286288
regioncx,
287-
opaque_type_values,
289+
opaque_type_values: remapped_opaque_tys,
288290
polonius_output,
289291
opt_closure_req: closure_region_requirements,
290292
nll_errors,

src/librustc_mir/borrow_check/region_infer/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use crate::borrow_check::{
3636

3737
mod dump_mir;
3838
mod graphviz;
39+
mod opaque_types;
3940

4041
pub mod values;
4142

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use rustc::hir::def_id::DefId;
2+
use rustc::infer::InferCtxt;
3+
use rustc::ty;
4+
use rustc_data_structures::fx::FxHashMap;
5+
use rustc_span::Span;
6+
7+
use super::RegionInferenceContext;
8+
9+
impl<'tcx> RegionInferenceContext<'tcx> {
10+
/// Resolve any opaque types that were encountered while borrow checking
11+
/// this item. This is then used to get the type in the `type_of` query.
12+
pub(in crate::borrow_check) fn infer_opaque_types(
13+
&self,
14+
infcx: &InferCtxt<'_, 'tcx>,
15+
opaque_ty_decls: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
16+
span: Span,
17+
) -> FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>> {
18+
opaque_ty_decls
19+
.into_iter()
20+
.map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| {
21+
debug!(
22+
"infer_opaque_types(concrete_type = {:?}, substs = {:?})",
23+
concrete_type, substs
24+
);
25+
26+
// Map back to "concrete" regions so that errors in
27+
// `infer_opaque_definition_from_instantiation` can show
28+
// sensible region names.
29+
let universal_concrete_type =
30+
infcx.tcx.fold_regions(&concrete_type, &mut false, |region, _| match region {
31+
&ty::ReVar(vid) => {
32+
let universal_bound = self.universal_upper_bound(vid);
33+
self.definitions[universal_bound]
34+
.external_name
35+
.filter(|_| self.eval_equal(universal_bound, vid))
36+
.unwrap_or(infcx.tcx.lifetimes.re_empty)
37+
}
38+
concrete => concrete,
39+
});
40+
let universal_substs =
41+
infcx.tcx.fold_regions(&substs, &mut false, |region, _| match region {
42+
ty::ReVar(vid) => {
43+
self.definitions[*vid].external_name.unwrap_or_else(|| {
44+
infcx.tcx.sess.delay_span_bug(
45+
span,
46+
"opaque type with non-universal region substs",
47+
);
48+
infcx.tcx.lifetimes.re_static
49+
})
50+
}
51+
concrete => concrete,
52+
});
53+
54+
debug!(
55+
"infer_opaque_types(universal_concrete_type = {:?}, universal_substs = {:?})",
56+
universal_concrete_type, universal_substs
57+
);
58+
59+
let remapped_type = infcx.infer_opaque_definition_from_instantiation(
60+
opaque_def_id,
61+
universal_substs,
62+
universal_concrete_type,
63+
span,
64+
);
65+
(
66+
opaque_def_id,
67+
ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs },
68+
)
69+
})
70+
.collect()
71+
}
72+
}

src/librustc_mir/borrow_check/type_check/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,8 +1267,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12671267
.at(&ObligationCause::dummy(), param_env)
12681268
.eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?,
12691269
);
1270-
opaque_type_values
1271-
.push((opaque_def_id, ty::ResolvedOpaqueTy { ..*opaque_defn_ty }));
1270+
opaque_type_values.push((
1271+
opaque_def_id,
1272+
ty::ResolvedOpaqueTy {
1273+
concrete_type: renumbered_opaque_defn_ty,
1274+
substs: opaque_decl.substs,
1275+
},
1276+
));
12721277
} else {
12731278
// We're using an opaque `impl Trait` type without
12741279
// 'revealing' it. For example, code like this:

0 commit comments

Comments
 (0)