Skip to content

Commit

Permalink
Fix missing type alias cycle detection
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez committed Oct 29, 2022
1 parent 9e7f02b commit c383c9d
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 42 deletions.
49 changes: 47 additions & 2 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitor,
self, AdtKind, DefIdTree, GenericParamDefKind, SubstsRef, ToPredicate, Ty, TyCtxt,
TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_middle::ty::{GenericArgKind, InternalSubsts};
use rustc_session::parse::feature_err;
Expand Down Expand Up @@ -239,6 +239,51 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
hir::ItemKind::TraitAlias(..) => {
check_trait(tcx, item);
}
hir::ItemKind::TyAlias { .. } => {
struct TyAliasPeeler<'t> {
tcx: TyCtxt<'t>,
visited: FxHashSet<(DefId, SubstsRef<'t>)>,
}

impl<'t> ty::TypeFolder<'t> for TyAliasPeeler<'t> {
fn tcx<'a>(&'a self) -> TyCtxt<'t> {
self.tcx
}

fn fold_ty(&mut self, t: Ty<'t>) -> Ty<'t> {
use crate::ty::fold::{TypeFoldable, TypeSuperFoldable};
use crate::ty::visit::TypeVisitable;

match *t.kind() {
ty::TyAlias(def_id, substs) => {
if !self.visited.insert((def_id, substs)) {
let def_span = self.tcx.def_span(def_id);
self.tcx
.sess
.struct_span_err(
def_span,
"cycle detected when expanding type alias",
)
.emit();
return t;
}
let binder_ty = self.tcx.bound_type_of(def_id);
let ty = binder_ty.subst(self.tcx, substs);
ty.fold_with(self)
}
_ if !t.has_ty_alias() => t,
_ => t.super_fold_with(self),
}
}
}

let ty = tcx.bound_type_of(item.def_id.to_def_id()).0;
if let ty::TyAlias(def_id, substs) = *ty.kind() {
let binder_ty = tcx.bound_type_of(def_id);
let ty = binder_ty.subst(tcx, substs);
ty.fold_with(&mut TyAliasPeeler { tcx, visited: FxHashSet::default() });
}
}
// `ForeignItem`s are handled separately.
hir::ItemKind::ForeignMod { .. } => {}
_ => {}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/variance/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use hir::def_id::{DefId, LocalDefId};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, Subst, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt};

use super::terms::VarianceTerm::*;
use super::terms::*;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_macros::LintDiagnostic;
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{
self, AdtKind, DefIdTree, Subst, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
};
use rustc_span::source_map;
use rustc_span::symbol::sym;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use rustc_middle::span_bug;
use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst, Node as ACNode};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind, Subst};
use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind};
use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_session::lint;
use rustc_span::hygiene::Transparency;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::subst::{Subst, SubstsRef};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
use rustc_middle::ty::DefIdTree;
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::def_id::DefId;
use rustc_infer::traits::Normalized;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use rustc_middle::ty::subst::{Subst, SubstsRef};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::DUMMY_SP;
Expand Down
11 changes: 5 additions & 6 deletions compiler/rustc_trait_selection/src/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
use rustc_middle::ty::walk::TypeWalker;
use rustc_middle::ty::{self, ParamEnv, Subst, ToPredicate, Ty, TyCtxt, TypeVisitable};
use rustc_middle::ty::{self, ParamEnv, ToPredicate, Ty, TyCtxt, TypeVisitable};
use rustc_span::Span;

use std::iter;
Expand Down Expand Up @@ -506,9 +506,9 @@ impl<'tcx> WfPredicates<'tcx> {
cause,
depth,
param_env,
ty::Binder::dummy(ty::PredicateKind::TypeOutlives(
ty::OutlivesPredicate(rty, r),
))
ty::Binder::dummy(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
rty, r,
)))
.to_predicate(self.tcx()),
));
}
Expand Down Expand Up @@ -606,8 +606,7 @@ impl<'tcx> WfPredicates<'tcx> {
cause.clone(),
depth,
param_env,
ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did))
.to_predicate(tcx),
ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)).to_predicate(tcx),
)
}));
}
Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/infinite/infinite-type-alias-mutual-recursion.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
type X1 = X2;
//~^ ERROR cycle detected when expanding type alias `X1`
//~^ ERROR cycle detected when expanding type alias
type X2 = X3;
//~^ ERROR cycle detected when expanding type alias
type X3 = X1;
//~^ ERROR cycle detected when expanding type alias

fn main() {}
42 changes: 14 additions & 28 deletions src/test/ui/infinite/infinite-type-alias-mutual-recursion.stderr
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
error[E0391]: cycle detected when expanding type alias `X1`
--> $DIR/infinite-type-alias-mutual-recursion.rs:1:11
|
LL | type X1 = X2;
| ^^
|
note: ...which requires expanding type alias `X2`...
--> $DIR/infinite-type-alias-mutual-recursion.rs:3:11
|
LL | type X2 = X3;
| ^^
note: ...which requires expanding type alias `X3`...
--> $DIR/infinite-type-alias-mutual-recursion.rs:4:11
error: cycle detected when expanding type alias
--> $DIR/infinite-type-alias-mutual-recursion.rs:5:1
|
LL | type X3 = X1;
| ^^
= note: ...which again requires expanding type alias `X1`, completing the cycle
= note: type aliases cannot be recursive
= help: consider using a struct, enum, or union instead to break the cycle
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
note: cycle used when collecting item types in top-level module
| ^^^^^^^

error: cycle detected when expanding type alias
--> $DIR/infinite-type-alias-mutual-recursion.rs:1:1
|
LL | / type X1 = X2;
LL | |
LL | | type X2 = X3;
LL | | type X3 = X1;
LL | |
LL | | fn main() {}
| |____________^
LL | type X1 = X2;
| ^^^^^^^

error: cycle detected when expanding type alias
--> $DIR/infinite-type-alias-mutual-recursion.rs:3:1
|
LL | type X2 = X3;
| ^^^^^^^

error: aborting due to previous error
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0391`.

0 comments on commit c383c9d

Please sign in to comment.