]> git.lizzy.rs Git - rust.git/commitdiff
Fall back when relating two opaques by substs in MIR typeck
authorMichael Goulet <michael@errs.io>
Wed, 3 Aug 2022 03:16:31 +0000 (03:16 +0000)
committerMichael Goulet <michael@errs.io>
Wed, 10 Aug 2022 03:27:41 +0000 (03:27 +0000)
compiler/rustc_infer/src/infer/nll_relate/mod.rs
src/test/ui/impl-trait/issue-100075-2.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-100075-2.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issue-100075.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-100075.stderr [new file with mode: 0644]

index bab4f3e9e362ffb4a4c2fcea4c83c45b85d97fcc..324aef9c01f6ee32f905ab8349f83c28f37154ba 100644 (file)
@@ -396,6 +396,32 @@ fn generalize_value<T: Relate<'tcx>>(
 
         generalizer.relate(value, value)
     }
+
+    fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
+        let mut generalize = |ty, ty_is_expected| {
+            let var = self.infcx.next_ty_var_id_in_universe(
+                TypeVariableOrigin {
+                    kind: TypeVariableOriginKind::MiscVariable,
+                    span: self.delegate.span(),
+                },
+                ty::UniverseIndex::ROOT,
+            );
+            if ty_is_expected {
+                self.relate_ty_var((ty, var))
+            } else {
+                self.relate_ty_var((var, ty))
+            }
+        };
+        let (a, b) = match (a.kind(), b.kind()) {
+            (&ty::Opaque(..), _) => (a, generalize(b, false)?),
+            (_, &ty::Opaque(..)) => (generalize(a, true)?, b),
+            _ => unreachable!(),
+        };
+        self.delegate.register_opaque_type(a, b, true)?;
+        trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
+        Ok(a)
+    }
 }
 
 /// When we instantiate an inference variable with a value in
@@ -572,32 +598,12 @@ fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>
             (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
 
             (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
-                self.infcx.super_combine_tys(self, a, b)
+                infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| {
+                    if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
+                })
             }
             (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
-                let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
-                let mut generalize = |ty, ty_is_expected| {
-                    let var = infcx.next_ty_var_id_in_universe(
-                        TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::MiscVariable,
-                            span: self.delegate.span(),
-                        },
-                        ty::UniverseIndex::ROOT,
-                    );
-                    if ty_is_expected {
-                        self.relate_ty_var((ty, var))
-                    } else {
-                        self.relate_ty_var((var, ty))
-                    }
-                };
-                let (a, b) = match (a.kind(), b.kind()) {
-                    (&ty::Opaque(..), _) => (a, generalize(b, false)?),
-                    (_, &ty::Opaque(..)) => (generalize(a, true)?, b),
-                    _ => unreachable!(),
-                };
-                self.delegate.register_opaque_type(a, b, true)?;
-                trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
-                Ok(a)
+                self.relate_opaques(a, b)
             }
 
             (&ty::Projection(projection_ty), _)
diff --git a/src/test/ui/impl-trait/issue-100075-2.rs b/src/test/ui/impl-trait/issue-100075-2.rs
new file mode 100644 (file)
index 0000000..cf059af
--- /dev/null
@@ -0,0 +1,8 @@
+fn opaque<T>(t: T) -> impl Sized {
+    //~^ ERROR cannot resolve opaque type
+    //~| WARNING function cannot return without recursing
+    opaque(Some(t))
+}
+
+#[allow(dead_code)]
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-100075-2.stderr b/src/test/ui/impl-trait/issue-100075-2.stderr
new file mode 100644 (file)
index 0000000..5a1f1a9
--- /dev/null
@@ -0,0 +1,24 @@
+warning: function cannot return without recursing
+  --> $DIR/issue-100075-2.rs:1:1
+   |
+LL | fn opaque<T>(t: T) -> impl Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+...
+LL |     opaque(Some(t))
+   |     --------------- recursive call site
+   |
+   = note: `#[warn(unconditional_recursion)]` on by default
+   = help: a `loop` may express intention better if this is on purpose
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/issue-100075-2.rs:1:23
+   |
+LL | fn opaque<T>(t: T) -> impl Sized {
+   |                       ^^^^^^^^^^ recursive opaque type
+...
+LL |     opaque(Some(t))
+   |     --------------- returning here with type `impl Sized`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/issue-100075.rs b/src/test/ui/impl-trait/issue-100075.rs
new file mode 100644 (file)
index 0000000..ea30abb
--- /dev/null
@@ -0,0 +1,21 @@
+trait Marker {}
+impl<T> Marker for T {}
+
+fn maybe<T>(
+    _t: T,
+) -> Option<
+    //removing the line below makes it compile
+    &'static T,
+> {
+    None
+}
+
+fn _g<T>(t: &'static T) -> &'static impl Marker {
+    //~^ ERROR cannot resolve opaque type
+    if let Some(t) = maybe(t) {
+        return _g(t);
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-100075.stderr b/src/test/ui/impl-trait/issue-100075.stderr
new file mode 100644 (file)
index 0000000..267ecfd
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0720]: cannot resolve opaque type
+  --> $DIR/issue-100075.rs:13:37
+   |
+LL | fn _g<T>(t: &'static T) -> &'static impl Marker {
+   |                                     ^^^^^^^^^^^ recursive opaque type
+...
+LL |         return _g(t);
+   |                ----- returning here with type `&impl Marker`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0720`.