{"action":"created","comment":{"url":"https://api.github.com/repos/apple/swift/pulls/comments/175270215","pull_request_review_id":104778412,"id":175270215,"diff_hunk":"@@ -3449,24 +3448,95 @@ ConstraintSystem::simplifyMemberConstraint(ConstraintKind kind,\n     instanceTy = MTT->getInstanceType();\n   \n   // Value member lookup has some hacks too.\n-  if (shouldAttemptFixes() && baseObjTy->getOptionalObjectType()) {\n+  auto unwrappedBaseObjTy = baseObjTy->getOptionalObjectType();\n+  if (unwrappedBaseObjTy) {\n     // If the base type was an optional, look through it.\n-    \n-    // Determine whether or not we want to provide an optional chaining fixit or\n-    // a force unwrap fixit.\n-    bool optionalChain;\n-    if (!getContextualType())\n-      optionalChain = !(Options & ConstraintSystemFlags::PreferForceUnwrapToOptional);\n-    else\n-      optionalChain = !getContextualType()->getOptionalObjectType().isNull();\n-    auto fixKind = optionalChain ? FixKind::OptionalChaining : FixKind::ForceOptional;\n-\n-    // Note the fix.\n-    if (recordFix(fixKind, locator))\n-      return SolutionKind::Error;\n-    \n+\n+    // Figure out if we have an existing optional chaining fix done earlier in\n+    // this dotted expression chain.\n+    bool continuingChain = false;\n+    if (auto dotExpr = dyn_cast<UnresolvedDotExpr>(locator->getAnchor())) {\n+      for (auto pair : Fixes) {\n+        if (pair.first.getKind() == FixKind::OptionalChaining) {\n+          auto innerExpr = dotExpr->getBase();\n+          while (innerExpr) {\n+            if (pair.second->getAnchor() == innerExpr) {\n+              continuingChain = true;\n+              break;\n+            }\n+            if (auto innerDot = dyn_cast<UnresolvedDotExpr>(innerExpr))\n+              innerExpr = innerDot->getBase();\n+          }\n+        }\n+      }\n+    }\n+\n+    // If we aren't continuing an existing chain, do we want to add a new fixit?\n+    if (!continuingChain) {\n+      if (!shouldAttemptFixes())\n+        return SolutionKind::Error;\n+\n+      auto contextTy = getContextualType();\n+      bool forceUnwrap;\n+      if (contextTy)\n+        forceUnwrap = contextTy->getOptionalObjectType().isNull();\n+      else\n+        forceUnwrap = Options.contains(ConstraintSystemFlags::PreferForceUnwrapToOptional);\n+\n+      // Note the fix.\n+      auto fixKind = forceUnwrap ? FixKind::ForceOptional : FixKind::OptionalChaining;\n+      if (recordFix(fixKind, locator))\n+        return SolutionKind::Error;\n+\n+      if (forceUnwrap) {\n+        // The simple case - just look through one level of optional.\n+        addValueMemberConstraint(unwrappedBaseObjTy,\n+                                 member, memberTy, useDC, functionRefKind, locator);\n+        return SolutionKind::Solved;\n+      }\n+    }\n+\n+    // See if there is a matching member with an optional type.\n+    // If so, then inserting an optional chaining fix won't produce a MORE optional result,\n+    // and it is safe to just fix with chaining.\n+    MemberLookupResult result =\n+      performMemberLookup(kind, member, unwrappedBaseObjTy, functionRefKind, locator,\n+                          /*includeInaccessibleMembers*/false);\n+    bool memberIsOptional = false;\n+    for (auto candidate : result.ViableCandidates) {\n+      if (candidate.isDecl())\n+        memberIsOptional |= !candidate.getDecl()->getInterfaceType()->\n+                              getOptionalObjectType().isNull();\n+    }\n+\n+    // If the member isn't already optional, we need to make the result optional.\n+    if (!memberIsOptional) {\n+      auto innerTV = createTypeVariable(locator, TVO_CanBindToLValue | TVO_CanBindToInOut);","path":"lib/Sema/CSSimplify.cpp","position":90,"original_position":90,"commit_id":"d5ed794f3fc7b75b0cf00e8308563ee8823f25d3","original_commit_id":"d5ed794f3fc7b75b0cf00e8308563ee8823f25d3","user":{"login":"slavapestov","id":66486,"avatar_url":"https://avatars1.githubusercontent.com/u/66486?v=4","gravatar_id":"","url":"https://api.github.com/users/slavapestov","html_url":"https://github.com/slavapestov","followers_url":"https://api.github.com/users/slavapestov/followers","following_url":"https://api.github.com/users/slavapestov/following{/other_user}","gists_url":"https://api.github.com/users/slavapestov/gists{/gist_id}","starred_url":"https://api.github.com/users/slavapestov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/slavapestov/subscriptions","organizations_url":"https://api.github.com/users/slavapestov/orgs","repos_url":"https://api.github.com/users/slavapestov/repos","events_url":"https://api.github.com/users/slavapestov/events{/privacy}","received_events_url":"https://api.github.com/users/slavapestov/received_events","type":"User","site_admin":false},"body":"“Can bind to inout” used to be the default. When I made an explicit flag for it, I went and added it in every place we were creating a type variable. Most of them can lose the flag - that was the original motivation for adding it - but nobody got around to cleaning that up yet. Maybe @CodaFi can do it :)","created_at":"2018-03-17T21:09:01Z","updated_at":"2018-03-17T21:09:02Z","html_url":"https://github.com/apple/swift/pull/15321#discussion_r175270215","pull_request_url":"https://api.github.com/repos/apple/swift/pulls/15321","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/apple/swift/pulls/comments/175270215"},"html":{"href":"https://github.com/apple/swift/pull/15321#discussion_r175270215"},"pull_request":{"href":"https://api.github.com/repos/apple/swift/pulls/15321"}},"in_reply_to_id":175248378},"pull_request":{"url":"https://api.github.com/repos/apple/swift/pulls/15321","id":175682367,"html_url":"https://github.com/apple/swift/pull/15321","diff_url":"https://github.com/apple/swift/pull/15321.diff","patch_url":"https://github.com/apple/swift/pull/15321.patch","issue_url":"https://api.github.com/repos/apple/swift/issues/15321","number":15321,"state":"open","locked":false,"title":"[Sema] More correct optional chaining vs. force unwrap fixits","user":{"login":"gregomni","id":15795449,"avatar_url":"https://avatars3.githubusercontent.com/u/15795449?v=4","gravatar_id":"","url":"https://api.github.com/users/gregomni","html_url":"https://github.com/gregomni","followers_url":"https://api.github.com/users/gregomni/followers","following_url":"https://api.github.com/users/gregomni/following{/other_user}","gists_url":"https://api.github.com/users/gregomni/gists{/gist_id}","starred_url":"https://api.github.com/users/gregomni/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gregomni/subscriptions","organizations_url":"https://api.github.com/users/gregomni/orgs","repos_url":"https://api.github.com/users/gregomni/repos","events_url":"https://api.github.com/users/gregomni/events{/privacy}","received_events_url":"https://api.github.com/users/gregomni/received_events","type":"User","site_admin":false},"body":"Be smarter about optional chaining fixits. Previously if we didn't already know a contextual result type to check for optionality we'd always optimistically offer an optional chaining fixit, which results in many new programmers hitting the fix button to add an \"?\" to an expression that needs a non-optional final value, only to hit the fix button again to add an \"!\" the next compile now that context is clearer.\r\n\r\nSee https://forums.swift.org/t/resolved-insert-is-a-bad-fixit/10764/34 for more.\r\n\r\nNow we make a disjunction to try both ways and get a correct result the first time. The code turns out to be a bit baroque for long dotted member chains because we need to stepwise make optional each member along the path because we don't have the advantage of rearranging the AST to group the whole chain here inside the constraint system, but we manage it while only making a single\r\nfixit and disjunction and referring back to that original fixit at each step. \r\n","created_at":"2018-03-17T04:17:02Z","updated_at":"2018-03-17T21:09:02Z","closed_at":null,"merged_at":null,"merge_commit_sha":"302c139c8f89cc2db3e6403ff2d779d07d4adbd1","assignee":null,"assignees":[],"requested_reviewers":[{"login":"xedin","id":21240,"avatar_url":"https://avatars1.githubusercontent.com/u/21240?v=4","gravatar_id":"","url":"https://api.github.com/users/xedin","html_url":"https://github.com/xedin","followers_url":"https://api.github.com/users/xedin/followers","following_url":"https://api.github.com/users/xedin/following{/other_user}","gists_url":"https://api.github.com/users/xedin/gists{/gist_id}","starred_url":"https://api.github.com/users/xedin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xedin/subscriptions","organizations_url":"https://api.github.com/users/xedin/orgs","repos_url":"https://api.github.com/users/xedin/repos","events_url":"https://api.github.com/users/xedin/events{/privacy}","received_events_url":"https://api.github.com/users/xedin/received_events","type":"User","site_admin":false},{"login":"rudkx","id":162784,"avatar_url":"https://avatars1.githubusercontent.com/u/162784?v=4","gravatar_id":"","url":"https://api.github.com/users/rudkx","html_url":"https://github.com/rudkx","followers_url":"https://api.github.com/users/rudkx/followers","following_url":"https://api.github.com/users/rudkx/following{/other_user}","gists_url":"https://api.github.com/users/rudkx/gists{/gist_id}","starred_url":"https://api.github.com/users/rudkx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rudkx/subscriptions","organizations_url":"https://api.github.com/users/rudkx/orgs","repos_url":"https://api.github.com/users/rudkx/repos","events_url":"https://api.github.com/users/rudkx/events{/privacy}","received_events_url":"https://api.github.com/users/rudkx/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/apple/swift/pulls/15321/commits","review_comments_url":"https://api.github.com/repos/apple/swift/pulls/15321/comments","review_comment_url":"https://api.github.com/repos/apple/swift/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apple/swift/issues/15321/comments","statuses_url":"https://api.github.com/repos/apple/swift/statuses/d5ed794f3fc7b75b0cf00e8308563ee8823f25d3","head":{"label":"gregomni:opty","ref":"opty","sha":"d5ed794f3fc7b75b0cf00e8308563ee8823f25d3","user":{"login":"gregomni","id":15795449,"avatar_url":"https://avatars3.githubusercontent.com/u/15795449?v=4","gravatar_id":"","url":"https://api.github.com/users/gregomni","html_url":"https://github.com/gregomni","followers_url":"https://api.github.com/users/gregomni/followers","following_url":"https://api.github.com/users/gregomni/following{/other_user}","gists_url":"https://api.github.com/users/gregomni/gists{/gist_id}","starred_url":"https://api.github.com/users/gregomni/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gregomni/subscriptions","organizations_url":"https://api.github.com/users/gregomni/orgs","repos_url":"https://api.github.com/users/gregomni/repos","events_url":"https://api.github.com/users/gregomni/events{/privacy}","received_events_url":"https://api.github.com/users/gregomni/received_events","type":"User","site_admin":false},"repo":{"id":47734038,"name":"swift","full_name":"gregomni/swift","owner":{"login":"gregomni","id":15795449,"avatar_url":"https://avatars3.githubusercontent.com/u/15795449?v=4","gravatar_id":"","url":"https://api.github.com/users/gregomni","html_url":"https://github.com/gregomni","followers_url":"https://api.github.com/users/gregomni/followers","following_url":"https://api.github.com/users/gregomni/following{/other_user}","gists_url":"https://api.github.com/users/gregomni/gists{/gist_id}","starred_url":"https://api.github.com/users/gregomni/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gregomni/subscriptions","organizations_url":"https://api.github.com/users/gregomni/orgs","repos_url":"https://api.github.com/users/gregomni/repos","events_url":"https://api.github.com/users/gregomni/events{/privacy}","received_events_url":"https://api.github.com/users/gregomni/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/gregomni/swift","description":"The Swift Programming Language","fork":true,"url":"https://api.github.com/repos/gregomni/swift","forks_url":"https://api.github.com/repos/gregomni/swift/forks","keys_url":"https://api.github.com/repos/gregomni/swift/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gregomni/swift/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gregomni/swift/teams","hooks_url":"https://api.github.com/repos/gregomni/swift/hooks","issue_events_url":"https://api.github.com/repos/gregomni/swift/issues/events{/number}","events_url":"https://api.github.com/repos/gregomni/swift/events","assignees_url":"https://api.github.com/repos/gregomni/swift/assignees{/user}","branches_url":"https://api.github.com/repos/gregomni/swift/branches{/branch}","tags_url":"https://api.github.com/repos/gregomni/swift/tags","blobs_url":"https://api.github.com/repos/gregomni/swift/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gregomni/swift/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gregomni/swift/git/refs{/sha}","trees_url":"https://api.github.com/repos/gregomni/swift/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gregomni/swift/statuses/{sha}","languages_url":"https://api.github.com/repos/gregomni/swift/languages","stargazers_url":"https://api.github.com/repos/gregomni/swift/stargazers","contributors_url":"https://api.github.com/repos/gregomni/swift/contributors","subscribers_url":"https://api.github.com/repos/gregomni/swift/subscribers","subscription_url":"https://api.github.com/repos/gregomni/swift/subscription","commits_url":"https://api.github.com/repos/gregomni/swift/commits{/sha}","git_commits_url":"https://api.github.com/repos/gregomni/swift/git/commits{/sha}","comments_url":"https://api.github.com/repos/gregomni/swift/comments{/number}","issue_comment_url":"https://api.github.com/repos/gregomni/swift/issues/comments{/number}","contents_url":"https://api.github.com/repos/gregomni/swift/contents/{+path}","compare_url":"https://api.github.com/repos/gregomni/swift/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gregomni/swift/merges","archive_url":"https://api.github.com/repos/gregomni/swift/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gregomni/swift/downloads","issues_url":"https://api.github.com/repos/gregomni/swift/issues{/number}","pulls_url":"https://api.github.com/repos/gregomni/swift/pulls{/number}","milestones_url":"https://api.github.com/repos/gregomni/swift/milestones{/number}","notifications_url":"https://api.github.com/repos/gregomni/swift/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gregomni/swift/labels{/name}","releases_url":"https://api.github.com/repos/gregomni/swift/releases{/id}","deployments_url":"https://api.github.com/repos/gregomni/swift/deployments","created_at":"2015-12-10T02:58:32Z","updated_at":"2018-03-14T01:12:44Z","pushed_at":"2018-03-17T04:09:55Z","git_url":"git://github.com/gregomni/swift.git","ssh_url":"git@github.com:gregomni/swift.git","clone_url":"https://github.com/gregomni/swift.git","svn_url":"https://github.com/gregomni/swift","homepage":"","size":252799,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"apple:master","ref":"master","sha":"ea83df4c9debcfc38d10635820f08240e529cb28","user":{"login":"apple","id":10639145,"avatar_url":"https://avatars0.githubusercontent.com/u/10639145?v=4","gravatar_id":"","url":"https://api.github.com/users/apple","html_url":"https://github.com/apple","followers_url":"https://api.github.com/users/apple/followers","following_url":"https://api.github.com/users/apple/following{/other_user}","gists_url":"https://api.github.com/users/apple/gists{/gist_id}","starred_url":"https://api.github.com/users/apple/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apple/subscriptions","organizations_url":"https://api.github.com/users/apple/orgs","repos_url":"https://api.github.com/users/apple/repos","events_url":"https://api.github.com/users/apple/events{/privacy}","received_events_url":"https://api.github.com/users/apple/received_events","type":"Organization","site_admin":false},"repo":{"id":44838949,"name":"swift","full_name":"apple/swift","owner":{"login":"apple","id":10639145,"avatar_url":"https://avatars0.githubusercontent.com/u/10639145?v=4","gravatar_id":"","url":"https://api.github.com/users/apple","html_url":"https://github.com/apple","followers_url":"https://api.github.com/users/apple/followers","following_url":"https://api.github.com/users/apple/following{/other_user}","gists_url":"https://api.github.com/users/apple/gists{/gist_id}","starred_url":"https://api.github.com/users/apple/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apple/subscriptions","organizations_url":"https://api.github.com/users/apple/orgs","repos_url":"https://api.github.com/users/apple/repos","events_url":"https://api.github.com/users/apple/events{/privacy}","received_events_url":"https://api.github.com/users/apple/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apple/swift","description":"The Swift Programming Language","fork":false,"url":"https://api.github.com/repos/apple/swift","forks_url":"https://api.github.com/repos/apple/swift/forks","keys_url":"https://api.github.com/repos/apple/swift/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apple/swift/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apple/swift/teams","hooks_url":"https://api.github.com/repos/apple/swift/hooks","issue_events_url":"https://api.github.com/repos/apple/swift/issues/events{/number}","events_url":"https://api.github.com/repos/apple/swift/events","assignees_url":"https://api.github.com/repos/apple/swift/assignees{/user}","branches_url":"https://api.github.com/repos/apple/swift/branches{/branch}","tags_url":"https://api.github.com/repos/apple/swift/tags","blobs_url":"https://api.github.com/repos/apple/swift/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apple/swift/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apple/swift/git/refs{/sha}","trees_url":"https://api.github.com/repos/apple/swift/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apple/swift/statuses/{sha}","languages_url":"https://api.github.com/repos/apple/swift/languages","stargazers_url":"https://api.github.com/repos/apple/swift/stargazers","contributors_url":"https://api.github.com/repos/apple/swift/contributors","subscribers_url":"https://api.github.com/repos/apple/swift/subscribers","subscription_url":"https://api.github.com/repos/apple/swift/subscription","commits_url":"https://api.github.com/repos/apple/swift/commits{/sha}","git_commits_url":"https://api.github.com/repos/apple/swift/git/commits{/sha}","comments_url":"https://api.github.com/repos/apple/swift/comments{/number}","issue_comment_url":"https://api.github.com/repos/apple/swift/issues/comments{/number}","contents_url":"https://api.github.com/repos/apple/swift/contents/{+path}","compare_url":"https://api.github.com/repos/apple/swift/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apple/swift/merges","archive_url":"https://api.github.com/repos/apple/swift/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apple/swift/downloads","issues_url":"https://api.github.com/repos/apple/swift/issues{/number}","pulls_url":"https://api.github.com/repos/apple/swift/pulls{/number}","milestones_url":"https://api.github.com/repos/apple/swift/milestones{/number}","notifications_url":"https://api.github.com/repos/apple/swift/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apple/swift/labels{/name}","releases_url":"https://api.github.com/repos/apple/swift/releases{/id}","deployments_url":"https://api.github.com/repos/apple/swift/deployments","created_at":"2015-10-23T21:15:07Z","updated_at":"2018-03-17T20:25:34Z","pushed_at":"2018-03-17T20:59:32Z","git_url":"git://github.com/apple/swift.git","ssh_url":"git@github.com:apple/swift.git","clone_url":"https://github.com/apple/swift.git","svn_url":"https://github.com/apple/swift","homepage":"https://swift.org/","size":271659,"stargazers_count":42990,"watchers_count":42990,"language":"C++","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":6773,"mirror_url":null,"archived":false,"open_issues_count":288,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":6773,"open_issues":288,"watchers":42990,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apple/swift/pulls/15321"},"html":{"href":"https://github.com/apple/swift/pull/15321"},"issue":{"href":"https://api.github.com/repos/apple/swift/issues/15321"},"comments":{"href":"https://api.github.com/repos/apple/swift/issues/15321/comments"},"review_comments":{"href":"https://api.github.com/repos/apple/swift/pulls/15321/comments"},"review_comment":{"href":"https://api.github.com/repos/apple/swift/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apple/swift/pulls/15321/commits"},"statuses":{"href":"https://api.github.com/repos/apple/swift/statuses/d5ed794f3fc7b75b0cf00e8308563ee8823f25d3"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"slavapestov"}}