Skip to content

Commit fce70ef

Browse files
cameelekpyron
authored andcommitted
Fixing type variables in defined type classes and functions
1 parent fd3c393 commit fce70ef

File tree

7 files changed

+130
-93
lines changed

7 files changed

+130
-93
lines changed

libsolidity/experimental/analysis/TypeInference.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,13 @@ bool TypeInference::visit(FunctionDefinition const& _functionDefinition)
166166
return false;
167167
}
168168

169+
void TypeInference::endVisit(FunctionDefinition const& _functionDefinition)
170+
{
171+
solAssert(m_expressionContext == ExpressionContext::Term);
172+
173+
m_env->fixTypeVars(TypeEnvironmentHelpers{*m_env}.typeVars(type(_functionDefinition)));
174+
}
175+
169176
void TypeInference::endVisit(Return const& _return)
170177
{
171178
solAssert(m_currentFunctionType);
@@ -204,6 +211,8 @@ bool TypeInference::visit(TypeClassDefinition const& _typeClassDefinition)
204211
solAssert(m_analysis.annotation<TypeClassRegistration>(_typeClassDefinition).typeClass.has_value());
205212
TypeClass typeClass = m_analysis.annotation<TypeClassRegistration>(_typeClassDefinition).typeClass.value();
206213
Type typeVar = m_typeSystem.typeClassVariable(typeClass);
214+
unify(type(_typeClassDefinition.typeVariable()), typeVar, _typeClassDefinition.location());
215+
207216
auto& typeMembersAnnotation = annotation().members[typeConstructor(&_typeClassDefinition)];
208217

209218
for (auto subNode: _typeClassDefinition.subNodes())
@@ -235,7 +244,6 @@ bool TypeInference::visit(TypeClassDefinition const& _typeClassDefinition)
235244
m_errorReporter.typeError(1807_error, _typeClassDefinition.location(), "Function " + functionName + " depends on invalid type variable.");
236245
}
237246

238-
unify(type(_typeClassDefinition.typeVariable()), m_typeSystem.freshTypeVariable({{typeClass}}), _typeClassDefinition.location());
239247
for (auto instantiation: m_analysis.annotation<TypeRegistration>(_typeClassDefinition).instantiations | ranges::views::values)
240248
// TODO: recursion-safety? Order of instantiation?
241249
instantiation->accept(*this);
@@ -663,6 +671,7 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation)
663671
}) | ranges::to<std::vector<Sort>>;
664672
}
665673
}
674+
m_env->fixTypeVars(arguments);
666675

667676
Type instanceType{TypeConstant{*typeConstructor, arguments}};
668677

@@ -682,12 +691,8 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation)
682691

683692
auto const& classFunctions = annotation().typeClassFunctions.at(typeClass);
684693

685-
TypeEnvironment newEnv = m_env->clone();
686-
if (!newEnv.unify(m_typeSystem.typeClassVariable(typeClass), instanceType).empty())
687-
{
688-
m_errorReporter.typeError(4686_error, _typeClassInstantiation.location(), "Unification of class and instance variable failed.");
689-
return false;
690-
}
694+
solAssert(std::holds_alternative<TypeVariable>(m_typeSystem.typeClassVariable(typeClass)));
695+
TypeVariable classVar = std::get<TypeVariable>(m_typeSystem.typeClassVariable(typeClass));
691696

692697
for (auto [name, classFunctionType]: classFunctions)
693698
{
@@ -696,11 +701,22 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation)
696701
m_errorReporter.typeError(6948_error, _typeClassInstantiation.location(), "Missing function: " + name);
697702
continue;
698703
}
704+
Type instantiatedClassFunctionType = TypeEnvironmentHelpers{*m_env}.substitute(classFunctionType, classVar, instanceType);
705+
699706
Type instanceFunctionType = functionTypes.at(name);
700707
functionTypes.erase(name);
701708

