Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix incorrect type inference for InclusiveRange #2886

Closed
Tracked by #2482
darkdrag00nv2 opened this issue Oct 19, 2023 · 5 comments · Fixed by #3009
Closed
Tracked by #2482

Fix incorrect type inference for InclusiveRange #2886

darkdrag00nv2 opened this issue Oct 19, 2023 · 5 comments · Fixed by #3009
Assignees
Labels
Bug Something isn't working

Comments

@darkdrag00nv2
Copy link
Contributor

darkdrag00nv2 commented Oct 19, 2023

Issue to be solved

https://github.com/onflow/cadence/pull/2523/files#r1361281514

While testing, I also ran into the following cases that currently report errors, but shouldn't:

The inclusive range constructor always takes Int as the type parameter's type.

let r = InclusiveRange<Int>(0, 10)    // Works
let r = InclusiveRange<Int8>(0, 10)    // Checker error (should also work)

Also probably related to above, Type inferring also doesn't infer the type parameter from LHS.

let r: InclusiveRange<Int8> = InclusiveRange(0, 10)   // Type-mismatch error

Suggested Solution

No response

@darkdrag00nv2
Copy link
Contributor Author

@SupunS

Did a bit of investigation on this. I can see that we don't support type inference of function arguments as suggested by this comment:

// TODO: remove this once type inferring support for parameters is added

So seems like both the cases mentioned are not bugs but more of an existing limitation.

I am happy to take a shot at adding this support but would it be possible to untie this with the InclusiveRange work? I would like to wrap up the grant work sooner if possible and then take this up unless we consider this to be a blocker for the InclusiveRange feature. Thoughts?

cc: @turbolent

@turbolent
Copy link
Member

turbolent commented Oct 28, 2023

I didn't realize we still had some gaps there. Aren't we already using this elsewhere, e.g. for the storage save function? Has this maybe improved on the feature/stable-cadence branch?

The work on the standard library identified this gap in the checker, but the work / grant for the standard library is not dependent on resolving these gaps, no worries.

We might still need to address these gaps before shipping the feature, to avoid UX issues like shown in the description, but that is separate from your grant.

I wouldn't consider this a bug, but rather just missing functionality in the type checker, as you shown 👍

@SupunS
Copy link
Member

SupunS commented Oct 30, 2023

Makes sense. If this is already an existing limitation, and fixing it requires changing the way type-parameters are type-checked in general, then yeah, we can/should do it separately 👍

Thanks for looking into this!

@darkdrag00nv2
Copy link
Contributor Author

I didn't realize we still had some gaps there. Aren't we already using this elsewhere, e.g. for the storage save function? Has this maybe improved on the feature/stable-cadence branch?

@turbolent No, this hasn't improved. Please check this test:

t.Run("with generics", func(t *testing.T) {
t.Parallel()
typeParameter := &sema.TypeParameter{
Name: "T",
TypeBound: nil,
}
_, err := parseAndCheckWithTestValue(t,
`
let res = test<[Int8]>([1, 2, 3])
`,
&sema.FunctionType{
TypeParameters: []*sema.TypeParameter{
typeParameter,
},
Parameters: []sema.Parameter{
{
Label: sema.ArgumentLabelNotRequired,
Identifier: "value",
TypeAnnotation: sema.NewTypeAnnotation(
&sema.GenericType{
TypeParameter: typeParameter,
},
),
},
},
ReturnTypeAnnotation: sema.VoidTypeAnnotation,
},
)
errs := RequireCheckerErrors(t, err, 2)
require.IsType(t, &sema.TypeParameterTypeMismatchError{}, errs[0])
typeParamMismatchErr := errs[0].(*sema.TypeParameterTypeMismatchError)
assert.Equal(
t,
&sema.VariableSizedType{
Type: sema.Int8Type,
},
typeParamMismatchErr.ExpectedType,
)
assert.Equal(
t,
&sema.VariableSizedType{
Type: sema.IntType,
},
typeParamMismatchErr.ActualType,
)
require.IsType(t, &sema.TypeMismatchError{}, errs[1])
typeMismatchErr := errs[1].(*sema.TypeMismatchError)
assert.Equal(
t,
&sema.VariableSizedType{
Type: sema.Int8Type,
},
typeMismatchErr.ExpectedType,
)
assert.Equal(
t,
&sema.VariableSizedType{
Type: sema.IntType,
},
typeMismatchErr.ActualType,
)
})

@turbolent
Copy link
Member

Looking into this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants