Skip to content

Fix a Hole in Extension Checking For Non-Nominal Types and Indirectly Nominal Types #26970

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 2 commits into from
Sep 3, 2019

Conversation

CodaFi
Copy link
Contributor

@CodaFi CodaFi commented Aug 30, 2019

Relates to #26967. We were allowing a narrow class of extensions of trickily-constructed nominal types that involved some kind of indirection through a typealias to slip through our semantic checks. Diagnose these, and offer an error in the cases where we know we can rewrite the underlying type to a valid nominal type.

See also rdar://54799560, whose general pattern is reproduced in the added test.

@CodaFi CodaFi changed the title Extension winding Fix a Hole in Extension Checking For Non-Nominal Types and Indirectly Nominal Types Aug 30, 2019
@CodaFi CodaFi force-pushed the extension-winding branch from f4e70a5 to 0f9d085 Compare August 30, 2019 22:59
@CodaFi CodaFi requested a review from slavapestov August 30, 2019 22:59
@CodaFi
Copy link
Contributor Author

CodaFi commented Aug 30, 2019

@swift-ci please smoke test

@CodaFi
Copy link
Contributor Author

CodaFi commented Aug 30, 2019

@swift-ci please test source compatibility

.highlight(ED->getExtendedTypeRepr()->getSourceRange());
ED->diagnose(diag::invalid_nominal_extension_rewrite, canExtType)
.fixItReplace(ED->getExtendedTypeRepr()->getSourceRange(),
canExtType->getString());
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't usually allow a bound generic type here. Can you try a few cases and see if the fixit makes sense?

@@ -153,3 +153,13 @@ extension DoesNotImposeClassReq_2 where Self : AnyObject {
set { property = newValue } // Okay
}
}

// Reject extension of nominal type via indirection through a typealias
Copy link
Contributor

Choose a reason for hiding this comment

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

Type aliases are fine -- the problematic case here is a typealias whose underlying type is a type parameter. We can't resolve it at extension binding time without a conformance check.

if (!ED->getGenericParams() &&
!ED->isInvalid()) {
ED->diagnose(diag::extension_nongeneric_trailing_where,
nominal->getFullName())
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: Indentation is off by one here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One day I will fix Xcode's C++ support...

@slavapestov
Copy link
Contributor

Looks great other than a few small suggestions, thanks!

slavapestov and others added 2 commits August 31, 2019 18:38
If getExtendedNominal() fails but getExtendedType() succeeds, we need
to diagnose otherwise we end up with a bogus extension not bound to
anything.
If the canonical type is a nominal type then we can offer a diagnostic
that rewrites to it.

Resolves rdar://54799560
@CodaFi
Copy link
Contributor Author

CodaFi commented Sep 1, 2019

@swift-ci please smoke test

@@ -50,14 +50,6 @@ extension K {
func replacement_finalFunction() {}
}

extension undeclared { // expected-error{{use of undeclared type 'undeclared'}}
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of deleting the test case, just update the expected-errors

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There aren't any meaningful errors in either file. We just diagnose the extension now.

Copy link
Contributor

Choose a reason for hiding this comment

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

My point still stands. We want to make sure we don’t regress and start crashing here. It’s testing a specific case where the extension has a missing type and a nested type is inside it.

@@ -8,12 +8,12 @@ extension G {
}
}

extension { // expected-error {{expected type name in extension declaration}}
struct S<T> {
extension G {
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of changing the test case, just update the expected-errors

Copy link
Contributor

Choose a reason for hiding this comment

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

Same point applies

@CodaFi
Copy link
Contributor Author

CodaFi commented Sep 3, 2019

⛵️

@CodaFi CodaFi merged commit 157613a into swiftlang:master Sep 3, 2019
@CodaFi CodaFi deleted the extension-winding branch September 3, 2019 16:37
CodaFi added a commit to CodaFi/swift that referenced this pull request Sep 6, 2019
Address review feedback on swiftlang#26970
@CodaFi CodaFi mentioned this pull request Sep 6, 2019
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