about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-07-13 00:31:38 +0000
committerMichael Goulet <michael@errs.io>2023-07-18 15:56:03 +0000
commit7db5f818531fe7f77853a66793584fe15bb464fc (patch)
treeef7506910c45be59ed845f682a5e12070d956dd7
parent8d361cbd91d827d703d2da46af8d89190ca1cb6a (diff)
Relax recursive opaque type check
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs24
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs34
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr14
3 files changed, 52 insertions, 20 deletions
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index cf6c7f70de3..2329a1f63ce 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -3,7 +3,6 @@
 // substitutions.
 
 use crate::FnCtxt;
-use hir::def_id::LocalDefId;
 use rustc_data_structures::unord::ExtendUnord;
 use rustc_errors::{ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
@@ -11,13 +10,12 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
+use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
 use std::mem;
-use std::ops::ControlFlow;
 
 ///////////////////////////////////////////////////////////////////////////
 // Entry point
@@ -565,23 +563,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
             let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
 
-            struct RecursionChecker {
-                def_id: LocalDefId,
-            }
-            impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for RecursionChecker {
-                type BreakTy = ();
-                fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-                    if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *t.kind() {
-                        if def_id == self.def_id.to_def_id() {
-                            return ControlFlow::Break(());
-                        }
-                    }
-                    t.super_visit_with(self)
-                }
-            }
-            if hidden_type
-                .visit_with(&mut RecursionChecker { def_id: opaque_type_key.def_id })
-                .is_break()
+            if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
+                && alias_ty.def_id == opaque_type_key.def_id.to_def_id()
+                && alias_ty.args == opaque_type_key.args
             {
                 continue;
             }
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
new file mode 100644
index 00000000000..e221f4f3f55
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
@@ -0,0 +1,34 @@
+// issue: 113596
+
+#![feature(type_alias_impl_trait)]
+
+trait Test {}
+
+struct A;
+
+impl Test for A {}
+
+struct B<T> {
+  inner: T,
+}
+
+impl<T: Test> Test for B<T> {}
+
+type TestImpl = impl Test;
+
+fn test() -> TestImpl {
+  A
+}
+
+fn make_option() -> Option<TestImpl> {
+  Some(test())
+}
+
+fn make_option2() -> Option<TestImpl> {
+  let inner = make_option().unwrap();
+
+  Some(B { inner })
+  //~^ ERROR concrete type differs from previous defining opaque type use
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
new file mode 100644
index 00000000000..e4209643b7a
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/recursive-tait-conflicting-defn.rs:30:3
+   |
+LL |   Some(B { inner })
+   |   ^^^^^^^^^^^^^^^^^ expected `A`, got `B<TestImpl>`
+   |
+note: previous use here
+  --> $DIR/recursive-tait-conflicting-defn.rs:20:3
+   |
+LL |   A
+   |   ^
+
+error: aborting due to previous error
+