about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2020-01-12 10:19:19 +0000
committerMatthew Jasper <mjjasper1@gmail.com>2020-02-14 22:40:03 +0000
commit6d9e270a4ddf517b008537f0d8b3768db20d5436 (patch)
tree88b297296b6e535c674ea18dd99c1cbefb61f53d
parent78e0ab53fb4ac444e7d62735f0b8dcc9a42004f6 (diff)
downloadrust-6d9e270a4ddf517b008537f0d8b3768db20d5436.tar.gz
rust-6d9e270a4ddf517b008537f0d8b3768db20d5436.zip
Fix and test nested impl Trait
-rw-r--r--src/librustc_mir/borrow_check/region_infer/opaque_types.rs18
-rw-r--r--src/test/ui/impl-trait/nested-return-type.rs16
2 files changed, 29 insertions, 5 deletions
diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
index 71702eb84e7..52d54f7b53c 100644
--- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
+++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs
@@ -13,8 +13,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// For example consider `fn f<'a>(x: &'a i32) -> impl Sized + 'a { x }`.
     /// This is lowered to give HIR something like
     ///
-    /// type _Return<'_a> = impl Sized + '_a;
-    /// fn f<'a>(x: &'a i32) -> _Return<'a> { x }
+    /// type f<'a>::_Return<'_a> = impl Sized + '_a;
+    /// fn f<'a>(x: &'a i32) -> f<'static>::_Return<'a> { x }
     ///
     /// When checking the return type record the type from the return and the
     /// type used in the return value. In this case they might be `_Return<'1>`
@@ -34,9 +34,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }`
     ///
     /// Then we map the regions in both the type and the subst to their
-    /// `external_name` giving `concrete_type = &'a i32, substs = ['a]`. This
-    /// will then allow `infer_opaque_definition_from_instantiation` to
-    /// determine that `_Return<'_a> = &'_a i32`.
+    /// `external_name` giving `concrete_type = &'a i32`,
+    /// `substs = ['static, 'a]`. This will then allow
+    /// `infer_opaque_definition_from_instantiation` to determine that
+    /// `_Return<'_a> = &'_a i32`.
     ///
     /// There's a slight complication around closures. Given
     /// `fn f<'a: 'a>() { || {} }` the closure's type is something like
@@ -72,6 +73,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                                 infcx.tcx.lifetimes.re_static
                             })
                         }
+                        // We don't fold regions in the predicates of opaque
+                        // types to `ReVar`s. This means that in a case like
+                        //
+                        // fn f<'a: 'a>() -> impl Iterator<Item = impl Sized>
+                        //
+                        // The inner opaque type has `'static` in its substs.
+                        ty::ReStatic => region,
                         _ => {
                             infcx.tcx.sess.delay_span_bug(
                                 span,
diff --git a/src/test/ui/impl-trait/nested-return-type.rs b/src/test/ui/impl-trait/nested-return-type.rs
new file mode 100644
index 00000000000..7d7a084b890
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type.rs
@@ -0,0 +1,16 @@
+// Check that nested impl Trait items work in functions with generic parameters.
+// check-pass
+
+trait Captures<'a> {}
+
+impl<T> Captures<'_> for T {}
+
+fn nested_assoc_type<'a: 'a, T>() -> impl Iterator<Item = impl Sized> {
+    [1].iter()
+}
+
+fn nested_assoc_lifetime<'a: 'a, T>() -> impl Iterator<Item = impl Captures<'a>> {
+    [1].iter()
+}
+
+fn main() {}