about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-02-22 17:09:25 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-03-28 17:02:21 +0000
commit2aa49d4005d00e7f3b6ee1c596f0c5875d74d90a (patch)
treea951a0ccaab3fa8e0f124dd91ba5c24dfa2097d9
parent4f6e27d4cf783e4a10326b16596e444dc325cf3d (diff)
downloadrust-2aa49d4005d00e7f3b6ee1c596f0c5875d74d90a.tar.gz
rust-2aa49d4005d00e7f3b6ee1c596f0c5875d74d90a.zip
Fix mixing lazy TAIT and RPIT in their defining scopes
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs79
-rw-r--r--src/test/ui/impl-trait/async_scope_creep.rs28
2 files changed, 68 insertions, 39 deletions
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 5920d12a93c..59aea2b2030 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -95,6 +95,45 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
         let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
             ty::Opaque(def_id, substs) => {
+                let origin = if self.defining_use_anchor.is_some() {
+                    // Check that this is `impl Trait` type is
+                    // declared by `parent_def_id` -- i.e., one whose
+                    // value we are inferring.  At present, this is
+                    // always true during the first phase of
+                    // type-check, but not always true later on during
+                    // NLL. Once we support named opaque types more fully,
+                    // this same scenario will be able to arise during all phases.
+                    //
+                    // Here is an example using type alias `impl Trait`
+                    // that indicates the distinction we are checking for:
+                    //
+                    // ```rust
+                    // mod a {
+                    //   pub type Foo = impl Iterator;
+                    //   pub fn make_foo() -> Foo { .. }
+                    // }
+                    //
+                    // mod b {
+                    //   fn foo() -> a::Foo { a::make_foo() }
+                    // }
+                    // ```
+                    //
+                    // Here, the return type of `foo` references an
+                    // `Opaque` indeed, but not one whose value is
+                    // presently being inferred. You can get into a
+                    // similar situation with closure return types
+                    // today:
+                    //
+                    // ```rust
+                    // fn foo() -> impl Iterator { .. }
+                    // fn bar() {
+                    //     let x = || foo(); // returns the Opaque assoc with `foo`
+                    // }
+                    // ```
+                    self.opaque_type_origin(def_id, cause.span)?
+                } else {
+                    self.opaque_ty_origin_unchecked(def_id, cause.span)
+                };
                 if let ty::Opaque(did2, _) = *b.kind() {
                     // We could accept this, but there are various ways to handle this situation, and we don't
                     // want to make a decision on it right now. Likely this case is so super rare anyway, that
@@ -126,45 +165,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     cause.clone(),
                     param_env,
                     b,
-                    if self.defining_use_anchor.is_some() {
-                        // Check that this is `impl Trait` type is
-                        // declared by `parent_def_id` -- i.e., one whose
-                        // value we are inferring.  At present, this is
-                        // always true during the first phase of
-                        // type-check, but not always true later on during
-                        // NLL. Once we support named opaque types more fully,
-                        // this same scenario will be able to arise during all phases.
-                        //
-                        // Here is an example using type alias `impl Trait`
-                        // that indicates the distinction we are checking for:
-                        //
-                        // ```rust
-                        // mod a {
-                        //   pub type Foo = impl Iterator;
-                        //   pub fn make_foo() -> Foo { .. }
-                        // }
-                        //
-                        // mod b {
-                        //   fn foo() -> a::Foo { a::make_foo() }
-                        // }
-                        // ```
-                        //
-                        // Here, the return type of `foo` references an
-                        // `Opaque` indeed, but not one whose value is
-                        // presently being inferred. You can get into a
-                        // similar situation with closure return types
-                        // today:
-                        //
-                        // ```rust
-                        // fn foo() -> impl Iterator { .. }
-                        // fn bar() {
-                        //     let x = || foo(); // returns the Opaque assoc with `foo`
-                        // }
-                        // ```
-                        self.opaque_type_origin(def_id, cause.span)?
-                    } else {
-                        self.opaque_ty_origin_unchecked(def_id, cause.span)
-                    },
+                    origin,
                 ))
             }
             _ => None,
diff --git a/src/test/ui/impl-trait/async_scope_creep.rs b/src/test/ui/impl-trait/async_scope_creep.rs
new file mode 100644
index 00000000000..7a9d64d339f
--- /dev/null
+++ b/src/test/ui/impl-trait/async_scope_creep.rs
@@ -0,0 +1,28 @@
+#![feature(type_alias_impl_trait)]
+// edition:2021
+// check-pass
+
+struct Pending {}
+
+struct CantOpen {}
+
+trait AsyncRead {}
+
+impl AsyncRead for i32 {}
+
+type PendingReader<'a> = impl AsyncRead + 'a;
+
+type OpeningReadFuture<'a> =
+    impl std::future::Future<Output = Result<PendingReader<'a>, CantOpen>>;
+
+impl Pending {
+    async fn read(&mut self) -> Result<impl AsyncRead + '_, CantOpen> {
+        Ok(42)
+    }
+
+    fn read_fut(&mut self) -> OpeningReadFuture<'_> {
+        self.read()
+    }
+}
+
+fn main() {}