• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_TORQUE_TYPE_INFERENCE_H_
6 #define V8_TORQUE_TYPE_INFERENCE_H_
7 
8 #include <string>
9 #include <unordered_map>
10 
11 #include "src/base/optional.h"
12 #include "src/torque/ast.h"
13 #include "src/torque/declarations.h"
14 #include "src/torque/types.h"
15 
16 namespace v8 {
17 namespace internal {
18 namespace torque {
19 
20 // Type argument inference computes a potential instantiation of a generic
21 // callable given some concrete argument types. As an example, consider the
22 // generic macro
23 //
24 //   macro Pick<T: type>(x: T, y: T): T
25 //
26 // along with a given call site, such as
27 //
28 //   Pick(1, 2);
29 //
30 // The inference proceeds by matching the term argument types (`constexpr
31 // int31`, in case of `1` and `2`) against the formal parameter types (`T` in
32 // both cases). During this matching we discover that `T` must equal `constexpr
33 // int31`.
34 //
35 // The inference will not perform any comprehensive type checking of its own,
36 // but *does* fail if type parameters cannot be soundly instantiated given the
37 // call site. For instance, for the following call site
38 //
39 //   const aSmi: Smi = ...;
40 //   Pick(1, aSmi);  // inference fails
41 //
42 // inference would fail, since `constexpr int31` is distinct from `Smi`. To
43 // allow for implicit conversions to be tried in a separate step after type
44 // argument inference, a number of type arguments may be given explicitly:
45 //
46 //   Pick<Smi>(1, aSmi);  // inference succeeds (doing nothing)
47 //
48 // In the above case the inference simply ignores inconsistent constraints on
49 // `T`. Similarly, we ignore all constraints arising from formal parameters
50 // that are function- or union-typed.
51 //
52 // Finally, note that term parameters are passed as type expressions, since
53 // we have no way of expressing a reference to type parameter as a Type. These
54 // type expressions are resolved during matching, so TypeArgumentInference
55 // should be instantiated in the appropriate scope.
56 class TypeArgumentInference {
57  public:
58   TypeArgumentInference(
59       const GenericParameters& type_parameters,
60       const TypeVector& explicit_type_arguments,
61       const std::vector<TypeExpression*>& term_parameters,
62       const std::vector<base::Optional<const Type*>>& term_argument_types);
63 
HasFailed()64   bool HasFailed() const { return failure_reason_.has_value(); }
GetFailureReason()65   const std::string& GetFailureReason() { return *failure_reason_; }
66   TypeVector GetResult() const;
Fail(std::string reason)67   void Fail(std::string reason) { failure_reason_ = {reason}; }
68 
69  private:
70   void Match(TypeExpression* parameter, const Type* argument_type);
71   void MatchGeneric(BasicTypeExpression* parameter, const Type* argument_type);
72 
73   size_t num_explicit_;
74   std::unordered_map<std::string, size_t> type_parameter_from_name_;
75   std::vector<base::Optional<const Type*>> inferred_;
76   base::Optional<std::string> failure_reason_;
77 };
78 
79 }  // namespace torque
80 }  // namespace internal
81 }  // namespace v8
82 
83 #endif  // V8_TORQUE_TYPE_INFERENCE_H_
84