Skip to content

Commit 209b2be

Browse files
committed
Auto merge of rust-lang#70164 - eddyb:walk-generic-arg, r=nikomatsakis
ty/walk: iterate `GenericArg`s instead of `Ty`s. Before this PR, `Ty::walk` only iterated over `Ty`s, but that's becoming an increasing problem with `const` generics, as `ty::Const`s in `Substs` are missed by it. By working with `GenericArg` instead, we can handle both `Ty`s and `ty::Const`s, but also `ty::Region`s, which used to require ad-hoc mechanisms such as `push_regions`. I've also removed `TraitRef::input_types`, as it's both long obsolete, and easy to misuse.
2 parents bf1f2ee + 626abc7 commit 209b2be

File tree

23 files changed

+618
-603
lines changed

23 files changed

+618
-603
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_infer/infer/outlives/verify.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ use crate::infer::{GenericKind, VerifyBound};
33
use crate::traits;
44
use rustc_data_structures::captures::Captures;
55
use rustc_hir::def_id::DefId;
6-
use rustc_middle::ty::subst::{InternalSubsts, Subst};
6+
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst};
77
use rustc_middle::ty::{self, Ty, TyCtxt};
88

9-
use smallvec::smallvec;
10-
119
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
1210
/// obligation into a series of `'a: 'b` constraints and "verifys", as
1311
/// described on the module comment. The final constraints are emitted
@@ -44,7 +42,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
4442
match ty.kind {
4543
ty::Param(p) => self.param_bound(p),
4644
ty::Projection(data) => self.projection_bound(data),
47-
_ => self.recursive_type_bound(ty),
45+
_ => self.recursive_bound(ty.into()),
4846
}
4947
}
5048

@@ -144,25 +142,33 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
144142

145143
// see the extensive comment in projection_must_outlive
146144
let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
147-
let recursive_bound = self.recursive_type_bound(ty);
145+
let recursive_bound = self.recursive_bound(ty.into());
148146

149147
VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound)
150148
}
151149

152-
fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
153-
let mut bounds = ty.walk_shallow().map(|subty| self.type_bound(subty)).collect::<Vec<_>>();
154-
155-
let mut regions = smallvec![];
156-
ty.push_regions(&mut regions);
157-
regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
158-
bounds.push(VerifyBound::AllBounds(
159-
regions.into_iter().map(|r| VerifyBound::OutlivedBy(r)).collect(),
160-
));
161-
162-
// remove bounds that must hold, since they are not interesting
163-
bounds.retain(|b| !b.must_hold());
150+
fn recursive_bound(&self, parent: GenericArg<'tcx>) -> VerifyBound<'tcx> {
151+
let mut bounds = parent
152+
.walk_shallow()
153+
.filter_map(|child| match child.unpack() {
154+
GenericArgKind::Type(ty) => Some(self.type_bound(ty)),
155+
GenericArgKind::Lifetime(lt) => {
156+
// Ignore late-bound regions.
157+
if !lt.is_late_bound() { Some(VerifyBound::OutlivedBy(lt)) } else { None }
158+
}
159+
GenericArgKind::Const(_) => Some(self.recursive_bound(child)),
160+
})
161+
.filter(|bound| {
162+
// Remove bounds that must hold, since they are not interesting.
163+
!bound.must_hold()
164+
});
164165

165-
if bounds.len() == 1 { bounds.pop().unwrap() } else { VerifyBound::AllBounds(bounds) }
166+
match (bounds.next(), bounds.next()) {
167+
(Some(first), None) => first,
168+
(first, second) => {
169+
VerifyBound::AllBounds(first.into_iter().chain(second).chain(bounds).collect())
170+
}
171+
}
166172
}
167173

168174
/// Searches the environment for where-clauses like `G: 'a` where

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/fold.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -263,20 +263,6 @@ where
263263
// Region folder
264264

265265
impl<'tcx> TyCtxt<'tcx> {
266-
/// Collects the free and escaping regions in `value` into `region_set`. Returns
267-
/// whether any late-bound regions were skipped
268-
pub fn collect_regions<T>(self, value: &T, region_set: &mut FxHashSet<ty::Region<'tcx>>) -> bool
269-
where
270-
T: TypeFoldable<'tcx>,
271-
{
272-
let mut have_bound_regions = false;
273-
self.fold_regions(value, &mut have_bound_regions, |r, d| {
274-
region_set.insert(self.mk_region(r.shifted_out_to_binder(d)));
275-
r
276-
});
277-
have_bound_regions
278-
}
279-
280266
/// Folds the escaping and free regions in `value` using `f`, and
281267
/// sets `skipped_regions` to true if any late-bound region was found
282268
/// and skipped.

0 commit comments

Comments
 (0)