Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 3410aed

Browse files
committed
ty: switch Ty::walk from Ty to GenericArg.
1 parent 26199f0 commit 3410aed

File tree

14 files changed

+301
-232
lines changed

14 files changed

+301
-232
lines changed

src/librustc_infer/infer/error_reporting/need_type_info.rs

Lines changed: 64 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,59 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
77
use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat};
88
use rustc_middle::hir::map::Map;
99
use rustc_middle::ty::print::Print;
10-
use rustc_middle::ty::{self, DefIdTree, Infer, Ty, TyVar};
10+
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
11+
use rustc_middle::ty::{self, DefIdTree, Ty};
1112
use rustc_span::source_map::DesugaringKind;
1213
use rustc_span::symbol::kw;
1314
use rustc_span::Span;
1415
use std::borrow::Cow;
1516

16-
struct FindLocalByTypeVisitor<'a, 'tcx> {
17+
struct FindHirNodeVisitor<'a, 'tcx> {
1718
infcx: &'a InferCtxt<'a, 'tcx>,
18-
target_ty: Ty<'tcx>,
19-
hir_map: Map<'tcx>,
19+
target: GenericArg<'tcx>,
20+
found_node_ty: Option<Ty<'tcx>>,
2021
found_local_pattern: Option<&'tcx Pat<'tcx>>,
2122
found_arg_pattern: Option<&'tcx Pat<'tcx>>,
22-
found_ty: Option<Ty<'tcx>>,
23-
found_closure: Option<&'tcx ExprKind<'tcx>>,
23+
found_closure: Option<&'tcx Expr<'tcx>>,
2424
found_method_call: Option<&'tcx Expr<'tcx>>,
2525
}
2626

27-
impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
28-
fn new(infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, hir_map: Map<'tcx>) -> Self {
27+
impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
28+
fn new(infcx: &'a InferCtxt<'a, 'tcx>, target: GenericArg<'tcx>) -> Self {
2929
Self {
3030
infcx,
31-
target_ty,
32-
hir_map,
31+
target,
32+
found_node_ty: None,
3333
found_local_pattern: None,
3434
found_arg_pattern: None,
35-
found_ty: None,
3635
found_closure: None,
3736
found_method_call: None,
3837
}
3938
}
4039

41-
fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
40+
fn node_ty_contains_target(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
4241
let ty_opt =
4342
self.infcx.in_progress_tables.and_then(|tables| tables.borrow().node_type_opt(hir_id));
4443
match ty_opt {
4544
Some(ty) => {
4645
let ty = self.infcx.resolve_vars_if_possible(&ty);
47-
if ty.walk().any(|inner_ty| {
48-
inner_ty == self.target_ty
49-
|| match (&inner_ty.kind, &self.target_ty.kind) {
50-
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => self
51-
.infcx
52-
.inner
53-
.borrow_mut()
54-
.type_variables
55-
.sub_unified(a_vid, b_vid),
46+
if ty.walk().any(|inner| {
47+
inner == self.target
48+
|| match (inner.unpack(), self.target.unpack()) {
49+
(GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
50+
match (&inner_ty.kind, &target_ty.kind) {
51+
(
52+
&ty::Infer(ty::TyVar(a_vid)),
53+
&ty::Infer(ty::TyVar(b_vid)),
54+
) => self
55+
.infcx
56+
.inner
57+
.borrow_mut()
58+
.type_variables
59+
.sub_unified(a_vid, b_vid),
60+
_ => false,
61+
}
62+
}
5663
_ => false,
5764
}
5865
}) {
@@ -66,36 +73,39 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> {
6673
}
6774
}
6875

69-
impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
76+
impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
7077
type Map = Map<'tcx>;
7178

7279
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
73-
NestedVisitorMap::OnlyBodies(self.hir_map)
80+
NestedVisitorMap::OnlyBodies(self.infcx.tcx.hir())
7481
}
7582

7683
fn visit_local(&mut self, local: &'tcx Local<'tcx>) {
77-
if let (None, Some(ty)) = (self.found_local_pattern, self.node_matches_type(local.hir_id)) {
84+
if let (None, Some(ty)) =
85+
(self.found_local_pattern, self.node_ty_contains_target(local.hir_id))
86+
{
7887
self.found_local_pattern = Some(&*local.pat);
79-
self.found_ty = Some(ty);
88+
self.found_node_ty = Some(ty);
8089
}
8190
intravisit::walk_local(self, local);
8291
}
8392

8493
fn visit_body(&mut self, body: &'tcx Body<'tcx>) {
8594
for param in body.params {
86-
if let (None, Some(ty)) = (self.found_arg_pattern, self.node_matches_type(param.hir_id))
95+
if let (None, Some(ty)) =
96+
(self.found_arg_pattern, self.node_ty_contains_target(param.hir_id))
8797
{
8898
self.found_arg_pattern = Some(&*param.pat);
89-
self.found_ty = Some(ty);
99+
self.found_node_ty = Some(ty);
90100
}
91101
}
92102
intravisit::walk_body(self, body);
93103
}
94104

95105
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
96-
if self.node_matches_type(expr.hir_id).is_some() {
106+
if self.node_ty_contains_target(expr.hir_id).is_some() {
97107
match expr.kind {
98-
ExprKind::Closure(..) => self.found_closure = Some(&expr.kind),
108+
ExprKind::Closure(..) => self.found_closure = Some(&expr),
99109
ExprKind::MethodCall(..) => self.found_method_call = Some(&expr),
100110
_ => {}
101111
}
@@ -213,6 +223,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
213223
(s, None, ty.prefix_string(), None, None)
214224
}
215225

226+
// FIXME(eddyb) generalize all of this to handle `ty::Const` inference variables as well.
216227
pub fn need_type_info_err(
217228
&self,
218229
body_id: Option<hir::BodyId>,
@@ -223,7 +234,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
223234
let ty = self.resolve_vars_if_possible(&ty);
224235
let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None);
225236

226-
let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, self.tcx.hir());
237+
let mut local_visitor = FindHirNodeVisitor::new(&self, ty.into());
227238
let ty_to_string = |ty: Ty<'tcx>| -> String {
228239
let mut s = String::new();
229240
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
@@ -276,7 +287,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
276287
(!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings)
277288
};
278289

279-
let ty_msg = match local_visitor.found_ty {
290+
let ty_msg = match local_visitor.found_node_ty {
280291
Some(ty::TyS { kind: ty::Closure(_, substs), .. }) => {
281292
let fn_sig = substs.as_closure().sig();
282293
let args = closure_args(&fn_sig);
@@ -310,28 +321,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
310321
error_code,
311322
);
312323

313-
let suffix = match local_visitor.found_ty {
324+
let suffix = match local_visitor.found_node_ty {
314325
Some(ty::TyS { kind: ty::Closure(_, substs), .. }) => {
315326
let fn_sig = substs.as_closure().sig();
316327
let ret = fn_sig.output().skip_binder().to_string();
317328

318-
if let Some(ExprKind::Closure(_, decl, body_id, ..)) = local_visitor.found_closure {
319-
if let Some(body) = self.tcx.hir().krate().bodies.get(body_id) {
320-
closure_return_type_suggestion(
321-
span,
322-
&mut err,
323-
&decl.output,
324-
&body,
325-
&descr,
326-
&name,
327-
&ret,
328-
parent_name,
329-
parent_descr,
330-
);
331-
// We don't want to give the other suggestions when the problem is the
332-
// closure return type.
333-
return err;
334-
}
329+
let closure_decl_and_body_id =
330+
local_visitor.found_closure.and_then(|closure| match &closure.kind {
331+
ExprKind::Closure(_, decl, body_id, ..) => Some((decl, *body_id)),
332+
_ => None,
333+
});
334+
335+
if let Some((decl, body_id)) = closure_decl_and_body_id {
336+
closure_return_type_suggestion(
337+
span,
338+
&mut err,
339+
&decl.output,
340+
self.tcx.hir().body(body_id),
341+
&descr,
342+
&name,
343+
&ret,
344+
parent_name,
345+
parent_descr,
346+
);
347+
// We don't want to give the other suggestions when the problem is the
348+
// closure return type.
349+
return err;
335350
}
336351

337352
// This shouldn't be reachable, but just in case we leave a reasonable fallback.

src/librustc_lint/builtin.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use rustc_hir::def_id::DefId;
3636
use rustc_hir::{GenericParamKind, PatKind};
3737
use rustc_hir::{HirIdSet, Node};
3838
use rustc_middle::lint::LintDiagnosticBuilder;
39+
use rustc_middle::ty::subst::GenericArgKind;
3940
use rustc_middle::ty::{self, Ty, TyCtxt};
4041
use rustc_session::lint::FutureIncompatibleInfo;
4142
use rustc_span::edition::Edition;
@@ -104,11 +105,13 @@ declare_lint_pass!(BoxPointers => [BOX_POINTERS]);
104105

105106
impl BoxPointers {
106107
fn check_heap_type(&self, cx: &LateContext<'_, '_>, span: Span, ty: Ty<'_>) {
107-
for leaf_ty in ty.walk() {
108-
if leaf_ty.is_box() {
109-
cx.struct_span_lint(BOX_POINTERS, span, |lint| {
110-
lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit()
111-
});
108+
for leaf in ty.walk() {
109+
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
110+
if leaf_ty.is_box() {
111+
cx.struct_span_lint(BOX_POINTERS, span, |lint| {
112+
lint.build(&format!("type uses owned (Box type) pointers: {}", ty)).emit()
113+
});
114+
}
112115
}
113116
}
114117
}

src/librustc_middle/ty/mod.rs

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use crate::traits::{self, Reveal};
1919
use crate::ty;
2020
use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
2121
use crate::ty::util::{Discr, IntTypeExt};
22-
use crate::ty::walk::TypeWalker;
2322
use rustc_ast::ast::{self, Ident, Name};
2423
use rustc_ast::node_id::{NodeId, NodeMap, NodeSet};
2524
use rustc_attr as attr;
@@ -2686,39 +2685,6 @@ impl<'tcx> ClosureKind {
26862685
}
26872686
}
26882687

2689-
impl<'tcx> TyS<'tcx> {
2690-
/// Iterator that walks `self` and any types reachable from
2691-
/// `self`, in depth-first order. Note that just walks the types
2692-
/// that appear in `self`, it does not descend into the fields of
2693-
/// structs or variants. For example:
2694-
///
2695-
/// ```notrust
2696-
/// isize => { isize }
2697-
/// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
2698-
/// [isize] => { [isize], isize }
2699-
/// ```
2700-
pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
2701-
TypeWalker::new(self.into())
2702-
}
2703-
2704-
/// Walks `ty` and any types appearing within `ty`, invoking the
2705-
/// callback `f` on each type. If the callback returns `false`, then the
2706-
/// children of the current type are ignored.
2707-
///
2708-
/// Note: prefer `ty.walk()` where possible.
2709-
pub fn maybe_walk<F>(&'tcx self, mut f: F)
2710-
where
2711-
F: FnMut(Ty<'tcx>) -> bool,
2712-
{
2713-
let mut walker = self.walk();
2714-
while let Some(ty) = walker.next() {
2715-
if !f(ty) {
2716-
walker.skip_current_subtree();
2717-
}
2718-
}
2719-
}
2720-
}
2721-
27222688
impl BorrowKind {
27232689
pub fn from_mutbl(m: hir::Mutability) -> BorrowKind {
27242690
match m {

src/librustc_middle/ty/walk.rs

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! An iterator over the type substructure.
22
//! WARNING: this does not keep track of the region depth.
33
4+
use crate::ty;
45
use crate::ty::subst::{GenericArg, GenericArgKind};
5-
use crate::ty::{self, Ty};
66
use smallvec::{self, SmallVec};
77

88
// The TypeWalker's stack is hot enough that it's worth going to some effort to
@@ -37,27 +37,33 @@ impl<'tcx> TypeWalker<'tcx> {
3737
}
3838

3939
impl<'tcx> Iterator for TypeWalker<'tcx> {
40-
type Item = Ty<'tcx>;
40+
type Item = GenericArg<'tcx>;
4141

42-
fn next(&mut self) -> Option<Ty<'tcx>> {
42+
fn next(&mut self) -> Option<GenericArg<'tcx>> {
4343
debug!("next(): stack={:?}", self.stack);
44-
while let Some(next) = self.stack.pop() {
45-
self.last_subtree = self.stack.len();
46-
push_inner(&mut self.stack, next);
47-
debug!("next: stack={:?}", self.stack);
48-
49-
// FIXME(eddyb) remove this filter and expose all `GenericArg`s.
50-
match next.unpack() {
51-
GenericArgKind::Type(ty) => return Some(ty),
52-
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => {}
53-
}
54-
}
55-
56-
None
44+
let next = self.stack.pop()?;
45+
self.last_subtree = self.stack.len();
46+
push_inner(&mut self.stack, next);
47+
debug!("next: stack={:?}", self.stack);
48+
Some(next)
5749
}
5850
}
5951

6052
impl GenericArg<'tcx> {
53+
/// Iterator that walks `self` and any types reachable from
54+
/// `self`, in depth-first order. Note that just walks the types
55+
/// that appear in `self`, it does not descend into the fields of
56+
/// structs or variants. For example:
57+
///
58+
/// ```notrust
59+
/// isize => { isize }
60+
/// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
61+
/// [isize] => { [isize], isize }
62+
/// ```
63+
pub fn walk(self) -> TypeWalker<'tcx> {
64+
TypeWalker::new(self)
65+
}
66+
6167
/// Iterator that walks the immediate children of `self`. Hence
6268
/// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
6369
/// (but not `i32`, like `walk`).
@@ -68,6 +74,22 @@ impl GenericArg<'tcx> {
6874
}
6975
}
7076

77+
impl<'tcx> super::TyS<'tcx> {
78+
/// Iterator that walks `self` and any types reachable from
79+
/// `self`, in depth-first order. Note that just walks the types
80+
/// that appear in `self`, it does not descend into the fields of
81+
/// structs or variants. For example:
82+
///
83+
/// ```notrust
84+
/// isize => { isize }
85+
/// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
86+
/// [isize] => { [isize], isize }
87+
/// ```
88+
pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
89+
TypeWalker::new(self.into())
90+
}
91+
}
92+
7193
// We push `GenericArg`s on the stack in reverse order so as to
7294
// maintain a pre-order traversal. As of the time of this
7395
// writing, the fact that the traversal is pre-order is not

0 commit comments

Comments
 (0)