Table of Contents

2.4.4 Deferred Types

The RD-VBA type system defines a category of deferred data types.

Note

Not implemented. Deferred types are not in use.

Deferred types address late-bound and other cases where MS-VBA would fail to resolve a valid compile-time data type.

Using late binding and duck typing to introduce and surface inherent deferred types to design-time symbols is a valid language core extension. Surfacing deferred types to design-time symbols enables LSP-level enhanced capabilities, notably around auto-completion lists; see RD-VBAL §1.1.2 Language Core Extensions.

A deferred type is a valid RD-VBA data type representing an undefined type. An undefined type is a workspace-defined data type that does not have any associated source code.

A deferred type may statically be one of the following data types:

Unresolved Names

The static-semantics layer consumes ModuleDirectives to decide whether an unresolved simple name is a deferred VBUnknownType or a VBC09302 Variable not defined compile-time error; see RD-VBAL §2.3.1.3 Name Resolution.

RD-VBA defers the actual type guess for an unresolved name to a later type-inference pass (IVBInferableType), rather than deciding it in the simple-name-expression rule; see RD-VBAL §5.6.10 Simple Name Expressions.

Deferred Names

Deferred symbol Name
Deferred type A candidate name. The candidate name can change depending on how the deferred type is being used.
Deferred member The identifier name identifying the member in the workspace source code.
Deferred parameter Arg followed by its 1-based position in the deferred member signature: the first parameter is Arg1, the second is Arg2, and so on.

Deferred members resolve as follows:

  • Any two symbols should be resolved to the same deferred member if the resolved qualifying module is the same for both symbols.
  • Without a qualifier, a deferred symbol is deemed to be an undeclared local variable, as per MS-VBAL scoping rules.
  • If a global-scope deferred symbol with the same identifier name exists, an unqualified deferred symbol (an undeclared local variable) should resolve to the global-scope deferred symbol (RD-VBAL §2.3.1.3 Name Resolution).

Deferred parameters are also defined from named arguments:

  • If a call site supplies a named argument that is not a defined deferred parameter, a deferred parameter with that name is defined at the end of the deferred member signature.
  • Multiple deferred parameters defined from unmatched named arguments are materialized in alphabetical order.
  • A deferred parameter defined from an unmatched named argument is deemed Optional.

Member Ownership

Deferred types cannot implement IVBMemberOwnerType, because the related symbols are unbound.

Deferred types implement IVBInferableType instead of IVBMemberOwnerType. IVBInferableType exposes an immutable hashset of candidate types that would be legal to materialize the deferred type with.

2.4.4.1 VBDeferredModuleType

VBDeferredModuleType represents a deferred VBStdModuleType.

A deferred member is presumed to belong to a deferred module, unless the deferred member is qualified:

Deferred member Owner
Unqualified A deferred module.
Qualified; the resolved module has a bound symbol The resolved module type's IVBMemberOwnerType.DeferredMembers array.
Qualified; the qualifying module symbol is unbound The named deferred module the qualifier denotes.

Only one unnamed deferred module may be semantically (but not statically) defined at any given time in a source project.

2.4.4.2 VBDeferredClassType

VBDeferredClassType represents a deferred VBClassType.

👉 Deferred class types cannot be presumed to have a default instance. A default instance is set by a VB_PredeclaredId module attribute with the value True; see RD-VBAL §3.1.1 Attributes and RD-VBAL §5.2.4 Class Module Declarations.

A deferred class is semantically defined when an unbound member call is made against an object variable of a class type that may or may not be defined in the workspace source code.

The default name of a deferred class is the word Class followed by a number, taken in numerical order until the class name is unique in the workspace: Class1, unless a Class1 module already exists in the workspace, in which case Class2, and so on.

Warning

The names of any deferred type defined in workspace source code must be considered "in use" for all operations involving the naming of a module, including the addition of new (bound) modules to the workspace or project.

2.4.4.3 VBDeferredTypeDesc

VBDeferredTypeDesc represents (describes) a VBDeferredType within the type system.

