Rollup merge of #65353 - Xanewok:sa-empty-tables, r=nikomatsakis
save-analysis: Don't ICE when resolving qualified type paths in struct members Previously, we failed since we use `qpath_res` via typeck tables - when using those we need to pass in a HirId that's local to the definition path the tables are rooted at (otherwise we risk frame of reference mismatch and an assertion against invalid lookup). In this case we can't get typeck tables for struct definition because it has no body, however the struct member type node is rooted under the struct definition and so we can't really do anything about it in terms of traversal. Instead, we try to "nest" the tables as always but change the default behaviour to use empty typeck tables rather than silently trying to use the current ones. This does work as we expect and for prior art, we use the same approach in the [privacy](7bc94cc3c2/src/librustc_privacy/lib.rs (L332-L341)
) [pass](7bc94cc3c2/src/librustc_privacy/lib.rs (L1007-L1028)
). Fixes #64659. Fixes #64821. r? @nikomatsakis (since this changes the default behaviour introduced ind7d3f197f6
)
This commit is contained in:
commit
820fb7ccbf
3 changed files with 31 additions and 13 deletions
|
@ -115,15 +115,17 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
F: FnOnce(&mut Self),
|
||||
{
|
||||
let item_def_id = self.tcx.hir().local_def_id_from_node_id(item_id);
|
||||
if self.tcx.has_typeck_tables(item_def_id) {
|
||||
let tables = self.tcx.typeck_tables_of(item_def_id);
|
||||
let old_tables = self.save_ctxt.tables;
|
||||
self.save_ctxt.tables = tables;
|
||||
f(self);
|
||||
self.save_ctxt.tables = old_tables;
|
||||
|
||||
let tables = if self.tcx.has_typeck_tables(item_def_id) {
|
||||
self.tcx.typeck_tables_of(item_def_id)
|
||||
} else {
|
||||
f(self);
|
||||
}
|
||||
self.save_ctxt.empty_tables
|
||||
};
|
||||
|
||||
let old_tables = self.save_ctxt.tables;
|
||||
self.save_ctxt.tables = tables;
|
||||
f(self);
|
||||
self.save_ctxt.tables = old_tables;
|
||||
}
|
||||
|
||||
fn span_from_span(&self, span: Span) -> SpanData {
|
||||
|
@ -530,12 +532,14 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
for field in def.fields() {
|
||||
self.process_struct_field_def(field, item.id);
|
||||
self.visit_ty(&field.ty);
|
||||
}
|
||||
self.nest_tables(item.id, |v| {
|
||||
for field in def.fields() {
|
||||
v.process_struct_field_def(field, item.id);
|
||||
v.visit_ty(&field.ty);
|
||||
}
|
||||
|
||||
self.process_generic_params(ty_params, &qualname, item.id);
|
||||
v.process_generic_params(ty_params, &qualname, item.id);
|
||||
});
|
||||
}
|
||||
|
||||
fn process_enum(
|
||||
|
|
|
@ -48,6 +48,9 @@ use log::{debug, error, info};
|
|||
pub struct SaveContext<'l, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
tables: &'l ty::TypeckTables<'tcx>,
|
||||
/// Used as a fallback when nesting the typeck tables during item processing
|
||||
/// (if these are not available for that item, e.g. don't own a body)
|
||||
empty_tables: &'l ty::TypeckTables<'tcx>,
|
||||
access_levels: &'l AccessLevels,
|
||||
span_utils: SpanUtils<'tcx>,
|
||||
config: Config,
|
||||
|
@ -1114,6 +1117,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(
|
|||
let save_ctxt = SaveContext {
|
||||
tcx,
|
||||
tables: &ty::TypeckTables::empty(None),
|
||||
empty_tables: &ty::TypeckTables::empty(None),
|
||||
access_levels: &access_levels,
|
||||
span_utils: SpanUtils::new(&tcx.sess),
|
||||
config: find_config(config),
|
||||
|
|
10
src/test/ui/save-analysis/issue-64659.rs
Normal file
10
src/test/ui/save-analysis/issue-64659.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
// check-pass
|
||||
// compile-flags: -Zsave-analysis
|
||||
|
||||
trait Trait { type Assoc; }
|
||||
|
||||
fn main() {
|
||||
struct Data<T: Trait> {
|
||||
x: T::Assoc,
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue