Skip to content

Commit

Permalink
GeneratedImpl generic args. (#6201)
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyalesokhin-starkware authored Aug 13, 2024
1 parent 54804c8 commit 86b6b55
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 25 deletions.
12 changes: 12 additions & 0 deletions crates/cairo-lang-semantic/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,18 @@ pub trait SemanticGroup:
#[salsa::interned]
fn intern_impl_var(&self, id: ImplVar) -> ImplVarId;

#[salsa::interned]
fn intern_generated_impl(
&self,
id: items::imp::GeneratedImplLongId,
) -> items::imp::GeneratedImplId;

#[salsa::interned]
fn intern_uninferred_generated_impl(
&self,
id: items::imp::UninferredGeneratedImplLongId,
) -> items::imp::UninferredGeneratedImplId;

// Const.
// ====
/// Private query to compute data about a constant definition.
Expand Down
3 changes: 2 additions & 1 deletion crates/cairo-lang-semantic/src/expr/inference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ use crate::items::functions::{
};
use crate::items::generics::{GenericParamConst, GenericParamImpl, GenericParamType};
use crate::items::imp::{
GeneratedImplId, ImplId, ImplImplId, ImplLongId, ImplLookupContext, UninferredImpl,
GeneratedImplId, GeneratedImplLongId, ImplId, ImplImplId, ImplLongId, ImplLookupContext,
UninferredGeneratedImplId, UninferredGeneratedImplLongId, UninferredImpl,
};
use crate::items::trt::{ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId};
use crate::substitution::{HasDb, RewriteResult, SemanticRewriter, SubstitutionRewriter};
Expand Down
5 changes: 4 additions & 1 deletion crates/cairo-lang-semantic/src/expr/inference/canonic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ use crate::items::functions::{
ImplGenericFunctionWithBodyId,
};
use crate::items::generics::{GenericParamConst, GenericParamImpl, GenericParamType};
use crate::items::imp::{GeneratedImplId, ImplId, ImplImplId, ImplLongId, UninferredImpl};
use crate::items::imp::{
GeneratedImplId, GeneratedImplLongId, ImplId, ImplImplId, ImplLongId,
UninferredGeneratedImplId, UninferredGeneratedImplLongId, UninferredImpl,
};
use crate::items::trt::{ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId};
use crate::substitution::{HasDb, RewriteResult, SemanticObject, SemanticRewriter};
use crate::types::{
Expand Down
2 changes: 1 addition & 1 deletion crates/cairo-lang-semantic/src/expr/inference/conform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ impl<'db> InferenceConform for Inference<'db> {
}
ImplLongId::ImplImpl(impl_impl) => self.impl_contains_var(impl_impl.impl_id(), var),
ImplLongId::GeneratedImpl(generated_impl) => self.generic_args_contain_var(
&generated_impl.concrete_trait.generic_args(self.db),
&generated_impl.concrete_trait(self.db).generic_args(self.db),
var,
),
}
Expand Down
18 changes: 16 additions & 2 deletions crates/cairo-lang-semantic/src/expr/inference/infers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ use super::{Inference, InferenceError, InferenceResult};
use crate::items::constant::ImplConstantId;
use crate::items::functions::{GenericFunctionId, ImplGenericFunctionId};
use crate::items::generics::GenericParamConst;
use crate::items::imp::{ImplId, ImplImplId, ImplLongId, ImplLookupContext, UninferredImpl};
use crate::items::imp::{
GeneratedImplLongId, ImplId, ImplImplId, ImplLongId, ImplLookupContext, UninferredImpl,
};
use crate::items::trt::{
ConcreteTraitConstantId, ConcreteTraitGenericFunctionId, ConcreteTraitImplId,
ConcreteTraitTypeId,
Expand Down Expand Up @@ -141,7 +143,19 @@ impl<'db> InferenceEmbeddings for Inference<'db> {
ImplLongId::GenericParameter(param_id).intern(self.db)
}
UninferredImpl::GeneratedImpl(generated_impl) => {
ImplLongId::GeneratedImpl(generated_impl).intern(self.db)
let long_id = generated_impl.lookup_intern(self.db);
ImplLongId::GeneratedImpl(
GeneratedImplLongId {
concrete_trait: long_id.concrete_trait,
generic_args: self.infer_generic_args(
&long_id.generic_params[..],
lookup_context,
stable_ptr,
)?,
}
.intern(self.db),
)
.intern(self.db)
}
};
Ok(impl_id)
Expand Down
99 changes: 80 additions & 19 deletions crates/cairo-lang-semantic/src/items/imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ impl ImplLongId {
ImplLongId::ImplVar(_) => false,
ImplLongId::ImplImpl(impl_impl) => impl_impl.impl_id().is_var_free(db),
ImplLongId::GeneratedImpl(generated_impl) => {
generated_impl.concrete_trait.is_var_free(db)
generated_impl.concrete_trait(db).is_var_free(db)
}
}
}
Expand All @@ -248,7 +248,7 @@ impl ImplLongId {
ImplLongId::ImplVar(_) => false,
ImplLongId::ImplImpl(_) | ImplLongId::TraitImpl(_) => false,
ImplLongId::GeneratedImpl(generated_impl) => {
generated_impl.concrete_trait.is_fully_concrete(db)
generated_impl.concrete_trait(db).is_fully_concrete(db)
}
}
}
Expand All @@ -266,7 +266,7 @@ impl DebugWithDb<dyn SemanticGroup> for ImplLongId {
ImplLongId::ImplImpl(impl_impl) => write!(f, "{:?}", impl_impl.debug(db)),
ImplLongId::TraitImpl(trait_impl) => write!(f, "{:?}", trait_impl.debug(db)),
ImplLongId::GeneratedImpl(generated_impl) => {
write!(f, "Generated {}", generated_impl.concrete_trait.full_path(db.upcast()))
write!(f, "{:?}", generated_impl.debug(db))
}
}
}
Expand Down Expand Up @@ -304,22 +304,47 @@ impl ImplId {
}
}

