This section contains definitions declared in the chpl::resolution namespace.

namespace chpl::resolution


using SubstitutionsMap = std::unordered_map<const uast::Decl*, types::QualifiedType>
using DeclMap = std::unordered_map<UniqueString, OwnedIdsWithName>
using LookupConfig = unsigned int


enum [anonymous]


enumerator LOOKUP_DECLS


static inline CanPassResult canPass(const types::QualifiedType &actualType, const types::QualifiedType &formalType)

Given an argument with QualifiedType actualType, can that argument be passed to a formal with QualifiedType formalType?

const ResolutionResultByPostorderID &resolveModule(Context *context, ID id)

Resolve the contents of a Module

const types::QualifiedType &typeForModuleLevelSymbol(Context *context, ID id)

Compute the type for a NamedDecl with a particular id.

const types::QualifiedType &typeForBuiltin(Context *context, UniqueString name)

Compute the type for a Builtin type using just its name

const TypedFnSignature *typedSignatureInitial(Context *context, const UntypedFnSignature *untypedSig)

Compute a TypedFnSignature from an UntypedFnSignature. The TypedFnSignature will represent generic and potentially unknown types if the function is generic.

const types::Type *typeForTypeDecl(Context *context, const uast::TypeDecl *d, bool useGenericFormalDefaults)

Returns a Type that represents the initial type provided by a TypeDecl (e.g. Class, Record, etc). This can have unknown or generic fields. The useGenericFormalDefaults argument indicates if the type should be non-generic if all generic fields have default values. This is the case in many uses of a type name but not the case when calling a type constructor or when inheriting.

const TypedFnSignature *typeConstructorInitial(Context *context, const types::Type *t)

Compute an initial TypedFnSignature for a type constructor for a particular type. If some fields of t are still generic, it will be necessary to call instantiateSignature on it.

const TypedFnSignature *instantiateSignature(Context *context, const TypedFnSignature *sig, const CallInfo &call, const PoiScope *poiScope)

Instantiate a TypedFnSignature from the result of typedSignatureInitial, a CallInfo describing the types at the call site, and a point-of-instantiation scope representing the POI scope of the call

Returns nullptr if the instantiation failed.

const ResolvedFunction *resolveFunction(Context *context, const TypedFnSignature *sig, const PoiScope *poiScope)

Compute a ResolvedFunction given a TypedFnSignature. Checks the generic cache for potential for reuse. When reuse occurs, the ResolvedFunction might point to a different TypedFnSignature.

const ResolvedFunction *resolveConcreteFunction(Context *context, ID id)

Resolves a concrete function using the above queries.

const ResolvedFunction *resolveOnlyCandidate(Context *context, const ResolvedExpression &r)

Returns the ResolvedFunction called by a particular ResolvedExpression, if there was exactly one candidate. Otherwise, it returns nullptr.

This function does not handle return intent overloading.

const types::QualifiedType &returnType(Context *context, const TypedFnSignature *sig, const PoiScope *poiScope)

Compute the return/yield type for a function.

const std::vector<const TypedFnSignature*> &filterCandidatesInitial(Context *context, std::vector<BorrowedIdsWithName> lst, CallInfo call)

Compute the (potentially generic) TypedFnSignatures of possibly applicable candidate functions from a list of visible functions.

void filterCandidatesInstantiating(Context *context, const std::vector<const TypedFnSignature*> &lst, const CallInfo &call, const Scope *inScope, const PoiScope *inPoiScope, std::vector<const TypedFnSignature*> &result)

Further filter the result of filterCandidatesInitial down by doing instantiations. After this, all of the resulting TypedFnSignatures are actually candidates.

If instantiation occurs, gets/creates the new POI scope for inScope/inPoiScope.

const MostSpecificCandidates &findMostSpecificCandidates(Context *context, std::vector<const TypedFnSignature*> lst, CallInfo call)

Given the result of filterCandidatesInstantiating, run overload resolution aka disambiguation to determine the most specific functions.

CallResolutionResult resolveCall(Context *context, const uast::Call *call, const CallInfo &ci, const Scope *inScope, const PoiScope *inPoiScope)

