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::result_large_err)]
54 #[allow(clippy::too_many_arguments)]
55 pub fn type_check(
56 handler: &Handler,
57 engines: &Engines,
58 parsed: &ParseProgram,
59 collection_ctx: &mut SymbolCollectionContext,
60 mut namespace: namespace::Namespace,
61 package_name: &str,
62 build_config: Option<&BuildConfig>,
63 experimental: ExperimentalFeatures,
64 ) -> Result<Self, TypeCheckFailed> {
65 let mut ctx =
66 TypeCheckContext::from_root(&mut namespace, collection_ctx, engines, experimental)
67 .with_kind(parsed.kind);
68
69 let ParseProgram { root, kind } = parsed;
70
71 let root = ty::TyModule::type_check(
72 handler,
73 ctx.by_ref(),
74 engines,
75 parsed.kind,
76 root,
77 build_config,
78 )
79 .map_err(|error| TypeCheckFailed {
80 error,
81 root_module: None,
82 namespace: ctx.namespace.current_package_ref().clone(),
83 })?;
84
85 let experimental = ctx.experimental;
86 let (kind, declarations, configurables) =
87 Self::validate_root(handler, engines, &root, *kind, package_name, experimental)
88 .map_err(|error| TypeCheckFailed {
89 error,
90 root_module: Some(root.clone()),
91 namespace: ctx.namespace.current_package_ref().clone(),
92 })?;
93
94 let mut namespace = ctx.namespace().clone();
95 Self::validate_coherence(handler, engines, &root, &mut namespace).map_err(|error| {
96 TypeCheckFailed {
97 error,
98 root_module: Some(root.clone()),
99 namespace: ctx.namespace.current_package_ref().clone(),
100 }
101 })?;
102
103 let program = TyProgram {
104 kind,
105 root_module: (*root).clone(),
106 namespace,
107 declarations,
108 configurables,
109 storage_slots: vec![],
110 logged_types: vec![],
111 messages_types: vec![],
112 };
113
114 Ok(program)
115 }
116
117 pub(crate) fn get_typed_program_with_initialized_storage_slots(
118 &mut self,
119 handler: &Handler,
120 engines: &Engines,
121 context: &mut Context,
122 md_mgr: &mut MetadataManager,
123 module: Module,
124 ) -> Result<(), ErrorEmitted> {
125 let decl_engine = engines.de();
126 match &self.kind {
127 ty::TyProgramKind::Contract { .. } => {
128 let storage_decl = self
129 .declarations
130 .iter()
131 .find(|decl| matches!(decl, ty::TyDecl::StorageDecl { .. }));
132
133 match storage_decl {
135 Some(ty::TyDecl::StorageDecl(ty::StorageDecl { decl_id, .. })) => {
136 let decl = decl_engine.get_storage(decl_id);
137 let mut storage_slots = decl.get_initialized_storage_slots(
138 handler, engines, context, md_mgr, module,
139 )?;
140 storage_slots.sort();
143 self.storage_slots = storage_slots;
144 Ok(())
145 }
146 _ => {
147 self.storage_slots = vec![];
148 Ok(())
149 }
150 }
151 }
152 _ => {
153 self.storage_slots = vec![];
154 Ok(())
155 }
156 }
157 }
158}
159
160impl TypeCheckAnalysis for TyProgram {
161 fn type_check_analyze(
162 &self,
163 handler: &Handler,
164 ctx: &mut TypeCheckAnalysisContext,
165 ) -> Result<(), ErrorEmitted> {
166 for node in self.root_module.all_nodes.iter() {
167 node.type_check_analyze(handler, ctx)?;
168 }
169 Ok(())
170 }
171}
172
173impl TypeCheckFinalization for TyProgram {
174 fn type_check_finalize(
175 &mut self,
176 handler: &Handler,
177 ctx: &mut TypeCheckFinalizationContext,
178 ) -> Result<(), ErrorEmitted> {
179 handler.scope(|handler| {
180 for node in self.root_module.all_nodes.iter_mut() {
181 let _ = node.type_check_finalize(handler, ctx);
182 }
183 Ok(())
184 })
185 }
186}