702-
if (!newEnv.typeEquals(instanceFunctionType, classFunctionType))
703-
m_errorReporter.typeError(7428_error, _typeClassInstantiation.location(), "Type mismatch for function " + name + " " + TypeEnvironmentHelpers{newEnv}.typeToString(instanceFunctionType) + " != " + TypeEnvironmentHelpers{newEnv}.typeToString(classFunctionType));
709+
if (!m_env->typeEquals(instanceFunctionType, instantiatedClassFunctionType))
710+
m_errorReporter.typeError(
711+
7428_error,
712+
_typeClassInstantiation.location(),
713+
fmt::format(
714+
"Instantiation function '{}' does not match the declaration in the type class ({} != {}).",
715+
name,
716+
TypeEnvironmentHelpers{*m_env}.typeToString(instanceFunctionType),
717+
TypeEnvironmentHelpers{*m_env}.typeToString(instantiatedClassFunctionType)
718+
)
719+
);
704720
}
705721

706722
if (!functionTypes.empty())

libsolidity/experimental/analysis/TypeInference.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class TypeInference: public ASTConstVisitor
5757
bool visit(VariableDeclaration const& _variableDeclaration) override;
5858

5959
bool visit(FunctionDefinition const& _functionDefinition) override;
60+
void endVisit(FunctionDefinition const& _functionDefinition) override;
6061
bool visit(ParameterList const&) override { return true; }
6162
void endVisit(ParameterList const& _parameterList) override;
6263
bool visit(SourceUnit const&) override { return true; }

