Auto merge of #98487 - cjgillot:variance-nohir, r=wesleywiser
Do not fetch HIR to compute variances. Everything can be done using higher-level queries. This simplifies the code, and should allow better incremental caching.
This commit is contained in:
commit
fac8fa5672
@ -63,6 +63,15 @@ impl ModuleItems {
|
|||||||
self.foreign_items.iter().copied()
|
self.foreign_items.iter().copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ {
|
||||||
|
self.items
|
||||||
|
.iter()
|
||||||
|
.map(|id| id.def_id)
|
||||||
|
.chain(self.trait_items.iter().map(|id| id.def_id))
|
||||||
|
.chain(self.impl_items.iter().map(|id| id.def_id))
|
||||||
|
.chain(self.foreign_items.iter().map(|id| id.def_id))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
|
pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
|
||||||
par_for_each_in(&self.items[..], |&id| f(id))
|
par_for_each_in(&self.items[..], |&id| f(id))
|
||||||
}
|
}
|
||||||
|
@ -64,25 +64,21 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
|
|||||||
|
|
||||||
let crate_items = tcx.hir_crate_items(());
|
let crate_items = tcx.hir_crate_items(());
|
||||||
|
|
||||||
for id in crate_items.items() {
|
for def_id in crate_items.definitions() {
|
||||||
constraint_cx.check_item(id);
|
let def_kind = tcx.def_kind(def_id);
|
||||||
}
|
match def_kind {
|
||||||
|
DefKind::Struct | DefKind::Union | DefKind::Enum => {
|
||||||
|
constraint_cx.build_constraints_for_item(def_id);
|
||||||
|
|
||||||
for id in crate_items.trait_items() {
|
let adt = tcx.adt_def(def_id);
|
||||||
if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
|
for variant in adt.variants() {
|
||||||
constraint_cx.check_node_helper(id.hir_id());
|
if let Some(ctor) = variant.ctor_def_id {
|
||||||
}
|
constraint_cx.build_constraints_for_item(ctor.expect_local());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for id in crate_items.impl_items() {
|
}
|
||||||
if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
|
DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id),
|
||||||
constraint_cx.check_node_helper(id.hir_id());
|
_ => {}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for id in crate_items.foreign_items() {
|
|
||||||
if let DefKind::Fn = tcx.def_kind(id.def_id) {
|
|
||||||
constraint_cx.check_node_helper(id.hir_id());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,48 +86,6 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||||
fn check_item(&mut self, id: hir::ItemId) {
|
|
||||||
let def_kind = self.tcx().def_kind(id.def_id);
|
|
||||||
match def_kind {
|
|
||||||
DefKind::Struct | DefKind::Union => {
|
|
||||||
let item = self.tcx().hir().item(id);
|
|
||||||
|
|
||||||
if let hir::ItemKind::Struct(ref struct_def, _)
|
|
||||||
| hir::ItemKind::Union(ref struct_def, _) = item.kind
|
|
||||||
{
|
|
||||||
self.check_node_helper(item.hir_id());
|
|
||||||
|
|
||||||
if let hir::VariantData::Tuple(..) = *struct_def {
|
|
||||||
self.check_node_helper(struct_def.ctor_hir_id().unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefKind::Enum => {
|
|
||||||
let item = self.tcx().hir().item(id);
|
|
||||||
|
|
||||||
if let hir::ItemKind::Enum(ref enum_def, _) = item.kind {
|
|
||||||
self.check_node_helper(item.hir_id());
|
|
||||||
|
|
||||||
for variant in enum_def.variants {
|
|
||||||
if let hir::VariantData::Tuple(..) = variant.data {
|
|
||||||
self.check_node_helper(variant.data.ctor_hir_id().unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefKind::Fn => {
|
|
||||||
self.check_node_helper(id.hir_id());
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_node_helper(&mut self, id: hir::HirId) {
|
|
||||||
let tcx = self.terms_cx.tcx;
|
|
||||||
let def_id = tcx.hir().local_def_id(id);
|
|
||||||
self.build_constraints_for_item(def_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.terms_cx.tcx
|
self.terms_cx.tcx
|
||||||
}
|
}
|
||||||
@ -145,8 +99,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = tcx.hir().local_def_id_to_hir_id(def_id);
|
let inferred_start = self.terms_cx.inferred_starts[&def_id];
|
||||||
let inferred_start = self.terms_cx.inferred_starts[&id];
|
|
||||||
let current_item = &CurrentItem { inferred_start };
|
let current_item = &CurrentItem { inferred_start };
|
||||||
match tcx.type_of(def_id).kind() {
|
match tcx.type_of(def_id).kind() {
|
||||||
ty::Adt(def, _) => {
|
ty::Adt(def, _) => {
|
||||||
@ -372,8 +325,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let (local, remote) = if let Some(def_id) = def_id.as_local() {
|
let (local, remote) = if let Some(def_id) = def_id.as_local() {
|
||||||
let id = self.tcx().hir().local_def_id_to_hir_id(def_id);
|
(Some(self.terms_cx.inferred_starts[&def_id]), None)
|
||||||
(Some(self.terms_cx.inferred_starts[&id]), None)
|
|
||||||
} else {
|
} else {
|
||||||
(None, Some(self.tcx().variances_of(def_id)))
|
(None, Some(self.tcx().variances_of(def_id)))
|
||||||
};
|
};
|
||||||
|
@ -96,8 +96,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
|
|||||||
self.terms_cx
|
self.terms_cx
|
||||||
.inferred_starts
|
.inferred_starts
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(&id, &InferredIndex(start))| {
|
.map(|(&def_id, &InferredIndex(start))| {
|
||||||
let def_id = tcx.hir().local_def_id(id);
|
|
||||||
let generics = tcx.generics_of(def_id);
|
let generics = tcx.generics_of(def_id);
|
||||||
let count = generics.count();
|
let count = generics.count();
|
||||||
|
|
||||||
|
@ -10,9 +10,8 @@
|
|||||||
// a variable.
|
// a variable.
|
||||||
|
|
||||||
use rustc_arena::DroplessArena;
|
use rustc_arena::DroplessArena;
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::HirIdMap;
|
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
@ -52,11 +51,11 @@ pub struct TermsContext<'a, 'tcx> {
|
|||||||
// For marker types, UnsafeCell, and other lang items where
|
// For marker types, UnsafeCell, and other lang items where
|
||||||
// variance is hardcoded, records the item-id and the hardcoded
|
// variance is hardcoded, records the item-id and the hardcoded
|
||||||
// variance.
|
// variance.
|
||||||
pub lang_items: Vec<(hir::HirId, Vec<ty::Variance>)>,
|
pub lang_items: Vec<(LocalDefId, Vec<ty::Variance>)>,
|
||||||
|
|
||||||
// Maps from the node id of an item to the first inferred index
|
// Maps from the node id of an item to the first inferred index
|
||||||
// used for its type & region parameters.
|
// used for its type & region parameters.
|
||||||
pub inferred_starts: HirIdMap<InferredIndex>,
|
pub inferred_starts: LocalDefIdMap<InferredIndex>,
|
||||||
|
|
||||||
// Maps from an InferredIndex to the term for that variable.
|
// Maps from an InferredIndex to the term for that variable.
|
||||||
pub inferred_terms: Vec<VarianceTermPtr<'a>>,
|
pub inferred_terms: Vec<VarianceTermPtr<'a>>,
|
||||||
@ -81,32 +80,31 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
|
|||||||
// - https://rustc-dev-guide.rust-lang.org/variance.html
|
// - https://rustc-dev-guide.rust-lang.org/variance.html
|
||||||
let crate_items = tcx.hir_crate_items(());
|
let crate_items = tcx.hir_crate_items(());
|
||||||
|
|
||||||
for id in crate_items.items() {
|
for def_id in crate_items.definitions() {
|
||||||
terms_cx.check_item(id);
|
debug!("add_inferreds for item {:?}", def_id);
|
||||||
}
|
|
||||||
|
|
||||||
for id in crate_items.trait_items() {
|
let def_kind = tcx.def_kind(def_id);
|
||||||
if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
|
|
||||||
terms_cx.add_inferreds_for_item(id.hir_id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for id in crate_items.impl_items() {
|
match def_kind {
|
||||||
if let DefKind::AssocFn = tcx.def_kind(id.def_id) {
|
DefKind::Struct | DefKind::Union | DefKind::Enum => {
|
||||||
terms_cx.add_inferreds_for_item(id.hir_id());
|
terms_cx.add_inferreds_for_item(def_id);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for id in crate_items.foreign_items() {
|
let adt = tcx.adt_def(def_id);
|
||||||
if let DefKind::Fn = tcx.def_kind(id.def_id) {
|
for variant in adt.variants() {
|
||||||
terms_cx.add_inferreds_for_item(id.hir_id());
|
if let Some(ctor) = variant.ctor_def_id {
|
||||||
|
terms_cx.add_inferreds_for_item(ctor.expect_local());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id),
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terms_cx
|
terms_cx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lang_items(tcx: TyCtxt<'_>) -> Vec<(hir::HirId, Vec<ty::Variance>)> {
|
fn lang_items(tcx: TyCtxt<'_>) -> Vec<(LocalDefId, Vec<ty::Variance>)> {
|
||||||
let lang_items = tcx.lang_items();
|
let lang_items = tcx.lang_items();
|
||||||
let all = [
|
let all = [
|
||||||
(lang_items.phantom_data(), vec![ty::Covariant]),
|
(lang_items.phantom_data(), vec![ty::Covariant]),
|
||||||
@ -114,18 +112,16 @@ fn lang_items(tcx: TyCtxt<'_>) -> Vec<(hir::HirId, Vec<ty::Variance>)> {
|
|||||||
];
|
];
|
||||||
|
|
||||||
all.into_iter() // iterating over (Option<DefId>, Variance)
|
all.into_iter() // iterating over (Option<DefId>, Variance)
|
||||||
.filter(|&(ref d, _)| d.is_some())
|
|
||||||
.map(|(d, v)| (d.unwrap(), v)) // (DefId, Variance)
|
|
||||||
.filter_map(|(d, v)| {
|
.filter_map(|(d, v)| {
|
||||||
d.as_local().map(|d| tcx.hir().local_def_id_to_hir_id(d)).map(|n| (n, v))
|
let def_id = d?.as_local()?; // LocalDefId
|
||||||
}) // (HirId, Variance)
|
Some((def_id, v))
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TermsContext<'a, 'tcx> {
|
impl<'a, 'tcx> TermsContext<'a, 'tcx> {
|
||||||
fn add_inferreds_for_item(&mut self, id: hir::HirId) {
|
fn add_inferreds_for_item(&mut self, def_id: LocalDefId) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let def_id = tcx.hir().local_def_id(id);
|
|
||||||
let count = tcx.generics_of(def_id).count();
|
let count = tcx.generics_of(def_id).count();
|
||||||
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
@ -134,7 +130,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
|
|||||||
|
|
||||||
// Record the start of this item's inferreds.
|
// Record the start of this item's inferreds.
|
||||||
let start = self.inferred_terms.len();
|
let start = self.inferred_terms.len();
|
||||||
let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none();
|
let newly_added = self.inferred_starts.insert(def_id, InferredIndex(start)).is_none();
|
||||||
assert!(newly_added);
|
assert!(newly_added);
|
||||||
|
|
||||||
// N.B., in the code below for writing the results back into the
|
// N.B., in the code below for writing the results back into the
|
||||||
@ -146,42 +142,4 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
|
|||||||
(start..(start + count)).map(|i| &*arena.alloc(InferredTerm(InferredIndex(i)))),
|
(start..(start + count)).map(|i| &*arena.alloc(InferredTerm(InferredIndex(i)))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, id: hir::ItemId) {
|
|
||||||
debug!("add_inferreds for item {}", self.tcx.hir().node_to_string(id.hir_id()));
|
|
||||||
|
|
||||||
let def_kind = self.tcx.def_kind(id.def_id);
|
|
||||||
match def_kind {
|
|
||||||
DefKind::Struct | DefKind::Union => {
|
|
||||||
let item = self.tcx.hir().item(id);
|
|
||||||
|
|
||||||
if let hir::ItemKind::Struct(ref struct_def, _)
|
|
||||||
| hir::ItemKind::Union(ref struct_def, _) = item.kind
|
|
||||||
{
|
|
||||||
self.add_inferreds_for_item(item.hir_id());
|
|
||||||
|
|
||||||
if let hir::VariantData::Tuple(..) = *struct_def {
|
|
||||||
self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefKind::Enum => {
|
|
||||||
let item = self.tcx.hir().item(id);
|
|
||||||
|
|
||||||
if let hir::ItemKind::Enum(ref enum_def, _) = item.kind {
|
|
||||||
self.add_inferreds_for_item(item.hir_id());
|
|
||||||
|
|
||||||
for variant in enum_def.variants {
|
|
||||||
if let hir::VariantData::Tuple(..) = variant.data {
|
|
||||||
self.add_inferreds_for_item(variant.data.ctor_hir_id().unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefKind::Fn => {
|
|
||||||
self.add_inferreds_for_item(id.hir_id());
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user