Skip to content

Commit b5ff9c3

Browse files
committed
Auto merge of #79773 - lcnr:type-visitor, r=oli-obk
small `TypeVisitor` refactor cc `@LeSeulArtichaut` `@scottmcm` adds `ControlFlow::map_break`
2 parents 2b76c48 + e3e4870 commit b5ff9c3

File tree

3 files changed

+55
-36
lines changed

3 files changed

+55
-36
lines changed

Diff for: compiler/rustc_mir/src/interpret/util.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,21 @@ where
1313
return Ok(());
1414
}
1515

16+
struct FoundParam;
1617
struct UsedParamsNeedSubstVisitor<'tcx> {
1718
tcx: TyCtxt<'tcx>,
1819
}
1920

2021
impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
21-
type BreakTy = ();
22+
type BreakTy = FoundParam;
2223

2324
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
2425
if !c.needs_subst() {
2526
return ControlFlow::CONTINUE;
2627
}
2728

2829
match c.val {
29-
ty::ConstKind::Param(..) => ControlFlow::BREAK,
30+
ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
3031
_ => c.super_visit_with(self),
3132
}
3233
}
@@ -37,7 +38,7 @@ where
3738
}
3839

3940
match *ty.kind() {
40-
ty::Param(_) => ControlFlow::BREAK,
41+
ty::Param(_) => ControlFlow::Break(FoundParam),
4142
ty::Closure(def_id, substs)
4243
| ty::Generator(def_id, substs, ..)
4344
| ty::FnDef(def_id, substs) => {
@@ -76,7 +77,7 @@ where
7677
}
7778

7879
let mut vis = UsedParamsNeedSubstVisitor { tcx };
79-
if ty.visit_with(&mut vis).is_break() {
80+
if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) {
8081
throw_inval!(TooGeneric);
8182
} else {
8283
Ok(())

Diff for: compiler/rustc_typeck/src/check/check.rs

+36-32
Original file line numberDiff line numberDiff line change
@@ -462,39 +462,25 @@ pub(super) fn check_opaque<'tcx>(
462462

463463
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
464464
/// in "inheriting lifetimes".
465+
#[instrument(skip(tcx, span))]
465466
pub(super) fn check_opaque_for_inheriting_lifetimes(
466467
tcx: TyCtxt<'tcx>,
467468
def_id: LocalDefId,
468469
span: Span,
469470
) {
470471
let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id));
471-
debug!(
472-
"check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}",
473-
def_id, span, item
474-
);
475-
476-
#[derive(Debug)]
477-
struct ProhibitOpaqueVisitor<'tcx> {
478-
opaque_identity_ty: Ty<'tcx>,
479-
generics: &'tcx ty::Generics,
480-
}
472+
debug!(?item, ?span);
481473

482-
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
483-
type BreakTy = Option<Ty<'tcx>>;
484-
485-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
486-
debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
487-
if t != self.opaque_identity_ty && t.super_visit_with(self).is_break() {
488-
return ControlFlow::Break(Some(t));
489-
}
490-
ControlFlow::CONTINUE
491-
}
474+
struct FoundParentLifetime;
475+
struct FindParentLifetimeVisitor<'tcx>(&'tcx ty::Generics);
476+
impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> {
477+
type BreakTy = FoundParentLifetime;
492478

493479
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
494-
debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r);
480+
debug!("FindParentLifetimeVisitor: r={:?}", r);
495481
if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
496-
if *index < self.generics.parent_count as u32 {
497-
return ControlFlow::Break(None);
482+
if *index < self.0.parent_count as u32 {
483+
return ControlFlow::Break(FoundParentLifetime);
498484
} else {
499485
return ControlFlow::CONTINUE;
500486
}
@@ -505,7 +491,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
505491

506492
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
507493
if let ty::ConstKind::Unevaluated(..) = c.val {
508-
// FIXME(#72219) We currenctly don't detect lifetimes within substs
494+
// FIXME(#72219) We currently don't detect lifetimes within substs
509495
// which would violate this check. Even though the particular substitution is not used
510496
// within the const, this should still be fixed.
511497
return ControlFlow::CONTINUE;
@@ -514,6 +500,26 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
514500
}
515501
}
516502

503+
#[derive(Debug)]
504+
struct ProhibitOpaqueVisitor<'tcx> {
505+
opaque_identity_ty: Ty<'tcx>,
506+
generics: &'tcx ty::Generics,
507+
}
508+
509+
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
510+
type BreakTy = Ty<'tcx>;
511+
512+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
513+
debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
514+
if t == self.opaque_identity_ty {
515+
ControlFlow::CONTINUE
516+
} else {
517+
t.super_visit_with(&mut FindParentLifetimeVisitor(self.generics))
518+
.map_break(|FoundParentLifetime| t)
519+
}
520+
}
521+
}
522+
517523
if let ItemKind::OpaqueTy(hir::OpaqueTy {
518524
origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn,
519525
..
@@ -555,14 +561,12 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
555561

556562
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
557563
if snippet == "Self" {
558-
if let Some(ty) = ty {
559-
err.span_suggestion(
560-
span,
561-
"consider spelling out the type instead",
562-
format!("{:?}", ty),
563-
Applicability::MaybeIncorrect,
564-
);
565-
}
564+
err.span_suggestion(
565+
span,
566+
"consider spelling out the type instead",
567+
format!("{:?}", ty),
568+
Applicability::MaybeIncorrect,
569+
);
566570
}
567571
}
568572
err.emit();

Diff for: library/core/src/ops/control_flow.rs

+14
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,20 @@ impl<B, C> ControlFlow<B, C> {
5656
ControlFlow::Break(x) => Some(x),
5757
}
5858
}
59+
60+
/// Maps `ControlFlow<B, C>` to `ControlFlow<T, C>` by applying a function
61+
/// to the break value in case it exists.
62+
#[inline]
63+
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
64+
pub fn map_break<T, F>(self, f: F) -> ControlFlow<T, C>
65+
where
66+
F: FnOnce(B) -> T,
67+
{
68+
match self {
69+
ControlFlow::Continue(x) => ControlFlow::Continue(x),
70+
ControlFlow::Break(x) => ControlFlow::Break(f(x)),
71+
}
72+
}
5973
}
6074

6175
impl<R: Try> ControlFlow<R, R::Ok> {

0 commit comments

Comments
 (0)