define_short_id!(
GeneratedImplId,
GeneratedImplLongId,
SemanticGroup,
lookup_intern_generated_impl,
intern_generated_impl
);
semantic_object_for_id!(
GeneratedImplId,
lookup_intern_generated_impl,
intern_generated_impl,
GeneratedImplLongId
);

impl GeneratedImplId {
pub fn concrete_trait(self, db: &dyn SemanticGroup) -> ConcreteTraitId {
db.lookup_intern_generated_impl(self).concrete_trait
}

pub fn trait_id(&self, db: &dyn SemanticGroup) -> TraitId {
self.concrete_trait(db).trait_id(db)
}
}

/// An impl that is generated by the compiler for a specific trait.
/// There can be only one such impl per concrete trait as otherwise there would be a
/// MultipleImplsFound ambiguity.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
pub struct GeneratedImplId {
#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
pub struct GeneratedImplLongId {
pub concrete_trait: ConcreteTraitId,
/// The generic arguments used by the generated impl, typically impls and negative impls.
pub generic_args: Vec<GenericArgumentId>,
}

impl DebugWithDb<dyn SemanticGroup> for GeneratedImplId {
impl DebugWithDb<dyn SemanticGroup> for GeneratedImplLongId {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
db: &(dyn SemanticGroup + 'static),
) -> std::fmt::Result {
write!(f, "Generated ")?;
self.concrete_trait.fmt(f, db)
write!(f, "Generated {:?}", self.concrete_trait.debug(db))
}
}

Expand Down Expand Up @@ -530,7 +555,7 @@ pub fn impl_concrete_trait(db: &dyn SemanticGroup, impl_id: ImplId) -> Maybe<Con
ImplLongId::ImplVar(var) => Ok(var.lookup_intern(db).concrete_trait_id),
ImplLongId::ImplImpl(impl_impl) => impl_impl_concrete_trait(db, impl_impl),
ImplLongId::TraitImpl(trait_impl) => db.trait_impl_concrete_trait(trait_impl),
ImplLongId::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait),
ImplLongId::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
}
}

Expand Down Expand Up @@ -1478,7 +1503,7 @@ pub enum UninferredImpl {
ImplAlias(ImplAliasId),
GenericParam(GenericParamId),
ImplImpl(ImplImplId),
GeneratedImpl(GeneratedImplId),
GeneratedImpl(UninferredGeneratedImplId),
}
impl UninferredImpl {
pub fn concrete_trait(&self, db: &dyn SemanticGroup) -> Maybe<ConcreteTraitId> {
Expand All @@ -1494,7 +1519,7 @@ impl UninferredImpl {
param.concrete_trait
}
UninferredImpl::ImplImpl(impl_impl_id) => db.impl_impl_concrete_trait(*impl_impl_id),
UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait),
UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.concrete_trait(db)),
}
}

Expand All @@ -1513,9 +1538,7 @@ impl UninferredImpl {
UninferredImpl::ImplImpl(impl_impl_id) => db
.impl_impl_concrete_trait(*impl_impl_id)
.map(|concrete_trait| concrete_trait.trait_id(db)),
UninferredImpl::GeneratedImpl(generated_impl) => {
Ok(generated_impl.concrete_trait.trait_id(db))
}
UninferredImpl::GeneratedImpl(generated_impl) => Ok(generated_impl.trait_id(db)),
}
}

