mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Turn Obligation into something similar to chalk_ir::DomainGoal
This includes starting to make use of Chalk's `Cast` trait.
This commit is contained in:
parent
8e7e405f6a
commit
7ec3b66f7a
14 changed files with 130 additions and 91 deletions
|
@ -56,8 +56,8 @@ use hir_ty::{
|
||||||
primitive::UintTy,
|
primitive::UintTy,
|
||||||
to_assoc_type_id,
|
to_assoc_type_id,
|
||||||
traits::{FnTrait, Solution, SolutionVariables},
|
traits::{FnTrait, Solution, SolutionVariables},
|
||||||
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex,
|
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, Cast, DebruijnIndex,
|
||||||
InEnvironment, Interner, Obligation, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind,
|
InEnvironment, Interner, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind,
|
||||||
TyVariableKind, WhereClause,
|
TyVariableKind, WhereClause,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -1767,7 +1767,7 @@ impl Type {
|
||||||
let goal = Canonical {
|
let goal = Canonical {
|
||||||
value: hir_ty::InEnvironment::new(
|
value: hir_ty::InEnvironment::new(
|
||||||
self.ty.environment.clone(),
|
self.ty.environment.clone(),
|
||||||
hir_ty::Obligation::Trait(trait_ref),
|
trait_ref.cast(&Interner),
|
||||||
),
|
),
|
||||||
kinds: Arc::new([]),
|
kinds: Arc::new([]),
|
||||||
};
|
};
|
||||||
|
@ -1789,14 +1789,15 @@ impl Type {
|
||||||
let goal = Canonical {
|
let goal = Canonical {
|
||||||
value: InEnvironment::new(
|
value: InEnvironment::new(
|
||||||
self.ty.environment.clone(),
|
self.ty.environment.clone(),
|
||||||
Obligation::AliasEq(AliasEq {
|
AliasEq {
|
||||||
alias: AliasTy::Projection(ProjectionTy {
|
alias: AliasTy::Projection(ProjectionTy {
|
||||||
associated_ty_id: to_assoc_type_id(alias.id),
|
associated_ty_id: to_assoc_type_id(alias.id),
|
||||||
substitution: subst,
|
substitution: subst,
|
||||||
}),
|
}),
|
||||||
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
|
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
|
||||||
.intern(&Interner),
|
.intern(&Interner),
|
||||||
}),
|
}
|
||||||
|
.cast(&Interner),
|
||||||
),
|
),
|
||||||
kinds: Arc::new([TyVariableKind::General]),
|
kinds: Arc::new([TyVariableKind::General]),
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
use std::iter::successors;
|
use std::iter::successors;
|
||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
|
use chalk_ir::cast::Cast;
|
||||||
use hir_def::lang_item::LangItemTarget;
|
use hir_def::lang_item::LangItemTarget;
|
||||||
use hir_expand::name::name;
|
use hir_expand::name::name;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
@ -15,8 +16,8 @@ use crate::{
|
||||||
to_assoc_type_id, to_chalk_trait_id,
|
to_assoc_type_id, to_chalk_trait_id,
|
||||||
traits::{InEnvironment, Solution},
|
traits::{InEnvironment, Solution},
|
||||||
utils::generics,
|
utils::generics,
|
||||||
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, Obligation, ProjectionTy,
|
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution,
|
||||||
Substitution, TraitRef, Ty, TyKind,
|
TraitRef, Ty, TyKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
const AUTODEREF_RECURSION_LIMIT: usize = 10;
|
const AUTODEREF_RECURSION_LIMIT: usize = 10;
|
||||||
|
@ -74,7 +75,7 @@ fn deref_by_trait(
|
||||||
let implements_goal = Canonical {
|
let implements_goal = Canonical {
|
||||||
kinds: ty.value.kinds.clone(),
|
kinds: ty.value.kinds.clone(),
|
||||||
value: InEnvironment {
|
value: InEnvironment {
|
||||||
value: Obligation::Trait(trait_ref),
|
value: trait_ref.cast(&Interner),
|
||||||
environment: ty.environment.clone(),
|
environment: ty.environment.clone(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -92,7 +93,7 @@ fn deref_by_trait(
|
||||||
.intern(&Interner),
|
.intern(&Interner),
|
||||||
};
|
};
|
||||||
|
|
||||||
let obligation = super::Obligation::AliasEq(projection);
|
let obligation = projection.cast(&Interner);
|
||||||
|
|
||||||
let in_env = InEnvironment { value: obligation, environment: ty.environment };
|
let in_env = InEnvironment { value: obligation, environment: ty.environment };
|
||||||
|
|
||||||
|
|
53
crates/hir_ty/src/chalk_cast.rs
Normal file
53
crates/hir_ty/src/chalk_cast.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
//! Implementations of the Chalk `Cast` trait for our types.
|
||||||
|
|
||||||
|
use chalk_ir::{
|
||||||
|
cast::{Cast, CastTo},
|
||||||
|
interner::HasInterner,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause};
|
||||||
|
|
||||||
|
macro_rules! has_interner {
|
||||||
|
($t:ty) => {
|
||||||
|
impl HasInterner for $t {
|
||||||
|
type Interner = crate::Interner;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
has_interner!(WhereClause);
|
||||||
|
has_interner!(DomainGoal);
|
||||||
|
|
||||||
|
impl CastTo<WhereClause> for TraitRef {
|
||||||
|
fn cast_to(self, _interner: &Interner) -> WhereClause {
|
||||||
|
WhereClause::Implemented(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CastTo<WhereClause> for AliasEq {
|
||||||
|
fn cast_to(self, _interner: &Interner) -> WhereClause {
|
||||||
|
WhereClause::AliasEq(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CastTo<DomainGoal> for WhereClause {
|
||||||
|
fn cast_to(self, _interner: &Interner) -> DomainGoal {
|
||||||
|
DomainGoal::Holds(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! transitive_impl {
|
||||||
|
($a:ty, $b:ty, $c:ty) => {
|
||||||
|
impl CastTo<$c> for $a {
|
||||||
|
fn cast_to(self, interner: &Interner) -> $c {
|
||||||
|
self.cast::<$b>(interner).cast(interner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// In Chalk, these can be done as blanket impls, but that doesn't work here
|
||||||
|
// because of coherence
|
||||||
|
|
||||||
|
transitive_impl!(TraitRef, WhereClause, DomainGoal);
|
||||||
|
transitive_impl!(AliasEq, WhereClause, DomainGoal);
|
|
@ -119,7 +119,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||||
fn trait_solve(
|
fn trait_solve(
|
||||||
&self,
|
&self,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
goal: crate::Canonical<crate::InEnvironment<crate::Obligation>>,
|
goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
|
||||||
) -> Option<crate::traits::Solution>;
|
) -> Option<crate::traits::Solution>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)]
|
#[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)]
|
||||||
|
|
|
@ -19,7 +19,7 @@ use hir_expand::name::Name;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
|
db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
|
||||||
to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy,
|
to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy,
|
||||||
CallableDefId, CallableSig, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy,
|
CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy,
|
||||||
ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause,
|
ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -805,22 +805,12 @@ impl HirDisplay for Lifetime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HirDisplay for Obligation {
|
impl HirDisplay for DomainGoal {
|
||||||
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
|
||||||
match self {
|
match self {
|
||||||
Obligation::Trait(tr) => {
|
DomainGoal::Holds(wc) => {
|
||||||
write!(f, "Implements(")?;
|
write!(f, "Holds(")?;
|
||||||
tr.hir_fmt(f)?;
|
wc.hir_fmt(f)?;
|
||||||
write!(f, ")")
|
|
||||||
}
|
|
||||||
Obligation::AliasEq(AliasEq { alias, ty }) => {
|
|
||||||
write!(f, "Normalize(")?;
|
|
||||||
match alias {
|
|
||||||
AliasTy::Projection(projection_ty) => projection_ty.hir_fmt(f)?,
|
|
||||||
AliasTy::Opaque(opaque) => opaque.hir_fmt(f)?,
|
|
||||||
}
|
|
||||||
write!(f, " => ")?;
|
|
||||||
ty.hir_fmt(f)?;
|
|
||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use std::mem;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use chalk_ir::Mutability;
|
use chalk_ir::{cast::Cast, Mutability};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
body::Body,
|
body::Body,
|
||||||
data::{ConstData, FunctionData, StaticData},
|
data::{ConstData, FunctionData, StaticData},
|
||||||
|
@ -37,7 +37,7 @@ use stdx::impl_from;
|
||||||
use syntax::SmolStr;
|
use syntax::SmolStr;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
traits::{Guidance, Obligation, Solution},
|
traits::{DomainGoal, Guidance, Solution},
|
||||||
InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk,
|
InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -204,7 +204,7 @@ struct InferenceContext<'a> {
|
||||||
resolver: Resolver,
|
resolver: Resolver,
|
||||||
table: unify::InferenceTable,
|
table: unify::InferenceTable,
|
||||||
trait_env: Arc<TraitEnvironment>,
|
trait_env: Arc<TraitEnvironment>,
|
||||||
obligations: Vec<Obligation>,
|
obligations: Vec<DomainGoal>,
|
||||||
result: InferenceResult,
|
result: InferenceResult,
|
||||||
/// The return type of the function being inferred, or the closure if we're
|
/// The return type of the function being inferred, or the closure if we're
|
||||||
/// currently within one.
|
/// currently within one.
|
||||||
|
@ -403,8 +403,8 @@ impl<'a> InferenceContext<'a> {
|
||||||
}),
|
}),
|
||||||
ty: ty.clone(),
|
ty: ty.clone(),
|
||||||
};
|
};
|
||||||
self.obligations.push(Obligation::Trait(trait_ref));
|
self.obligations.push(trait_ref.cast(&Interner));
|
||||||
self.obligations.push(Obligation::AliasEq(alias_eq));
|
self.obligations.push(alias_eq.cast(&Interner));
|
||||||
self.resolve_ty_as_possible(ty)
|
self.resolve_ty_as_possible(ty)
|
||||||
}
|
}
|
||||||
None => self.err_ty(),
|
None => self.err_ty(),
|
||||||
|
@ -430,7 +430,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
|
fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
|
||||||
let var = self.table.new_type_var();
|
let var = self.table.new_type_var();
|
||||||
let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
|
let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
|
||||||
let obligation = Obligation::AliasEq(alias_eq);
|
let obligation = alias_eq.cast(&Interner);
|
||||||
self.obligations.push(obligation);
|
self.obligations.push(obligation);
|
||||||
var
|
var
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,11 @@
|
||||||
//!
|
//!
|
||||||
//! See: https://doc.rust-lang.org/nomicon/coercions.html
|
//! See: https://doc.rust-lang.org/nomicon/coercions.html
|
||||||
|
|
||||||
use chalk_ir::{Mutability, TyVariableKind};
|
use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
|
||||||
use hir_def::lang_item::LangItemTarget;
|
use hir_def::lang_item::LangItemTarget;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
autoderef, to_chalk_trait_id, traits::Solution, Interner, Obligation, Substitution, TraitRef,
|
autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind,
|
||||||
Ty, TyKind,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{InEnvironment, InferenceContext};
|
use super::{InEnvironment, InferenceContext};
|
||||||
|
@ -143,7 +142,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
.build();
|
.build();
|
||||||
let trait_ref =
|
let trait_ref =
|
||||||
TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs };
|
TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs };
|
||||||
let goal = InEnvironment::new(self.trait_env.clone(), Obligation::Trait(trait_ref));
|
let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner));
|
||||||
|
|
||||||
let canonicalizer = self.canonicalizer();
|
let canonicalizer = self.canonicalizer();
|
||||||
let canonicalized = canonicalizer.canonicalize_obligation(goal);
|
let canonicalized = canonicalizer.canonicalize_obligation(goal);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use std::iter::{repeat, repeat_with};
|
use std::iter::{repeat, repeat_with};
|
||||||
use std::{mem, sync::Arc};
|
use std::{mem, sync::Arc};
|
||||||
|
|
||||||
use chalk_ir::{Mutability, TyVariableKind};
|
use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
|
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
|
||||||
path::{GenericArg, GenericArgs},
|
path::{GenericArg, GenericArgs},
|
||||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||||
to_assoc_type_id, to_chalk_trait_id,
|
to_assoc_type_id, to_chalk_trait_id,
|
||||||
traits::{chalk::from_chalk, FnTrait, InEnvironment},
|
traits::{chalk::from_chalk, FnTrait, InEnvironment},
|
||||||
utils::{generics, variant_data, Generics},
|
utils::{generics, variant_data, Generics},
|
||||||
AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, Rawness, Scalar,
|
AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar,
|
||||||
Substitution, TraitRef, Ty, TyKind,
|
Substitution, TraitRef, Ty, TyKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,10 +90,9 @@ impl<'a> InferenceContext<'a> {
|
||||||
Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
|
Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
|
||||||
|
|
||||||
let trait_env = Arc::clone(&self.trait_env);
|
let trait_env = Arc::clone(&self.trait_env);
|
||||||
let implements_fn_trait = Obligation::Trait(TraitRef {
|
let implements_fn_trait: DomainGoal =
|
||||||
trait_id: to_chalk_trait_id(fn_once_trait),
|
TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() }
|
||||||
substitution: substs.clone(),
|
.cast(&Interner);
|
||||||
});
|
|
||||||
let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
|
let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
|
||||||
value: implements_fn_trait.clone(),
|
value: implements_fn_trait.clone(),
|
||||||
environment: trait_env,
|
environment: trait_env,
|
||||||
|
@ -938,22 +937,20 @@ impl<'a> InferenceContext<'a> {
|
||||||
let generic_predicates = self.db.generic_predicates(def.into());
|
let generic_predicates = self.db.generic_predicates(def.into());
|
||||||
for predicate in generic_predicates.iter() {
|
for predicate in generic_predicates.iter() {
|
||||||
let predicate = predicate.clone().subst(parameters);
|
let predicate = predicate.clone().subst(parameters);
|
||||||
if let Some(obligation) = Obligation::from_predicate(predicate) {
|
self.obligations.push(predicate.cast(&Interner));
|
||||||
self.obligations.push(obligation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// add obligation for trait implementation, if this is a trait method
|
// add obligation for trait implementation, if this is a trait method
|
||||||
match def {
|
match def {
|
||||||
CallableDefId::FunctionId(f) => {
|
CallableDefId::FunctionId(f) => {
|
||||||
if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
|
if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
|
||||||
{
|
{
|
||||||
// construct a TraitDef
|
// construct a TraitRef
|
||||||
let substs =
|
let substs =
|
||||||
parameters.prefix(generics(self.db.upcast(), trait_.into()).len());
|
parameters.prefix(generics(self.db.upcast(), trait_.into()).len());
|
||||||
self.obligations.push(Obligation::Trait(TraitRef {
|
self.obligations.push(
|
||||||
trait_id: to_chalk_trait_id(trait_),
|
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
|
||||||
substitution: substs,
|
.cast(&Interner),
|
||||||
}));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
|
CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
|
use chalk_ir::cast::Cast;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
path::{Path, PathSegment},
|
path::{Path, PathSegment},
|
||||||
resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
|
resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
|
||||||
|
@ -256,10 +257,13 @@ impl<'a> InferenceContext<'a> {
|
||||||
.push(ty.clone())
|
.push(ty.clone())
|
||||||
.fill(std::iter::repeat_with(|| self.table.new_type_var()))
|
.fill(std::iter::repeat_with(|| self.table.new_type_var()))
|
||||||
.build();
|
.build();
|
||||||
self.obligations.push(super::Obligation::Trait(TraitRef {
|
self.obligations.push(
|
||||||
trait_id: to_chalk_trait_id(trait_),
|
TraitRef {
|
||||||
substitution: trait_substs.clone(),
|
trait_id: to_chalk_trait_id(trait_),
|
||||||
}));
|
substitution: trait_substs.clone(),
|
||||||
|
}
|
||||||
|
.cast(&Interner),
|
||||||
|
);
|
||||||
Some(trait_substs)
|
Some(trait_substs)
|
||||||
}
|
}
|
||||||
AssocContainerId::ModuleId(_) => None,
|
AssocContainerId::ModuleId(_) => None,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::borrow::Cow;
|
||||||
use chalk_ir::{FloatTy, IntTy, TyVariableKind};
|
use chalk_ir::{FloatTy, IntTy, TyVariableKind};
|
||||||
use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
|
use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
|
||||||
|
|
||||||
use super::{InferenceContext, Obligation};
|
use super::{DomainGoal, InferenceContext};
|
||||||
use crate::{
|
use crate::{
|
||||||
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar,
|
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar,
|
||||||
Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause,
|
Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause,
|
||||||
|
@ -87,14 +87,11 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
|
||||||
|
|
||||||
pub(crate) fn canonicalize_obligation(
|
pub(crate) fn canonicalize_obligation(
|
||||||
mut self,
|
mut self,
|
||||||
obligation: InEnvironment<Obligation>,
|
obligation: InEnvironment<DomainGoal>,
|
||||||
) -> Canonicalized<InEnvironment<Obligation>> {
|
) -> Canonicalized<InEnvironment<DomainGoal>> {
|
||||||
let result = match obligation.value {
|
let result = match obligation.value {
|
||||||
Obligation::Trait(tr) => {
|
DomainGoal::Holds(wc) => {
|
||||||
Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST))
|
DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
|
||||||
}
|
|
||||||
Obligation::AliasEq(alias_eq) => {
|
|
||||||
Obligation::AliasEq(self.do_canonicalize(alias_eq, DebruijnIndex::INNERMOST))
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.into_canonicalized(InEnvironment {
|
self.into_canonicalized(InEnvironment {
|
||||||
|
|
|
@ -13,6 +13,7 @@ mod op;
|
||||||
mod lower;
|
mod lower;
|
||||||
pub(crate) mod infer;
|
pub(crate) mod infer;
|
||||||
pub(crate) mod utils;
|
pub(crate) mod utils;
|
||||||
|
mod chalk_cast;
|
||||||
|
|
||||||
pub mod display;
|
pub mod display;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
|
@ -45,9 +46,11 @@ pub use lower::{
|
||||||
associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
|
associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
|
||||||
TyDefId, TyLoweringContext, ValueTyDefId,
|
TyDefId, TyLoweringContext, ValueTyDefId,
|
||||||
};
|
};
|
||||||
pub use traits::{AliasEq, InEnvironment, Obligation, TraitEnvironment};
|
pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment};
|
||||||
|
|
||||||
pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind};
|
pub use chalk_ir::{
|
||||||
|
cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
|
||||||
|
};
|
||||||
|
|
||||||
pub use crate::traits::chalk::Interner;
|
pub use crate::traits::chalk::Interner;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::{iter, sync::Arc};
|
||||||
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use chalk_ir::Mutability;
|
use chalk_ir::{cast::Cast, Mutability};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule,
|
lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule,
|
||||||
ImplId, Lookup, ModuleId, TraitId,
|
ImplId, Lookup, ModuleId, TraitId,
|
||||||
|
@ -767,7 +767,7 @@ fn generic_implements_goal(
|
||||||
env: Arc<TraitEnvironment>,
|
env: Arc<TraitEnvironment>,
|
||||||
trait_: TraitId,
|
trait_: TraitId,
|
||||||
self_ty: Canonical<Ty>,
|
self_ty: Canonical<Ty>,
|
||||||
) -> Canonical<InEnvironment<super::Obligation>> {
|
) -> Canonical<InEnvironment<super::DomainGoal>> {
|
||||||
let mut kinds = self_ty.kinds.to_vec();
|
let mut kinds = self_ty.kinds.to_vec();
|
||||||
let substs = super::Substitution::build_for_def(db, trait_)
|
let substs = super::Substitution::build_for_def(db, trait_)
|
||||||
.push(self_ty.value)
|
.push(self_ty.value)
|
||||||
|
@ -775,7 +775,7 @@ fn generic_implements_goal(
|
||||||
.build();
|
.build();
|
||||||
kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1));
|
kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1));
|
||||||
let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs };
|
let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs };
|
||||||
let obligation = super::Obligation::Trait(trait_ref);
|
let obligation = trait_ref.cast(&Interner);
|
||||||
Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
|
Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ use hir_def::{lang_item::LangItemTarget, TraitId};
|
||||||
use stdx::panic_context;
|
use stdx::panic_context;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, TraitRef, Ty,
|
db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind,
|
||||||
TyKind, TypeWalk, WhereClause,
|
TypeWalk, WhereClause,
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::chalk::{from_chalk, Interner, ToChalk};
|
use self::chalk::{from_chalk, Interner, ToChalk};
|
||||||
|
@ -88,20 +88,8 @@ impl<T> InEnvironment<T> {
|
||||||
/// a certain type implements a certain trait. Proving the Obligation might
|
/// a certain type implements a certain trait. Proving the Obligation might
|
||||||
/// result in additional information about inference variables.
|
/// result in additional information about inference variables.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum Obligation {
|
pub enum DomainGoal {
|
||||||
/// Prove that a certain type implements a trait (the type is the `Self` type
|
Holds(WhereClause),
|
||||||
/// parameter to the `TraitRef`).
|
|
||||||
Trait(TraitRef),
|
|
||||||
AliasEq(AliasEq),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Obligation {
|
|
||||||
pub fn from_predicate(predicate: WhereClause) -> Option<Obligation> {
|
|
||||||
match predicate {
|
|
||||||
WhereClause::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)),
|
|
||||||
WhereClause::AliasEq(alias_eq) => Some(Obligation::AliasEq(alias_eq)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
@ -136,16 +124,20 @@ impl TypeWalk for AliasEq {
|
||||||
pub(crate) fn trait_solve_query(
|
pub(crate) fn trait_solve_query(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
goal: Canonical<InEnvironment<Obligation>>,
|
goal: Canonical<InEnvironment<DomainGoal>>,
|
||||||
) -> Option<Solution> {
|
) -> Option<Solution> {
|
||||||
let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value {
|
let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value {
|
||||||
Obligation::Trait(it) => db.trait_data(it.hir_trait_id()).name.to_string(),
|
DomainGoal::Holds(WhereClause::Implemented(it)) => {
|
||||||
Obligation::AliasEq(_) => "alias_eq".to_string(),
|
db.trait_data(it.hir_trait_id()).name.to_string()
|
||||||
|
}
|
||||||
|
DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(),
|
||||||
});
|
});
|
||||||
log::info!("trait_solve_query({})", goal.value.value.display(db));
|
log::info!("trait_solve_query({})", goal.value.value.display(db));
|
||||||
|
|
||||||
if let Obligation::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), .. }) =
|
if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
|
||||||
&goal.value.value
|
alias: AliasTy::Projection(projection_ty),
|
||||||
|
..
|
||||||
|
})) = &goal.value.value
|
||||||
{
|
{
|
||||||
if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) {
|
if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) {
|
||||||
// Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
|
// Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
from_assoc_type_id,
|
from_assoc_type_id,
|
||||||
primitive::UintTy,
|
primitive::UintTy,
|
||||||
traits::{Canonical, Obligation},
|
traits::{Canonical, DomainGoal},
|
||||||
AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution,
|
AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution,
|
||||||
TraitRef, Ty, WhereClause,
|
TraitRef, Ty, WhereClause,
|
||||||
};
|
};
|
||||||
|
@ -422,13 +422,15 @@ impl ToChalk for AliasEq {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToChalk for Obligation {
|
impl ToChalk for DomainGoal {
|
||||||
type Chalk = chalk_ir::DomainGoal<Interner>;
|
type Chalk = chalk_ir::DomainGoal<Interner>;
|
||||||
|
|
||||||
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
|
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
|
||||||
match self {
|
match self {
|
||||||
Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner),
|
DomainGoal::Holds(WhereClause::Implemented(tr)) => tr.to_chalk(db).cast(&Interner),
|
||||||
Obligation::AliasEq(alias_eq) => alias_eq.to_chalk(db).cast(&Interner),
|
DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => {
|
||||||
|
alias_eq.to_chalk(db).cast(&Interner)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue