Skip to content

Provide a fix-it that inserts omitted generic parameters when they can't be inferred #4682

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 3 commits into from
Sep 22, 2016

Conversation

jrose-apple
Copy link
Contributor

This will help when migrating to Swift 3 and Objective-C classes with newly-added generic parameters.

Still to do:

  • More tests
  • See if there's a way to handle conflicting context

rdar://problem/27087345

@jrose-apple
Copy link
Contributor Author

@nkcsgexi, @akyrtzi, what do you think about what's there so far? In particular, what do you think about the defaults?

  • No constraints, class X<T>: X<Any>(). Should this be X<<#T: Any##Any#>> instead?
  • Superclass constraint only, class X<T: UIView>: X<UIView>().
  • Class-bound only, class X<T: class>: X<AnyObject>(). Should this be X<<#T: class##AnyObject#>> instead?
  • Single ObjC protocol, class X<T: NSCoding>: X<NSCoding>().
  • Multiple protocols, or class+protocols: class X<T: UIViewController, UITableViewDataSource>: X<<#T: UIViewController & UITableViewDataSource#>>

Stepping back, is it okay to use placeholders at all here? (@DougGregor?) I see we have one other diagnostic with placeholders. Maybe we can change the text output format to special-case them (later).

@jrose-apple
Copy link
Contributor Author

@swift-ci Please smoke test

