sway_core/semantic_analysis/
program.rs1use std::sync::Arc;
2
3use crate::{
4 language::{
5 parsed::ParseProgram,
6 ty::{self, TyModule, TyProgram},
7 },
8 metadata::MetadataManager,
9 semantic_analysis::{
10 namespace::{self, Package},
11 TypeCheckContext,
12 },
13 BuildConfig, Engines,
14};
15use sway_error::handler::{ErrorEmitted, Handler};
16use sway_features::ExperimentalFeatures;
17use sway_ir::{Context, Module};
18
19use super::{
20 symbol_collection_context::SymbolCollectionContext, TypeCheckAnalysis,
21 TypeCheckAnalysisContext, TypeCheckFinalization, TypeCheckFinalizationContext,
22};
23
24#[derive(Clone, Debug)]
25pub struct TypeCheckFailed {
26 pub root_module: Option<Arc<TyModule>>,
27 pub namespace: Package,
28 pub error: ErrorEmitted,
29}
30
31impl TyProgram {
32 pub fn collect(
37 handler: &Handler,
38 engines: &Engines,
39 parsed: &ParseProgram,
40 namespace: namespace::Namespace,
41 ) -> Result<SymbolCollectionContext, ErrorEmitted> {
42 let mut ctx = SymbolCollectionContext::new(namespace);
43 let ParseProgram { root, kind: _ } = parsed;
44
45 ty::TyModule::collect(handler, engines, &mut ctx, root)?;
46 Ok(ctx)
47 }
48
49 #[allow(clippy::too_many_arguments)]
54 pub fn type_check(
55 handler: &Handler,
56 engines: &Engines,
57 parsed: &ParseProgram,
58 collection_ctx: &mut SymbolCollectionContext,
59 mut namespace: namespace::Namespace,
60 package_name: &str,
61 build_config: Option<&BuildConfig>,
62 experimental: ExperimentalFeatures,
63 ) -> Result<Self, TypeCheckFailed> {
64 let mut ctx =
65 TypeCheckContext::from_root(&mut namespace, collection_ctx, engines, experimental)
66 .with_kind(parsed.kind);
67
68 let ParseProgram { root, kind } = parsed;
69
70 let root = ty::TyModule::type_check(
71 handler,
72 ctx.by_ref(),
73 engines,
74 parsed.kind,
75 root,
76 build_config,
77 )
78 .map_err(|error| TypeCheckFailed {
79 error,
80 root_module: None,
81 namespace: ctx.namespace.current_package_ref().clone(),
82 })?;
83
84 let experimental = ctx.experimental;
85 let (kind, declarations, configurables) =
86 Self::validate_root(handler, engines, &root, *kind, package_name, experimental)
87 .map_err(|error| TypeCheckFailed {
88 error,
89 root_module: Some(root.clone()),
90 namespace: ctx.namespace.current_package_ref().clone(),
91 })?;
92
93 let mut namespace = ctx.namespace().clone();
94 Self::validate_coherence(handler, engines, &root, &mut namespace).map_err(|error| {
95 TypeCheckFailed {
96 error,
97 root_module: Some(root.clone()),
98 namespace: ctx.namespace.current_package_ref().clone(),
99 }
100 })?;
101
102 let program = TyProgram {
103 kind,
104 root_module: (*root).clone(),
105 namespace,
106 declarations,
107 configurables,
108 storage_slots: vec![],
109 logged_types: vec![],
110 messages_types: vec![],
111 };
112
113 Ok(program)
114 }
115
116 pub(crate) fn get_typed_program_with_initialized_storage_slots(
117 &mut self,
118 handler: &Handler,
119 engines: &Engines,
120 context: &mut Context,
121 md_mgr: &mut MetadataManager,
122 module: Module,
123 ) -> Result<(), ErrorEmitted> {
124 let decl_engine = engines.de();
125 match &self.kind {
126 ty::TyProgramKind::Contract { .. } => {
127 let storage_decl = self
128 .declarations
129 .iter()
130 .find(|decl| matches!(decl, ty::TyDecl::StorageDecl { .. }));
131
132 match storage_decl {
134 Some(ty::TyDecl::StorageDecl(ty::StorageDecl { decl_id, .. })) => {
135 let decl = decl_engine.get_storage(decl_id);
136 let mut storage_slots = decl.get_initialized_storage_slots(
137 handler, engines, context, md_mgr, module,
138 )?;
139 storage_slots.sort();
142 self.storage_slots = storage_slots;
143 Ok(())
144 }
145 _ => {
146 self.storage_slots = vec![];
147 Ok(())
148 }
149 }
150 }
151 _ => {
152 self.storage_slots = vec![];
153 Ok(())
154 }
155 }
156 }
157}
158
159impl TypeCheckAnalysis for TyProgram {
160 fn type_check_analyze(
161 &self,
162 handler: &Handler,
163 ctx: &mut TypeCheckAnalysisContext,
164 ) -> Result<(), ErrorEmitted> {
165 for node in self.root_module.all_nodes.iter() {
166 node.type_check_analyze(handler, ctx)?;
167 }
168 Ok(())
169 }
170}
171
172impl TypeCheckFinalization for TyProgram {
173 fn type_check_finalize(
174 &mut self,
175 handler: &Handler,
176 ctx: &mut TypeCheckFinalizationContext,
177 ) -> Result<(), ErrorEmitted> {
178 handler.scope(|handler| {
179 for node in self.root_module.all_nodes.iter_mut() {
180 let _ = node.type_check_finalize(handler, ctx);
181 }
182 Ok(())
183 })
184 }
185}