Use TypeVisitor::BreakTy
in structural_match::Search
This commit is contained in:
parent
e0f3119103
commit
17b395d296
1 changed files with 15 additions and 36 deletions
|
@ -55,9 +55,7 @@ pub fn search_for_structural_match_violation<'tcx>(
|
||||||
) -> Option<NonStructuralMatchTy<'tcx>> {
|
) -> Option<NonStructuralMatchTy<'tcx>> {
|
||||||
// FIXME: we should instead pass in an `infcx` from the outside.
|
// FIXME: we should instead pass in an `infcx` from the outside.
|
||||||
tcx.infer_ctxt().enter(|infcx| {
|
tcx.infer_ctxt().enter(|infcx| {
|
||||||
let mut search = Search { infcx, span, found: None, seen: FxHashSet::default() };
|
ty.visit_with(&mut Search { infcx, span, seen: FxHashSet::default() }).break_value()
|
||||||
ty.visit_with(&mut search);
|
|
||||||
search.found
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,9 +114,6 @@ struct Search<'a, 'tcx> {
|
||||||
|
|
||||||
infcx: InferCtxt<'a, 'tcx>,
|
infcx: InferCtxt<'a, 'tcx>,
|
||||||
|
|
||||||
/// Records first ADT that does not implement a structural-match trait.
|
|
||||||
found: Option<NonStructuralMatchTy<'tcx>>,
|
|
||||||
|
|
||||||
/// Tracks ADTs previously encountered during search, so that
|
/// Tracks ADTs previously encountered during search, so that
|
||||||
/// we will not recur on them again.
|
/// we will not recur on them again.
|
||||||
seen: FxHashSet<hir::def_id::DefId>,
|
seen: FxHashSet<hir::def_id::DefId>,
|
||||||
|
@ -135,38 +130,33 @@ impl Search<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
||||||
|
type BreakTy = NonStructuralMatchTy<'tcx>;
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
debug!("Search visiting ty: {:?}", ty);
|
debug!("Search visiting ty: {:?}", ty);
|
||||||
|
|
||||||
let (adt_def, substs) = match *ty.kind() {
|
let (adt_def, substs) = match *ty.kind() {
|
||||||
ty::Adt(adt_def, substs) => (adt_def, substs),
|
ty::Adt(adt_def, substs) => (adt_def, substs),
|
||||||
ty::Param(_) => {
|
ty::Param(_) => {
|
||||||
self.found = Some(NonStructuralMatchTy::Param);
|
return ControlFlow::Break(NonStructuralMatchTy::Param);
|
||||||
return ControlFlow::BREAK;
|
|
||||||
}
|
}
|
||||||
ty::Dynamic(..) => {
|
ty::Dynamic(..) => {
|
||||||
self.found = Some(NonStructuralMatchTy::Dynamic);
|
return ControlFlow::Break(NonStructuralMatchTy::Dynamic);
|
||||||
return ControlFlow::BREAK;
|
|
||||||
}
|
}
|
||||||
ty::Foreign(_) => {
|
ty::Foreign(_) => {
|
||||||
self.found = Some(NonStructuralMatchTy::Foreign);
|
return ControlFlow::Break(NonStructuralMatchTy::Foreign);
|
||||||
return ControlFlow::BREAK;
|
|
||||||
}
|
}
|
||||||
ty::Opaque(..) => {
|
ty::Opaque(..) => {
|
||||||
self.found = Some(NonStructuralMatchTy::Opaque);
|
return ControlFlow::Break(NonStructuralMatchTy::Opaque);
|
||||||
return ControlFlow::BREAK;
|
|
||||||
}
|
}
|
||||||
ty::Projection(..) => {
|
ty::Projection(..) => {
|
||||||
self.found = Some(NonStructuralMatchTy::Projection);
|
return ControlFlow::Break(NonStructuralMatchTy::Projection);
|
||||||
return ControlFlow::BREAK;
|
|
||||||
}
|
}
|
||||||
ty::Generator(..) | ty::GeneratorWitness(..) => {
|
ty::Generator(..) | ty::GeneratorWitness(..) => {
|
||||||
self.found = Some(NonStructuralMatchTy::Generator);
|
return ControlFlow::Break(NonStructuralMatchTy::Generator);
|
||||||
return ControlFlow::BREAK;
|
|
||||||
}
|
}
|
||||||
ty::Closure(..) => {
|
ty::Closure(..) => {
|
||||||
self.found = Some(NonStructuralMatchTy::Closure);
|
return ControlFlow::Break(NonStructuralMatchTy::Closure);
|
||||||
return ControlFlow::BREAK;
|
|
||||||
}
|
}
|
||||||
ty::RawPtr(..) => {
|
ty::RawPtr(..) => {
|
||||||
// structural-match ignores substructure of
|
// structural-match ignores substructure of
|
||||||
|
@ -206,8 +196,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
||||||
|
|
||||||
ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
|
ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
|
||||||
// First check all contained types and then tell the caller to continue searching.
|
// First check all contained types and then tell the caller to continue searching.
|
||||||
ty.super_visit_with(self);
|
return ty.super_visit_with(self);
|
||||||
return ControlFlow::CONTINUE;
|
|
||||||
}
|
}
|
||||||
ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
|
ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
|
||||||
bug!("unexpected type during structural-match checking: {:?}", ty);
|
bug!("unexpected type during structural-match checking: {:?}", ty);
|
||||||
|
@ -227,8 +216,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
||||||
|
|
||||||
if !self.type_marked_structural(ty) {
|
if !self.type_marked_structural(ty) {
|
||||||
debug!("Search found ty: {:?}", ty);
|
debug!("Search found ty: {:?}", ty);
|
||||||
self.found = Some(NonStructuralMatchTy::Adt(&adt_def));
|
return ControlFlow::Break(NonStructuralMatchTy::Adt(&adt_def));
|
||||||
return ControlFlow::BREAK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// structural-match does not care about the
|
// structural-match does not care about the
|
||||||
|
@ -244,20 +232,11 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
|
||||||
// even though we skip super_visit_with, we must recur on
|
// even though we skip super_visit_with, we must recur on
|
||||||
// fields of ADT.
|
// fields of ADT.
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) {
|
adt_def.all_fields().map(|field| field.ty(tcx, substs)).try_for_each(|field_ty| {
|
||||||
let ty = self.tcx().normalize_erasing_regions(ty::ParamEnv::empty(), field_ty);
|
let ty = self.tcx().normalize_erasing_regions(ty::ParamEnv::empty(), field_ty);
|
||||||
debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty);
|
debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty);
|
||||||
|
ty.visit_with(self)
|
||||||
if ty.visit_with(self).is_break() {
|
})
|
||||||
// found an ADT without structural-match; halt visiting!
|
|
||||||
assert!(self.found.is_some());
|
|
||||||
return ControlFlow::BREAK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Even though we do not want to recur on substs, we do
|
|
||||||
// want our caller to continue its own search.
|
|
||||||
ControlFlow::CONTINUE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue