Skip to content

[NameLookup] Swift 4 compatibility hack for cross-module var overloads in generic type extensions #18488

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

Conversation

hamishknight
Copy link
Contributor

In Swift 4, we only gave custom overload types to properties defined in extensions of generic types, using the null type for any other var decl. This meant that a property defined in such an extension would never shadow a property not defined in such an extension. As a result, this permitted cross-module overloads of properties of different types on generic types in certain cases.

#15412 changed the overload type logic to produce more consistent overload types, but in doing so inadvertently caused a source breakage by rejecting such cross-module property overloads (as we now always consider the property in the current module to shadow the imported one).

This PR adds an exception to the shadowing rules for properties defined in generic type extensions under Swift 4 mode. Permitting cross-module property overloads in the general case would be source breaking (causing ambiguity errors), so this can be handled in a follow-up Swift 5 mode PR if desired.

In addition, this PR adds a test case for an AnyObject lookup ambiguity error introduced by #15412.

Resolves SR-7341.

@hamishknight
Copy link
Contributor Author

cc. @jrose-apple & @DougGregor. I know it's pretty late in the release cycle, but would it be possible to cherry pick this to 4.2?

Copy link
Member

@DougGregor DougGregor left a comment

Choose a reason for hiding this comment

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

This change LGTM!

@DougGregor
Copy link
Member

I think we've missed the window for Swift 4.2, particularly with changes that could affect source compatibility. This looks good for master, though, thanks!

@jrose-apple
Copy link
Contributor

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Aug 3, 2018

Build failed
Swift Test OS X Platform
Git Sha - bac01cf400ba6cc541789cfd792601638fef7ebe

@hamishknight
Copy link
Contributor Author

I think we've missed the window for Swift 4.2

That's what I feared – thanks for confirming!

Can you confirm whether or not we want cross-module property overloading in the general case for Swift 5 mode (bearing in mind it being potentially source-breaking)? If so, I'm happy to work on that as a follow-up.

@hamishknight
Copy link
Contributor Author

Also looks like the OS X buildbot is failing consistently with:

invalid argument '-mmacosx-version-min=10.9' not allowed with '-mtvos-simulator-version-min=9.0'

@swift-ci
Copy link
Contributor

swift-ci commented Aug 3, 2018

Build failed
Swift Test Linux Platform
Git Sha - bac01cf400ba6cc541789cfd792601638fef7ebe

@jrose-apple
Copy link
Contributor

cc @clackary, @shahmishal

@shahmishal
Copy link
Member

This issue should be resolved, we reverted the commit which caused the issue.

@shahmishal
Copy link
Member

@swift-ci test

@slavapestov
Copy link
Contributor

@hamishknight Maybe this warrants some evolution discussion, if not a full proposal just a thread. I'd like to understand the new rules in 4.2 as well as the compatibility hacks you added to remain compatible with 4.1, and come up with a model that's simple and consistent. It's OK to have minor source breaks in -swift-version 5 mode; we just have to ensure the new behavior makes the most sense going forward.

// This is due to the fact that in Swift 4, we only gave custom overload
// types to properties in extensions of generic types, otherwise we
// used the null type.
if (!ctx.isSwiftVersionAtLeast(5)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What if we instead said that in Swift 5, all properties get a real overload signature? Why should properties be any different from methods in this regard?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@slavapestov By "real overload signature", do you mean that two properties of different type would always be allowed to overload each other? I'm not mad on this idea, as IMO it would encourage tricky code that relies on overload resolution by "return type", which I believe is something we want to discourage (listed in the API design guidelines under "General conventions" > "Methods can share a base name").

However given that we already allow what would otherwise be re-declarations across module boundaries for both properties and methods, I personally think that it seems reasonable to allow different typed properties to overload across modules (as the shadowing behaviour is otherwise a bit unintuitive).

Though whatever we choose, I agree we should definitely make the behaviour consistent in Swift 5 mode!

@hamishknight
Copy link
Contributor Author

@slavapestov Thanks for the suggestion! I'm happy to open to an evolution thread to discuss this change (and the more general behaviour going forwards) in more detail – I'll try and do so before the end of the day.

@hamishknight
Copy link
Contributor Author

@hamishknight
Copy link
Contributor Author

Just resolved a merge conflict – is this good to merge? I'll file a JIRA to track the Swift 5 mode changes.

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.

Looks good, can you fix the test case and rebase and then we'll merge?


func useString(_ str: String) {}

// In Swift 5, we currently consistently reject cross-module property overloading.
Copy link
Contributor

Choose a reason for hiding this comment

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

You should have test errors that expect errors in that case

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks Slava, I've gone ahead and made that change.

Copy link
Contributor

Choose a reason for hiding this comment

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

Did you not push it yet?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did push, and it shows up on GitHub for me (HEAD at c54ab4d). Should I re-rebase and try to push again?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm looking at this part:

// In Swift 5, we currently consistently reject cross-module property overloading.
 // FIX-ME: This seems reasonable to permit.

Is there a test for this behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@slavapestov Apologies, I realise now that the comment isn't particularly well-worded. When I say "reject cross-module property overloading", what I really mean is "properties from this module always shadow properties from the other module, and therefore the other module's properties never show up in the overload set" – which is what the tests in that file are testing.

Your original comment prompted me to add expected-errors in order to ensure the other module's properties didn't show up in the overload set (previously I was just testing that a bare reference wasn't ambiguous).

I'll edit the comment in the test file to clarify things.

@slavapestov slavapestov self-assigned this Aug 15, 2018
@hamishknight hamishknight force-pushed the swift4-cross-module-var-overload branch 2 times, most recently from c54ab4d to be88c40 Compare August 18, 2018 11:30
…s in generic type extensions

In Swift 4, we only gave custom overload types to properties defined in extensions of generic types, using the null type for any other var decl. This meant that a property defined in such an extension would never shadow a property not defined in such an extension. As a result, this permitted cross-module overloads of properties of different types on generic types in certain cases.

This patch adds an exception to the shadowing rules for properties defined in generic type extensions under Swift 4 mode. Permitting cross-module property overloads in the general case would also be source breaking (causing ambiguity errors), so this can be handled in a follow-up Swift 5 mode PR if desired.

Resolves SR-7341.
@hamishknight hamishknight force-pushed the swift4-cross-module-var-overload branch from be88c40 to 1e764cc Compare August 18, 2018 11:35
@slavapestov
Copy link
Contributor

@swift-ci Please test

@slavapestov
Copy link
Contributor

@swift-ci Please test source compatibility

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - bac01cf400ba6cc541789cfd792601638fef7ebe

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - bac01cf400ba6cc541789cfd792601638fef7ebe

@slavapestov slavapestov merged commit 98e95bd into swiftlang:master Aug 22, 2018
@hamishknight hamishknight deleted the swift4-cross-module-var-overload branch August 22, 2018 10:08
@hamishknight
Copy link
Contributor Author

Thanks Slava! I've filed a JIRA for the Swift 5 mode changes: https://bugs.swift.org/browse/SR-8619.

@hamishknight
Copy link
Contributor Author

@slavapestov Do you think this would be worth cherry picking to the 4.2 branch now that it's taking changes for a potential 4.2.1 release? IMO the risk should be minimal.

@slavapestov
Copy link
Contributor

There's no harm in opening a PR; final decision rests with @tkremenek though.

@hamishknight
Copy link
Contributor Author

Opened a 4.2 PR: #19223

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.

6 participants