Skip to content

Commit 3afec24

Browse files
committed
Deduplicate visitor.
1 parent d470ac9 commit 3afec24

File tree

2 files changed

+22
-99
lines changed

2 files changed

+22
-99
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+19-96
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
1010
use rustc_hir::def_id::{DefId, LocalDefId};
1111
use rustc_hir::intravisit::Visitor;
1212
use rustc_hir::{ItemKind, Node, PathSegment};
13+
use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
1314
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1415
use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
1516
use rustc_infer::traits::Obligation;
@@ -254,100 +255,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
254255
let item = tcx.hir().expect_item(def_id);
255256
debug!(?item, ?span);
256257

257-
#[derive(Debug)]
258-
struct FoundParentLifetime;
259-
struct FindParentLifetimeVisitor<'tcx> {
260-
tcx: TyCtxt<'tcx>,
261-
parent_count: u32,
262-
}
263-
impl<'tcx> ty::visit::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> {
264-
type BreakTy = FoundParentLifetime;
265-
266-
#[instrument(level = "trace", skip(self), ret)]
267-
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
268-
if let ty::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = *r {
269-
if index < self.parent_count {
270-
return ControlFlow::Break(FoundParentLifetime);
271-
} else {
272-
return ControlFlow::CONTINUE;
273-
}
274-
}
275-
276-
r.super_visit_with(self)
277-
}
278-
279-
#[instrument(level = "trace", skip(self), ret)]
280-
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
281-
// We're only interested in types involving regions
282-
if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
283-
return ControlFlow::CONTINUE;
284-
}
285-
286-
match ty.kind() {
287-
ty::Closure(_, ref substs) => {
288-
// Skip lifetime parameters of the enclosing item(s)
289-
290-
substs.as_closure().tupled_upvars_ty().visit_with(self)?;
291-
substs.as_closure().sig_as_fn_ptr_ty().visit_with(self)?;
292-
}
293-
294-
ty::Generator(_, ref substs, _) => {
295-
// Skip lifetime parameters of the enclosing item(s)
296-
// Also skip the witness type, because that has no free regions.
297-
298-
substs.as_generator().tupled_upvars_ty().visit_with(self)?;
299-
substs.as_generator().return_ty().visit_with(self)?;
300-
substs.as_generator().yield_ty().visit_with(self)?;
301-
substs.as_generator().resume_ty().visit_with(self)?;
302-
}
303-
304-
ty::Opaque(def_id, ref substs) => {
305-
// Skip lifetime paramters that are not captures.
306-
let variances = self.tcx.variances_of(*def_id);
307-
308-
for (v, s) in std::iter::zip(variances, substs.iter()) {
309-
if *v != ty::Variance::Bivariant {
310-
s.visit_with(self)?;
311-
}
312-
}
313-
}
314-
315-
ty::Projection(proj)
316-
if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
317-
{
318-
// Skip lifetime paramters that are not captures.
319-
let variances = self.tcx.variances_of(proj.item_def_id);
320-
321-
for (v, s) in std::iter::zip(variances, proj.substs.iter()) {
322-
if *v != ty::Variance::Bivariant {
323-
s.visit_with(self)?;
324-
}
325-
}
326-
}
327-
328-
_ => {
329-
ty.super_visit_with(self)?;
330-
}
331-
}
332-
333-
ControlFlow::CONTINUE
334-
}
335-
336-
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
337-
if let ty::ConstKind::Unevaluated(..) = c.kind() {
338-
// FIXME(#72219) We currently don't detect lifetimes within substs
339-
// which would violate this check. Even though the particular substitution is not used
340-
// within the const, this should still be fixed.
341-
return ControlFlow::CONTINUE;
342-
}
343-
c.super_visit_with(self)
344-
}
345-
}
346-
347258
struct ProhibitOpaqueVisitor<'tcx> {
348259
tcx: TyCtxt<'tcx>,
349260
opaque_identity_ty: Ty<'tcx>,
350-
generics: &'tcx ty::Generics,
261+
parent_count: u32,
262+
references_parent_regions: bool,
351263
selftys: Vec<(Span, Option<String>)>,
352264
}
353265

@@ -359,11 +271,21 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
359271
if t == self.opaque_identity_ty {
360272
ControlFlow::CONTINUE
361273
} else {
362-
t.visit_with(&mut FindParentLifetimeVisitor {
274+
t.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
363275
tcx: self.tcx,
364-
parent_count: self.generics.parent_count as u32,
365-
})
366-
.map_break(|FoundParentLifetime| t)
276+
op: |region| {
277+
if let ty::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = *region
278+
&& index < self.parent_count
279+
{
280+
self.references_parent_regions= true;
281+
}
282+
},
283+
});
284+
if self.references_parent_regions {
285+
ControlFlow::Break(t)
286+
} else {
287+
ControlFlow::CONTINUE
288+
}
367289
}
368290
}
369291
}
@@ -408,7 +330,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
408330
};
409331
let mut visitor = ProhibitOpaqueVisitor {
410332
opaque_identity_ty,
411-
generics: tcx.generics_of(def_id),
333+
parent_count: tcx.generics_of(def_id).parent_count as u32,
334+
references_parent_regions: false,
412335
tcx,
413336
selftys: vec![],
414337
};

compiler/rustc_infer/src/infer/opaque_types.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,9 @@ impl<'tcx> InferCtxt<'tcx> {
423423
//
424424
// We ignore any type parameters because impl trait values are assumed to
425425
// capture all the in-scope type parameters.
426-
struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP> {
427-
tcx: TyCtxt<'tcx>,
428-
op: OP,
426+
pub struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP: FnMut(ty::Region<'tcx>)> {
427+
pub tcx: TyCtxt<'tcx>,
428+
pub op: OP,
429429
}
430430

431431
impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>

0 commit comments

Comments
 (0)