Given a CallInfo representing a call, a Scope representing the scope of that call, and a PoiScope representing the point-of-instantiation scope of that call, find the most specific candidates as well as the point-of-instantiation scopes that were used when resolving them.

bool createsScope(uast::ASTTag tag)

Returns true if this AST type can create a scope.

const Scope *scopeForId(Context *context, ID id)

Returns the Scope for an ID.

const Scope *scopeForModule(Context *context, ID moduleId)

Given an ID for a Module, returns a Scope that represents the Module scope (and what symbols are defined in it).

const ResolvedVisibilityScope *resolveVisibilityStmts(Context *context, const Scope *scope)

Given a Scope, compute the ResolvedVisibilityScope by processing the use/import statements in order.

If the scope didn’t have use/imports, returns nullptr.

std::vector<BorrowedIdsWithName> lookupInScope(Context *context, const Scope *scope, const uast::Expression *expr, LookupConfig config)

Given an Expression and a Scope, return the things that Expression might refer to.

The config argument is a group of or-ed together bit flags that adjusts the behavior of the lookup:

If LOOKUP_DECLS is set, looks for symbols declared in this Scope. If LOOKUP_IMPORT_AND_USE is set, looks for symbols from use/import statements in this Scope. If LOOKUP_PARENTS is set, looks for symbols from parent scopes (but not parent modules of a module) including looking for declarations and handling imports, and including finding declarations in the root module. If LOOKUP_TOPLEVEL is set, checks for a toplevel module with this name. If LOOKUP_INNERMOST is true, limits search to the innermost scope with a match.

std::vector<BorrowedIdsWithName> lookupNameInScope(Context *context, const Scope *scope, UniqueString name, LookupConfig config)

Same as lookupInScope above but uses a name instead of an Expression.

std::vector<BorrowedIdsWithName> lookupInScopeWithSet(Context *context, const Scope *scope, const uast::Expression *expr, LookupConfig config, std::unordered_set<const Scope*> &visited)

Same as lookupInScope but includes a set tracking visited scopes.

std::vector<BorrowedIdsWithName> lookupNameInScopeWithSet(Context *context, const Scope *scope, UniqueString name, LookupConfig config, std::unordered_set<const Scope*> &visited)

Same as lookupNameInScope but includes a set tracking visited scopes.

bool isWholeScopeVisibleFromScope(Context *context, const Scope *checkScope, const Scope *fromScope)

Returns true if all of checkScope is visible from fromScope due to scope containment or whole-module use statements.

const PoiScope *pointOfInstantiationScope(Context *context, const Scope *scope, const PoiScope *parentPoiScope)

Returns a unique’d point-of-instantiation scope for the passed scope and parent POI scope. Collapses away POI scopes that do not affect visible functions.

const InnermostMatch &findInnermostDecl(Context *context, const Scope *scope, UniqueString name)

Given a name and a Scope, return the innermost and first ID for a definition of that name, and an indication of whether 0, 1, or more matches were found.

class BorrowedIdsWithName
#include <scope-types.h>

Contains IDs with a particular name. This class is a lightweight reference to a collection stored in OwnedIdsWithName.

Public Functions

inline BorrowedIdsWithName()

Construct an empty BorrowedIdsWithName

inline BorrowedIdsWithName(ID id)

Construct a BorrowedIdsWithName referring to one ID

inline BorrowedIdsWithName(const OwnedIdsWithName &o)

Construct a BorrowedIdsWithName referring to the same IDs as the passed OwnedIdsWithName. This BorrowedIdsWithName assumes that the OwnedIdsWithName will continue to exist.

inline int numIds() const

Return the number of IDs stored here

inline const ID &id(int i) const

Returns the i’th ID. id(0) is always available.

inline const ID *begin() const

Returns an iterator referring to the first element stored.

inline const ID *end() const

Returns an iterator referring just past the last element stored.

inline bool operator==(const BorrowedIdsWithName &other) const
inline bool operator!=(const BorrowedIdsWithName &other) const
inline size_t hash() const
class CallInfo
#include <resolution-types.h>


Public Types

using CallInfoActualIterable = Iterable<std::vector<CallInfoActual>>

Public Functions

inline CallInfo(UniqueString name, bool hasQuestionArg, std::vector<CallInfoActual> actuals)
inline UniqueString name() const

