From 86b6b559ea15359ffaf35b3aa6474836179c57ce Mon Sep 17 00:00:00 2001 From: ilyalesokhin-starkware Date: Tue, 13 Aug 2024 17:44:52 +0300 Subject: [PATCH] GeneratedImpl generic args. (#6201) --- crates/cairo-lang-semantic/src/db.rs | 12 +++ .../cairo-lang-semantic/src/expr/inference.rs | 3 +- .../src/expr/inference/canonic.rs | 5 +- .../src/expr/inference/conform.rs | 2 +- .../src/expr/inference/infers.rs | 18 +++- crates/cairo-lang-semantic/src/items/imp.rs | 99 +++++++++++++++---- .../cairo-lang-semantic/src/substitution.rs | 8 +- 7 files changed, 122 insertions(+), 25 deletions(-) diff --git a/crates/cairo-lang-semantic/src/db.rs b/crates/cairo-lang-semantic/src/db.rs index 8d32a94f827..9c8045e0341 100644 --- a/crates/cairo-lang-semantic/src/db.rs +++ b/crates/cairo-lang-semantic/src/db.rs @@ -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. diff --git a/crates/cairo-lang-semantic/src/expr/inference.rs b/crates/cairo-lang-semantic/src/expr/inference.rs index 28e81826456..7aea4989686 100644 --- a/crates/cairo-lang-semantic/src/expr/inference.rs +++ b/crates/cairo-lang-semantic/src/expr/inference.rs @@ -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}; diff --git a/crates/cairo-lang-semantic/src/expr/inference/canonic.rs b/crates/cairo-lang-semantic/src/expr/inference/canonic.rs index 302c970b019..8fdc61d3a26 100644 --- a/crates/cairo-lang-semantic/src/expr/inference/canonic.rs +++ b/crates/cairo-lang-semantic/src/expr/inference/canonic.rs @@ -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::{ diff --git a/crates/cairo-lang-semantic/src/expr/inference/conform.rs b/crates/cairo-lang-semantic/src/expr/inference/conform.rs index 11c0d965736..39054df8fb8 100644 --- a/crates/cairo-lang-semantic/src/expr/inference/conform.rs +++ b/crates/cairo-lang-semantic/src/expr/inference/conform.rs @@ -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, ), } diff --git a/crates/cairo-lang-semantic/src/expr/inference/infers.rs b/crates/cairo-lang-semantic/src/expr/inference/infers.rs index 0a824ac23e7..9273e347f9e 100644 --- a/crates/cairo-lang-semantic/src/expr/inference/infers.rs +++ b/crates/cairo-lang-semantic/src/expr/inference/infers.rs @@ -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, @@ -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) diff --git a/crates/cairo-lang-semantic/src/items/imp.rs b/crates/cairo-lang-semantic/src/items/imp.rs index c84b9de0e77..ec6197b54c7 100644 --- a/crates/cairo-lang-semantic/src/items/imp.rs +++ b/crates/cairo-lang-semantic/src/items/imp.rs @@ -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) } } } @@ -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) } } } @@ -266,7 +266,7 @@ impl DebugWithDb 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)) } } } @@ -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, } -impl DebugWithDb for GeneratedImplId { +impl DebugWithDb 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)) } } @@ -530,7 +555,7 @@ pub fn impl_concrete_trait(db: &dyn SemanticGroup, impl_id: ImplId) -> Maybe 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)), } } @@ -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 { @@ -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)), } } @@ -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)), } } @@ -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() } } } @@ -1545,13 +1568,51 @@ impl DebugWithDb 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, +} + +impl DebugWithDb 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, @@ -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( diff --git a/crates/cairo-lang-semantic/src/substitution.rs b/crates/cairo-lang-semantic/src/substitution.rs index af93b70c298..3174d9503b3 100644 --- a/crates/cairo-lang-semantic/src/substitution.rs +++ b/crates/cairo-lang-semantic/src/substitution.rs @@ -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, @@ -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)*);