// Copyright 2019 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_TORQUE_TYPE_INFERENCE_H_ #define V8_TORQUE_TYPE_INFERENCE_H_ #include #include #include "src/base/optional.h" #include "src/torque/ast.h" #include "src/torque/declarations.h" #include "src/torque/types.h" namespace v8 { namespace internal { namespace torque { // Type argument inference computes a potential instantiation of a generic // callable given some concrete argument types. As an example, consider the // generic macro // // macro Pick(x: T, y: T): T // // along with a given call site, such as // // Pick(1, 2); // // The inference proceeds by matching the term argument types (`constexpr // int31`, in case of `1` and `2`) against the formal parameter types (`T` in // both cases). During this matching we discover that `T` must equal `constexpr // int31`. // // The inference will not perform any comprehensive type checking of its own, // but *does* fail if type parameters cannot be soundly instantiated given the // call site. For instance, for the following call site // // const aSmi: Smi = ...; // Pick(1, aSmi); // inference fails // // inference would fail, since `constexpr int31` is distinct from `Smi`. To // allow for implicit conversions to be tried in a separate step after type // argument inference, a number of type arguments may be given explicitly: // // Pick(1, aSmi); // inference succeeds (doing nothing) // // In the above case the inference simply ignores inconsistent constraints on // `T`. Similarly, we ignore all constraints arising from formal parameters // that are function- or union-typed. // // Finally, note that term parameters are passed as type expressions, since // we have no way of expressing a reference to type parameter as a Type. These // type expressions are resolved during matching, so TypeArgumentInference // should be instantiated in the appropriate scope. class TypeArgumentInference { public: TypeArgumentInference(const NameVector& type_parameters, const TypeVector& explicit_type_arguments, const std::vector& term_parameters, const TypeVector& term_argument_types); bool HasFailed() const { return failure_reason_.has_value(); } const char* GetFailureReason() { return *failure_reason_; } TypeVector GetResult() const; private: void Fail(const char* reason) { failure_reason_ = {reason}; } void Match(TypeExpression* parameter, const Type* argument_type); void MatchGeneric(BasicTypeExpression* parameter, const StructType* argument_type); size_t num_explicit_; std::unordered_map type_parameter_from_name_; std::vector> inferred_; base::Optional failure_reason_; }; } // namespace torque } // namespace internal } // namespace v8 #endif // V8_TORQUE_TYPE_INFERENCE_H_