Description
Most of the Visitor default methods in visit.rs do a walk over the substructure of the ast node being visited. E.g. a sample of the code in visit.rs:
fn visit_item(&mut self, i:@item, e:E) { walk_item(self, i, e) }
fn visit_local(&mut self, l:@Local, e:E) { walk_local(self, l, e) }
fn visit_block(&mut self, b:&Block, e:E) { walk_block(self, b, e) }
but there are exceptions, and one of them is visit_ty
:
fn visit_ty(&mut self, _t:&Ty, _e:E) { }
I deliberately made that function a no-op when I introduced the Visitor refactoring (#7081), because I was attempting to do a pure refactoring of the existing record-of-closures syntax visitor, which also skipped traversing types by default, see e.g. oldvisit.rs.
@jbclements recently asked why we do this, and I do not have an answer. At first I thought "well maybe we want to force people to opt-into traversing over type structure, since in the common case you'll only want to look at value-producing expressions in many visitors." The problem with that logic is that we do allow some expressions within a type expression (namely const expressions, such as within the bounds of a fixed-length vector type), and thus if you want to traverse all of the subexpressions, you still need to traverse the types.
One tricky side of this is that I think in my early attempts at the visit.rs refactoring, I did attempt to include ty-traversal as the visit_ty default, and this led to some sort of errors. (i don't recall what sort of errors; all I remember is eventually narrowing the problem down to the visit_ty implementation, and at that point I threw my hands up.)
But even so, we can easily change all of the existing visitor implementations that don't override the default visit_ty to now override it with a no-op. That would trivially lead the way to making visit_ty call walk_ty, which might be a better default behavior for future visitor code.