Skip to content

Don't canonicalize invalid GenericFunctionTypes in diagnostics #38327

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

Conversation

slavapestov
Copy link
Contributor

When emitting diagnostics we sometimes build GenericFunctionTypes with some requirements omitted, for brevity.

Unfortunately a GenericFunctionType with requirements omitted causes difficulties for getCanonicalType(), which tries to replace interface types inside the function type with their canonical representatives by calling into the GSB. While previously the GSB would accept various invalid inputs, the new requirement machine implementation is stricter and will assert if you pass an invalid interface type.

I found three places where types were canonicalized in diagnostics:

  • TypeBase::getASTContext() computes the canonical type, because a TypeBase stores either an ASTContext (if its canonical) or its canonical type (if its not canonical). Since canonicalizing a GenericFunctionType can be very expensive, this adds a fast path; if the type in question is a GenericFunctionType, we instead call getASTContext() on a structural sub-component that is known to exist (I picked the first generic parameter).
  • shouldShowAKA() was calling getCanonicalType(), but it should just use getAkaTypeForDisplay().
  • typeSpellingIsAmbiguous() was calling TypeBase::isEqual() which canonicalizes both sides, but it should just use pointer equality.

A better long term solution is to not build invalid GenericFunctionTypes at all; instead, we should use PrintOptions to enable various forms of filtering and customization for the generic signature that is output. But for now, these changes work, and they don't make anything worse, in my opinion.

…xt()

A TypeBase stores either an ASTContext if its canonical, or its canonical
type if it is not.

getASTContext() will then canonicalize the type if its not canonical.
While this is very clever, in the case of a GenericFunctionType, it
triggers the rather expensive creation of a GenericSignatureBuilder.

Avoid this by special-casing GenericFunctionType here and getting the
ASTContext from a structural sub-component that is known to exist
instead.
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test macOS

@slavapestov slavapestov merged commit 8530969 into swiftlang:main Jul 9, 2021
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.

2 participants