about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2019-12-26 21:16:28 +0000
committerMatthew Jasper <mjjasper1@gmail.com>2020-02-14 22:40:02 +0000
commitd9b9f00109aefcaf565c9da3c6fdf9e446f4876c (patch)
treed49a7dc86e527252b1bdca172585c148a39340ba
parent75ac0cca3678d5d309c737f1bd8ef237628a278b (diff)
downloadrust-d9b9f00109aefcaf565c9da3c6fdf9e446f4876c.tar.gz
rust-d9b9f00109aefcaf565c9da3c6fdf9e446f4876c.zip
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.
-rw-r--r--src/librustc_mir/borrow_check/nll.rs4
-rw-r--r--src/librustc_mir/borrow_check/region_infer/mod.rs1
-rw-r--r--src/librustc_mir/borrow_check/region_infer/opaque_types.rs72
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs9
4 files changed, 83 insertions, 3 deletions
diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs
index 4acf1cf7c2b..e4e5fe35d7f 100644
--- a/src/librustc_mir/borrow_check/nll.rs
+++ b/src/librustc_mir/borrow_check/nll.rs
@@ -282,9 +282,11 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
     let (closure_region_requirements, nll_errors) =
         regioncx.solve(infcx, &body, def_id, polonius_output.clone());
 
+    let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values, body.span);
+
     NllOutput {
         regioncx,
-        opaque_type_values,
+        opaque_type_values: remapped_opaque_tys,
         polonius_output,
         opt_closure_req: closure_region_requirements,
         nll_errors,
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index 6abca481eac..4a2f398c6d5 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -36,6 +36,7 @@ use crate::borrow_check::{
 
 mod dump_mir;
 mod graphviz;
+mod opaque_types;
 
 pub mod values;
 
diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
new file mode 100644
index 00000000000..e16a2c838eb
--- /dev/null
+++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
@@ -0,0 +1,72 @@
+use rustc::hir::def_id::DefId;
+use rustc::infer::InferCtxt;
+use rustc::ty;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_span::Span;
+
+use super::RegionInferenceContext;
+
+impl<'tcx> RegionInferenceContext<'tcx> {
+    /// Resolve any opaque types that were encountered while borrow checking
+    /// this item. This is then used to get the type in the `type_of` query.
+    pub(in crate::borrow_check) fn infer_opaque_types(
+        &self,
+        infcx: &InferCtxt<'_, 'tcx>,
+        opaque_ty_decls: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
+        span: Span,
+    ) -> FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>> {
+        opaque_ty_decls
+            .into_iter()
+            .map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| {
+                debug!(
+                    "infer_opaque_types(concrete_type = {:?}, substs = {:?})",
+                    concrete_type, substs
+                );
+
+                // Map back to "concrete" regions so that errors in
+                // `infer_opaque_definition_from_instantiation` can show
+                // sensible region names.
+                let universal_concrete_type =
+                    infcx.tcx.fold_regions(&concrete_type, &mut false, |region, _| match region {
+                        &ty::ReVar(vid) => {
+                            let universal_bound = self.universal_upper_bound(vid);
+                            self.definitions[universal_bound]
+                                .external_name
+                                .filter(|_| self.eval_equal(universal_bound, vid))
+                                .unwrap_or(infcx.tcx.lifetimes.re_empty)
+                        }
+                        concrete => concrete,
+                    });
+                let universal_substs =
+                    infcx.tcx.fold_regions(&substs, &mut false, |region, _| match region {
+                        ty::ReVar(vid) => {
+                            self.definitions[*vid].external_name.unwrap_or_else(|| {
+                                infcx.tcx.sess.delay_span_bug(
+                                    span,
+                                    "opaque type with non-universal region substs",
+                                );
+                                infcx.tcx.lifetimes.re_static
+                            })
+                        }
+                        concrete => concrete,
+                    });
+
+                debug!(
+                    "infer_opaque_types(universal_concrete_type = {:?}, universal_substs = {:?})",
+                    universal_concrete_type, universal_substs
+                );
+
+                let remapped_type = infcx.infer_opaque_definition_from_instantiation(
+                    opaque_def_id,
+                    universal_substs,
+                    universal_concrete_type,
+                    span,
+                );
+                (
+                    opaque_def_id,
+                    ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs },
+                )
+            })
+            .collect()
+    }
+}
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index c6809f9e37e..5c6f3a0ffa9 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -1267,8 +1267,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                     .at(&ObligationCause::dummy(), param_env)
                                     .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?,
                             );
-                            opaque_type_values
-                                .push((opaque_def_id, ty::ResolvedOpaqueTy { ..*opaque_defn_ty }));
+                            opaque_type_values.push((
+                                opaque_def_id,
+                                ty::ResolvedOpaqueTy {
+                                    concrete_type: renumbered_opaque_defn_ty,
+                                    substs: opaque_decl.substs,
+                                },
+                            ));
                         } else {
                             // We're using an opaque `impl Trait` type without
                             // 'revealing' it. For example, code like this: