Relax recursive opaque type check

This commit is contained in:
Michael Goulet 2023-07-13 00:31:38 +00:00
parent 8d361cbd91
commit 7db5f81853
3 changed files with 52 additions and 20 deletions

View File

@ -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;
}

View File

@ -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() {}

View File

@ -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