1use std::collections::BTreeMap;
2
3use crate::{
4 decl_engine::{
5 parsed_id::ParsedDeclId, DeclEngineGetParsedDeclId, DeclEngineInsert, DeclId, DeclRef,
6 },
7 engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext},
8 language::{
9 parsed::{FunctionDeclaration, StructDeclaration},
10 ty, CallPath, QualifiedCallPath,
11 },
12 semantic_analysis::{
13 symbol_resolve::ResolveSymbols, symbol_resolve_context::SymbolResolveContext,
14 TypeCheckContext,
15 },
16 type_system::priv_prelude::*,
17 EnforceTypeArguments, Ident,
18};
19use serde::{Deserialize, Serialize};
20use sway_ast::Intrinsic;
21use sway_error::handler::{ErrorEmitted, Handler};
22use sway_types::{Span, Spanned};
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct TypeBinding<T> {
85 pub inner: T,
86 pub type_arguments: TypeArgs,
87 pub span: Span,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
109pub enum TypeArgs {
110 Regular(Vec<GenericArgument>),
112 Prefix(Vec<GenericArgument>),
115}
116
117impl TypeArgs {
118 pub fn to_vec(&self) -> Vec<GenericArgument> {
119 match self {
120 TypeArgs::Regular(vec) => vec.to_vec(),
121 TypeArgs::Prefix(vec) => vec.to_vec(),
122 }
123 }
124
125 pub fn as_slice(&self) -> &[GenericArgument] {
126 match self {
127 TypeArgs::Regular(vec) | TypeArgs::Prefix(vec) => vec,
128 }
129 }
130
131 pub(crate) fn to_vec_mut(&mut self) -> &mut Vec<GenericArgument> {
132 match self {
133 TypeArgs::Regular(vec) => vec,
134 TypeArgs::Prefix(vec) => vec,
135 }
136 }
137}
138
139impl Spanned for TypeArgs {
140 fn span(&self) -> Span {
141 Span::join_all(self.to_vec().iter().map(sway_types::Spanned::span))
142 }
143}
144
145impl PartialEqWithEngines for TypeArgs {
146 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
147 match (self, other) {
148 (TypeArgs::Regular(vec1), TypeArgs::Regular(vec2)) => vec1.eq(vec2, ctx),
149 (TypeArgs::Prefix(vec1), TypeArgs::Prefix(vec2)) => vec1.eq(vec2, ctx),
150 _ => false,
151 }
152 }
153}
154
155impl<T> Spanned for TypeBinding<T> {
156 fn span(&self) -> Span {
157 self.span.clone()
158 }
159}
160
161impl PartialEqWithEngines for TypeBinding<Ident> {
162 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
163 self.inner == other.inner
164 && self.span == other.span
165 && self.type_arguments.eq(&other.type_arguments, ctx)
166 }
167}
168
169impl PartialEqWithEngines for TypeBinding<Intrinsic> {
170 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
171 self.inner == other.inner
172 && self.span == other.span
173 && self.type_arguments.eq(&other.type_arguments, ctx)
174 }
175}
176
177impl<T> EqWithEngines for TypeBinding<T> where T: EqWithEngines {}
178impl<T> PartialEqWithEngines for TypeBinding<T>
179where
180 T: PartialEqWithEngines,
181{
182 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
183 self.inner.eq(&other.inner, ctx)
184 && self.span == other.span
185 && self.type_arguments.eq(&other.type_arguments, ctx)
186 }
187}
188
189impl<T> TypeBinding<T> {
190 pub fn strip_inner(self) -> TypeBinding<()> {
191 TypeBinding {
192 inner: (),
193 type_arguments: self.type_arguments,
194 span: self.span,
195 }
196 }
197
198 pub(crate) fn resolve_symbols(&mut self, handler: &Handler, mut ctx: SymbolResolveContext<'_>) {
199 match self.type_arguments {
200 TypeArgs::Regular(ref mut args) => args
201 .iter_mut()
202 .for_each(|arg| arg.resolve_symbols(handler, ctx.by_ref())),
203 TypeArgs::Prefix(ref mut args) => args
204 .iter_mut()
205 .for_each(|arg| arg.resolve_symbols(handler, ctx.by_ref())),
206 }
207 }
208}
209
210impl TypeBinding<CallPath<(TypeInfo, Ident)>> {
211 pub(crate) fn type_check_with_type_info(
212 &self,
213 handler: &Handler,
214 ctx: &mut TypeCheckContext,
215 ) -> Result<TypeId, ErrorEmitted> {
216 let type_engine = ctx.engines.te();
217 let engines = ctx.engines();
218
219 let (type_info, type_ident) = self.inner.suffix.clone();
220 let type_info_span = type_ident.span();
221
222 let full_path = self.inner.to_fullpath(engines, ctx.namespace());
224 ctx.namespace()
225 .require_module_from_absolute_path(handler, &full_path.prefixes)?;
226
227 let type_info = type_info.apply_type_arguments(
229 handler,
230 self.type_arguments.to_vec(),
231 &type_info_span,
232 )?;
233
234 let type_id = ctx
236 .resolve_type(
237 handler,
238 type_engine.insert(engines, type_info, type_info_span.source_id()),
239 &type_info_span,
240 EnforceTypeArguments::No,
241 Some(&full_path.prefixes),
242 )
243 .unwrap_or_else(|err| type_engine.id_of_error_recovery(err));
244
245 Ok(type_id)
246 }
247}
248
249impl EqWithEngines for (TypeInfo, Ident) {}
250impl PartialEqWithEngines for (TypeInfo, Ident) {
251 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
252 self.0.eq(&other.0, ctx) && self.1 == other.1
253 }
254}
255
256impl TypeBinding<CallPath> {
257 pub(crate) fn strip_prefixes(&mut self) {
258 self.inner.prefixes = vec![];
259 }
260}
261
262#[allow(clippy::type_complexity)]
265pub(crate) trait TypeCheckTypeBinding<T> {
266 fn type_check(
267 &mut self,
268 handler: &Handler,
269 ctx: TypeCheckContext,
270 ) -> Result<(DeclRef<DeclId<T>>, Option<TypeId>, Option<ty::TyDecl>), ErrorEmitted>;
271}
272
273#[allow(clippy::type_complexity)]
274pub trait SymbolResolveTypeBinding<T> {
275 fn resolve_symbol(
276 &mut self,
277 handler: &Handler,
278 ctx: SymbolResolveContext,
279 ) -> Result<ParsedDeclId<T>, ErrorEmitted>;
280}
281
282impl SymbolResolveTypeBinding<FunctionDeclaration> for TypeBinding<CallPath> {
283 fn resolve_symbol(
284 &mut self,
285 handler: &Handler,
286 ctx: SymbolResolveContext,
287 ) -> Result<ParsedDeclId<FunctionDeclaration>, ErrorEmitted> {
288 let engines = ctx.engines();
289 let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
291
292 let fn_decl = unknown_decl
294 .resolve_parsed(engines.de())
295 .to_fn_ref(handler, engines)?;
296 Ok(fn_decl)
297 }
298}
299
300impl TypeCheckTypeBinding<ty::TyFunctionDecl> for TypeBinding<CallPath> {
301 fn type_check(
302 &mut self,
303 handler: &Handler,
304 mut ctx: TypeCheckContext,
305 ) -> Result<
306 (
307 DeclRef<DeclId<ty::TyFunctionDecl>>,
308 Option<TypeId>,
309 Option<ty::TyDecl>,
310 ),
311 ErrorEmitted,
312 > {
313 let type_engine = ctx.engines.te();
314 let decl_engine = ctx.engines.de();
315
316 let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
318 let fn_ref = unknown_decl.to_fn_ref(handler, ctx.engines())?;
320 let mut new_copy = (*decl_engine.get_function(fn_ref.id())).clone();
322
323 match self.type_arguments {
324 TypeArgs::Regular(_) => {
326 ctx.monomorphize(
327 handler,
328 &mut new_copy,
329 self.type_arguments.to_vec_mut(),
330 BTreeMap::new(),
331 EnforceTypeArguments::No,
332 &self.span,
333 )?;
334 }
335 TypeArgs::Prefix(_) => {
336 for type_argument in self.type_arguments.to_vec_mut().iter_mut() {
338 ctx.resolve_type(
339 handler,
340 type_argument.type_id(),
341 &type_argument.span(),
342 EnforceTypeArguments::Yes,
343 None,
344 )
345 .unwrap_or_else(|err| type_engine.id_of_error_recovery(err));
346 }
347 }
348 }
349 let new_fn_ref = decl_engine
351 .insert(
352 new_copy,
353 decl_engine.get_parsed_decl_id(fn_ref.id()).as_ref(),
354 )
355 .with_parent(ctx.engines.de(), fn_ref.id().into());
356
357 Ok((new_fn_ref, None, None))
358 }
359}
360
361impl SymbolResolveTypeBinding<StructDeclaration> for TypeBinding<CallPath> {
362 fn resolve_symbol(
363 &mut self,
364 handler: &Handler,
365 ctx: SymbolResolveContext,
366 ) -> Result<ParsedDeclId<StructDeclaration>, ErrorEmitted> {
367 let engines = ctx.engines();
368 let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
370
371 let struct_decl = unknown_decl.to_struct_decl(handler, engines)?;
373 struct_decl
374 .resolve_parsed(engines.de())
375 .to_struct_decl(handler, engines)
376 }
377}
378
379impl TypeCheckTypeBinding<ty::TyStructDecl> for TypeBinding<CallPath> {
380 fn type_check(
381 &mut self,
382 handler: &Handler,
383 mut ctx: TypeCheckContext,
384 ) -> Result<
385 (
386 DeclRef<DeclId<ty::TyStructDecl>>,
387 Option<TypeId>,
388 Option<ty::TyDecl>,
389 ),
390 ErrorEmitted,
391 > {
392 let type_engine = ctx.engines.te();
393 let decl_engine = ctx.engines.de();
394 let engines = ctx.engines();
395 let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
397 let struct_id = unknown_decl.to_struct_decl(handler, engines)?;
399 let mut new_copy = (*decl_engine.get_struct(&struct_id)).clone();
401 ctx.monomorphize(
403 handler,
404 &mut new_copy,
405 self.type_arguments.to_vec_mut(),
406 BTreeMap::new(),
407 EnforceTypeArguments::No,
408 &self.span,
409 )?;
410 let new_struct_ref = decl_engine.insert(
412 new_copy,
413 decl_engine.get_parsed_decl_id(&struct_id).as_ref(),
414 );
415 let type_id = type_engine.insert_struct(engines, *new_struct_ref.id());
416 Ok((new_struct_ref, Some(type_id), None))
417 }
418}
419
420impl TypeCheckTypeBinding<ty::TyEnumDecl> for TypeBinding<CallPath> {
421 fn type_check(
422 &mut self,
423 handler: &Handler,
424 mut ctx: TypeCheckContext,
425 ) -> Result<
426 (
427 DeclRef<DeclId<ty::TyEnumDecl>>,
428 Option<TypeId>,
429 Option<ty::TyDecl>,
430 ),
431 ErrorEmitted,
432 > {
433 let type_engine = ctx.engines.te();
434 let decl_engine = ctx.engines.de();
435 let engines = ctx.engines();
436 let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
438
439 let enum_id = if let ty::TyDecl::EnumVariantDecl(ty::EnumVariantDecl { enum_ref, .. }) =
441 &unknown_decl
442 {
443 *enum_ref.id()
444 } else {
445 unknown_decl.to_enum_id(handler, engines)?
447 };
448
449 let mut new_copy = (*decl_engine.get_enum(&enum_id)).clone();
450
451 ctx.monomorphize(
453 handler,
454 &mut new_copy,
455 self.type_arguments.to_vec_mut(),
456 BTreeMap::new(),
457 EnforceTypeArguments::No,
458 &self.span,
459 )?;
460 let new_enum_ref =
462 decl_engine.insert(new_copy, decl_engine.get_parsed_decl_id(&enum_id).as_ref());
463 let type_id = type_engine.insert_enum(engines, *new_enum_ref.id());
464 Ok((new_enum_ref, Some(type_id), Some(unknown_decl)))
465 }
466}
467
468impl TypeBinding<QualifiedCallPath> {
469 pub(crate) fn type_check_qualified(
470 &mut self,
471 handler: &Handler,
472 ctx: &mut TypeCheckContext,
473 ) -> Result<DeclRef<DeclId<ty::TyConstantDecl>>, ErrorEmitted> {
474 let unknown_decl = ctx.resolve_qualified_call_path(handler, &self.inner)?;
476
477 let const_ref = unknown_decl.to_const_ref(handler, ctx.engines())?;
479
480 Ok(const_ref)
481 }
482}
483
484impl TypeCheckTypeBinding<ty::TyConstantDecl> for TypeBinding<CallPath> {
485 fn type_check(
486 &mut self,
487 handler: &Handler,
488 ctx: TypeCheckContext,
489 ) -> Result<
490 (
491 DeclRef<DeclId<ty::TyConstantDecl>>,
492 Option<TypeId>,
493 Option<ty::TyDecl>,
494 ),
495 ErrorEmitted,
496 > {
497 let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
499
500 let const_ref = unknown_decl.to_const_ref(handler, ctx.engines())?;
502
503 Ok((const_ref, None, None))
504 }
505}