Expand All @@ -1529,7 +1552,7 @@ impl UninferredImpl {
UninferredImpl::GenericParam(param) => param.module_file_id(defs_db).0.into(),
UninferredImpl::ImplImpl(impl_impl_id) => impl_impl_id.impl_id.into(),
UninferredImpl::GeneratedImpl(generated_impl) => {
generated_impl.concrete_trait.trait_id(db).module_file_id(defs_db).0.into()
generated_impl.trait_id(db).module_file_id(defs_db).0.into()
}
}
}
Expand All @@ -1545,13 +1568,51 @@ impl DebugWithDb<dyn SemanticGroup> for UninferredImpl {
write!(f, "generic param {}", param.name(db.upcast()).unwrap_or_else(|| "_".into()))
}
UninferredImpl::ImplImpl(impl_impl) => impl_impl.fmt(f, db.elongate()),
UninferredImpl::GeneratedImpl(generated_impl) => {
write!(f, "Generated {}", generated_impl.concrete_trait.full_path(db.upcast()))
}
UninferredImpl::GeneratedImpl(generated_impl) => generated_impl.fmt(f, db.elongate()),
}
}
}

define_short_id!(
UninferredGeneratedImplId,
UninferredGeneratedImplLongId,
SemanticGroup,
lookup_intern_uninferred_generated_impl,
intern_uninferred_generated_impl
);
semantic_object_for_id!(
UninferredGeneratedImplId,
lookup_intern_uninferred_generated_impl,
intern_uninferred_generated_impl,
UninferredGeneratedImplLongId
);

impl UninferredGeneratedImplId {
pub fn concrete_trait(self, db: &dyn SemanticGroup) -> ConcreteTraitId {
db.lookup_intern_uninferred_generated_impl(self).concrete_trait
}

pub fn trait_id(&self, db: &dyn SemanticGroup) -> TraitId {
self.concrete_trait(db).trait_id(db)
}
}

/// Generated impls before inference, see GeneratedImplLongId for more details.
#[derive(Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
pub struct UninferredGeneratedImplLongId {
pub concrete_trait: ConcreteTraitId,
pub generic_params: Vec<GenericParam>,
}

impl DebugWithDb<dyn SemanticGroup> for UninferredGeneratedImplLongId {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
db: &(dyn SemanticGroup + 'static),
) -> std::fmt::Result {
write!(f, "Generated {:?}", self.concrete_trait.debug(db))
}
}
/// Finds all the implementations of a concrete trait, in a specific lookup context.
pub fn find_candidates_at_context(
db: &dyn SemanticGroup,
Expand Down Expand Up @@ -2225,7 +2286,7 @@ pub fn impl_constant_concrete_implized_type(
ImplLongId::ImplVar(var) => var.lookup_intern(db).concrete_trait_id,
ImplLongId::ImplImpl(impl_impl) => db.impl_impl_concrete_trait(impl_impl)?,
ImplLongId::TraitImpl(trait_impl) => db.trait_impl_concrete_trait(trait_impl)?,
ImplLongId::GeneratedImpl(generated_impl) => generated_impl.concrete_trait,
ImplLongId::GeneratedImpl(generated_impl) => generated_impl.concrete_trait(db),
};

let ty = db.concrete_trait_constant_type(ConcreteTraitConstantId::new(
Expand Down
8 changes: 7 additions & 1 deletion crates/cairo-lang-semantic/src/substitution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ use crate::items::functions::{
ImplGenericFunctionWithBodyId,
};
use crate::items::generics::{GenericParamConst, GenericParamImpl, GenericParamType};
use crate::items::imp::{GeneratedImplId, ImplId, ImplImplId, ImplLongId, UninferredImpl};
use crate::items::imp::{
GeneratedImplId, GeneratedImplLongId, ImplId, ImplImplId, ImplLongId,
UninferredGeneratedImplId, UninferredGeneratedImplLongId, UninferredImpl,
};
use crate::items::trt::{ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId};
use crate::types::{
ClosureTypeLongId, ConcreteEnumLongId, ConcreteExternTypeLongId, ConcreteStructLongId,
Expand Down Expand Up @@ -326,11 +329,14 @@ macro_rules! add_basic_rewrites {
$crate::prune_single!(__regular_helper, ConcreteTraitGenericFunctionLongId, $($exclude)*);
$crate::prune_single!(__regular_helper, ConcreteTraitGenericFunctionId, $($exclude)*);
$crate::prune_single!(__regular_helper, GeneratedImplId, $($exclude)*);
$crate::prune_single!(__regular_helper, GeneratedImplLongId, $($exclude)*);
$crate::prune_single!(__regular_helper, ImplLongId, $($exclude)*);
$crate::prune_single!(__regular_helper, ImplId, $($exclude)*);
$crate::prune_single!(__regular_helper, ImplTypeId, $($exclude)*);
$crate::prune_single!(__regular_helper, ImplConstantId, $($exclude)*);
$crate::prune_single!(__regular_helper, ImplImplId, $($exclude)*);
$crate::prune_single!(__regular_helper, UninferredGeneratedImplId, $($exclude)*);
$crate::prune_single!(__regular_helper, UninferredGeneratedImplLongId, $($exclude)*);
$crate::prune_single!(__regular_helper, UninferredImpl, $($exclude)*);
$crate::prune_single!(__regular_helper, ExprVarMemberPath, $($exclude)*);
$crate::prune_single!(__regular_helper, ExprVar, $($exclude)*);
Expand Down

0 comments on commit 86b6b55

Please sign in to comment.