Re-use InferenceTable
by snapshotting in method resolution
This commit is contained in:
parent
2898c4217d
commit
593156a357
@ -113,7 +113,7 @@ pub(crate) fn autoderef_step(
|
||||
ty: Ty,
|
||||
explicit: bool,
|
||||
) -> Option<(AutoderefKind, Ty)> {
|
||||
if let Some(derefed) = builtin_deref(table, &ty, explicit) {
|
||||
if let Some(derefed) = builtin_deref(table.db, &ty, explicit) {
|
||||
Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed)))
|
||||
} else {
|
||||
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty)?))
|
||||
@ -121,7 +121,7 @@ pub(crate) fn autoderef_step(
|
||||
}
|
||||
|
||||
pub(crate) fn builtin_deref<'ty>(
|
||||
table: &mut InferenceTable<'_>,
|
||||
db: &dyn HirDatabase,
|
||||
ty: &'ty Ty,
|
||||
explicit: bool,
|
||||
) -> Option<&'ty Ty> {
|
||||
@ -129,7 +129,7 @@ pub(crate) fn builtin_deref<'ty>(
|
||||
TyKind::Ref(.., ty) => Some(ty),
|
||||
TyKind::Raw(.., ty) if explicit => Some(ty),
|
||||
&TyKind::Adt(chalk_ir::AdtId(adt), ref substs) => {
|
||||
if crate::lang_items::is_box(table.db, adt) {
|
||||
if crate::lang_items::is_box(db, adt) {
|
||||
substs.at(Interner, 0).ty(Interner)
|
||||
} else {
|
||||
None
|
||||
|
@ -657,7 +657,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(derefed) = builtin_deref(&mut self.table, &inner_ty, true) {
|
||||
if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) {
|
||||
self.resolve_ty_shallow(derefed)
|
||||
} else {
|
||||
deref_by_trait(&mut self.table, inner_ty)
|
||||
|
@ -243,7 +243,7 @@ pub(crate) struct InferenceTable<'a> {
|
||||
pub(crate) db: &'a dyn HirDatabase,
|
||||
pub(crate) trait_env: Arc<TraitEnvironment>,
|
||||
var_unification_table: ChalkInferenceTable,
|
||||
type_variable_table: Vec<TypeVariableFlags>,
|
||||
type_variable_table: SmallVec<[TypeVariableFlags; 16]>,
|
||||
pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
|
||||
/// Double buffer used in [`Self::resolve_obligations_as_possible`] to cut down on
|
||||
/// temporary allocations.
|
||||
@ -252,8 +252,8 @@ pub(crate) struct InferenceTable<'a> {
|
||||
|
||||
pub(crate) struct InferenceTableSnapshot {
|
||||
var_table_snapshot: chalk_solve::infer::InferenceSnapshot<Interner>,
|
||||
type_variable_table: SmallVec<[TypeVariableFlags; 16]>,
|
||||
pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
|
||||
type_variable_table_snapshot: Vec<TypeVariableFlags>,
|
||||
}
|
||||
|
||||
impl<'a> InferenceTable<'a> {
|
||||
@ -262,7 +262,7 @@ pub(crate) fn new(db: &'a dyn HirDatabase, trait_env: Arc<TraitEnvironment>) ->
|
||||
db,
|
||||
trait_env,
|
||||
var_unification_table: ChalkInferenceTable::new(),
|
||||
type_variable_table: Vec::new(),
|
||||
type_variable_table: SmallVec::new(),
|
||||
pending_obligations: Vec::new(),
|
||||
resolve_obligations_buffer: Vec::new(),
|
||||
}
|
||||
@ -575,19 +575,15 @@ pub(crate) fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
|
||||
|
||||
pub(crate) fn snapshot(&mut self) -> InferenceTableSnapshot {
|
||||
let var_table_snapshot = self.var_unification_table.snapshot();
|
||||
let type_variable_table_snapshot = self.type_variable_table.clone();
|
||||
let type_variable_table = self.type_variable_table.clone();
|
||||
let pending_obligations = self.pending_obligations.clone();
|
||||
InferenceTableSnapshot {
|
||||
var_table_snapshot,
|
||||
pending_obligations,
|
||||
type_variable_table_snapshot,
|
||||
}
|
||||
InferenceTableSnapshot { var_table_snapshot, pending_obligations, type_variable_table }
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) fn rollback_to(&mut self, snapshot: InferenceTableSnapshot) {
|
||||
self.var_unification_table.rollback_to(snapshot.var_table_snapshot);
|
||||
self.type_variable_table = snapshot.type_variable_table_snapshot;
|
||||
self.type_variable_table = snapshot.type_variable_table;
|
||||
self.pending_obligations = snapshot.pending_obligations;
|
||||
}
|
||||
|
||||
|
@ -972,10 +972,9 @@ pub fn iterate_method_candidates_dyn(
|
||||
|
||||
deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| {
|
||||
iterate_method_candidates_with_autoref(
|
||||
&mut table,
|
||||
&receiver_ty,
|
||||
adj,
|
||||
db,
|
||||
env.clone(),
|
||||
traits_in_scope,
|
||||
visible_from_module,
|
||||
name,
|
||||
@ -1000,10 +999,9 @@ pub fn iterate_method_candidates_dyn(
|
||||
|
||||
#[tracing::instrument(skip_all, fields(name = ?name))]
|
||||
fn iterate_method_candidates_with_autoref(
|
||||
table: &mut InferenceTable<'_>,
|
||||
receiver_ty: &Canonical<Ty>,
|
||||
first_adjustment: ReceiverAdjustments,
|
||||
db: &dyn HirDatabase,
|
||||
env: Arc<TraitEnvironment>,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: VisibleFromModule,
|
||||
name: Option<&Name>,
|
||||
@ -1016,10 +1014,9 @@ fn iterate_method_candidates_with_autoref(
|
||||
|
||||
let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| {
|
||||
iterate_method_candidates_by_receiver(
|
||||
table,
|
||||
receiver_ty,
|
||||
first_adjustment,
|
||||
db,
|
||||
env.clone(),
|
||||
traits_in_scope,
|
||||
visible_from_module,
|
||||
name,
|
||||
@ -1058,50 +1055,49 @@ fn iterate_method_candidates_with_autoref(
|
||||
|
||||
#[tracing::instrument(skip_all, fields(name = ?name))]
|
||||
fn iterate_method_candidates_by_receiver(
|
||||
table: &mut InferenceTable<'_>,
|
||||
receiver_ty: &Canonical<Ty>,
|
||||
receiver_adjustments: ReceiverAdjustments,
|
||||
db: &dyn HirDatabase,
|
||||
env: Arc<TraitEnvironment>,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: VisibleFromModule,
|
||||
name: Option<&Name>,
|
||||
mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
|
||||
) -> ControlFlow<()> {
|
||||
let mut table = InferenceTable::new(db, env);
|
||||
let receiver_ty = table.instantiate_canonical(receiver_ty.clone());
|
||||
let snapshot = table.snapshot();
|
||||
// We're looking for methods with *receiver* type receiver_ty. These could
|
||||
// be found in any of the derefs of receiver_ty, so we have to go through
|
||||
// that, including raw derefs.
|
||||
let mut autoderef = autoderef::Autoderef::new(&mut table, receiver_ty.clone(), true);
|
||||
while let Some((self_ty, _)) = autoderef.next() {
|
||||
iterate_inherent_methods(
|
||||
&self_ty,
|
||||
autoderef.table,
|
||||
name,
|
||||
Some(&receiver_ty),
|
||||
Some(receiver_adjustments.clone()),
|
||||
visible_from_module,
|
||||
&mut callback,
|
||||
)?
|
||||
}
|
||||
table.run_in_snapshot(|table| {
|
||||
let receiver_ty = table.instantiate_canonical(receiver_ty.clone());
|
||||
// We're looking for methods with *receiver* type receiver_ty. These could
|
||||
// be found in any of the derefs of receiver_ty, so we have to go through
|
||||
// that, including raw derefs.
|
||||
table.run_in_snapshot(|table| {
|
||||
let mut autoderef = autoderef::Autoderef::new(table, receiver_ty.clone(), true);
|
||||
while let Some((self_ty, _)) = autoderef.next() {
|
||||
iterate_inherent_methods(
|
||||
&self_ty,
|
||||
autoderef.table,
|
||||
name,
|
||||
Some(&receiver_ty),
|
||||
Some(receiver_adjustments.clone()),
|
||||
visible_from_module,
|
||||
&mut callback,
|
||||
)?
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
})?;
|
||||
|
||||
table.rollback_to(snapshot);
|
||||
|
||||
let mut autoderef = autoderef::Autoderef::new(&mut table, receiver_ty.clone(), true);
|
||||
while let Some((self_ty, _)) = autoderef.next() {
|
||||
iterate_trait_method_candidates(
|
||||
&self_ty,
|
||||
autoderef.table,
|
||||
traits_in_scope,
|
||||
name,
|
||||
Some(&receiver_ty),
|
||||
Some(receiver_adjustments.clone()),
|
||||
&mut callback,
|
||||
)?
|
||||
}
|
||||
|
||||
ControlFlow::Continue(())
|
||||
let mut autoderef = autoderef::Autoderef::new(table, receiver_ty.clone(), true);
|
||||
while let Some((self_ty, _)) = autoderef.next() {
|
||||
iterate_trait_method_candidates(
|
||||
&self_ty,
|
||||
autoderef.table,
|
||||
traits_in_scope,
|
||||
name,
|
||||
Some(&receiver_ty),
|
||||
Some(receiver_adjustments.clone()),
|
||||
&mut callback,
|
||||
)?
|
||||
}
|
||||
ControlFlow::Continue(())
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all, fields(name = ?name))]
|
||||
|
Loading…
Reference in New Issue
Block a user