return the name of the called thing

inline bool isMethod() const

check if the call is a method call

inline bool hasQuestionArg() const

check if the call includes ? arg for type constructor

inline CallInfoActualIterable actuals() const

return the actuals

inline const CallInfoActual &actuals(size_t i) const

return the i’th actual

inline size_t numActuals() const

return the number of actuals

inline bool operator==(const CallInfo &other) const
inline bool operator!=(const CallInfo &other) const
inline size_t hash() const
class CallInfoActual
#include <resolution-types.h>


Public Functions

inline CallInfoActual(types::QualifiedType type, UniqueString byName)
inline const types::QualifiedType &type() const

return the qualified type

inline UniqueString byName() const

return the name, if any, that the argument was passed with. Ex: in f(number=3), byName() would be “number”

inline bool operator==(const CallInfoActual &other) const
inline bool operator!=(const CallInfoActual &other) const
inline size_t hash() const
class CallResolutionResult
#include <resolution-types.h>


Public Functions

inline CallResolutionResult(types::QualifiedType exprType)
inline CallResolutionResult(MostSpecificCandidates mostSpecific, types::QualifiedType exprType, PoiInfo poiInfo)
inline const MostSpecificCandidates &mostSpecific() const

get the most specific candidates for return-intent overloading

inline const types::QualifiedType &exprType() const

type of the call expression

inline const PoiInfo &poiInfo() const

point-of-instantiation scopes used when resolving signature or body

inline bool operator==(const CallResolutionResult &other) const
inline bool operator!=(const CallResolutionResult &other) const
inline void swap(CallResolutionResult &other)
class CanPassResult

Public Types

enum ConversionKind


enumerator NONE

No implicit conversion is needed


A narrowing param conversion is needed. These are only applicable to the particular param value e.g. 1:int converting to int(8) because 1 fits in int(8). The input of such a conversion must be param and the result is always a param.

enumerator NUMERIC

A numeric or bool conversion.

enumerator SUBTYPE

A conversion that implements subtyping

enumerator OTHER

Non-subtype conversion that doesn’t produce a param

Public Functions

inline CanPassResult()
~CanPassResult() = default
inline bool passes()

Returns true if the argument is passable

inline bool instantiates()

Returns true if passing the argument will require instantiation

inline bool promotes()

Returns true if passing the argument will require promotion

inline bool converts()

Returns true if implicit conversion is required

inline ConversionKind conversionKind()

What type of implicit conversion, if any, is needed?

Public Static Functions

static CanPassResult canPass(const types::QualifiedType &actualType, const types::QualifiedType &formalType)
struct FormalActual
#include <resolution-types.h>

FormalActual holds information on a function formal and its binding (if any)

Public Members

const uast::Decl *formal = nullptr
types::QualifiedType formalType
bool hasActual = false
int actualIdx = -1
types::QualifiedType actualType
class FormalActualMap
#include <resolution-types.h>

FormalActualMap maps formals to actuals

Public Types

using FormalActualIterable = Iterable<std::vector<FormalActual>>

Public Functions

inline FormalActualMap(const UntypedFnSignature *sig, const CallInfo &call)
inline FormalActualMap(const TypedFnSignature *sig, const CallInfo &call)
inline bool isValid() const

check if mapping is valid

inline FormalActualIterable byFormalIdx() const

get the FormalActual’s

class InnermostMatch
#include <scope-types.h>


Public Types

enum MatchesFound


enumerator ZERO
enumerator ONE
enumerator MANY

Public Functions

inline InnermostMatch()
inline InnermostMatch(ID id, MatchesFound found)
inline ID id() const

Return the id

inline MatchesFound found() const

Return the matches found

inline bool operator==(const InnermostMatch &other) const
inline bool operator!=(const InnermostMatch &other) const
inline void swap(InnermostMatch &other)
class MostSpecificCandidates
#include <resolution-types.h>

Stores the most specific candidates when resolving a function call.

Public Types

enum Intent


enumerator REF
enumerator CONST_REF
enumerator VALUE
enumerator NUM_INTENTS

Public Functions

