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

compiler: temporary disallow generics usages #3041

Merged
merged 5 commits into from
Aug 18, 2023
Merged

Conversation

AnnaShaleva
Copy link
Member

@AnnaShaleva AnnaShaleva commented Jun 14, 2023

This PR includes the following changes:

  1. Properly retrieve name of generic functions (fix panic described in panic: interface conversion: ast.Expr is *ast.IndexExpr, not *ast.Ident #3040).
  2. Disallow generics usages in the following cases:
    • Generic method receiver
    • Generic function parameters
    • Generic type declaration

Close #3040. Ref. #2377.

@AnnaShaleva
Copy link
Member Author

AnnaShaleva commented Jun 14, 2023

@roman-khimov, this problem is completely generics-related, I'm not sure we'd like to fix this panic right now with some temporary solution. Please, see the #3040 (comment).

@codecov
Copy link

codecov bot commented Jun 14, 2023

Codecov Report

Merging #3041 (66a8001) into master (90f1b0f) will increase coverage by 0.08%.
Report is 10 commits behind head on master.
The diff coverage is 94.02%.

@@            Coverage Diff             @@
##           master    #3041      +/-   ##
==========================================
+ Coverage   84.78%   84.86%   +0.08%     
==========================================
  Files         329      329              
  Lines       43953    44023      +70     
==========================================
+ Hits        37265    37360      +95     
+ Misses       5189     5160      -29     
- Partials     1499     1503       +4     
Files Changed Coverage Δ
pkg/compiler/func_scope.go 92.85% <73.33%> (-7.15%) ⬇️
pkg/compiler/analysis.go 96.46% <100.00%> (+0.30%) ⬆️
pkg/compiler/codegen.go 92.04% <100.00%> (+0.02%) ⬆️
pkg/compiler/debug.go 92.97% <100.00%> (ø)

... and 8 files with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@roman-khimov
Copy link
Member

We can just return an error if we detect any code using generics.

@AnnaShaleva
Copy link
Member Author

getFuncNameFromDecl is used in many places (including the map keys) and returns single string. Is it worth to change all its usages as temprary solution?

@roman-khimov
Copy link
Member

I don't know if there is any way to detect generic code use without going that deep. That'd be perfect, but if we don't have it then we can:

  • believe in this local fix to be sufficient for at least some subset of problems (maybe it really allows to compile something? maybe it'll fail in some other place?)
  • try leveraging c.prog.Err
  • try leveraging analyzeFuncAndGlobalVarUsage that looks at every function anyway and it does so before code-generating functions (btw, this seems to be easy enough to do)
  • at least panicing with some more meaningful message

@AnnaShaleva AnnaShaleva changed the title compiler: allow generic method receiver compiler: disallow generic method receiver Jun 14, 2023
@AnnaShaleva
Copy link
Member Author

Close #3040.

@AnnaShaleva
Copy link
Member Author

AnnaShaleva commented Jun 14, 2023

I've adjusted the behaviour for method receiver, now the proper error is returned to the user and it is done inside the analyzeFuncAndGlobalVarUsage before the compilation itself and #3040 is fixed by the currently presented commit. But I need some more time to carefully handle other cases of generics usages and not to break the existing code. Do we need to include these fixes to 0.102.0?

@roman-khimov
Copy link
Member

If you don't feel comfortable with these changes, it's OK to postpone them for 0.102.1, no need to rush here.

@AnnaShaleva AnnaShaleva changed the title compiler: disallow generic method receiver compiler: temporary disallow generics usages Aug 17, 2023
@AnnaShaleva AnnaShaleva marked this pull request as ready for review August 17, 2023 09:52
@AnnaShaleva
Copy link
Member Author

@roman-khimov, I've reworked the initial structure a bit so that it'll be easier for us to revert generics-related commits. Now all generics-related checks are separated in the checkGenerics* functions.

@AnnaShaleva AnnaShaleva added this to the v0.102.0 milestone Aug 18, 2023
Copy link
Member

@roman-khimov roman-khimov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we at least partially fix #3023 here? Our compiler documentation still doesn't say a word about generics.

case *ast.IndexExpr:
// Generic func declaration receiver: func (x *Pointer[T]) Load() *T
name = t.X.(*ast.IndexExpr).X.(*ast.Ident).Name + "." + name
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Panic by default?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we won't panic here. We will retrieve the proper name and I want this code to be kept in future (unlike the rest of commits in this PR). We will analize whether the method is generic in a separate place.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got your idea, will fix.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

name = t.X.(*ast.IndexExpr).X.(*ast.Ident).Name + "." + name
}
case *ast.IndexExpr:
switch t.X.(type) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a switch here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because there might be some other types, and if so, then we'll handle only the known one. Do you want to panic on something unexpected?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there needs to be some reasonable error, otherwise we have an undefined behavior and that's not what I would like to have in the compiler.

@@ -19,6 +19,8 @@ var (
ErrMissingExportedParamName = errors.New("exported method is not allowed to have unnamed parameter")
// ErrInvalidExportedRetCount is returned when exported contract method has invalid return values count.
ErrInvalidExportedRetCount = errors.New("exported method is not allowed to have more than one return value")
// ErrGenericsUnsuppored is returned when generics-related tokens are encountered.
ErrGenericsUnsuppored = errors.New("generics are currently unsupported, please, see the https://github.com/nspcc-dev/neo-go/issues/2377")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2376! Commits should reference it as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Fix panic described in #3040. Ref. #2376.

Signed-off-by: Anna Shaleva <[email protected]>
Either non-pointer or pointer, both cases are disallowed to be generic.
Need to be reverted and properly handled within the scope of #2376.

Signed-off-by: Anna Shaleva <[email protected]>
Need to be reverted and properly handled within the scope of #2376.

Signed-off-by: Anna Shaleva <[email protected]>
Need to be reverted and properly handled within the scope of #2376.

Signed-off-by: Anna Shaleva <[email protected]>
@AnnaShaleva AnnaShaleva force-pushed the generic-decl branch 3 times, most recently from 27edec4 to ec814da Compare August 18, 2023 13:29
docs/compiler.md Outdated
@@ -31,6 +31,8 @@ a dialect of Go rather than a complete port of the language:
* type assertion with two return values is not supported; single return value (of the desired type)
is supported; type assertion panics if value can't be asserted to the desired type, therefore
it's up to the programmer whether assert can be performed successfully.
* type aliases including the built-in `any` alias are supported.
* generics are not supported, but eventually will be, ref. https://github.com/nspcc-dev/neo-go/issues/2376.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure they will be supported properly, but partially maybe.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjusted.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hope, they will. At least function arguments can be supported, it doesn't seem impossible.

@roman-khimov roman-khimov merged commit 227b0c5 into master Aug 18, 2023
@roman-khimov roman-khimov deleted the generic-decl branch August 18, 2023 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

panic: interface conversion: ast.Expr is *ast.IndexExpr, not *ast.Ident
2 participants