Skip to content

Commit 656ce3f

Browse files
authored
Rollup merge of rust-lang#64250 - Xanewok:save-analysis-assoc-nested, r=varkor
save-analysis: Nest typeck tables when processing functions/methods Fixes an issue where we did not nest tables correctly when resolving associated types in formal argument/return type positions. This was the minimized reproduction case that I tested the fix on: ```rust pub trait Trait { type Assoc; } pub struct A; pub fn func() { fn _inner1<U: Trait>(_: U::Assoc) {} fn _inner2<U: Trait>() -> U::Assoc { unimplemented!() } impl A { fn _inner1<U: Trait>(self, _: U::Assoc) {} fn _inner2<U: Trait>(self) -> U::Assoc { unimplemented!() } } } ``` using `debug_assertions`-enabled rustc and by additionally passing `-Zsave-analysis`. Unfortunately the original assertion fired is a *debug* one and from what I can tell we don't run the tests with these on, so I'm not adding a test here. If I missed it and there is a way to run tests with these on, I'd love to add a test case for this. Closes rust-lang#63663 Closes rust-lang#50328 Closes rust-lang#43982
2 parents 71f3fbc + 7730ef1 commit 656ce3f

File tree

3 files changed

+79
-62
lines changed

3 files changed

+79
-62
lines changed

src/librustc/ty/context.rs

+18-20
Original file line numberDiff line numberDiff line change
@@ -205,26 +205,24 @@ pub struct LocalTableInContext<'a, V> {
205205
fn validate_hir_id_for_typeck_tables(local_id_root: Option<DefId>,
206206
hir_id: hir::HirId,
207207
mut_access: bool) {
208-
if cfg!(debug_assertions) {
209-
if let Some(local_id_root) = local_id_root {
210-
if hir_id.owner != local_id_root.index {
211-
ty::tls::with(|tcx| {
212-
bug!("node {} with HirId::owner {:?} cannot be placed in \
213-
TypeckTables with local_id_root {:?}",
214-
tcx.hir().node_to_string(hir_id),
215-
DefId::local(hir_id.owner),
216-
local_id_root)
217-
});
218-
}
219-
} else {
220-
// We use "Null Object" TypeckTables in some of the analysis passes.
221-
// These are just expected to be empty and their `local_id_root` is
222-
// `None`. Therefore we cannot verify whether a given `HirId` would
223-
// be a valid key for the given table. Instead we make sure that
224-
// nobody tries to write to such a Null Object table.
225-
if mut_access {
226-
bug!("access to invalid TypeckTables")
227-
}
208+
if let Some(local_id_root) = local_id_root {
209+
if hir_id.owner != local_id_root.index {
210+
ty::tls::with(|tcx| {
211+
bug!("node {} with HirId::owner {:?} cannot be placed in \
212+
TypeckTables with local_id_root {:?}",
213+
tcx.hir().node_to_string(hir_id),
214+
DefId::local(hir_id.owner),
215+
local_id_root)
216+
});
217+
}
218+
} else {
219+
// We use "Null Object" TypeckTables in some of the analysis passes.
220+
// These are just expected to be empty and their `local_id_root` is
221+
// `None`. Therefore we cannot verify whether a given `HirId` would
222+
// be a valid key for the given table. Instead we make sure that
223+
// nobody tries to write to such a Null Object table.
224+
if mut_access {
225+
bug!("access to invalid TypeckTables")
228226
}
229227
}
230228
}

src/librustc_save_analysis/dump_visitor.rs

+38-42
Original file line numberDiff line numberDiff line change
@@ -283,36 +283,32 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
283283
) {
284284
debug!("process_method: {}:{}", id, ident);
285285

286-
if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident, span) {
287-
let sig_str = crate::make_signature(&sig.decl, &generics);
288-
if body.is_some() {
289-
self.nest_tables(
290-
id,
291-
|v| v.process_formals(&sig.decl.inputs, &method_data.qualname),
292-
);
293-
}
286+
let hir_id = self.tcx.hir().node_to_hir_id(id);
287+
self.nest_tables(id, |v| {
288+
if let Some(mut method_data) = v.save_ctxt.get_method_data(id, ident, span) {
289+
v.process_formals(&sig.decl.inputs, &method_data.qualname);
290+
v.process_generic_params(&generics, &method_data.qualname, id);
294291

295-
self.process_generic_params(&generics, &method_data.qualname, id);
292+
method_data.value = crate::make_signature(&sig.decl, &generics);
293+
method_data.sig = sig::method_signature(id, ident, generics, sig, &v.save_ctxt);
296294

297-
method_data.value = sig_str;
298-
method_data.sig = sig::method_signature(id, ident, generics, sig, &self.save_ctxt);
299-
let hir_id = self.tcx.hir().node_to_hir_id(id);
300-
self.dumper.dump_def(&access_from_vis!(self.save_ctxt, vis, hir_id), method_data);
301-
}
295+
v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, hir_id), method_data);
296+
}
302297

303-
// walk arg and return types
304-
for arg in &sig.decl.inputs {
305-
self.visit_ty(&arg.ty);
306-
}
298+
// walk arg and return types
299+
for arg in &sig.decl.inputs {
300+
v.visit_ty(&arg.ty);
301+
}
307302

308-
if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
309-
self.visit_ty(ret_ty);
310-
}
303+
if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output {
304+
v.visit_ty(ret_ty);
305+
}
311306