inline const TypedFnSignature *const *begin() const
inline const TypedFnSignature *const *end() const
inline void setBestRef(const TypedFnSignature *sig)
inline void setBestConstRef(const TypedFnSignature *sig)
inline void setBestValue(const TypedFnSignature *sig)
inline const TypedFnSignature *bestRef() const
inline const TypedFnSignature *bestConstRef() const
inline const TypedFnSignature *bestValue() const
inline const TypedFnSignature *only() const

If there is exactly one candidate, return that candidate. Otherwise, return nullptr.

inline bool operator==(const MostSpecificCandidates &other) const
inline bool operator!=(const MostSpecificCandidates &other) const
inline void swap(MostSpecificCandidates &other)
class OwnedIdsWithName
#include <scope-types.h>

Collects IDs with a particular name. These can be referred to by a BorrowedIdsWithName in a way that avoids copies.

Public Functions

inline OwnedIdsWithName(ID id)

Construct an OwnedIdsWithName containing one ID.

inline void appendId(ID newId)

Append an ID to an OwnedIdsWithName.

inline bool operator==(const OwnedIdsWithName &other) const
inline bool operator!=(const OwnedIdsWithName &other) const
class PoiInfo
#include <resolution-types.h>

Contains information about symbols available from point-of-instantiation in order to implement caching of instantiations.

Public Functions

inline PoiInfo()
inline PoiInfo(const PoiScope *poiScope)
inline PoiInfo(std::set<std::pair<ID, ID>> poiFnIdsUsed)
inline const PoiScope *poiScope() const

return the poiScope

inline void setPoiScope(const PoiScope *poiScope)

set the poiScope

inline void setResolved(bool resolved)

set resolved

inline const std::set<std::pair<ID, ID>> &poiFnIdsUsed() const
inline void addIds(ID a, ID b)
inline void swap(PoiInfo &other)
void accumulate(const PoiInfo &addPoiInfo)
bool canReuse(const PoiInfo &check) const
inline size_t hash() const
inline bool operator==(const PoiInfo &other) const
inline bool operator!=(const PoiInfo &other) const

Public Static Functions

static inline bool updateEquals(const PoiInfo &a, const PoiInfo &b)
static inline bool reuseEquals(const PoiInfo &a, const PoiInfo &b)
class PoiScope
#include <scope-types.h>

PoiScope is a point-of-instantiation scope

Public Functions

inline PoiScope(const Scope *scope, const PoiScope *poiScope)
inline const Scope *inScope() const

return the parent scope for the call

inline const PoiScope *inFnPoi() const

return the POI of this POI

inline bool operator==(const PoiScope &other) const
inline bool operator!=(const PoiScope &other) const
class ResolutionResultByPostorderID
#include <resolution-types.h>

This type is a mapping from postOrderId (which is an integer) to ResolvedExpression for storing resolution results within a symbol.

Note that an inner Function would not be covered here.

Public Functions

void setupForSymbol(const uast::ASTNode *ast)

prepare to resolve the contents of the passed symbol

void setupForSignature(const uast::Function *func)

prepare to resolve the signature of the passed function

void setupForFunction(const uast::Function *func)

prepare to resolve the body of the passed function

inline ResolvedExpression &byIdExpanding(const ID &id)
inline ResolvedExpression &byAstExpanding(const uast::ASTNode *ast)
inline ResolvedExpression &byId(const ID &id)
inline const ResolvedExpression &byId(const ID &id) const
inline ResolvedExpression &byAst(const uast::ASTNode *ast)
inline const ResolvedExpression &byAst(const uast::ASTNode *ast) const
inline bool operator==(const ResolutionResultByPostorderID &other) const
inline bool operator!=(const ResolutionResultByPostorderID &other) const
inline void swap(ResolutionResultByPostorderID &other)

Public Static Functions

static bool update(ResolutionResultByPostorderID &keep, ResolutionResultByPostorderID &addin)
class ResolvedExpression
#include <resolution-types.h>

This type represents a resolved expression.

Public Functions

inline ResolvedExpression()
inline const types::QualifiedType &type() const

get the qualified type

inline ID toId() const

for simple (non-function Identifier) cases, the ID of a NamedDecl it refers to

inline const MostSpecificCandidates &mostSpecific() const

