type-inference.h 2.97 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
// 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 <string>
#include <unordered_map>

#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<T: type>(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<Smi>(1, aSmi);  // inference succeeds (doing nothing)
//
// In the above case the inference simply ignores inconsistent constraints on
49 50
// `T`. Similarly, we ignore all constraints arising from formal parameters
// that are function- or union-typed.
51 52 53 54 55
//
// 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.
56 57
class TypeArgumentInference {
 public:
58 59 60 61 62
  TypeArgumentInference(
      const GenericParameters& type_parameters,
      const TypeVector& explicit_type_arguments,
      const std::vector<TypeExpression*>& term_parameters,
      const std::vector<base::Optional<const Type*>>& term_argument_types);
63 64

  bool HasFailed() const { return failure_reason_.has_value(); }
65
  const std::string& GetFailureReason() { return *failure_reason_; }
66
  TypeVector GetResult() const;
67
  void Fail(std::string reason) { failure_reason_ = {reason}; }
68 69 70

 private:
  void Match(TypeExpression* parameter, const Type* argument_type);
71
  void MatchGeneric(BasicTypeExpression* parameter, const Type* argument_type);
72 73 74 75

  size_t num_explicit_;
  std::unordered_map<std::string, size_t> type_parameter_from_name_;
  std::vector<base::Optional<const Type*>> inferred_;
76
  base::Optional<std::string> failure_reason_;
77 78 79 80 81 82 83
};

}  // namespace torque
}  // namespace internal
}  // namespace v8

#endif  // V8_TORQUE_TYPE_INFERENCE_H_