libsolidity/experimental/ast/TypeSystem.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ std::variant<TypeClass, std::string> TypeSystem::declareTypeClass(std::string _n
301301
Type typeVariable = (_primitive ? freshVariable({{typeClass}}) : freshTypeVariable({{typeClass}}));
302302
solAssert(std::holds_alternative<TypeVariable>(typeVariable));
303303

304+
m_globalTypeEnvironment.fixTypeVars({typeVariable});
305+
304306
m_typeClasses.emplace_back(TypeClassInfo{
305307
typeVariable,
306308
_name,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
pragma experimental solidity;
2+
3+
type T;
4+
type U;
5+
6+
class Self: C {
7+
function f(self: Self);
8+
}
9+
10+
instantiation T: C {
11+
function f(self: U) {}
12+
}
13+
// ====
14+
// EVMVersion: >=constantinople
15+
// compileViaYul: true
16+
// ----
17+
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
18+
// TypeError 7428: (95-144): Instantiation function 'f' does not match the declaration in the type class (U -> () != T -> ()).

test/libsolidity/syntaxTests/experimental/inference/polymorphic_function_call.sol

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ function run(a: T, b: U(T), c: U(U(T))) {
1818
// Info 4164: (39-49): Inferred type: tfun(?u:type, U(?u:type))
1919
// Info 4164: (45-48): Inferred type: ?t:type
2020
// Info 4164: (46-47): Inferred type: ?t:type
21-
// Info 4164: (51-82): Inferred type: (?x:type, ?y:type, U(?ba:type)) -> ()
22-
// Info 4164: (61-79): Inferred type: (?x:type, ?y:type, U(?ba:type))
23-
// Info 4164: (62-63): Inferred type: ?x:type
24-
// Info 4164: (65-69): Inferred type: ?y:type
25-
// Info 4164: (68-69): Inferred type: ?y:type
26-
// Info 4164: (71-78): Inferred type: U(?ba:type)
27-
// Info 4164: (74-78): Inferred type: U(?ba:type)
28-
// Info 4164: (74-75): Inferred type: tfun(?ba:type, U(?ba:type))
29-
// Info 4164: (76-77): Inferred type: ?ba:type
21+
// Info 4164: (51-82): Inferred type: ('x:type, 'y:type, U('ba:type)) -> ()
22+
// Info 4164: (61-79): Inferred type: ('x:type, 'y:type, U('ba:type))
23+
// Info 4164: (62-63): Inferred type: 'x:type
24+
// Info 4164: (65-69): Inferred type: 'y:type
25+
// Info 4164: (68-69): Inferred type: 'y:type
26+
// Info 4164: (71-78): Inferred type: U('ba:type)
27+
// Info 4164: (74-78): Inferred type: U('ba:type)
28+
// Info 4164: (74-75): Inferred type: tfun('ba:type, U('ba:type))
29+
// Info 4164: (76-77): Inferred type: 'ba:type
3030
// Info 4164: (84-159): Inferred type: (T, U(T), U(U(T))) -> ()
3131
// Info 4164: (96-123): Inferred type: (T, U(T), U(U(T)))
3232
// Info 4164: (97-101): Inferred type: T

test/libsolidity/syntaxTests/experimental/inference/polymorphic_type.sol

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,24 @@ function run() {
2424
// Info 4164: (48-55): Inferred type: U
2525
// Info 4164: (56-63): Inferred type: V
2626
// Info 4164: (65-81): Inferred type: C
27-
// Info 4164: (71-75): Inferred type: ?be:(type, C)
27+
// Info 4164: (71-75): Inferred type: 'k:(type, C)
2828
// Info 4164: (82-98): Inferred type: D
29-
// Info 4164: (88-92): Inferred type: ?bg:(type, D)
29+
// Info 4164: (88-92): Inferred type: 'l:(type, D)
3030
// Info 4164: (100-170): Inferred type: () -> ()
3131
// Info 4164: (112-114): Inferred type: ()
32-
// Info 4164: (125-141): Inferred type: T(U, ?bm:type, ?bo:(type, C))
33-
// Info 4164: (128-141): Inferred type: T(U, ?bm:type, ?bo:(type, C))
34-
// Info 4164: (128-129): Inferred type: tfun((U, ?bm:type, ?bo:(type, C)), T(U, ?bm:type, ?bo:(type, C)))
32+
// Info 4164: (125-141): Inferred type: T(U, ?bk:type, ?bm:(type, C))
33+
// Info 4164: (128-141): Inferred type: T(U, ?bk:type, ?bm:(type, C))
34+
// Info 4164: (128-129): Inferred type: tfun((U, ?bk:type, ?bm:(type, C)), T(U, ?bk:type, ?bm:(type, C)))
3535
// Info 4164: (130-131): Inferred type: U
36-
// Info 4164: (133-134): Inferred type: ?bm:type
37-
// Info 4164: (136-140): Inferred type: ?bo:(type, C)
38-
// Info 4164: (136-137): Inferred type: ?bo:(type, C)
39-
// Info 4164: (139-140): Inferred type: ?bo:(type, C)
40-
// Info 4164: (151-167): Inferred type: T(V, ?bt:type, ?bv:(type, D))
41-
// Info 4164: (154-167): Inferred type: T(V, ?bt:type, ?bv:(type, D))
42-
// Info 4164: (154-155): Inferred type: tfun((V, ?bt:type, ?bv:(type, D)), T(V, ?bt:type, ?bv:(type, D)))
36+
// Info 4164: (133-134): Inferred type: ?bk:type
37+
// Info 4164: (136-140): Inferred type: ?bm:(type, C)
38+
// Info 4164: (136-137): Inferred type: ?bm:(type, C)
39+
// Info 4164: (139-140): Inferred type: ?bm:(type, C)
40+
// Info 4164: (151-167): Inferred type: T(V, ?br:type, ?bt:(type, D))
41+
// Info 4164: (154-167): Inferred type: T(V, ?br:type, ?bt:(type, D))
42+
// Info 4164: (154-155): Inferred type: tfun((V, ?br:type, ?bt:(type, D)), T(V, ?br:type, ?bt:(type, D)))
4343
// Info 4164: (156-157): Inferred type: V
44-
// Info 4164: (159-160): Inferred type: ?bt:type
45-
// Info 4164: (162-166): Inferred type: ?bv:(type, D)
46-
// Info 4164: (162-163): Inferred type: ?bv:(type, D)
47-
// Info 4164: (165-166): Inferred type: ?bv:(type, D)
44+
// Info 4164: (159-160): Inferred type: ?br:type
45+
// Info 4164: (162-166): Inferred type: ?bt:(type, D)
46+
// Info 4164: (162-163): Inferred type: ?bt:(type, D)
47+
// Info 4164: (165-166): Inferred type: ?bt:(type, D)

test/libsolidity/syntaxTests/experimental/inference/polymorphic_type_instantiation_and_operators.sol

Lines changed: 59 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -57,79 +57,79 @@ function fun(a: T(int: P3), b: T(str: P4)) {
5757
// Info 4164: (74-83): Inferred type: int
5858
// Info 4164: (84-93): Inferred type: str
5959
// Info 4164: (95-156): Inferred type: C
60-
// Info 4164: (101-105): Inferred type: ?bd:(type, C)
61-
// Info 4164: (115-154): Inferred type: (?bd:(type, C), ?bd:(type, C)) -> ?bd:(type, C)
62-
// Info 4164: (127-145): Inferred type: (?bd:(type, C), ?bd:(type, C))
63-
// Info 4164: (128-135): Inferred type: ?bd:(type, C)
64-
// Info 4164: (131-135): Inferred type: ?bd:(type, C)
65-
// Info 4164: (137-144): Inferred type: ?bd:(type, C)
66-
// Info 4164: (140-144): Inferred type: ?bd:(type, C)
67-
// Info 4164: (149-153): Inferred type: ?bd:(type, C)
60+
// Info 4164: (101-105): Inferred type: 'k:(type, C)
61+
// Info 4164: (115-154): Inferred type: ('k:(type, C), 'k:(type, C)) -> 'k:(type, C)
62+
// Info 4164: (127-145): Inferred type: ('k:(type, C), 'k:(type, C))
63+
// Info 4164: (128-135): Inferred type: 'k:(type, C)
64+
// Info 4164: (131-135): Inferred type: 'k:(type, C)
65+
// Info 4164: (137-144): Inferred type: 'k:(type, C)
66+
// Info 4164: (140-144): Inferred type: 'k:(type, C)
67+
// Info 4164: (149-153): Inferred type: 'k:(type, C)
6868
// Info 4164: (158-175): Inferred type: P1
69-
// Info 4164: (164-168): Inferred type: ?bg:(type, P1)
69+
// Info 4164: (164-168): Inferred type: 'l:(type, P1)
7070
// Info 4164: (176-193): Inferred type: P2
71-
// Info 4164: (182-186): Inferred type: ?bj:(type, P2)
71+
// Info 4164: (182-186): Inferred type: 'm:(type, P2)
7272
// Info 4164: (194-211): Inferred type: P3
73-
// Info 4164: (200-204): Inferred type: ?bw:(type, P3)
73+
// Info 4164: (200-204): Inferred type: 'n:(type, P3)
7474
// Info 4164: (212-229): Inferred type: P4
75-
// Info 4164: (218-222): Inferred type: ?by:(type, P4)
75+
// Info 4164: (218-222): Inferred type: 'o:(type, P4)
7676
// Info 4164: (231-255): Inferred type: void
7777
// Info 4164: (256-280): Inferred type: void
7878
// Info 4164: (281-305): Inferred type: void
7979
// Info 4164: (307-331): Inferred type: void
8080
// Info 4164: (332-356): Inferred type: void
8181
// Info 4164: (357-381): Inferred type: void
8282
// Info 4164: (383-458): Inferred type: void
83-
// Info 4164: (398-405): Inferred type: ?ca:(type, P1)
84-
// Info 4164: (399-404): Inferred type: ?ca:(type, P1)
85-
// Info 4164: (402-404): Inferred type: ?ca:(type, P1)
86-
// Info 4164: (415-456): Inferred type: (T(?ca:(type, P1)), T(?ca:(type, P1))) -> T(?ca:(type, P1))
87-
// Info 4164: (427-445): Inferred type: (T(?ca:(type, P1)), T(?ca:(type, P1)))
88-
// Info 4164: (428-435): Inferred type: T(?ca:(type, P1))
89-
// Info 4164: (431-435): Inferred type: T(?ca:(type, P1))
90-
// Info 4164: (431-432): Inferred type: tfun(?ca:(type, P1), T(?ca:(type, P1)))
91-
// Info 4164: (433-434): Inferred type: ?ca:(type, P1)
92-
// Info 4164: (437-444): Inferred type: T(?ca:(type, P1))
93-
// Info 4164: (440-444): Inferred type: T(?ca:(type, P1))
94-
// Info 4164: (440-441): Inferred type: tfun(?ca:(type, P1), T(?ca:(type, P1)))
95-
// Info 4164: (442-443): Inferred type: ?ca:(type, P1)
96-
// Info 4164: (449-453): Inferred type: T(?ca:(type, P1))
97-
// Info 4164: (449-450): Inferred type: tfun(?ca:(type, P1), T(?ca:(type, P1)))
98-
// Info 4164: (451-452): Inferred type: ?ca:(type, P1)
83+
// Info 4164: (398-405): Inferred type: 'bv:(type, P1)
84+
// Info 4164: (399-404): Inferred type: 'bv:(type, P1)
85+
// Info 4164: (402-404): Inferred type: 'bv:(type, P1)
86+
// Info 4164: (415-456): Inferred type: (T('bv:(type, P1)), T('bv:(type, P1))) -> T('bv:(type, P1))
87+
// Info 4164: (427-445): Inferred type: (T('bv:(type, P1)), T('bv:(type, P1)))
88+
// Info 4164: (428-435): Inferred type: T('bv:(type, P1))
89+
// Info 4164: (431-435): Inferred type: T('bv:(type, P1))
90+
// Info 4164: (431-432): Inferred type: tfun('bv:(type, P1), T('bv:(type, P1)))
91+
// Info 4164: (433-434): Inferred type: 'bv:(type, P1)
92+
// Info 4164: (437-444): Inferred type: T('bv:(type, P1))
93+
// Info 4164: (440-444): Inferred type: T('bv:(type, P1))
94+
// Info 4164: (440-441): Inferred type: tfun('bv:(type, P1), T('bv:(type, P1)))
95+
// Info 4164: (442-443): Inferred type: 'bv:(type, P1)
96+
// Info 4164: (449-453): Inferred type: T('bv:(type, P1))
97+
// Info 4164: (449-450): Inferred type: tfun('bv:(type, P1), T('bv:(type, P1)))
98+
// Info 4164: (451-452): Inferred type: 'bv:(type, P1)
9999
// Info 4164: (460-535): Inferred type: void
100-
// Info 4164: (475-482): Inferred type: ?ck:(type, P2)
101-
// Info 4164: (476-481): Inferred type: ?ck:(type, P2)
102-
// Info 4164: (479-481): Inferred type: ?ck:(type, P2)
103-
// Info 4164: (493-533): Inferred type: (T(?ck:(type, P2)), T(?ck:(type, P2))) -> bool
104-
// Info 4164: (504-522): Inferred type: (T(?ck:(type, P2)), T(?ck:(type, P2)))
105-
// Info 4164: (505-512): Inferred type: T(?ck:(type, P2))
106-
// Info 4164: (508-512): Inferred type: T(?ck:(type, P2))
107-
// Info 4164: (508-509): Inferred type: tfun(?ck:(type, P2), T(?ck:(type, P2)))
108-
// Info 4164: (510-511): Inferred type: ?ck:(type, P2)
109-
// Info 4164: (514-521): Inferred type: T(?ck:(type, P2))
110-
// Info 4164: (517-521): Inferred type: T(?ck:(type, P2))
111-
// Info 4164: (517-518): Inferred type: tfun(?ck:(type, P2), T(?ck:(type, P2)))
112-
// Info 4164: (519-520): Inferred type: ?ck:(type, P2)
100+
// Info 4164: (475-482): Inferred type: 'cf:(type, P2)
101+
// Info 4164: (476-481): Inferred type: 'cf:(type, P2)
102+
// Info 4164: (479-481): Inferred type: 'cf:(type, P2)
103+
// Info 4164: (493-533): Inferred type: (T('cf:(type, P2)), T('cf:(type, P2))) -> bool
104+
// Info 4164: (504-522): Inferred type: (T('cf:(type, P2)), T('cf:(type, P2)))
105+
// Info 4164: (505-512): Inferred type: T('cf:(type, P2))
106+
// Info 4164: (508-512): Inferred type: T('cf:(type, P2))
107+
// Info 4164: (508-509): Inferred type: tfun('cf:(type, P2), T('cf:(type, P2)))
108+
// Info 4164: (510-511): Inferred type: 'cf:(type, P2)
109+
// Info 4164: (514-521): Inferred type: T('cf:(type, P2))
110+
// Info 4164: (517-521): Inferred type: T('cf:(type, P2))
111+
// Info 4164: (517-518): Inferred type: tfun('cf:(type, P2), T('cf:(type, P2)))
112+
// Info 4164: (519-520): Inferred type: 'cf:(type, P2)
113113
// Info 4164: (526-530): Inferred type: bool
114114
// Info 4164: (537-618): Inferred type: void
115-
// Info 4164: (552-565): Inferred type: ?bm:(type, P1, P2)
116-
// Info 4164: (553-564): Inferred type: ?bm:(type, P1, P2)
117-
// Info 4164: (556-564): Inferred type: ?bm:(type, P1, P2)
118-
// Info 4164: (557-559): Inferred type: ?bm:(type, P1, P2)
119-
// Info 4164: (561-563): Inferred type: ?bm:(type, P1, P2)
120-
// Info 4164: (575-616): Inferred type: (T(?bm:(type, P1, P2)), T(?bm:(type, P1, P2))) -> T(?bm:(type, P1, P2))
121-
// Info 4164: (587-605): Inferred type: (T(?bm:(type, P1, P2)), T(?bm:(type, P1, P2)))
122-
// Info 4164: (588-595): Inferred type: T(?bm:(type, P1, P2))
123-
// Info 4164: (591-595): Inferred type: T(?bm:(type, P1, P2))
124-
// Info 4164: (591-592): Inferred type: tfun(?bm:(type, P1, P2), T(?bm:(type, P1, P2)))
125-
// Info 4164: (593-594): Inferred type: ?bm:(type, P1, P2)
126-
// Info 4164: (597-604): Inferred type: T(?bm:(type, P1, P2))
127-
// Info 4164: (600-604): Inferred type: T(?bm:(type, P1, P2))
128-
// Info 4164: (600-601): Inferred type: tfun(?bm:(type, P1, P2), T(?bm:(type, P1, P2)))
129-
// Info 4164: (602-603): Inferred type: ?bm:(type, P1, P2)
130-
// Info 4164: (609-613): Inferred type: T(?bm:(type, P1, P2))
131-
// Info 4164: (609-610): Inferred type: tfun(?bm:(type, P1, P2), T(?bm:(type, P1, P2)))
132-
// Info 4164: (611-612): Inferred type: ?bm:(type, P1, P2)
115+
// Info 4164: (552-565): Inferred type: 'bj:(type, P1, P2)
116+
// Info 4164: (553-564): Inferred type: 'bj:(type, P1, P2)
117+
// Info 4164: (556-564): Inferred type: 'bj:(type, P1, P2)
118+
// Info 4164: (557-559): Inferred type: 'bj:(type, P1, P2)
119+
// Info 4164: (561-563): Inferred type: 'bj:(type, P1, P2)
120+
// Info 4164: (575-616): Inferred type: (T('bj:(type, P1, P2)), T('bj:(type, P1, P2))) -> T('bj:(type, P1, P2))
121+
// Info 4164: (587-605): Inferred type: (T('bj:(type, P1, P2)), T('bj:(type, P1, P2)))
122+
// Info 4164: (588-595): Inferred type: T('bj:(type, P1, P2))
123+
// Info 4164: (591-595): Inferred type: T('bj:(type, P1, P2))
124+
// Info 4164: (591-592): Inferred type: tfun('bj:(type, P1, P2), T('bj:(type, P1, P2)))
125+
// Info 4164: (593-594): Inferred type: 'bj:(type, P1, P2)
126+
// Info 4164: (597-604): Inferred type: T('bj:(type, P1, P2))
127+
// Info 4164: (600-604): Inferred type: T('bj:(type, P1, P2))
128+
// Info 4164: (600-601): Inferred type: tfun('bj:(type, P1, P2), T('bj:(type, P1, P2)))
129+
// Info 4164: (602-603): Inferred type: 'bj:(type, P1, P2)
130+
// Info 4164: (609-613): Inferred type: T('bj:(type, P1, P2))
131+
// Info 4164: (609-610): Inferred type: tfun('bj:(type, P1, P2), T('bj:(type, P1, P2)))
132+
// Info 4164: (611-612): Inferred type: 'bj:(type, P1, P2)
133133
// Info 4164: (620-748): Inferred type: (T(int), T(str)) -> ()
134134
// Info 4164: (632-662): Inferred type: (T(int), T(str))
135135
// Info 4164: (633-646): Inferred type: T(int)

0 commit comments

Comments
 (0)