Skip to content

Commit 44bf143

Browse files
authored
named tuple enum variant inference, named tuple parameter info (#239)
1 parent 5cc4caa commit 44bf143

File tree

8 files changed

+134
-46
lines changed

8 files changed

+134
-46
lines changed

src/main/kotlin/org/move/ide/hints/CallInfo.kt

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ class CallInfo(
2323

2424
companion object {
2525
fun resolve(callExpr: MvCallExpr): CallInfo? {
26-
val fn = callExpr.path.reference?.resolveFollowingAliases() as? MvFunction ?: return null
2726
val msl = callExpr.isMsl()
2827
val callTy = callExpr.inference(msl)?.getCallableType(callExpr) as? TyFunction ?: return null
29-
return buildFunctionParameters(fn, callTy)
28+
val item = callExpr.path.reference?.resolveFollowingAliases() ?: return null
29+
return buildFunctionParameters(item, callTy)
3030
}
3131

3232
fun resolve(assertMacroExpr: MvAssertMacroExpr): CallInfo {
@@ -43,14 +43,24 @@ class CallInfo(
4343
return buildFunctionParameters(fn, callTy)
4444
}
4545

46-
private fun buildFunctionParameters(function: MvFunction, ty: TyFunction): CallInfo {
47-
val tys = ty.paramTypes.drop(if (function.isMethod) 1 else 0)
48-
val params = function.parameters
49-
.drop(if (function.isMethod) 1 else 0).map { it.name to it.type }
50-
val self = function.selfParam?.let {
51-
ty.paramTypes.firstOrNull()?.let { "self: ${tyToString(it)}" } ?: "_"
46+
private fun buildFunctionParameters(item: MvElement, ty: TyFunction): CallInfo? {
47+
return when (item) {
48+
is MvFunction -> {
49+
val tys = ty.paramTypes.drop(if (item.isMethod) 1 else 0)
50+
val params = item.parameters
51+
.drop(if (item.isMethod) 1 else 0).map { it.name to it.type }
52+
val self = item.selfParam?.let {
53+
ty.paramTypes.firstOrNull()?.let { "self: ${tyToString(it)}" } ?: "_"
54+
}
55+
CallInfo(self, buildParameters(tys, params))
56+
}
57+
is MvStruct, is MvEnumVariant -> {
58+
// tuple struct
59+
val tys = ty.paramTypes
60+
CallInfo(null, tys.map { Parameter(null, null, it) })
61+
}
62+
else -> null
5263
}
53-
return CallInfo(self, buildParameters(tys, params))
5464
}
5565

5666
private fun buildParameters(

src/main/kotlin/org/move/ide/hints/paramInfo/CompositeParameterInfoHandler.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ class CompositeParameterInfoHandler: ParameterInfoHandler<PsiElement, ParameterI
4747
context.offset,
4848
MvElementTypes.COMMA
4949
)
50-
// if (listElement.valueArgumentList.isEmpty()) {
51-
// 0
52-
// } else {
53-
// }
5450
}
5551
context.setCurrentParameter(currentParameterIndex)
5652
}

src/main/kotlin/org/move/lang/core/types/infer/TyLowering.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ class TyLowering {
7474
val explicitTypeParams = explicitTypeParamsSubst(methodOrPath, namedItem, msl)
7575
baseTy.substitute(explicitTypeParams)
7676
}
77-
is MvEnumVariant -> lowerPath(methodOrPath, namedItem.enumItem, msl)
77+
is MvEnumVariant -> {
78+
// has to be MvPath of form `ENUM_NAME::ENUM_VARIANT_NAME`
79+
val enumPath = (methodOrPath as? MvPath)?.qualifier ?: return TyUnknown
80+
lowerPath(enumPath, namedItem.enumItem, msl)
81+
}
7882
else -> debugErrorOrFallback(
7983
"${namedItem.elementType} path cannot be inferred into type",
8084
TyUnknown
@@ -84,16 +88,17 @@ class TyLowering {
8488

8589
fun lowerCallable(
8690
methodOrPath: MvMethodOrPath,
87-
item: MvGenericDeclaration,
91+
namedItem: MvGenericDeclaration,
8892
parameterTypes: List<Ty>,
8993
returnType: Ty,
9094
msl: Boolean
9195
): TyFunction {
92-
val typeParamsSubst = item.typeParamsToTypeParamsSubst
93-
val acqTypes = (item as? MvFunctionLike)?.acquiresPathTypes.orEmpty().map { it.loweredType(msl) }
94-
val baseTy = TyFunction(item, typeParamsSubst, parameterTypes, returnType, acqTypes)
96+
val acqTypes = (namedItem as? MvFunctionLike)?.acquiresPathTypes.orEmpty().map { it.loweredType(msl) }
97+
val typeParamsSubst = namedItem.typeParamsToTypeParamsSubst
98+
99+
val baseTy = TyFunction(namedItem, typeParamsSubst, parameterTypes, returnType, acqTypes)
95100

96-
val explicitTypeParams = explicitTypeParamsSubst(methodOrPath, item, msl)
101+
val explicitTypeParams = explicitTypeParamsSubst(methodOrPath, namedItem, msl)
97102
return baseTy.substitute(explicitTypeParams) as TyFunction
98103
}
99104

src/main/kotlin/org/move/lang/core/types/infer/TypeInferenceWalker.kt

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ class TypeInferenceWalker(
324324
TyUnknown
325325
}
326326
}
327-
is MvEnumVariant -> item.enumItem.declaredType(ctx.msl)
327+
is MvEnumVariant -> TyLowering().lowerPath(pathExpr.path, item, ctx.msl)
328328
is MvModule -> TyUnknown
329329
else -> debugErrorOrFallback(
330330
"Referenced item ${item.elementType} " +
@@ -403,8 +403,7 @@ class TypeInferenceWalker(
403403
is MvFieldsOwner -> {
404404
val tupleFields = namedItem.tupleFields
405405
if (tupleFields == null) return TyUnknown
406-
val itemTy = instantiateTupleCallable(tupleFields, path, namedItem)
407-
itemTy
406+
instantiateTupleCallable(tupleFields, path, namedItem) ?: return TyUnknown
408407
}
409408
is MvPatBinding -> {
410409
ctx.getBindingType(namedItem) as? TyLambda
@@ -594,34 +593,24 @@ class TypeInferenceWalker(
594593

595594
private fun instantiateTupleCallable(
596595
tupleFields: MvTupleFields,
597-
methodOrPath: MvMethodOrPath,
596+
path: MvPath,
598597
item: MvFieldsOwner
599-
): TyFunction {
600-
val genericItem = when (item) {
601-
is MvStruct -> item
602-
is MvEnumVariant -> item.enumItem
598+
): TyFunction? {
599+
val (genericItem, genericPath) = when (item) {
600+
is MvStruct -> item to path
601+
is MvEnumVariant -> {
602+
val qualifierPath = path.qualifier ?: return null
603+
item.enumItem to qualifierPath
604+
}
603605
else -> error("exhaustive")
604606
}
605-
//
606607
val parameterTypes = tupleFields.tupleFieldDeclList.map { it.type.loweredType(msl) }
607608
val returnType = genericItem.declaredType(msl)
609+
val baseFuncTy =
610+
TyLowering().lowerCallable(genericPath, genericItem, parameterTypes, returnType, msl)
608611

609-
val funcTy = TyLowering().lowerCallable(methodOrPath, genericItem, parameterTypes, returnType, msl)
610-
//
611-
// val baseTy = TyFunction(
612-
// genericItem,
613-
// genericItem.typeParamsToTypeParamsSubst,
614-
// paramTypes = parameterTypes,
615-
// returnType = returnType,
616-
// acquiresTypes = emptyList(),
617-
// )
618-
//
619-
// val explicitTypeParamsSubst = TyLowering().explicitTypeParamsSubst(methodOrPath, genericItem, msl)
620-
// val funcTy = baseTy.substitute(explicitTypeParamsSubst)
621-
622-
// val baseTy = TyLowering().lowerTupleCallable(methodOrPath, item, tupleFields, msl)
623612
val tyVarsSubst = genericItem.tyVarsSubst
624-
return funcTy.substitute(tyVarsSubst) as TyFunction
613+
return baseFuncTy.substitute(tyVarsSubst) as TyFunction
625614
}
626615

627616
fun inferMacroCallExprTy(macroExpr: MvAssertMacroExpr): Ty {

src/main/kotlin/org/move/lang/core/types/ty/TyFunction.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,19 @@ data class TyFunction(
6060
}
6161
}
6262

63-
// do not account for explicit type arguments
63+
// does not account for explicit type arguments
6464
fun MvFunctionLike.functionTy(msl: Boolean): TyFunction = rawFunctionTy(this, msl)
6565

6666
private fun rawFunctionTy(item: MvFunctionLike, msl: Boolean): TyFunction {
6767
val typeParamsSubst = item.typeParamsToTypeParamsSubst
6868
val paramTypes = item.parameters.map { it.type?.loweredType(msl) ?: TyUnknown }
69-
val acquiredTypes = item.acquiresPathTypes.map { it.loweredType(msl) }
69+
val acqTypes = item.acquiresPathTypes.map { it.loweredType(msl) }
7070
val retType = item.returnTypeTy(msl)
7171
return TyFunction(
7272
item,
7373
typeParamsSubst,
7474
paramTypes,
7575
retType,
76-
acquiredTypes,
76+
acqTypes,
7777
)
7878
}

src/test/kotlin/org/move/ide/hints/ParameterInfoHandlerTest.kt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,44 @@ class ParameterInfoHandlerTest:
205205
}
206206
""", "_: bool, err: u64", 0
207207
)
208+
209+
@MoveV2
210+
fun `test parameter info for named tuple struct`() = checkByText("""
211+
module 0x1::m {
212+
struct S(u8, u16);
213+
fun main() {
214+
S(/*caret*/);
215+
}
216+
}
217+
""", "u8, u16", 0)
218+
219+
@MoveV2
220+
fun `test parameter info for generic named tuple struct`() = checkByText("""
221+
module 0x1::m {
222+
struct S<T>(T, T);
223+
fun main() {
224+
S<u8>(/*caret*/);
225+
}
226+
}
227+
""", "u8, u8", 0)
228+
229+
@MoveV2
230+
fun `test parameter info for named tuple enum variant`() = checkByText("""
231+
module 0x1::m {
232+
enum S { One(u8, u8) }
233+
fun main() {
234+
S::One(/*caret*/);
235+
}
236+
}
237+
""", "u8, u8", 0)
238+
239+
@MoveV2
240+
fun `test parameter info for generic named tuple enum variant`() = checkByText("""
241+
module 0x1::m {
242+
enum S<T> { One(T, T) }
243+
fun main() {
244+
S<u8>::One(/*caret*/);
245+
}
246+
}
247+
""", "u8, u8", 0)
208248
}

src/test/kotlin/org/move/lang/types/CallableTypeTest.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package org.move.lang.types
22

33
import org.intellij.lang.annotations.Language
44
import org.move.ide.presentation.text
5+
import org.move.lang.core.psi.MvCallExpr
56
import org.move.lang.core.psi.MvMethodCall
67
import org.move.lang.core.psi.ext.MvCallable
78
import org.move.lang.core.psi.ext.isMsl
@@ -54,6 +55,17 @@ class CallableTypeTest: TypificationTestCase() {
5455
}
5556
""")
5657

58+
fun `test function with explicit integer parameter callable type`() = testFunctionType("""
59+
module 0x1::m {
60+
fun call<T>(t: T): T { t }
61+
fun main() {
62+
call<u8>(1);
63+
//^ fn(u8) -> u8
64+
}
65+
}
66+
""")
67+
68+
private fun testFunctionType(@Language("Move") code: String) = testCallableType<MvCallExpr>(code)
5769
private fun testMethodType(@Language("Move") code: String) = testCallableType<MvMethodCall>(code)
5870

5971
private inline fun <reified T: MvCallable> testCallableType(@Language("Move") code: String) {

src/test/kotlin/org/move/lang/types/ExpressionTypesTest.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.move.lang.types
22

3+
import org.move.utils.tests.MoveV2
34
import org.move.utils.tests.NamedAddress
45
import org.move.utils.tests.types.TypificationTestCase
56

@@ -2185,4 +2186,39 @@ module 0x1::main {
21852186
}
21862187
}
21872188
""")
2189+
2190+
@MoveV2
2191+
fun `test generic enum variant`() = testExpr("""
2192+
module 0x1::m {
2193+
enum S<T> { One }
2194+
fun main() {
2195+
let a = S<u8>::One;
2196+
a;
2197+
//^ 0x1::m::S<u8>
2198+
}
2199+
}
2200+
""")
2201+
2202+
@MoveV2
2203+
fun `test generic enum variant with positional fields`() = testExpr("""
2204+
module 0x1::m {
2205+
enum S<T> { One(T, T) }
2206+
fun main() {
2207+
let a = S<u8>::One(1, 1);
2208+
a;
2209+
//^ 0x1::m::S<u8>
2210+
}
2211+
}
2212+
""")
2213+
2214+
fun `test function with explicit integer parameter return type`() = testExpr("""
2215+
module 0x1::m {
2216+
fun call<T>(t: T): T { t }
2217+
fun main() {
2218+
let a = call<u8>(1);
2219+
a;
2220+
//^ u8
2221+
}
2222+
}
2223+
""")
21882224
}

0 commit comments

Comments
 (0)