Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ use hir_ty::{
primitive::UintTy,
to_assoc_type_id,
traits::{FnTrait, Solution, SolutionVariables},
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex,
InEnvironment, Interner, Obligation, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind,
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, Cast, DebruijnIndex,
InEnvironment, Interner, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind,
TyVariableKind, WhereClause,
};
use itertools::Itertools;
Expand Down Expand Up @@ -1767,7 +1767,7 @@ impl Type {
let goal = Canonical {
value: hir_ty::InEnvironment::new(
self.ty.environment.clone(),
hir_ty::Obligation::Trait(trait_ref),
trait_ref.cast(&Interner),
),
kinds: Arc::new([]),
};
Expand All @@ -1789,14 +1789,15 @@ impl Type {
let goal = Canonical {
value: InEnvironment::new(
self.ty.environment.clone(),
Obligation::AliasEq(AliasEq {
AliasEq {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(alias.id),
substitution: subst,
}),
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
.intern(&Interner),
}),
}
.cast(&Interner),
),
kinds: Arc::new([TyVariableKind::General]),
};
Expand Down
9 changes: 5 additions & 4 deletions crates/hir_ty/src/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use std::iter::successors;

use base_db::CrateId;
use chalk_ir::cast::Cast;
use hir_def::lang_item::LangItemTarget;
use hir_expand::name::name;
use log::{info, warn};
Expand All @@ -15,8 +16,8 @@ use crate::{
to_assoc_type_id, to_chalk_trait_id,
traits::{InEnvironment, Solution},
utils::generics,
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, Obligation, ProjectionTy,
Substitution, TraitRef, Ty, TyKind,
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution,
TraitRef, Ty, TyKind,
};

const AUTODEREF_RECURSION_LIMIT: usize = 10;
Expand Down Expand Up @@ -74,7 +75,7 @@ fn deref_by_trait(
let implements_goal = Canonical {
kinds: ty.value.kinds.clone(),
value: InEnvironment {
value: Obligation::Trait(trait_ref),
value: trait_ref.cast(&Interner),
environment: ty.environment.clone(),
},
};
Expand All @@ -92,7 +93,7 @@ fn deref_by_trait(
.intern(&Interner),
};

let obligation = super::Obligation::AliasEq(projection);
let obligation = projection.cast(&Interner);

let in_env = InEnvironment { value: obligation, environment: ty.environment };

Expand Down
53 changes: 53 additions & 0 deletions crates/hir_ty/src/chalk_cast.rs
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion crates/hir_ty/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
fn trait_solve(
&self,
krate: CrateId,
goal: crate::Canonical<crate::InEnvironment<crate::Obligation>>,
goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
) -> Option<crate::traits::Solution>;

#[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)]
Expand Down
20 changes: 5 additions & 15 deletions crates/hir_ty/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use hir_expand::name::Name;
use crate::{
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,
CallableDefId, CallableSig, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy,
CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy,
ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause,
};

Expand Down Expand Up @@ -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> {
match self {
Obligation::Trait(tr) => {
write!(f, "Implements(")?;
tr.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)?;
DomainGoal::Holds(wc) => {
write!(f, "Holds(")?;
wc.hir_fmt(f)?;
write!(f, ")")
}
}
Expand Down
12 changes: 6 additions & 6 deletions crates/hir_ty/src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::mem;
use std::ops::Index;
use std::sync::Arc;

use chalk_ir::Mutability;
use chalk_ir::{cast::Cast, Mutability};
use hir_def::{
body::Body,
data::{ConstData, FunctionData, StaticData},
Expand All @@ -37,7 +37,7 @@ use stdx::impl_from;
use syntax::SmolStr;

use super::{
traits::{Guidance, Obligation, Solution},
traits::{DomainGoal, Guidance, Solution},
InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk,
};
use crate::{
Expand Down Expand Up @@ -204,7 +204,7 @@ struct InferenceContext<'a> {
resolver: Resolver,
table: unify::InferenceTable,
trait_env: Arc<TraitEnvironment>,
obligations: Vec<Obligation>,
obligations: Vec<DomainGoal>,
result: InferenceResult,
/// The return type of the function being inferred, or the closure if we're
/// currently within one.
Expand Down Expand Up @@ -403,8 +403,8 @@ impl<'a> InferenceContext<'a> {
}),
ty: ty.clone(),
};
self.obligations.push(Obligation::Trait(trait_ref));
self.obligations.push(Obligation::AliasEq(alias_eq));
self.obligations.push(trait_ref.cast(&Interner));
self.obligations.push(alias_eq.cast(&Interner));
self.resolve_ty_as_possible(ty)
}
None => self.err_ty(),
Expand All @@ -430,7 +430,7 @@ impl<'a> InferenceContext<'a> {
fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
let var = self.table.new_type_var();
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);
var
}
Expand Down
7 changes: 3 additions & 4 deletions crates/hir_ty/src/infer/coerce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
//!
//! 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 crate::{
autoderef, to_chalk_trait_id, traits::Solution, Interner, Obligation, Substitution, TraitRef,
Ty, TyKind,
autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind,
};

