about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2019-11-18 14:46:16 -0500
committerAaron Hill <aa1ronham@gmail.com>2019-11-24 14:37:24 -0500
commitcec7d944baa4a1d5ae0c09d68537ce20fe6b47f4 (patch)
tree47b3f277ba86aa435350df7b15e0ebdb7db6f9cd
parent542383f65b5419820e90f4374f93d2d1207f3f08 (diff)
downloadrust-cec7d944baa4a1d5ae0c09d68537ce20fe6b47f4.tar.gz
rust-cec7d944baa4a1d5ae0c09d68537ce20fe6b47f4.zip
Add example and extra documentation
-rw-r--r--src/librustc_typeck/check/mod.rs32
1 files changed, 32 insertions, 0 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a1f1ac3f2d3..9182eb10545 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -879,6 +879,30 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: DefId) -> &DefIdSet {
 /// variables introduced by the projection of associated types. This ensures that
 /// any opaque types used in the signature continue to refer to generic parameters,
 /// allowing them to be considered for defining uses in the function body
+///
+/// For example, consider this code.
+///
+/// ```rust
+/// trait MyTrait {
+///     type MyItem;
+///     fn use_it(self) -> Self::MyItem
+/// }
+/// impl<T, I> MyTrait for T where T: Iterator<Item = I> {
+///     type MyItem = impl Iterator<Item = I>;
+///     fn use_it(self) -> Self::MyItem {
+///         self
+///     }
+/// }
+/// ```
+///
+/// When we normalize the signature of `use_it` from the impl block,
+/// we will normalize `Self::MyItem` to the opaque type `impl Iterator<Item = I>`
+/// However, this projection result may contain inference variables, due
+/// to the way that projection works. We didn't have any inference variables
+/// in the signature to begin with - leaving them in will cause us to incorrectly
+/// conclude that we don't have a defining use of `MyItem`. By mapping inference
+/// variables back to the actual generic parameters, we will correctly see that
+/// we have a defining use of `MyItem`
 fn fixup_opaque_types<'tcx, T>(tcx: TyCtxt<'tcx>, val: &T) -> T where T: TypeFoldable<'tcx> {
     struct FixupFolder<'tcx> {
         tcx: TyCtxt<'tcx>
@@ -893,6 +917,14 @@ fn fixup_opaque_types<'tcx, T>(tcx: TyCtxt<'tcx>, val: &T) -> T where T: TypeFol
             match ty.kind {
                 ty::Opaque(def_id, substs) => {
                     debug!("fixup_opaque_types: found type {:?}", ty);
+                    // Here, we replace any inference variables that occur within
+                    // the substs of an opaque type. By definition, any type occuring
+                    // in the substs has a corresponding generic parameter, which is what
+                    // we replace it with.
+                    // This replacement is only run on the function signature, so any
+                    // inference variables that we come across must be the rust of projection
+                    // (there's no other way for a user to get inference variables into
+                    // a function signature).
                     if ty.needs_infer() {
                         let new_substs = InternalSubsts::for_item(self.tcx, def_id, |param, _| {
                             let old_param = substs[param.index as usize];