sway_core/type_system/ast_elements/
binding.rs

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/// A `TypeBinding` is the result of using turbofish to bind types to
25/// generic parameters.
26///
27/// For example:
28///
29/// ```ignore
30/// let data = Data::<bool> {
31///   value: true
32/// };
33/// ```
34///
35/// Would produce the type binding (in pseudocode):
36///
37/// ```ignore
38/// TypeBinding {
39///     inner: CallPath(["Data"]),
40///     type_arguments: [bool]
41/// }
42/// ```
43///
44/// ---
45///
46/// Further:
47///
48/// ```ignore
49/// struct Data<T> {
50///   value: T
51/// }
52///
53/// let data1 = Data {
54///   value: true
55/// };
56///
57/// let data2 = Data::<bool> {
58///   value: true
59/// };
60///
61/// let data3: Data<bool> = Data {
62///   value: true
63/// };
64///
65/// let data4: Data<bool> = Data::<bool> {
66///   value: true
67/// };
68/// ```
69///
70/// Each of these 4 examples generates a valid struct expression for `Data`
71/// and passes type checking. But each does so in a unique way:
72/// - `data1` has no type ascription and no type arguments in the `TypeBinding`,
73///   so both are inferred from the value passed to `value`
74/// - `data2` has no type ascription but does have type arguments in the
75///   `TypeBinding`, so the type ascription and type of the value passed to
76///   `value` are both unified to the `TypeBinding`
77/// - `data3` has a type ascription but no type arguments in the `TypeBinding`,
78///   so the type arguments in the `TypeBinding` and the type of the value
79///   passed to `value` are both unified to the type ascription
80/// - `data4` has a type ascription and has type arguments in the `TypeBinding`,
81///   so, with the type from the value passed to `value`, all three are unified
82///   together
83#[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/// A [TypeArgs] contains a `Vec<TypeArgument>` either in the variant `Regular`
91/// or in the variant `Prefix`.
92///
93/// `Regular` variant indicates the type arguments are located after the suffix.
94/// `Prefix` variant indicates the type arguments are located between the last
95/// prefix and the suffix.
96///
97/// In the case of an enum we can have either the type parameters in the `Regular`
98/// variant, case of:
99/// ```ignore
100/// let z = Option::Some::<u32>(10);
101/// ```
102/// Or the enum can have the type parameters in the `Prefix` variant, case of:
103/// ```ignore
104/// let z = Option::<u32>::Some(10);
105/// ```
106/// So we can have type parameters in the `Prefix` or `Regular` variant but not
107/// in both.
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub enum TypeArgs {
110    /// `Regular` variant indicates the type arguments are located after the suffix.
111    Regular(Vec<GenericArgument>),
112    /// `Prefix` variant indicates the type arguments are located between the last
113    /// prefix and the suffix.
114    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        // find the module that the symbol is in
223        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        // create the type info object
228        let type_info = type_info.apply_type_arguments(
229            handler,
230            self.type_arguments.to_vec(),
231            &type_info_span,
232        )?;
233
234        // resolve the type of the type info object
235        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/// Trait that adds a workaround for easy generic returns in Rust:
263/// https://blog.jcoglan.com/2019/04/22/generic-returns-in-rust/
264#[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        // Grab the declaration.
290        let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
291
292        // Check to see if this is a function declaration.
293        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        // Grab the declaration.
317        let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
318        // Check to see if this is a fn declaration.
319        let fn_ref = unknown_decl.to_fn_ref(handler, ctx.engines())?;
320        // Get a new copy from the declaration engine.
321        let mut new_copy = (*decl_engine.get_function(fn_ref.id())).clone();
322
323        match self.type_arguments {
324            // Monomorphize the copy, in place.
325            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                // Resolve the type arguments without monomorphizing.
337                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        // Insert the new copy into the declaration engine.
350        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        // Grab the declaration.
369        let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
370
371        // Check to see if this is a struct declaration.
372        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        // Grab the declaration.
396        let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
397        // Check to see if this is a struct declaration.
398        let struct_id = unknown_decl.to_struct_decl(handler, engines)?;
399        // Get a new copy from the declaration engine.
400        let mut new_copy = (*decl_engine.get_struct(&struct_id)).clone();
401        // Monomorphize the copy, in place.
402        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        // Insert the new copy into the declaration engine.
411        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        // Grab the declaration.
437        let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
438
439        // Get a new copy from the declaration engine.
440        let enum_id = if let ty::TyDecl::EnumVariantDecl(ty::EnumVariantDecl { enum_ref, .. }) =
441            &unknown_decl
442        {
443            *enum_ref.id()
444        } else {
445            // Check to see if this is a enum declaration.
446            unknown_decl.to_enum_id(handler, engines)?
447        };
448
449        let mut new_copy = (*decl_engine.get_enum(&enum_id)).clone();
450
451        // Monomorphize the copy, in place.
452        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        // Insert the new copy into the declaration engine.
461        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        // Grab the declaration.
475        let unknown_decl = ctx.resolve_qualified_call_path(handler, &self.inner)?;
476
477        // Check to see if this is a const declaration.
478        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        // Grab the declaration.
498        let unknown_decl = ctx.resolve_call_path_with_visibility_check(handler, &self.inner)?;
499
500        // Check to see if this is a const declaration.
501        let const_ref = unknown_decl.to_const_ref(handler, ctx.engines())?;
502
503        Ok((const_ref, None, None))
504    }
505}