From 7db5f818531fe7f77853a66793584fe15bb464fc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Jul 2023 00:31:38 +0000 Subject: [PATCH 1/2] Relax recursive opaque type check --- compiler/rustc_hir_typeck/src/writeback.rs | 24 +++---------- .../recursive-tait-conflicting-defn.rs | 34 +++++++++++++++++++ .../recursive-tait-conflicting-defn.stderr | 14 ++++++++ 3 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs create mode 100644 tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index cf6c7f70de3f1..2329a1f63ceca 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> for RecursionChecker { - type BreakTy = (); - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - 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 0000000000000..e221f4f3f55c8 --- /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 { + inner: T, +} + +impl Test for B {} + +type TestImpl = impl Test; + +fn test() -> TestImpl { + A +} + +fn make_option() -> Option { + Some(test()) +} + +fn make_option2() -> Option { + 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 0000000000000..e4209643b7a3d --- /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` + | +note: previous use here + --> $DIR/recursive-tait-conflicting-defn.rs:20:3 + | +LL | A + | ^ + +error: aborting due to previous error + From 687558992430dc3992fab19a05fdb01b8af17708 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Jul 2023 16:24:04 +0000 Subject: [PATCH 2/2] Add additional test --- .../recursive-tait-conflicting-defn-2.rs | 21 +++++++++++++++++++ .../recursive-tait-conflicting-defn-2.stderr | 14 +++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs create mode 100644 tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs new file mode 100644 index 0000000000000..10588398c9d7f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs @@ -0,0 +1,21 @@ +// issue: 113314 + +#![feature(type_alias_impl_trait)] + +type Op = impl std::fmt::Display; +fn foo() -> Op { &"hello world" } + +fn transform() -> impl std::fmt::Display { + &0usize +} +fn bad() -> Op { + transform::() + //~^ ERROR concrete type differs from previous defining opaque type use +} + +fn main() { + let mut x = foo(); + println!("{x}"); + x = bad(); + println!("{x}"); +} diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr new file mode 100644 index 0000000000000..7481557fcbade --- /dev/null +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr @@ -0,0 +1,14 @@ +error: concrete type differs from previous defining opaque type use + --> $DIR/recursive-tait-conflicting-defn-2.rs:12:5 + | +LL | transform::() + | ^^^^^^^^^^^^^^^^^ expected `&'static &'static str`, got `impl std::fmt::Display` + | +note: previous use here + --> $DIR/recursive-tait-conflicting-defn-2.rs:6:18 + | +LL | fn foo() -> Op { &"hello world" } + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error +