For a function call, what is the most specific candidate, or when using return intent overloading, what are the most specific candidates? The choice between these needs to happen later than the main function resolution.

inline const PoiScope *poiScope() const
inline void setToId(ID toId)

set the toId

inline void setType(const types::QualifiedType &type)

set the type

inline void setMostSpecific(const MostSpecificCandidates &mostSpecific)

set the most specific

inline void setPoiScope(const PoiScope *poiScope)

set the point-of-instantiation scope

inline bool operator==(const ResolvedExpression &other) const
inline bool operator!=(const ResolvedExpression &other) const
inline void swap(ResolvedExpression &other)
std::string toString() const
class ResolvedFunction
#include <resolution-types.h>

This type represents a resolved function.

Public Functions

inline ResolvedFunction(const TypedFnSignature *signature, uast::Function::ReturnIntent returnIntent, ResolutionResultByPostorderID resolutionById, PoiInfo poiInfo)
inline const TypedFnSignature *signature() const

The type signature

inline uast::Function::ReturnIntent returnIntent() const

the return intent

inline const ResolutionResultByPostorderID &resolutionById() const

this is the output of the resolution process

inline const PoiInfo &poiInfo() const

the set of point-of-instantiations used by the instantiation

inline bool operator==(const ResolvedFunction &other) const
inline bool operator!=(const ResolvedFunction &other) const
inline void swap(ResolvedFunction &other)
inline const ResolvedExpression &byId(const ID &id) const
inline const ResolvedExpression &byAst(const uast::ASTNode *ast) const
inline const ID &id() const
class ResolvedVisibilityScope
#include <scope-types.h>

Stores the result of in-order resolution of use/import statements.

Public Types

using VisibilitySymbolsIterable = Iterable<std::vector<VisibilitySymbols>>

Public Functions

inline ResolvedVisibilityScope(const Scope *scope)
inline const Scope *scope() const

Return the scope

inline VisibilitySymbolsIterable visibilityClauses() const

Return an iterator over the visibility clauses

inline void addVisibilityClause(const VisibilitySymbols &clause)

Add a visibility clause

inline bool operator==(const ResolvedVisibilityScope &other) const
inline bool operator!=(const ResolvedVisibilityScope &other) const
class Scope
#include <scope-types.h>

A scope roughly corresponds to a { } block. Anywhere a new symbol could be defined / is defined is a scope.

The scope contains a mapping from name to ID for symbols defined within. For the root scope, it can also contain empty IDs for builtin types and symbols.

While generic instantiations generate something scope-like, the point-of-instantiation reasoning will need to be handled with a different type.

Public Functions

inline Scope()

Construct an empty scope. This scope will not yet store any defined symbols.

Scope(const uast::ASTNode *ast, const Scope *parentScope)

Construct a Scope for a particular AST node and with a particular parent.

void addBuiltin(UniqueString name)

Add a builtin type with the provided name. This needs to be called to populate the root scope with builtins.

inline const Scope *parentScope() const

Return the parent scope for this scope.

inline uast::asttags::ASTTag tag() const

Returns the AST tag of the construct that this Scope represents.

inline const ID &id() const

Return the ID of the Block or other AST node construct that this Scope represents. An empty ID indicates that this Scope is the root scope.

inline bool containsUseImport() const

Returns ‘true’ if this Scope directly contains use or import statements

inline bool containsFunctionDecls() const

Returns ‘true’ if this Scope directly contains any Functions

inline int numDeclared() const
inline bool lookupInScope(UniqueString name, std::vector<BorrowedIdsWithName> &result) const

If the scope contains IDs with the provided name, append the relevant BorrowedIdsToName the the vector. Returns true if something was appended.

inline bool operator==(const Scope &other) const
inline bool operator!=(const Scope &other) const
class TypedFnSignature
#include <resolution-types.h>

This represents a typed function signature.

Public Types

enum WhereClauseResult


enumerator WHERE_NONE
enumerator WHERE_TBD
enumerator WHERE_TRUE
enumerator WHERE_FALSE

Public Functions

