about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_middle/src/ty/context.rs28
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/mod.rs56
-rw-r--r--compiler/rustc_trait_selection/src/opaque_types.rs12
3 files changed, 85 insertions, 11 deletions
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 73991436b7b..a74070100f4 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -392,6 +392,34 @@ pub struct TypeckResults<'tcx> {
     /// (including late-bound regions) are replaced with free
     /// equivalents. This table is not used in codegen (since regions
     /// are erased there) and hence is not serialized to metadata.
+    ///
+    /// This table also contains the "revealed" values for any `impl Trait`
+    /// that appear in the signature and whose values are being inferred
+    /// by this function.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// fn foo(x: &u32) -> impl Debug { *x }
+    /// ```
+    ///
+    /// The function signature here would be:
+    ///
+    /// ```
+    /// for<'a> fn(&'a u32) -> Foo
+    /// ```
+    ///
+    /// where `Foo` is an opaque type created for this function.
+    ///
+    ///
+    /// The *liberated* form of this would be
+    ///
+    /// ```
+    /// fn(&'a u32) -> u32
+    /// ```
+    ///
+    /// Note that `'a` is not bound (it would be an `ReFree`) and
+    /// that the `Foo` opaque type is replaced by its hidden type.
     liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
 
     /// For each FRU expression, record the normalized types of the fields
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index 09cafddeeff..984a9a7f053 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -1206,6 +1206,35 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         Ok(())
     }
 
+    /// Equates a type `anon_ty` that may contain opaque types whose
+    /// values are to be inferred by the MIR with def-id `anon_owner_def_id`.
+    ///
+    /// The type `revealed_ty` contains the same type as `anon_ty`, but with the
+    /// hidden types for impl traits revealed.
+    ///
+    /// # Example
+    ///
+    /// Consider a piece of code like
+    ///
+    /// ```rust
+    /// type Foo<U> = impl Debug;
+    ///
+    /// fn foo<T: Debug>(t: T) -> Box<Foo<T>> {
+    ///      Box::new((t, 22_u32))
+    /// }
+    /// ```
+    ///
+    /// Here, the function signature would be something like
+    /// `fn(T) -> Box<impl Debug>`. The MIR return slot would have
+    /// the type with the opaque type revealed, so `Box<(T, u32)>`.
+    ///
+    /// In terms of our function parameters:
+    ///
+    /// * `anon_ty` would be `Box<Foo<T>>` where `Foo` is an opaque type
+    ///   scoped to this function (note that it is parameterized by the
+    ///   generics of `foo`).
+    /// * `revealed_ty` would be `Box<(Foo<T>, u32)>`
+    /// * `anon_owner_def_id` would be the def-id of `foo`
     fn eq_opaque_type_and_type(
         &mut self,
         revealed_ty: Ty<'tcx>,
@@ -1240,6 +1269,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let tcx = infcx.tcx;
         let param_env = self.param_env;
         let body = self.body;
+
+        // the "concrete opaque types" maps
         let concrete_opaque_types = &tcx.typeck(anon_owner_def_id).concrete_opaque_types;
         let mut opaque_type_values = VecMap::new();
 
@@ -1252,6 +1283,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     let mut obligations = ObligationAccumulator::default();
 
                     let dummy_body_id = hir::CRATE_HIR_ID;
+
+                    // Replace the opaque types defined by this function with
+                    // inference variables, creating a map. In our example above,
+                    // this would transform the type `Box<Foo<T>>` (where `Foo` is an opaque type)
+                    // to `Box<?T>`, returning an `opaque_type_map` mapping `{Foo<T> -> ?T}`.
+                    // (Note that the key of the map is both the def-id of `Foo` along with
+                    // any generic parameters.)
                     let (output_ty, opaque_type_map) =
                         obligations.add(infcx.instantiate_opaque_types(
                             anon_owner_def_id,
@@ -1267,6 +1305,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                          revealed_ty={:?}",
                         output_ty, opaque_type_map, revealed_ty
                     );
+
                     // Make sure that the inferred types are well-formed. I'm
                     // not entirely sure this is needed (the HIR type check
                     // didn't do this) but it seems sensible to prevent opaque
@@ -1282,6 +1321,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             .eq(output_ty, revealed_ty)?,
                     );
 
+                    // For each opaque type `Foo<T>` inferred by this value, we want to equate
+                    // the inference variable `?T` with the revealed type that was computed
+                    // earlier by type check.
                     for &(opaque_type_key, opaque_decl) in &opaque_type_map {
                         let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty);
                         let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
@@ -1290,6 +1332,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             false
                         };
 
+                        // The revealed type computed by the earlier phase of type check.
+                        // In our example, this would be `(U, u32)`. Note that this references
+                        // the type parameter `U` from the definition of `Foo`.
                         let concrete_ty = match concrete_opaque_types
                             .get_by(|(key, _)| key.def_id == opaque_type_key.def_id)
                         {
@@ -1308,7 +1353,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             Some(concrete_ty) => concrete_ty,
                         };
                         debug!("concrete_ty = {:?}", concrete_ty);
+
+                        // Apply the substitution, in this case `[U -> T]`, so that the
+                        // concrete type becomes `Foo<(T, u32)>`
                         let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_type_key.substs);
+
+                        // "Renumber" this, meaning that we replace all the regions
+                        // with fresh inference variables. Not relevant to our example.
                         let renumbered_opaque_defn_ty =
                             renumber::renumber_regions(infcx, subst_opaque_defn_ty);
 
@@ -1318,8 +1369,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         );
 
                         if !concrete_is_opaque {
-                            // Equate concrete_ty (an inference variable) with
-                            // the renumbered type from typeck.
+                            // Equate the instantiated opaque type `opaque_decl.concrete_ty` (`?T`,
+                            // in our example) with the renumbered version that we took from
+                            // the type check results (`Foo<(T, u32)>`).
                             obligations.add(
                                 infcx
                                     .at(&ObligationCause::dummy(), param_env)
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index 89ec211f262..0061ce4ed37 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -5,7 +5,6 @@ use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::vec_map::VecMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::Node;
 use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
 use rustc_infer::infer::free_regions::FreeRegionRelations;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -982,8 +981,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
                             let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
                             parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
                         };
-                        let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
-                            Some(Node::Item(item)) => match item.kind {
+                        let (in_definition_scope, origin) =
+                            match tcx.hir().expect_item(opaque_hir_id).kind {
                                 // Anonymous `impl Trait`
                                 hir::ItemKind::OpaqueTy(hir::OpaqueTy {
                                     impl_trait_fn: Some(parent),
@@ -1000,12 +999,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
                                     origin,
                                 ),
                                 _ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),
-                            },
-                            _ => bug!(
-                                "expected item, found {}",
-                                tcx.hir().node_to_string(opaque_hir_id),
-                            ),
-                        };
+                            };
                         if in_definition_scope {
                             let opaque_type_key =
                                 OpaqueTypeKey { def_id: def_id.to_def_id(), substs };