Path: blob/master/Analysis/include/Luau/OverloadResolution.h
2727 views
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details1#pragma once23#include "Luau/Ast.h"4#include "Luau/Error.h"5#include "Luau/InsertionOrderedMap.h"6#include "Luau/Location.h"7#include "Luau/NotNull.h"8#include "Luau/Subtyping.h"9#include "Luau/TypeFwd.h"1011namespace Luau12{1314struct BuiltinTypes;15struct TypeArena;16struct Scope;17struct InternalErrorReporter;18struct TypeCheckLimits;19struct Subtyping;2021class Normalizer;2223// There are essentially two reasons why we might consider an overload24// to be unsuitable:25//26// First, subtyping might fail. This also includes cases where we27// cannot find a generic substitution scheme that results in a28// callable function.29//30// Second, subtyping might succeed, but it might result in the31// presence of an unreducible type function. (eg add<string, string>)32//33// TODO: Subtyping should probably also be the thing that checks for34// unreducible type functions. This would be nice because it would35// mean that overload resolution would not have to talk about type36// functions at all.37using IncompatibilityReason = Variant<SubtypingReasonings, ErrorVec>;3839/**40* Struct representing "selecting" an overload from `OverloadResolution::resolveOverload`.41*/42struct SelectedOverload43{44/**45* An unambiguous overload, if one can be selected. This is _not_ necessarily46* an overload that is valid for the argument pack provided. For example:47*48* local f: ((string) -> "one") & ((string, string) -> "two")49*50* -- We will select `(string) -> "one"` here based on arity. Type checking51* -- will later inform us that `42` is not a string, but that's ok.52* f(42)53*/54std::optional<TypeId> overload;5556/**57* Any associated constraints with selecting this overload. For example, in58* the code block:59*60* local f: ((string, number) -> string) & ((number, boolean) -> number)61* local function g(x)62* -- When selecting an overload at this point, we'll reject the63* -- second overload, and claim that this is the only possible64* -- overload with a constraint of `x <: string`.65* f(x, 42)66* end67*/68std::vector<ConstraintV> assumedConstraints;6970/**71* Whether we should potentially defer selecting an overload, such as in:72*73* local f: ((string) -> string) & ((number) -> number)74* local function g(x)75* -- There *may* be another constraint on `x` later that allows us to76* -- unambiguously select an overload.77* f(x)78* end79*/80bool shouldRetry;81};8283struct OverloadResolution84{85// Overloads that will work86std::vector<TypeId> ok;8788// "Overloads" that aren't callable.89std::vector<TypeId> nonFunctions;9091// Overloads that could match, but require that other constraints also be satisfied.92std::vector<std::pair<TypeId, std::vector<ConstraintV>>> potentialOverloads;9394// Overloads that have the correct arity, but do not work.95std::vector<std::pair<TypeId, IncompatibilityReason>> incompatibleOverloads;9697// Overloads that will never work specifically because of an arity mismatch.98std::vector<TypeId> arityMismatches;99100// If a particular overload is a __call metamethod, then type inference101// needs to know so that it can prepend the self argument to the argument102// list when it infers.103DenseHashSet<TypeId> metamethods{nullptr};104105/**106* Try to determine an unambiguous overload. See `SelectedOverload` for107* documentation.108*/109SelectedOverload getUnambiguousOverload() const;110};111112struct OverloadResolver113{114OverloadResolver(115NotNull<BuiltinTypes> builtinTypes,116NotNull<TypeArena> arena,117NotNull<Normalizer> normalizer,118NotNull<TypeFunctionRuntime> typeFunctionRuntime,119NotNull<Scope> scope,120NotNull<InternalErrorReporter> reporter,121NotNull<TypeCheckLimits> limits,122Location callLocation123);124125NotNull<BuiltinTypes> builtinTypes;126NotNull<TypeArena> arena;127NotNull<Normalizer> normalizer;128NotNull<TypeFunctionRuntime> typeFunctionRuntime;129NotNull<Scope> scope;130NotNull<InternalErrorReporter> ice;131NotNull<TypeCheckLimits> limits;132Subtyping subtyping;133Location callLoc;134135// Given a (potentially overloaded) function and a set of arguments, test each overload.136OverloadResolution resolveOverload(137TypeId fnTy,138TypePackId args,139Location fnLocation,140NotNull<DenseHashSet<TypeId>> uniqueTypes,141bool useFreeTypeBounds142);143144void reportErrors(145ErrorVec& errors,146TypeId fnTy,147Location fnLocation,148const ModuleName& moduleName,149TypePackId argPack,150const std::vector<AstExpr*>& argExprs,151const SubtypingReasoning& reason152) const;153154private:155void testFunctionOrUnion(156OverloadResolution& result,157TypeId fnTy,158TypePackId argsPack,159Location fnLocation,160NotNull<DenseHashSet<TypeId>> uniqueTypes161);162163void testFunction(OverloadResolution& result, TypeId fnTy, TypePackId argsPack, Location fnLocation, NotNull<DenseHashSet<TypeId>> uniqueTypes);164165void testFunctionOrCallMetamethod(166OverloadResolution& result,167TypeId fnTy,168TypePackId argsPack,169Location fnLocation,170NotNull<DenseHashSet<TypeId>> uniqueTypes171);172173void maybeEmplaceError(174ErrorVec* errors,175Location argLocation,176const SubtypingReasoning* reason,177std::optional<TypeId> wantedTy,178std::optional<TypeId> givenTy179) const;180181void maybeEmplaceError(182ErrorVec* errors,183Location argLocation,184const ModuleName& moduleName,185const SubtypingReasoning* reason,186std::optional<TypeId> wantedTy,187std::optional<TypeId> givenTy188) const;189190void maybeEmplaceError(191ErrorVec* errors,192Location argLocation,193const ModuleName& moduleName,194const SubtypingReasoning* reason,195std::optional<TypePackId> wantedTp,196std::optional<TypePackId> givenTp197) const;198199void maybeEmplaceError(200ErrorVec* errors,201Location argLocation,202const ModuleName& moduleName,203const SubtypingReasoning* reason,204std::optional<TypeOrPack> wantedType,205std::optional<TypeOrPack> givenType206) const;207208// Checks if the candidate args are arity-compatible with the desired parameters.209// Used during overload selection to do arity-based filtering of overloads.210// We do not accept nil in place of a generic unless that generic is explicitly optional.211bool isArityCompatible(TypePackId candidate, TypePackId desired, NotNull<BuiltinTypes> builtinTypes) const;212};213214// Helper utility, presently used for binary operator type functions.215//216// Given a function and a set of arguments, select a suitable overload.217218} // namespace Luau219220221