Skip to content

[ASTPrinter] Fix issue printing Self resolved to a generic type #36784

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

Merged
merged 1 commit into from
Apr 12, 2021

Conversation

ahoppen
Copy link
Member

@ahoppen ahoppen commented Apr 6, 2021

In some situations (see added test case), we end up with types that contain both an archetype and a generic type parameter. Trying to map them out of context would fail because mapTypeOutOfContext asserts that there are no type parameters in the type.

IIUC leaving the generic type parameters unchanged in MapTypeOutOfContext and removing the assertion should be the intended behaviour.

Fixes rdar://76021569

@ahoppen ahoppen requested review from akyrtzi and slavapestov April 6, 2021 22:39
Copy link
Contributor

@slavapestov slavapestov left a comment

Choose a reason for hiding this comment

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

I think this will mask other bugs. Types should never contain a mix of archetypes and interface types. Can we fix the downstream issue in the IDE code instead?

@ahoppen
Copy link
Member Author

ahoppen commented Apr 8, 2021

Thanks, for that info @slavapestov. I wasn’t sure if these mixed types really should never occur or if they just happened to not occur so far.

I have updated the PR to compute the interface type first before substituting it in for Self. Could you take another look?

Copy link
Contributor

@slavapestov slavapestov left a comment

Choose a reason for hiding this comment

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

Thanks, this is more maintainable, in my opinion at least!

@slavapestov slavapestov changed the title [AST] Skip GenericParamTypes in MapTypeOutOfContext [ASTPrinter] Fix issue printing Self resolved to a generic type Apr 8, 2021
@ahoppen
Copy link
Member Author

ahoppen commented Apr 8, 2021

Thanks, this is more maintainable, in my opinion at least!

I agree.

@akyrtzi This change caused some USRs to change. Could you take a look if this is can be considered a fix, problem or something we don’t have to care about?

In this definition

extension S3: P6 where Wrapped: P6 {}

The USR of the Wrapped generic param changed from

- s:4cake2S3VA2A2P6RzrlE7Wrappedxmfp ---> (extension in cake):cake.S3< where A: cake.P6>.Wrapped
+ s4cake2S3V7Wrappedxmfp ---> cake.S3.Wrapped

And here

extension D: _SomeProto where T: Equatable {
    public typealias Item = T
    
}

The USR of T changed as follows:

- s:16UnderscoredProto1DVAASQRzrlE1Txmfp ---> (extension in UnderscoredProto):UnderscoredProto.D< where A: Swift.Equatable>.T
+ s:16UnderscoredProto1DV1Txmfp ---> UnderscoredProto.D.T

@ahoppen
Copy link
Member Author

ahoppen commented Apr 9, 2021

After quite a bit of investigation, I think there is a bigger underlying issue with the USRs here that’s out of the scope of this PR to fix.

Each extension that makes restrictions on generic parameters redeclares those parameters with implicit GenericParamDecls. These new implicit declarations also encode the restrictions. Currently, in extensions we use these redeclared parameters. I think this is already counter-intuitive in terms of USRs because e.g. renaming a generic parameter in the original definition should also rename it in any extensions.

With this change, things start falling apart once we introduce typealiass. In a simplified example consider:

class MyClass<T> {
  typealias MyAlias = T
}
extension MyClass where T: Equatable {
  var x: MyAlias
}

There are two ways we can interpret MyAlias, which are AFAICT equivalent for all purposes apart from USRs:
1.) MyAlias refers to T declared in the extension, thus behaving more like a preprocessor statement (this is the current behavior)
2.) MyAlias refers to T declared in MyClass because we do a lookup on MyAlias, leading us into the definition of MyClass in which we know nothing of the extension.

My proposal would be to

  • Merge this PR as-is to resolve the crash in rdar://76021569, accepting that the USR assignment for generic params is somewhat broken and was so even before this PR

and in a follow-up PR

  • Canonicalize all generic params to refer to their original definition (opposed to their re-definition) in ASTPrinter. That way global rename would be able to rename also the generic params in extensions.

@akyrtzi What do you think?

@ahoppen
Copy link
Member Author

ahoppen commented Apr 9, 2021

@swift-ci Please smoke test

@akyrtzi
Copy link
Contributor

akyrtzi commented Apr 9, 2021

SGTM! Thanks for digging into this and discovering the issue!

When printing a type in type through `ASTPrinter::printTransformedTypeWithOptions`, we are removing any contextual types by mapping the type out of context. However, when substituting `Self` (or any other type member) with their concrete type from `CurrentType`, we might re-introduce contextual types.

To fix this, make sure that `CurrentType` is always an interface type that has all contextual types removed.

Fixes rdar://76021569
@ahoppen
Copy link
Member Author

ahoppen commented Apr 12, 2021

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 9ba892c

@ahoppen
Copy link
Member Author

ahoppen commented Apr 12, 2021

@swift-ci Please test macOS

@ahoppen ahoppen merged commit 501c716 into swiftlang:main Apr 12, 2021
@ahoppen ahoppen deleted the pr/rdar76021569 branch April 13, 2021 07:45
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.

4 participants