312-
// walk the fn body
313-
if let Some(body) = body {
314-
self.nest_tables(id, |v| v.visit_block(body));
315-
}
307+
// walk the fn body
308+
if let Some(body) = body {
309+
v.visit_block(body);
310+
}
311+
});
316312
}
317313

318314
fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
@@ -377,26 +373,26 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
377373
ty_params: &'l ast::Generics,
378374
body: &'l ast::Block,
379375
) {
380-
if let Some(fn_data) = self.save_ctxt.get_item_data(item) {
381-
down_cast_data!(fn_data, DefData, item.span);
382-
self.nest_tables(
383-
item.id,
384-
|v| v.process_formals(&decl.inputs, &fn_data.qualname),
385-
);
386-
self.process_generic_params(ty_params, &fn_data.qualname, item.id);
387-
let hir_id = self.tcx.hir().node_to_hir_id(item.id);
388-
self.dumper.dump_def(&access_from!(self.save_ctxt, item, hir_id), fn_data);
389-
}
376+
let hir_id = self.tcx.hir().node_to_hir_id(item.id);
377+
self.nest_tables(item.id, |v| {
378+
if let Some(fn_data) = v.save_ctxt.get_item_data(item) {
379+
down_cast_data!(fn_data, DefData, item.span);
380+
v.process_formals(&decl.inputs, &fn_data.qualname);
381+
v.process_generic_params(ty_params, &fn_data.qualname, item.id);
390382

391-
for arg in &decl.inputs {
392-
self.visit_ty(&arg.ty);
393-
}
383+
v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), fn_data);
384+
}
394385

395-
if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
396-
self.visit_ty(&ret_ty);
397-
}
386+
for arg in &decl.inputs {
387+
v.visit_ty(&arg.ty)
388+
}
398389

399-
self.nest_tables(item.id, |v| v.visit_block(&body));
390+
if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output {
391+
v.visit_ty(&ret_ty);
392+
}
393+
394+
v.visit_block(&body);
395+
});
400396
}
401397

402398
fn process_static_or_const_item(
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// check-pass
2+
// compile-flags: -Zsave-analysis
3+
4+
// Check that this doesn't ICE when processing associated const in formal
5+
// argument and return type of functions defined inside function/method scope.
6+
7+
pub trait Trait {
8+
type Assoc;
9+
}
10+
11+
pub struct A;
12+
13+
pub fn func() {
14+
fn _inner1<U: Trait>(_: U::Assoc) {}
15+
fn _inner2<U: Trait>() -> U::Assoc { unimplemented!() }
16+
17+
impl A {
18+
fn _inner1<U: Trait>(self, _: U::Assoc) {}
19+
fn _inner2<U: Trait>(self) -> U::Assoc { unimplemented!() }
20+
}
21+
}
22+
23+
fn main() {}

0 commit comments

Comments
 (0)