Auto merge of #14448 - Veykril:infer-table, r=Veykril

internal: Don't expose InferenceTable outside of hir-ty
This commit is contained in:
bors 2023-03-30 12:49:23 +00:00
commit 5390949c11
6 changed files with 49 additions and 37 deletions

View File

@ -3,12 +3,17 @@
//! reference to a type with the field `bar`. This is an approximation of the //! reference to a type with the field `bar`. This is an approximation of the
//! logic in rustc (which lives in rustc_hir_analysis/check/autoderef.rs). //! logic in rustc (which lives in rustc_hir_analysis/check/autoderef.rs).
use std::sync::Arc;
use chalk_ir::cast::Cast; use chalk_ir::cast::Cast;
use hir_def::lang_item::LangItem; use hir_def::lang_item::LangItem;
use hir_expand::name::name; use hir_expand::name::name;
use limit::Limit; use limit::Limit;
use crate::{infer::unify::InferenceTable, Goal, Interner, ProjectionTyExt, Ty, TyBuilder, TyKind}; use crate::{
db::HirDatabase, infer::unify::InferenceTable, Canonical, Goal, Interner, ProjectionTyExt,
TraitEnvironment, Ty, TyBuilder, TyKind,
};
static AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(10); static AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(10);
@ -18,16 +23,31 @@ pub(crate) enum AutoderefKind {
Overloaded, Overloaded,
} }
pub fn autoderef(
db: &dyn HirDatabase,
env: Arc<TraitEnvironment>,
ty: Canonical<Ty>,
) -> impl Iterator<Item = Canonical<Ty>> + '_ {
let mut table = InferenceTable::new(db, env);
let ty = table.instantiate_canonical(ty);
let mut autoderef = Autoderef::new(&mut table, ty);
let mut v = Vec::new();
while let Some((ty, _steps)) = autoderef.next() {
v.push(autoderef.table.canonicalize(ty).value);
}
v.into_iter()
}
#[derive(Debug)] #[derive(Debug)]
pub struct Autoderef<'a, 'db> { pub(crate) struct Autoderef<'a, 'db> {
pub table: &'a mut InferenceTable<'db>, pub(crate) table: &'a mut InferenceTable<'db>,
ty: Ty, ty: Ty,
at_start: bool, at_start: bool,
steps: Vec<(AutoderefKind, Ty)>, steps: Vec<(AutoderefKind, Ty)>,
} }
impl<'a, 'db> Autoderef<'a, 'db> { impl<'a, 'db> Autoderef<'a, 'db> {
pub fn new(table: &'a mut InferenceTable<'db>, ty: Ty) -> Self { pub(crate) fn new(table: &'a mut InferenceTable<'db>, ty: Ty) -> Self {
let ty = table.resolve_ty_shallow(&ty); let ty = table.resolve_ty_shallow(&ty);
Autoderef { table, ty, at_start: true, steps: Vec::new() } Autoderef { table, ty, at_start: true, steps: Vec::new() }
} }

View File

@ -23,7 +23,7 @@
use syntax::ast::RangeOp; use syntax::ast::RangeOp;
use crate::{ use crate::{
autoderef::{self, Autoderef}, autoderef::{builtin_deref, deref_by_trait, Autoderef},
consteval, consteval,
infer::{ infer::{
coerce::CoerceMany, find_continuable, pat::contains_explicit_ref_binding, BreakableKind, coerce::CoerceMany, find_continuable, pat::contains_explicit_ref_binding, BreakableKind,
@ -675,12 +675,10 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
); );
} }
} }
if let Some(derefed) = if let Some(derefed) = builtin_deref(&mut self.table, &inner_ty, true) {
autoderef::builtin_deref(&mut self.table, &inner_ty, true)
{
self.resolve_ty_shallow(derefed) self.resolve_ty_shallow(derefed)
} else { } else {
autoderef::deref_by_trait(&mut self.table, inner_ty) deref_by_trait(&mut self.table, inner_ty)
.unwrap_or_else(|| self.err_ty()) .unwrap_or_else(|| self.err_ty())
} }
} }
@ -793,7 +791,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
let canonicalized = self.canonicalize(base_ty.clone()); let canonicalized = self.canonicalize(base_ty.clone());
let receiver_adjustments = method_resolution::resolve_indexing_op( let receiver_adjustments = method_resolution::resolve_indexing_op(
self.db, self.db,
&mut self.table, self.table.trait_env.clone(),
canonicalized.value, canonicalized.value,
index_trait, index_trait,
); );

View File