if (FoundGenericTypeBase && !isa<GenericIdentTypeRepr>(FoundGenericTypeBase)){
assert(FoundDecl);

SmallString<64> genericParamBuf;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this in any way similar to diagnoseUnboundGenericType() in TypeCheckType.cpp?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, good catch. I'll see if I can factor out common logic here. (I like my implementation better.)

@nkcsgexi
Copy link
Contributor

nkcsgexi commented Sep 9, 2016

I like the idea of using placeholders in fixits. We have a precedent of that in the fixits for auto-filling protocol conformances skeletons.

@DougGregor
Copy link
Member

I like the idea of using placeholders. It works very well in Xcode, and is fairly easy to handle in other tools that might want to present Fix-Its to the user.

@jrose-apple
Copy link
Contributor Author

Implementation mostly done, but I still need to write tests.

@swift-ci Please test

@jrose-apple
Copy link
Contributor Author

jrose-apple commented Sep 13, 2016

Apple, Linux

@jrose-apple
Copy link
Contributor Author

@nkcsgexi, would you mind reviewing this formally for the Swift 3.0 branch? And would you like me to make sure these fix-its are all enabled in migration mode?

@swift-ci Please test

@jrose-apple
Copy link
Contributor Author

Whoops, a test change snuck in there. Gotta fix that.

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 85b793e37a974dcbba3f9d78dcaf232c4eef59cc
Test requested by - @jrose-apple

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 85b793e37a974dcbba3f9d78dcaf232c4eef59cc
Test requested by - @jrose-apple

@jrose-apple
Copy link
Contributor Author

And it looks like master's messed up at the moment. I'll wait.

@jrose-apple jrose-apple changed the title [WIP] Provide a fix-it that inserts omitted generic parameters when they can't be inferred Provide a fix-it that inserts omitted generic parameters when they can't be inferred Sep 20, 2016
@nkcsgexi
Copy link
Contributor

Will review. This is a fixit associated with error, right? Isn't that automatically picked up by migrator?

@jrose-apple
Copy link
Contributor Author

I guess also:

  • @slavapestov, is this an okay use of GenericTypeParamDecl, or should I be using the generic signature and environment?
  • @DougGregor or @rudkx, is this a reasonable way to fish for resolved type parameters?

@jrose-apple
Copy link
Contributor Author

@nkcsgexi The new fix-it is on a note because usually you want a more specific type than the default…but in migration, you might not have a type because in Swift 2.3 it wasn't generic.

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

1 similar comment
@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 634055e298806183286699b229646be08c200860
Test requested by - @jrose-apple

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test Linux platform

@jrose-apple
Copy link
Contributor Author

macOS full tests passed earlier.

@swift-ci Please smoke test macOS platform

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 634055e298806183286699b229646be08c200860
Test requested by - @jrose-apple

@jrose-apple
Copy link
Contributor Author

^ @aciidb0mb3r, have you seen this SwiftPM failure before? (unrelated to this patch)

@aciidgh
Copy link
Contributor

aciidgh commented Sep 21, 2016

@jrose-apple unfortunately yes, I disabled a similar test failure here
swiftlang/swift-package-manager@57c5be1

will disable all related tests.

@aciidgh
Copy link
Contributor

aciidgh commented Sep 21, 2016

Disabled here: swiftlang/swift-package-manager@76714d2

@jrose-apple
Copy link
Contributor Author

Thanks, Ankit.

@swift-ci Please test Linux platform

return Type();

TypeVariableType *unused;
Type maybeFixedType = cs.getFixedTypeRecursive(preferred, unused,
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 a little confused here. If we can get generic argument type, why do we invoke CS to fix it? to remove unsubstituted type variables?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is for cases where we have some but not all of the generic arguments. Suggesting <Int, Any> is usually better than <Any, Any>.

Copy link
Contributor

Choose a reason for hiding this comment

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

oh, I see. Mind adding some inline comments?


if (protocols.empty()) {
genericParamText << "Any";
return;
Copy link
Contributor

Choose a reason for hiding this comment

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

For future proof, can we retrieve "Any" from ASTContext.getAnyDecl()->getName().

Copy link
Contributor

Choose a reason for hiding this comment

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

Otherwise, LGTM!

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's no "Any" decl anymore, but I'll switch it to Context.ID_Any so it's at least more searchable.

@jrose-apple
Copy link
Contributor Author

Updated for Xi's review comments.

@swift-ci Please smoke test

@nkcsgexi
Copy link
Contributor

Thank you!

For example, if someone tries to use the newly-generic type Cache,
from Foundation:

  var cache = Cache()

they'll now get a fix-it to substitute the default generic parameters:

  var cache = Cache<AnyObject, AnyObject>()

The rules for choosing this placeholder type are based on constraints
and won't be right 100% of the time, but they should be reasonable.
(In particular, constraints on associated types are ignored.)
In cases where there's no one concrete type that will work, an Xcode-
style placeholder is inserted instead.

- An unconstrained generic parameter defaults to 'Any'.
- A superclass-constrained parameter defaults to that class,
  e.g. 'UIView'.
- A parameter constrained to a single @objc protocol (or to AnyObject)
  defaults to that protocol, e.g. 'NSCoding'.
- Anything else gets a placeholder using the generic parameter's name
  and protocol composition syntax.

rdar://problem/27087345
Slava pointed out that we have an existing version of the code from
the previous commit that's only used when checking types. Replace it
with the new code, which handles more cases.
@jrose-apple
Copy link
Contributor Author

@swift-ci Please smoke test

1 similar comment
@jrose-apple
Copy link
Contributor Author

@swift-ci Please smoke test

@jrose-apple
Copy link
Contributor Author

Connectivity issue.

@swift-ci Please smoke test OS X platform

@jrose-apple
Copy link
Contributor Author

@swift-ci Please smoke test OS X platform

1 similar comment
@shahmishal
Copy link
Member

@swift-ci Please smoke test OS X platform

@jrose-apple jrose-apple merged commit 00d0b55 into swiftlang:master Sep 22, 2016
@jrose-apple jrose-apple deleted the generic-param-fix-it branch September 22, 2016 01:28
jrose-apple added a commit to jrose-apple/swift that referenced this pull request Sep 22, 2016
Provide a fix-it that inserts omitted generic parameters when they can't be inferred.

rdar://problem/27087345
@jrose-apple
Copy link
Contributor Author

Still waiting for feedback from @DougGregor or @rudkx on accessing the constraint system, and @slavapestov on the use of GenericTypeParamDecl.

@rudkx
Copy link
Contributor

rudkx commented Sep 22, 2016

@jrose-apple I suspect this is safe, but I could not guarantee it.

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.

8 participants