Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling use star in Semantics. #6592

Merged
merged 1 commit into from
Nov 24, 2024
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
52 changes: 51 additions & 1 deletion crates/cairo-lang-defs/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub trait DefsGroup:
#[salsa::interned]
fn intern_use(&self, id: UseLongId) -> UseId;
#[salsa::interned]
fn intern_global_use(&self, id: GlobalUseLongId) -> GlobalUseId;
#[salsa::interned]
fn intern_free_function(&self, id: FreeFunctionLongId) -> FreeFunctionId;
#[salsa::interned]
fn intern_impl_type_def(&self, id: ImplTypeDefLongId) -> ImplTypeDefId;
Expand Down Expand Up @@ -162,6 +164,10 @@ pub trait DefsGroup:
free_function_id: FreeFunctionId,
) -> Maybe<Option<ast::FunctionWithBody>>;
fn module_items(&self, module_id: ModuleId) -> Maybe<Arc<[ModuleItemId]>>;
fn module_global_uses(
&self,
module_id: ModuleId,
) -> Maybe<Arc<OrderedHashMap<GlobalUseId, ast::UsePathStar>>>;
/// Returns the stable ptr of the name of a module item.
fn module_item_name_stable_ptr(
&self,
Expand All @@ -174,6 +180,10 @@ pub trait DefsGroup:
) -> Maybe<Arc<OrderedHashMap<UseId, ast::UsePathLeaf>>>;
fn module_uses_ids(&self, module_id: ModuleId) -> Maybe<Arc<[UseId]>>;
fn module_use_by_id(&self, use_id: UseId) -> Maybe<Option<ast::UsePathLeaf>>;
fn module_global_use_by_id(
&self,
global_use_id: GlobalUseId,
) -> Maybe<Option<ast::UsePathStar>>;
fn module_structs(
&self,
module_id: ModuleId,
Expand Down Expand Up @@ -394,6 +404,7 @@ pub struct ModuleData {
impls: Arc<OrderedHashMap<ImplDefId, ast::ItemImpl>>,
extern_types: Arc<OrderedHashMap<ExternTypeId, ast::ItemExternType>>,
extern_functions: Arc<OrderedHashMap<ExternFunctionId, ast::ItemExternFunction>>,
global_uses: Arc<OrderedHashMap<GlobalUseId, ast::UsePathStar>>,

files: Vec<FileId>,
/// Generation info for each file. Virtual files have Some. Other files have None.
Expand Down Expand Up @@ -452,6 +463,7 @@ fn priv_module_data(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<ModuleData
let mut impls = OrderedHashMap::default();
let mut extern_types = OrderedHashMap::default();
let mut extern_functions = OrderedHashMap::default();
let mut global_uses = OrderedHashMap::default();
let mut aux_data = Vec::new();
let mut files = Vec::new();
let mut plugin_diagnostics = Vec::new();
Expand Down Expand Up @@ -487,6 +499,10 @@ fn priv_module_data(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<ModuleData
uses.insert(id, leaf);
items.push(ModuleItemId::Use(id));
}
for star in get_all_path_stars(db.upcast(), &us) {
let id = GlobalUseLongId(module_file_id, star.stable_ptr()).intern(db);
global_uses.insert(id, star);
}
}
ast::ModuleItem::FreeFunction(function) => {
let item_id =
Expand Down Expand Up @@ -568,6 +584,7 @@ fn priv_module_data(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<ModuleData
impls: impls.into(),
extern_types: extern_types.into(),
extern_functions: extern_functions.into(),
global_uses: global_uses.into(),
files,
generated_file_aux_data: aux_data,
plugin_diagnostics,
Expand Down Expand Up @@ -773,7 +790,24 @@ pub fn get_all_path_leaves(db: &dyn SyntaxGroup, use_item: &ast::ItemUse) -> Vec
ast::UsePath::Multi(use_path) => {
stack.extend(use_path.use_paths(db).elements(db).into_iter().rev())
}
ast::UsePath::Star(_) => todo!("Change function to collect `star` use as well."),
ast::UsePath::Star(_) => {}
}
}
res
}

/// Returns all the path stars under a given use item.
pub fn get_all_path_stars(db: &dyn SyntaxGroup, use_item: &ast::ItemUse) -> Vec<ast::UsePathStar> {
let mut res = vec![];
let mut stack = vec![use_item.use_path(db)];
while let Some(use_path) = stack.pop() {
match use_path {
ast::UsePath::Leaf(_) => {}
ast::UsePath::Single(use_path) => stack.push(use_path.use_path(db)),
ast::UsePath::Multi(use_path) => {
stack.extend(use_path.use_paths(db).elements(db).into_iter().rev())
}
ast::UsePath::Star(use_path) => res.push(use_path),
}
}
res
Expand Down Expand Up @@ -853,6 +887,15 @@ pub fn module_use_by_id(db: &dyn DefsGroup, use_id: UseId) -> Maybe<Option<ast::
Ok(module_uses.get(&use_id).cloned())
}

/// Returns the `use *` of the given module, by its ID.
pub fn module_global_use_by_id(
db: &dyn DefsGroup,
global_use_id: GlobalUseId,
) -> Maybe<Option<ast::UsePathStar>> {
let module_global_uses = db.module_global_uses(global_use_id.module_file_id(db.upcast()).0)?;
Ok(module_global_uses.get(&global_use_id).cloned())
}

/// Returns all the structs of the given module.
pub fn module_structs(
db: &dyn DefsGroup,
Expand Down Expand Up @@ -1038,6 +1081,13 @@ fn module_items(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[ModuleIte
Ok(db.priv_module_data(module_id)?.items)
}

fn module_global_uses(
db: &dyn DefsGroup,
module_id: ModuleId,
) -> Maybe<Arc<OrderedHashMap<GlobalUseId, ast::UsePathStar>>> {
Ok(db.priv_module_data(module_id)?.global_uses)
}

fn module_item_name_stable_ptr(
db: &dyn DefsGroup,
module_id: ModuleId,
Expand Down
7 changes: 7 additions & 0 deletions crates/cairo-lang-defs/src/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,13 @@ define_top_level_language_element_id!(
lookup_intern_constant,
intern_constant
);
define_language_element_id_basic!(
GlobalUseId,
GlobalUseLongId,
ast::UsePathStar,
lookup_intern_global_use,
intern_global_use
);
define_top_level_language_element_id!(
UseId,
UseLongId,
Expand Down
16 changes: 12 additions & 4 deletions crates/cairo-lang-semantic/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::diagnostic_utils::StableLocation;
use cairo_lang_defs::ids::{
ConstantId, EnumId, ExternFunctionId, ExternTypeId, FreeFunctionId, FunctionTitleId,
FunctionWithBodyId, GenericParamId, GenericTypeId, ImplAliasId, ImplConstantDefId, ImplDefId,
ImplFunctionId, ImplImplDefId, ImplItemId, ImplTypeDefId, LanguageElementId, LookupItemId,
ModuleFileId, ModuleId, ModuleItemId, ModuleTypeAliasId, StructId, TraitConstantId,
TraitFunctionId, TraitId, TraitImplId, TraitItemId, TraitTypeId, UseId, VariantId,
FunctionWithBodyId, GenericParamId, GenericTypeId, GlobalUseId, ImplAliasId, ImplConstantDefId,
ImplDefId, ImplFunctionId, ImplImplDefId, ImplItemId, ImplTypeDefId, LanguageElementId,
LookupItemId, ModuleFileId, ModuleId, ModuleItemId, ModuleTypeAliasId, StructId,
TraitConstantId, TraitFunctionId, TraitId, TraitImplId, TraitItemId, TraitTypeId, UseId,
VariantId,
};
use cairo_lang_diagnostics::{Diagnostics, DiagnosticsBuilder, Maybe};
use cairo_lang_filesystem::db::{AsFilesGroupMut, FilesGroup};
Expand Down Expand Up @@ -175,6 +176,13 @@ pub trait SemanticGroup:
#[salsa::cycle(items::us::use_resolver_data_cycle)]
fn use_resolver_data(&self, use_id: UseId) -> Maybe<Arc<ResolverData>>;

// Global Use.
// ====
/// Private query to compute data about a global use.
#[salsa::invoke(items::us::priv_global_use_semantic_data)]
fn priv_global_use_semantic_data(&self, use_id: GlobalUseId)
-> Maybe<items::us::UseGlobalData>;

// Module.
// ====

Expand Down
25 changes: 24 additions & 1 deletion crates/cairo-lang-semantic/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::corelib::LiteralError;
use crate::db::SemanticGroup;
use crate::expr::inference::InferenceError;
use crate::items::feature_kind::FeatureMarkerDiagnostic;
use crate::resolve::ResolvedConcreteItem;
use crate::resolve::{ResolvedConcreteItem, ResolvedGenericItem};
use crate::types::peel_snapshots;
use crate::{ConcreteTraitId, semantic};

Expand Down Expand Up @@ -633,6 +633,9 @@ impl DiagnosticEntry for SemanticDiagnostic {
SemanticDiagnosticKind::NameDefinedMultipleTimes(name) => {
format!("The name `{name}` is defined multiple times.")
}
SemanticDiagnosticKind::NonPrivateUseStar => {
"`pub` not supported for global `use`.".into()
}
SemanticDiagnosticKind::NamedArgumentsAreNotSupported => {
"Named arguments are not supported in this context.".into()
}
Expand Down Expand Up @@ -1162,6 +1165,7 @@ pub enum SemanticDiagnosticKind {
PanicableExternFunction,
PluginDiagnostic(PluginDiagnostic),
NameDefinedMultipleTimes(SmolStr),
NonPrivateUseStar,
NamedArgumentsAreNotSupported,
ArgPassedToNegativeImpl,
UnnamedArgumentFollowsNamed,
Expand Down Expand Up @@ -1303,6 +1307,25 @@ impl From<&ResolvedConcreteItem> for ElementKind {
}
}
}
impl From<&ResolvedGenericItem> for ElementKind {
fn from(val: &ResolvedGenericItem) -> Self {
match val {
ResolvedGenericItem::GenericConstant(_) => ElementKind::Constant,
ResolvedGenericItem::Module(_) => ElementKind::Module,
ResolvedGenericItem::GenericFunction(_) => ElementKind::Function,
ResolvedGenericItem::TraitFunction(_) => ElementKind::TraitFunction,
ResolvedGenericItem::GenericType(_) | ResolvedGenericItem::GenericTypeAlias(_) => {
ElementKind::Type
}
ResolvedGenericItem::Variant(_) => ElementKind::Variant,
ResolvedGenericItem::Trait(_) => ElementKind::Trait,
ResolvedGenericItem::Impl(_) | ResolvedGenericItem::GenericImplAlias(_) => {
ElementKind::Impl
}
ResolvedGenericItem::Variable(_) => ElementKind::Variable,
}
}
}
impl Display for ElementKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let res = match self {
Expand Down
7 changes: 4 additions & 3 deletions crates/cairo-lang-semantic/src/expr/inference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use std::ops::{Deref, DerefMut};
use cairo_lang_debug::DebugWithDb;
use cairo_lang_defs::ids::{
ConstantId, EnumId, ExternFunctionId, ExternTypeId, FreeFunctionId, GenericParamId,
ImplAliasId, ImplDefId, ImplFunctionId, ImplImplDefId, LanguageElementId, LocalVarId,
LookupItemId, MemberId, ParamId, StructId, TraitConstantId, TraitFunctionId, TraitId,
TraitImplId, TraitTypeId, VarId, VariantId,
GlobalUseId, ImplAliasId, ImplDefId, ImplFunctionId, ImplImplDefId, LanguageElementId,
LocalVarId, LookupItemId, MemberId, ParamId, StructId, TraitConstantId, TraitFunctionId,
TraitId, TraitImplId, TraitTypeId, VarId, VariantId,
};
use cairo_lang_diagnostics::{DiagnosticAdded, Maybe, skip_diagnostic};
use cairo_lang_proc_macros::{DebugWithDb, SemanticObject};
Expand Down Expand Up @@ -86,6 +86,7 @@ pub enum InferenceId {
ImplAliasImplDef(ImplAliasId),
GenericParam(GenericParamId),
GenericImplParamTrait(GenericParamId),
GlobalUseStar(GlobalUseId),
Canonical,
/// For resolving that will not be used anywhere in the semantic model.
NoContext,
Expand Down
51 changes: 51 additions & 0 deletions crates/cairo-lang-semantic/src/expr/semantic_test_data/use
Original file line number Diff line number Diff line change
Expand Up @@ -1022,3 +1022,54 @@ Block(
)

//! > expected_diagnostics

//! > ==========================================================================

//! > Testing use star without implementation in Semantic

//! > test_runner_name
test_expr_semantics(expect_diagnostics: true)

//! > module_code
/// TODO(Tomer-StarkWare): Implement use star in Semantic
pub mod a {
const C: u8 = 2;
}
pub mod b {
use super::a::*;
}

//! > function_body

//! > expr_code
{
let _s = b::C;
}

//! > expected_semantics
Block(
ExprBlock {
statements: [
Let(
StatementLet {
pattern: Variable(
_s,
),
expr: Missing(
ExprMissing {
ty: <missing>,
},
),
},
),
],
tail: None,
ty: (),
},
)

//! > expected_diagnostics
error: Identifier not found.
--> lib.cairo:10:17
let _s = b::C;
^
20 changes: 18 additions & 2 deletions crates/cairo-lang-semantic/src/items/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::sync::Arc;

use cairo_lang_defs::db::DefsGroup;
use cairo_lang_defs::ids::{
LanguageElementId, LookupItemId, ModuleId, ModuleItemId, NamedLanguageElementId, TraitId,
GlobalUseId, LanguageElementId, LookupItemId, ModuleId, ModuleItemId, NamedLanguageElementId,
TraitId,
};
use cairo_lang_diagnostics::{Diagnostics, DiagnosticsBuilder, Maybe};
use cairo_lang_syntax::attribute::structured::{Attribute, AttributeListStructurize};
Expand Down Expand Up @@ -32,6 +33,7 @@ pub struct ModuleItemInfo {
pub struct ModuleSemanticData {
/// The items in the module without duplicates.
pub items: OrderedHashMap<SmolStr, ModuleItemInfo>,
pub global_uses: OrderedHashMap<GlobalUseId, Visibility>,
pub diagnostics: Diagnostics<SemanticDiagnostic>,
}

Expand Down Expand Up @@ -110,7 +112,21 @@ pub fn priv_module_semantic_data(
);
}
}
Ok(Arc::new(ModuleSemanticData { items, diagnostics: diagnostics.build() }))

let global_uses = db
.module_global_uses(module_id)?
.iter()
.map(|(global_use_id, use_path_star)| {
let item = ast::UsePath::Star(use_path_star.clone()).get_item(syntax_db);
let visibility = item.visibility(syntax_db);
// TODO(Tomer-StarkWare): Add implementation for public imports.
if !matches!(visibility, ast::Visibility::Default(_)) {
diagnostics.report(use_path_star, SemanticDiagnosticKind::NonPrivateUseStar);
}
(*global_use_id, Visibility::Private)
})
.collect();
Ok(Arc::new(ModuleSemanticData { items, global_uses, diagnostics: diagnostics.build() }))
}

pub fn module_item_by_name(
Expand Down
Loading