inline TypedFnSignature(const UntypedFnSignature *untypedSignature, std::vector<types::QualifiedType> formalTypes, WhereClauseResult whereClauseResult, bool needsInstantiation, const TypedFnSignature *instantiatedFrom, const TypedFnSignature *parentFn)
inline bool operator==(const TypedFnSignature &other) const
inline bool operator!=(const TypedFnSignature &other) const
std::string toString() const
inline const ID &id() const

Returns the id of the relevant uast node (usually a Function but it can be a Record or Class for compiler-generated functions)

inline const UntypedFnSignature *untyped() const

Returns the UntypedFnSignature

inline WhereClauseResult whereClauseResult() const

Returns the result of evaluating the where clause

inline bool needsInstantiation() const

Returns if any of the formals are generic or unknown

inline const TypedFnSignature *instantiatedFrom() const

Is this TypedFnSignature representing an instantiation? If so, returns the generic TypedFnSignature that was instantiated. Otherwise, returns nullptr.

inline const TypedFnSignature *parentFn() const

Is this for an inner Function? If so, what is the parent function signature?

inline int numFormals() const

Returns the number of formals

inline UniqueString formalName(int i) const

Returns the name of the i’th formal

inline const types::QualifiedType &formalType(int i) const

Returns the type of the i’th formal

class UntypedFnSignature
#include <resolution-types.h>

An untyped function signature. This is really just the part of a function including the formals. It exists so that the process of identifying candidates does not need to depend on the bodies of the function (in terms of incremental recomputation).

Public Functions

inline bool operator==(const UntypedFnSignature &other) const
inline bool operator!=(const UntypedFnSignature &other) const
inline const ID &id() const

Returns the id of the relevant uast node (usually a Function but it can be a Record or Class for compiler-generated functions)

inline UniqueString name() const

Returns the name of the function this signature represents

inline bool idIsFunction() const

Returns true if id() refers to a Function

inline bool isTypeConstructor() const

Returns true if this is a type constructor

inline int numFormals() const

Returns the number of formals

inline UniqueString formalName(int i) const

Returns the name of the i’th formal.

inline bool formalHasDefault(int i) const

Return whether the i’th formal has a default value.

inline const uast::Decl *formalDecl(int i) const

Returns the Decl for the i’th formal. This will return nullptr for compiler-generated functions.

Public Static Functions

static const UntypedFnSignature *get(Context *context, ID id, UniqueString name, bool isMethod, bool idIsFunction, bool isTypeConstructor, uast::Function::Kind kind, std::vector<FormalDetail> formals, const uast::Expression *whereClause)

Get the unique UntypedFnSignature containing these components

static const UntypedFnSignature *get(Context *context, const uast::Function *function)

Get the unique UntypedFnSignature representing a Function’s signature.

struct FormalDetail

Public Functions

inline FormalDetail(UniqueString name, bool hasDefault, const uast::Decl *decl)
inline bool operator==(const FormalDetail &other) const
inline bool operator!=(const FormalDetail &other) const
inline size_t hash() const

Public Members

UniqueString name
bool hasDefaultValue = false
const uast::Decl *decl = nullptr
class VisibilitySymbols
#include <scope-types.h>

This class supports both use and import. It stores a normalized form of the symbols made available by a use/import clause.

Public Types

enum Kind

The kind of import symbol


enumerator SYMBOL_ONLY

the named symbol itself only (one name in names)

enumerator ALL_CONTENTS

(and names is empty)

enumerator ONLY_CONTENTS

only the contents named in names


except the contents named in names (no renaming)

Public Functions

inline VisibilitySymbols()
inline VisibilitySymbols(ID symbolId, Kind kind, bool isPrivate, std::vector<std::pair<UniqueString, UniqueString>> names)
inline const ID &symbolId() const

Return the ID of the imported symbol, e.g. ID of a Module

inline Kind kind() const

Return the kind of the imported symbol

inline bool isPrivate() const

Return whether or not the imported symbol is private

inline bool lookupName(const UniqueString &name, UniqueString &declared) const

Lookup the declared name for a given name Returns true if name is found in the list of renamed names and stores the declared name in declared Returns false if name is not found

inline bool operator==(const VisibilitySymbols &other) const
inline bool operator!=(const VisibilitySymbols &other) const
inline void swap(VisibilitySymbols &other)