use super::{InEnvironment, InferenceContext};
Expand Down Expand Up @@ -143,7 +142,7 @@ impl<'a> InferenceContext<'a> {
.build();
let trait_ref =
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 canonicalized = canonicalizer.canonicalize_obligation(goal);
Expand Down
25 changes: 11 additions & 14 deletions crates/hir_ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::iter::{repeat, repeat_with};
use std::{mem, sync::Arc};

use chalk_ir::{Mutability, TyVariableKind};
use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
use hir_def::{
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
path::{GenericArg, GenericArgs},
Expand All @@ -21,7 +21,7 @@ use crate::{
to_assoc_type_id, to_chalk_trait_id,
traits::{chalk::from_chalk, FnTrait, InEnvironment},
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,
};

Expand Down Expand Up @@ -90,10 +90,9 @@ impl<'a> InferenceContext<'a> {
Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();

let trait_env = Arc::clone(&self.trait_env);
let implements_fn_trait = Obligation::Trait(TraitRef {
trait_id: to_chalk_trait_id(fn_once_trait),
substitution: substs.clone(),
});
let implements_fn_trait: DomainGoal =
TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() }
.cast(&Interner);
let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
value: implements_fn_trait.clone(),
environment: trait_env,
Expand Down Expand Up @@ -938,22 +937,20 @@ impl<'a> InferenceContext<'a> {
let generic_predicates = self.db.generic_predicates(def.into());
for predicate in generic_predicates.iter() {
let predicate = predicate.clone().subst(parameters);
if let Some(obligation) = Obligation::from_predicate(predicate) {
self.obligations.push(obligation);
}
self.obligations.push(predicate.cast(&Interner));
}
// add obligation for trait implementation, if this is a trait method
match def {
CallableDefId::FunctionId(f) => {
if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
{
// construct a TraitDef
// construct a TraitRef
let substs =
parameters.prefix(generics(self.db.upcast(), trait_.into()).len());
self.obligations.push(Obligation::Trait(TraitRef {
trait_id: to_chalk_trait_id(trait_),
substitution: substs,
}));
self.obligations.push(
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
.cast(&Interner),
);
}
}
CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
Expand Down
12 changes: 8 additions & 4 deletions crates/hir_ty/src/infer/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::iter;

use chalk_ir::cast::Cast;
use hir_def::{
path::{Path, PathSegment},
resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
Expand Down Expand Up @@ -256,10 +257,13 @@ impl<'a> InferenceContext<'a> {
.push(ty.clone())
.fill(std::iter::repeat_with(|| self.table.new_type_var()))
.build();
self.obligations.push(super::Obligation::Trait(TraitRef {
trait_id: to_chalk_trait_id(trait_),
substitution: trait_substs.clone(),
}));
self.obligations.push(
TraitRef {
trait_id: to_chalk_trait_id(trait_),
substitution: trait_substs.clone(),
}
.cast(&Interner),
);
Some(trait_substs)
}
AssocContainerId::ModuleId(_) => None,
Expand Down
13 changes: 5 additions & 8 deletions crates/hir_ty/src/infer/unify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::borrow::Cow;
use chalk_ir::{FloatTy, IntTy, TyVariableKind};
use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};

use super::{InferenceContext, Obligation};
use super::{DomainGoal, InferenceContext};
use crate::{
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar,
Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause,
Expand Down Expand Up @@ -87,14 +87,11 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {

pub(crate) fn canonicalize_obligation(
mut self,
obligation: InEnvironment<Obligation>,
) -> Canonicalized<InEnvironment<Obligation>> {
obligation: InEnvironment<DomainGoal>,
) -> Canonicalized<InEnvironment<DomainGoal>> {
let result = match obligation.value {
Obligation::Trait(tr) => {
Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST))
}
Obligation::AliasEq(alias_eq) => {
Obligation::AliasEq(self.do_canonicalize(alias_eq, DebruijnIndex::INNERMOST))
DomainGoal::Holds(wc) => {
DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
}
};
self.into_canonicalized(InEnvironment {
Expand Down
7 changes: 5 additions & 2 deletions crates/hir_ty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod op;
mod lower;
pub(crate) mod infer;
pub(crate) mod utils;
mod chalk_cast;

pub mod display;
pub mod db;
Expand Down Expand Up @@ -45,9 +46,11 @@ pub use lower::{
associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
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;

Expand Down
Loading