fn lookup_field(
        &mut self,
        loc: &Loc,
        struct_ty: &Type,
        name: &Name,
    ) -> Option<(QualifiedId<StructId>, FieldId, Type)> {
        // Similar as with Index, we must concretize the type of the expression on which
        // field selection is performed, violating pure type inference rules, so we can actually
        // check and retrieve the field. To avoid this, we would need to introduce the concept
        // of a type constraint to type unification, where the constraint would be
        // 'type var X where X has field F'. This makes unification significant more complex,
        // so lets see how far we get without this.
        let struct_ty = self.subs.specialize(&struct_ty);
        let field_name = self.symbol_pool().make(&name.value);
        if let Type::Struct(mid, sid, targs) = &struct_ty {
            // Lookup the StructEntry in the translator. It must be defined for valid
            // Type::Struct instances.
            let struct_name = self
                .parent
                .parent
                .reverse_struct_table
                .get(&(*mid, *sid))
                .expect("invalid Type::Struct");
            let entry = self
                .parent
                .parent
                .struct_table
                .get(struct_name)
                .expect("invalid Type::Struct");
            // Lookup the field in the struct.
            if let Some(fields) = &entry.fields {
                if let Some((_, field_ty)) = fields.get(&field_name) {
                    // We must instantiate the field type by the provided type args.
                    let field_ty = field_ty.instantiate(targs);
                    Some((
                        entry.module_id.qualified(entry.struct_id),
                        FieldId::new(field_name),
                        field_ty,
                    ))
                } else {
                    self.error(
                        &loc,
                        &format!(
                            "field `{}` not declared in struct `{}`",
                            field_name.display(self.symbol_pool()),
                            struct_name.display(self.symbol_pool())
                        ),
                    );
                    None
                }
            } else {
                self.error(
                    &loc,
                    &format!(
                        "struct `{}` is native and does not support field selection",
                        struct_name.display(self.symbol_pool())
                    ),
                );
                None
            }
        } else {
            self.error(
                &loc,
                &format!(
                    "type `{}` cannot be resolved as a struct",
                    struct_ty.display(&self.type_display_context()),
                ),
            );
            None
        }
    }
/// Loops up a field in a struct. Returns field information or None after reporting errors.
Loops up a field in a struct. Returns field information or None after reporting errors.
Loops up a field in a struct . Returns field information or None after reporting errors .
fn lookup_field(
        &mut self,
        loc: &Loc,
        struct_ty: &Type,
        name: &Name,
    ) -> Option<(QualifiedId<StructId>, FieldId, Type)> {
        // Similar as with Index, we must concretize the type of the expression on which
        // field selection is performed, violating pure type inference rules, so we can actually
        // check and retrieve the field. To avoid this, we would need to introduce the concept
        // of a type constraint to type unification, where the constraint would be
        // 'type var X where X has field F'. This makes unification significant more complex,
        // so lets see how far we get without this.
        let struct_ty = self.subs.specialize(&struct_ty);
        let field_name = self.symbol_pool().make(&name.value);
        if let Type::Struct(mid, sid, targs) = &struct_ty {
            // Lookup the StructEntry in the translator. It must be defined for valid
            // Type::Struct instances.
            let struct_name = self
                .parent
                .parent
                .reverse_struct_table
                .get(&(*mid, *sid))
                .expect("invalid Type::Struct");
            let entry = self
                .parent
                .parent
                .struct_table
                .get(struct_name)
                .expect("invalid Type::Struct");
            // Lookup the field in the struct.
            if let Some(fields) = &entry.fields {
                if let Some((_, field_ty)) = fields.get(&field_name) {
                    // We must instantiate the field type by the provided type args.
                    let field_ty = field_ty.instantiate(targs);
                    Some((
                        entry.module_id.qualified(entry.struct_id),
                        FieldId::new(field_name),
                        field_ty,
                    ))
                } else {
                    self.error(
                        &loc,
                        &format!(
                            "field `{}` not declared in struct `{}`",
                            field_name.display(self.symbol_pool()),
                            struct_name.display(self.symbol_pool())
                        ),
                    );
                    None
                }
            } else {
                self.error(
                    &loc,
                    &format!(
                        "struct `{}` is native and does not support field selection",
                        struct_name.display(self.symbol_pool())
                    ),
                );
                None
            }
        } else {
            self.error(
                &loc,
                &format!(
                    "type `{}` cannot be resolved as a struct",
                    struct_ty.display(&self.type_display_context()),
                ),
            );
            None
        }
    }
fn lookup_field ( & mut self , loc : & Loc , struct_ty : & Type , name : & Name , ) -> Option < ( QualifiedId < StructId > , FieldId , Type ) > { // Similar as with Index, we must concretize the type of the expression on which // field selection is performed, violating pure type inference rules, so we can actually // check and retrieve the field. To avoid this, we would need to introduce the concept // of a type constraint to type unification, where the constraint would be // 'type var X where X has field F'. This makes unification significant more complex, // so lets see how far we get without this. let struct_ty = self . subs . specialize ( & struct_ty ) ; let field_name = self . symbol_pool ( ) . make ( & name . value ) ; if let Type :: Struct ( mid , sid , targs ) = & struct_ty { // Lookup the StructEntry in the translator. It must be defined for valid // Type::Struct instances. let struct_name = self . parent . parent . reverse_struct_table . get ( & ( * mid , * sid ) ) . expect ( " " ) ; let entry = self . parent . parent . struct_table . get ( struct_name ) . expect ( " " ) ; // Lookup the field in the struct. if let Some ( fields ) = & entry . fields { if let Some ( ( _ , field_ty ) ) = fields . get ( & field_name ) { // We must instantiate the field type by the provided type args. let field_ty = field_ty . instantiate ( targs ) ; Some ( ( entry . module_id . qualified ( entry . struct_id ) , FieldId :: new ( field_name ) , field_ty , ) ) } else { self . error ( & loc , & format ! ( " " field_name display ( self symbol_pool ( ) ) struct_name display ( self symbol_pool ( ) ) ) , ) ; None } } else { self . error ( & loc , & format ! ( " " struct_name display ( self symbol_pool ( ) ) ) , ) ; None } } else { self . error ( & loc , & format ! ( " " struct_ty display ( self type_display_context ( ) ) ) , ) ; None } }
Loops up a field in a struct.
Loops up a field in a struct .
&mut self
loc
&Loc
struct_ty
&Type
name
&Name
&mut self
loc
&Loc
struct_ty
&Type
name
&Name