👉 A value of the VBDeferredTypeDesc meta type, a VBDeferredTypeDescValue, is used in the implementation of the Is relational operator; see RD-VBAL §5.6.9.7 Is Operator. The Is operator uses a deferred type descriptor value because its semantics demand knowledge of a data type where a value is normally required.

Note

Not implemented. None of the other deferred descriptor types are in use.

All deferred descriptor types inherit the corresponding non-deferred descriptor type (RD-VBAL §2.4.3 Meta and Advanced Types). A deferred descriptor type that describes a type explicitly shadows (hides) the static TypeInfo property of the non-deferred descriptor type it inherits.

2.4.4.4 VBDeferredMemberDesc

VBDeferredMemberDesc is a descriptor that represents (describes) any VBDeferredTypeMemberSymbol.

RD-VBAL groups the following descriptors under VBDeferredMemberDesc:

Section Descriptor
§2.4.4.4.1 VBDeferredProcedureMemberDesc
§2.4.4.4.2 VBDeferredPropertyLetProcedureDesc
§2.4.4.4.3 VBDeferredPropertySetProcedureDesc
§2.4.4.4.4 VBDeferredFunctionProcedureDesc
§2.4.4.4.5 VBDeferredPropertyGetProcedureDesc
§2.4.4.4.6 VBDeferredParameterDesc

2.4.4.4.1 VBDeferredProcedureMemberDesc

VBDeferredProcedureMemberDesc is a descriptor that represents (describes) a non-returning deferred procedure member symbol (a VBDeferredTypeMemberSymbol).

2.4.4.4.2 VBDeferredPropertyLetProcedureDesc

VBDeferredPropertyLetProcedureDesc is a descriptor that represents (describes) a deferred Property Let member.

2.4.4.4.3 VBDeferredPropertySetProcedureDesc

VBDeferredPropertySetProcedureDesc is a descriptor that represents (describes) a deferred Property Set member.

2.4.4.4.4 VBDeferredFunctionProcedureDesc

VBDeferredFunctionProcedureDesc is a descriptor that represents (describes) a deferred Function member.

2.4.4.4.5 VBDeferredPropertyGetProcedureDesc

VBDeferredPropertyGetProcedureDesc is a descriptor that represents (describes) a deferred Property Get member.

2.4.4.4.6 VBDeferredParameterDesc

VBDeferredParameterDesc is a descriptor that represents (describes) a single parameter of a deferred member.

👉 Deferred parameters are inferred from the arguments provided at the call sites of deferred members.

The data type of a deferred parameter depends on how many call sites supply an argument for the parameter. It also depends on the data types of the arguments supplied for it at the call sites:

Call-site arguments Deferred parameter data type Parameter
Only VBBooleanValue arguments VBBooleanType ByVal
Only VBObjectValue arguments VBObjectType ByVal
Only VBObjectValue arguments whose class type is resolvable (whether deferred or not) That specific class type ByVal
Any number of VBStringType (string) arguments VBStringType ByVal
Any number of VBEnumType (enum) arguments VBIntegerType ByVal
Any number of IIntegralNumericType arguments The largest of the candidate types ByVal
Any number of IFixedPointNumericType arguments VBCurrencyType ByVal
Any number of IFloatingPointNumericType arguments VBDoubleType ByVal
A specific VBUserDefinedTypeValue The data type of the specified UDT ByRef
Any number of VBArrayValue arguments Variant ByRef
Mixed-bag (heterogeneous) arguments Variant ByRef

A deferred ByVal parameter is passed by value. A deferred ByRef parameter must be passed by reference.

Note

A deferred parameter inferred as Variant (from array or heterogeneous arguments) may not be materializable.

A deferred parameter inferred as Variant should issue semantic flags as appropriate, to signal the case to any listening language-level extensions; see RD-VBAL §1.1.3 Core Semantic Flags.


⏮️ RD-VBAL §2.4.3 Meta and Advanced Types | ⏭️ RD-VBAL §2.5 Runtime Values