sway_core/semantic_analysis/ast_node/
mod.rs1pub mod code_block;
2pub mod declaration;
3pub mod expression;
4pub mod modes;
5
6pub(crate) use expression::*;
7pub(crate) use modes::*;
8
9use crate::{
10 language::{parsed::*, ty},
11 semantic_analysis::*,
12 type_system::*,
13 Engines, Ident,
14};
15
16use sway_error::{
17 handler::{ErrorEmitted, Handler},
18 warning::{CompileWarning, Warning},
19};
20use sway_types::{span::Span, Spanned};
21
22use super::symbol_collection_context::SymbolCollectionContext;
23
24impl ty::TyAstNode {
25 pub(crate) fn collect(
26 handler: &Handler,
27 engines: &Engines,
28 ctx: &mut SymbolCollectionContext,
29 node: &AstNode,
30 ) -> Result<(), ErrorEmitted> {
31 match node.content.clone() {
32 AstNodeContent::UseStatement(stmt) => {
33 collect_use_statement(handler, engines, ctx, &stmt);
34 }
35 AstNodeContent::IncludeStatement(_i) => (),
36 AstNodeContent::Declaration(decl) => ty::TyDecl::collect(handler, engines, ctx, decl)?,
37 AstNodeContent::Expression(expr) => {
38 ty::TyExpression::collect(handler, engines, ctx, &expr)?
39 }
40 AstNodeContent::Error(_spans, _err) => (),
41 };
42
43 Ok(())
44 }
45
46 pub(crate) fn type_check(
47 handler: &Handler,
48 mut ctx: TypeCheckContext,
49 node: &AstNode,
50 ) -> Result<Self, ErrorEmitted> {
51 let type_engine = ctx.engines.te();
52 let decl_engine = ctx.engines.de();
53 let engines = ctx.engines();
54
55 let node = ty::TyAstNode {
56 content: match node.content.clone() {
57 AstNodeContent::UseStatement(stmt) => {
58 handle_use_statement(&mut ctx, &stmt, handler);
59 ty::TyAstNodeContent::SideEffect(ty::TySideEffect {
60 side_effect: ty::TySideEffectVariant::UseStatement(ty::TyUseStatement {
61 alias: stmt.alias,
62 call_path: stmt.call_path,
63 span: stmt.span,
64 is_relative_to_package_root: stmt.is_relative_to_package_root,
65 import_type: stmt.import_type,
66 }),
67 })
68 }
69 AstNodeContent::IncludeStatement(i) => {
70 ty::TyAstNodeContent::SideEffect(ty::TySideEffect {
71 side_effect: ty::TySideEffectVariant::IncludeStatement(
72 ty::TyIncludeStatement {
73 mod_name: i.mod_name,
74 span: i.span,
75 visibility: i.visibility,
76 },
77 ),
78 })
79 }
80 AstNodeContent::Declaration(decl) => ty::TyAstNodeContent::Declaration(
81 ty::TyDecl::type_check(handler, &mut ctx, decl)?,
82 ),
83 AstNodeContent::Expression(expr) => {
84 let mut ctx = ctx;
85 match expr.kind {
86 ExpressionKind::ImplicitReturn(_) => {
87 }
91 _ => {
92 ctx = ctx
93 .with_help_text("")
94 .with_type_annotation(type_engine.new_unknown());
95 }
96 }
97 let inner = ty::TyExpression::type_check(handler, ctx, &expr)
98 .unwrap_or_else(|err| ty::TyExpression::error(err, expr.span(), engines));
99 ty::TyAstNodeContent::Expression(inner)
100 }
101 AstNodeContent::Error(spans, err) => ty::TyAstNodeContent::Error(spans, err),
102 },
103 span: node.span.clone(),
104 };
105
106 if let ty::TyAstNode {
107 content: ty::TyAstNodeContent::Expression(ty::TyExpression { expression, .. }),
108 ..
109 } = &node
110 {
111 match expression {
112 ty::TyExpressionVariant::ImplicitReturn(_) => {}
113 _ => {
114 if !node
115 .type_info(type_engine)
116 .can_safely_ignore(type_engine, decl_engine)
117 {
118 handler.emit_warn(CompileWarning {
119 warning_content: Warning::UnusedReturnValue {
120 r#type: engines.help_out(node.type_info(type_engine)).to_string(),
121 },
122 span: node.span.clone(),
123 })
124 };
125 }
126 }
127 }
128
129 Ok(node)
130 }
131}
132
133fn collect_use_statement(
134 handler: &Handler,
135 engines: &Engines,
136 ctx: &mut SymbolCollectionContext,
137 stmt: &UseStatement,
138) {
139 let path = ctx.namespace.parsed_path_to_full_path(
140 engines,
141 &stmt.call_path,
142 stmt.is_relative_to_package_root,
143 );
144
145 let _ = match stmt.import_type {
146 ImportType::Star => {
147 let star_import_handler = Handler::default();
149 let import = ctx.star_import(&star_import_handler, engines, &path, stmt.reexport);
150 if import.is_ok() {
151 handler.append(star_import_handler);
152 import
153 } else if path.len() >= 2 {
154 if let Some((enum_name, path)) = path.split_last() {
156 let variant_import_handler = Handler::default();
157 let variant_import = ctx.variant_star_import(
158 &variant_import_handler,
159 engines,
160 path,
161 enum_name,
162 stmt.reexport,
163 );
164 if variant_import.is_ok() {
165 handler.append(variant_import_handler);
166 variant_import
167 } else {
168 handler.append(star_import_handler);
169 import
170 }
171 } else {
172 handler.append(star_import_handler);
173 import
174 }
175 } else {
176 handler.append(star_import_handler);
177 import
178 }
179 }
180 ImportType::SelfImport(_) => {
181 ctx.self_import(handler, engines, &path, stmt.alias.clone(), stmt.reexport)
182 }
183 ImportType::Item(ref s) => {
184 let item_import_handler = Handler::default();
186 let import = ctx.item_import(
187 &item_import_handler,
188 engines,
189 &path,
190 s,
191 stmt.alias.clone(),
192 stmt.reexport,
193 );
194
195 if import.is_ok() {
196 handler.append(item_import_handler);
197 import
198 } else if path.len() >= 2 {
199 if let Some((enum_name, path)) = path.split_last() {
202 let variant_import_handler = Handler::default();
203 let variant_import = ctx.variant_import(
204 &variant_import_handler,
205 engines,
206 path,
207 enum_name,
208 s,
209 stmt.alias.clone(),
210 stmt.reexport,
211 );
212
213 if variant_import.is_ok() {
214 handler.append(variant_import_handler);
215 variant_import
216 } else {
217 handler.append(item_import_handler);
218 import
219 }
220 } else {
221 handler.append(item_import_handler);
222 import
223 }
224 } else {
225 handler.append(item_import_handler);
226 import
227 }
228 }
229 };
230}
231
232fn handle_use_statement(ctx: &mut TypeCheckContext<'_>, stmt: &UseStatement, handler: &Handler) {
234 let path = ctx.namespace.parsed_path_to_full_path(
235 ctx.engines,
236 &stmt.call_path,
237 stmt.is_relative_to_package_root,
238 );
239 let _ = match stmt.import_type {
240 ImportType::Star => {
241 let star_import_handler = Handler::default();
243 let import = ctx.star_import(&star_import_handler, &path, stmt.reexport);
244 if import.is_ok() {
245 handler.append(star_import_handler);
246 import
247 } else if path.len() >= 2 {
248 if let Some((enum_name, path)) = path.split_last() {
250 let variant_import_handler = Handler::default();
251 let variant_import = ctx.variant_star_import(
252 &variant_import_handler,
253 path,
254 enum_name,
255 stmt.reexport,
256 );
257 if variant_import.is_ok() {
258 handler.append(variant_import_handler);
259 variant_import
260 } else {
261 handler.append(star_import_handler);
262 import
263 }
264 } else {
265 handler.append(star_import_handler);
266 import
267 }
268 } else {
269 handler.append(star_import_handler);
270 import
271 }
272 }
273 ImportType::SelfImport(_) => {
274 ctx.self_import(handler, &path, stmt.alias.clone(), stmt.reexport)
275 }
276 ImportType::Item(ref s) => {
277 let item_import_handler = Handler::default();
279 let import = ctx.item_import(
280 &item_import_handler,
281 &path,
282 s,
283 stmt.alias.clone(),
284 stmt.reexport,
285 );
286
287 if import.is_ok() {
288 handler.append(item_import_handler);
289 import
290 } else if path.len() >= 2 {
291 if let Some((enum_name, path)) = path.split_last() {
294 let variant_import_handler = Handler::default();
295 let variant_import = ctx.variant_import(
296 &variant_import_handler,
297 path,
298 enum_name,
299 s,
300 stmt.alias.clone(),
301 stmt.reexport,
302 );
303 if variant_import.is_ok() {
304 handler.append(variant_import_handler);
305 variant_import
306 } else {
307 handler.append(item_import_handler);
308 import
309 }
310 } else {
311 handler.append(item_import_handler);
312 import
313 }
314 } else {
315 handler.append(item_import_handler);
316 import
317 }
318 }
319 };
320}