Skip to content

Commit 17b395d

Browse files
Use TypeVisitor::BreakTy in structural_match::Search
1 parent e0f3119 commit 17b395d

File tree

1 file changed

+15
-36
lines changed

1 file changed

+15
-36
lines changed

compiler/rustc_trait_selection/src/traits/structural_match.rs

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,7 @@ pub fn search_for_structural_match_violation<'tcx>(
5555
) -> Option<NonStructuralMatchTy<'tcx>> {
5656
// FIXME: we should instead pass in an `infcx` from the outside.
5757
tcx.infer_ctxt().enter(|infcx| {
58-
let mut search = Search { infcx, span, found: None, seen: FxHashSet::default() };
59-
ty.visit_with(&mut search);
60-
search.found
58+
ty.visit_with(&mut Search { infcx, span, seen: FxHashSet::default() }).break_value()
6159
})
6260
}
6361

@@ -116,9 +114,6 @@ struct Search<'a, 'tcx> {
116114

117115
infcx: InferCtxt<'a, 'tcx>,
118116

119-
/// Records first ADT that does not implement a structural-match trait.
120-
found: Option<NonStructuralMatchTy<'tcx>>,
121-
122117
/// Tracks ADTs previously encountered during search, so that
123118
/// we will not recur on them again.
124119
seen: FxHashSet<hir::def_id::DefId>,
@@ -135,38 +130,33 @@ impl Search<'a, 'tcx> {
135130
}
136131

137132
impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
133+
type BreakTy = NonStructuralMatchTy<'tcx>;
134+
138135
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
139136
debug!("Search visiting ty: {:?}", ty);
140137

141138
let (adt_def, substs) = match *ty.kind() {
142139
ty::Adt(adt_def, substs) => (adt_def, substs),
143140
ty::Param(_) => {
144-
self.found = Some(NonStructuralMatchTy::Param);
145-
return ControlFlow::BREAK;
141+
return ControlFlow::Break(NonStructuralMatchTy::Param);
146142
}
147143
ty::Dynamic(..) => {
148-
self.found = Some(NonStructuralMatchTy::Dynamic);
149-
return ControlFlow::BREAK;
144+
return ControlFlow::Break(NonStructuralMatchTy::Dynamic);
150145
}
151146
ty::Foreign(_) => {
152-
self.found = Some(NonStructuralMatchTy::Foreign);
153-
return ControlFlow::BREAK;
147+
return ControlFlow::Break(NonStructuralMatchTy::Foreign);
154148
}
155149
ty::Opaque(..) => {
156-
self.found = Some(NonStructuralMatchTy::Opaque);
157-
return ControlFlow::BREAK;
150+
return ControlFlow::Break(NonStructuralMatchTy::Opaque);
158151
}
159152
ty::Projection(..) => {
160-
self.found = Some(NonStructuralMatchTy::Projection);
161-
return ControlFlow::BREAK;
153+
return ControlFlow::Break(NonStructuralMatchTy::Projection);
162154
}
163155
ty::Generator(..) | ty::GeneratorWitness(..) => {
164-
self.found = Some(NonStructuralMatchTy::Generator);
165-
return ControlFlow::BREAK;
156+
return ControlFlow::Break(NonStructuralMatchTy::Generator);
166157
}
167158
ty::Closure(..) => {
168-
self.found = Some(NonStructuralMatchTy::Closure);
169-
return ControlFlow::BREAK;
159+
return ControlFlow::Break(NonStructuralMatchTy::Closure);
170160
}
171161
ty::RawPtr(..) => {
172162
// structural-match ignores substructure of
@@ -206,8 +196,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
206196

207197
ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
208198
// First check all contained types and then tell the caller to continue searching.
209-
ty.super_visit_with(self);
210-
return ControlFlow::CONTINUE;
199+
return ty.super_visit_with(self);
211200
}
212201
ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
213202
bug!("unexpected type during structural-match checking: {:?}", ty);
@@ -227,8 +216,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
227216

228217
if !self.type_marked_structural(ty) {
229218
debug!("Search found ty: {:?}", ty);
230-
self.found = Some(NonStructuralMatchTy::Adt(&adt_def));
231-
return ControlFlow::BREAK;
219+
return ControlFlow::Break(NonStructuralMatchTy::Adt(&adt_def));
232220
}
233221

234222
// structural-match does not care about the
@@ -244,20 +232,11 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
244232
// even though we skip super_visit_with, we must recur on
245233
// fields of ADT.
246234
let tcx = self.tcx();
247-
for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) {
235+
adt_def.all_fields().map(|field| field.ty(tcx, substs)).try_for_each(|field_ty| {
248236
let ty = self.tcx().normalize_erasing_regions(ty::ParamEnv::empty(), field_ty);
249237
debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty);
250-
251-
if ty.visit_with(self).is_break() {
252-
// found an ADT without structural-match; halt visiting!
253-
assert!(self.found.is_some());
254-
return ControlFlow::BREAK;
255-
}
256-
}
257-
258-
// Even though we do not want to recur on substs, we do
259-
// want our caller to continue its own search.
260-
ControlFlow::CONTINUE
238+
ty.visit_with(self)
239+
})
261240
}
262241
}
263242

0 commit comments

Comments
 (0)