diff options
5 files changed, 87 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-2.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs new file mode 100644 index 00000000000..10588398c9d --- /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<S>() -> impl std::fmt::Display { + &0usize +} +fn bad() -> Op { + transform::<Op>() + //~^ 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 00000000000..7481557fcba --- /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::<Op>() + | ^^^^^^^^^^^^^^^^^ 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 + 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 + |