@ -32,11 +32,11 @@ pub(super) fn canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = In
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Canonicalized<T> pub(crate) struct Canonicalized<T>
where where
T: HasInterner<Interner = Interner>, T: HasInterner<Interner = Interner>,
{ {
pub value: Canonical<T>, pub(crate) value: Canonical<T>,
free_vars: Vec<GenericArg>, free_vars: Vec<GenericArg>,
} }
@ -140,7 +140,7 @@ pub(crate) struct TypeVariableFlags: u8 {
type ChalkInferenceTable = chalk_solve::infer::InferenceTable<Interner>; type ChalkInferenceTable = chalk_solve::infer::InferenceTable<Interner>;
#[derive(Clone)] #[derive(Clone)]
pub struct InferenceTable<'a> { pub(crate) struct InferenceTable<'a> {
pub(crate) db: &'a dyn HirDatabase, pub(crate) db: &'a dyn HirDatabase,
pub(crate) trait_env: Arc<TraitEnvironment>, pub(crate) trait_env: Arc<TraitEnvironment>,
var_unification_table: ChalkInferenceTable, var_unification_table: ChalkInferenceTable,
@ -155,7 +155,7 @@ pub(crate) struct InferenceTableSnapshot {
} }
impl<'a> InferenceTable<'a> { impl<'a> InferenceTable<'a> {
pub fn new(db: &'a dyn HirDatabase, trait_env: Arc<TraitEnvironment>) -> Self { pub(crate) fn new(db: &'a dyn HirDatabase, trait_env: Arc<TraitEnvironment>) -> Self {
InferenceTable { InferenceTable {
db, db,
trait_env, trait_env,
@ -204,7 +204,7 @@ fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
.intern(Interner) .intern(Interner)
} }
pub fn canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>( pub(crate) fn canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
&mut self, &mut self,
t: T, t: T,
) -> Canonicalized<T> ) -> Canonicalized<T>
@ -320,7 +320,7 @@ pub(crate) fn fresh_subst(&mut self, binders: &[CanonicalVarKind<Interner>]) ->
) )
} }
pub fn instantiate_canonical<T>(&mut self, canonical: Canonical<T>) -> T pub(crate) fn instantiate_canonical<T>(&mut self, canonical: Canonical<T>) -> T
where where
T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + std::fmt::Debug, T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + std::fmt::Debug,
{ {

View File

@ -52,14 +52,16 @@ macro_rules! eprintln {
use traits::FnTrait; use traits::FnTrait;
use utils::Generics; use utils::Generics;
use crate::{consteval::unknown_const, db::HirDatabase, utils::generics}; use crate::{
consteval::unknown_const, db::HirDatabase, infer::unify::InferenceTable, utils::generics,
};
pub use autoderef::Autoderef; pub use autoderef::autoderef;
pub use builder::{ParamKind, TyBuilder}; pub use builder::{ParamKind, TyBuilder};
pub use chalk_ext::*; pub use chalk_ext::*;
pub use infer::{ pub use infer::{
could_coerce, could_unify, unify::InferenceTable, Adjust, Adjustment, AutoBorrow, BindingMode, could_coerce, could_unify, Adjust, Adjustment, AutoBorrow, BindingMode, InferenceDiagnostic,
InferenceDiagnostic, InferenceResult, OverloadedDeref, PointerCast, InferenceResult, OverloadedDeref, PointerCast,
}; };
pub use interner::Interner; pub use interner::Interner;
pub use lower::{ pub use lower::{

View File

@ -1263,14 +1263,15 @@ fn impls_for_self_ty(
} }
/// Returns the receiver type for the index trait call. /// Returns the receiver type for the index trait call.
pub fn resolve_indexing_op( pub(crate) fn resolve_indexing_op(
db: &dyn HirDatabase, db: &dyn HirDatabase,
table: &mut InferenceTable<'_>, env: Arc<TraitEnvironment>,
ty: Canonical<Ty>, ty: Canonical<Ty>,
index_trait: TraitId, index_trait: TraitId,
) -> Option<ReceiverAdjustments> { ) -> Option<ReceiverAdjustments> {
let mut table = InferenceTable::new(db, env.clone());
let ty = table.instantiate_canonical(ty); let ty = table.instantiate_canonical(ty);
let deref_chain = autoderef_method_receiver(table, ty); let deref_chain = autoderef_method_receiver(&mut table, ty);
for (ty, adj) in deref_chain { for (ty, adj) in deref_chain {
let goal = generic_implements_goal(db, table.trait_env.clone(), index_trait, &ty); let goal = generic_implements_goal(db, table.trait_env.clone(), index_trait, &ty);
if db if db

View File

@ -57,7 +57,7 @@
}; };
use hir_expand::{name::name, MacroCallKind}; use hir_expand::{name::name, MacroCallKind};
use hir_ty::{ use hir_ty::{
all_super_traits, all_super_traits, autoderef,
consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt}, consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt},
diagnostics::BodyValidationDiagnostic, diagnostics::BodyValidationDiagnostic,
display::HexifiedConst, display::HexifiedConst,
@ -66,10 +66,9 @@
mir::{self, interpret_mir}, mir::{self, interpret_mir},
primitive::UintTy, primitive::UintTy,
traits::FnTrait, traits::FnTrait,
AliasTy, Autoderef, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId,
GenericArgData, InferenceTable, Interner, ParamKind, QuantifiedWhereClause, Scalar, GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, WhereClause,
WhereClause,
}; };
use itertools::Itertools; use itertools::Itertools;
use nameres::diagnostics::DefDiagnosticKind; use nameres::diagnostics::DefDiagnosticKind;
@ -3518,15 +3517,7 @@ pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item =
fn autoderef_<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Ty> + 'a { fn autoderef_<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Ty> + 'a {
// There should be no inference vars in types passed here // There should be no inference vars in types passed here
let canonical = hir_ty::replace_errors_with_variables(&self.ty); let canonical = hir_ty::replace_errors_with_variables(&self.ty);
autoderef(db, self.env.clone(), canonical).map(|canonical| canonical.value)
let mut table = InferenceTable::new(db, self.env.clone());
let ty = table.instantiate_canonical(canonical);
let mut autoderef = Autoderef::new(&mut table, ty);
let mut v = Vec::new();
while let Some((ty, _steps)) = autoderef.next() {
v.push(autoderef.table.canonicalize(ty).value);
}
v.into_iter().map(|canonical| canonical.value)
} }
// This would be nicer if it just returned an iterator, but that runs into // This would be nicer if it just returned an iterator, but that runs into