{"action":"created","comment":{"url":"https://api.github.com/repos/apple/swift/pulls/comments/233855951","pull_request_review_id":175366302,"id":233855951,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzMzg1NTk1MQ==","diff_hunk":"@@ -2356,3 +2356,110 @@ Expr *constraints::simplifyLocatorToAnchor(ConstraintSystem &cs,\n \n   return locator->getAnchor();\n }\n+\n+bool ConstraintSystem::isConversionNonEphemeral(\n+    ConversionRestrictionKind conversion, ConstraintLocatorBuilder locator) {\n+  switch (conversion) {\n+  case ConversionRestrictionKind::ArrayToPointer:\n+  case ConversionRestrictionKind::StringToPointer:\n+    // Always ephemeral.\n+    return false;\n+  case ConversionRestrictionKind::InoutToPointer: {\n+    // Ephemeral, except if the expression is a reference to a global or\n+    // static stored variable, or a simple stored property on such a variable.\n+    SourceRange range;\n+    auto *argLoc = simplifyLocator(*this, getConstraintLocator(locator), range);\n+    auto *expr = argLoc->getAnchor()->getSemanticsProvidingExpr();\n+\n+    auto *subExpr = cast<InOutExpr>(expr)->getSubExpr();\n+\n+    auto isDirectlyAccessedStoredVar = [&](ValueDecl *decl) -> bool {\n+      auto *asd = dyn_cast_or_null<AbstractStorageDecl>(decl);\n+      if (!asd)\n+        return false;\n+\n+      // Check what access strategy is used for a read-write access. It must be\n+      // direct-to-storage in order for the conversion to be non-ephemeral.\n+      auto access = asd->getAccessStrategy(AccessSemantics::Ordinary,\n+                                           AccessKind::ReadWrite, DC);\n+      return access.getKind() == AccessStrategy::Storage;\n+    };\n+\n+    auto isValidBaseDecl = [&](ValueDecl *baseDecl) -> bool {\n+      if (!isDirectlyAccessedStoredVar(baseDecl))\n+        return false;\n+\n+      // The base decl must either be static or global in order for it to be\n+      // non-ephemeral.\n+      return baseDecl->isStatic() ||\n+             baseDecl->getDeclContext()->isModuleScopeContext();\n+    };\n+\n+    bool isMember = false;\n+    while (true) {\n+      subExpr = subExpr->getSemanticsProvidingExpr();\n+\n+      if (auto *fve = dyn_cast<ForceValueExpr>(subExpr)) {\n+        subExpr = fve->getSubExpr();\n+        continue;\n+      }\n+\n+      // Look through load exprs. These can occur when projecting through a\n+      // property on a class, which we want to support if the class is\n+      // non-final.\n+      if (auto *le = dyn_cast<LoadExpr>(subExpr)) {\n+        subExpr = le->getSubExpr();\n+        continue;\n+      }\n+\n+      if (auto *tee = dyn_cast<TupleElementExpr>(subExpr)) {\n+        isMember = true;\n+        subExpr = tee->getBase();\n+        continue;\n+      }\n+\n+      if (auto *mre = dyn_cast<MemberRefExpr>(subExpr)) {\n+        if (!isDirectlyAccessedStoredVar(mre->getMember().getDecl()))\n+          return false;\n+        isMember = true;\n+        subExpr = mre->getBase();\n+        continue;\n+      }\n+      // TODO: Handle UnresolvedDotExpr.\n+      break;\n+    }\n+\n+    // First check if the base expr is a metatype – if so, we're dealing with\n+    // a static member, which is non-ephemeral.\n+    if (isMember && simplifyType(getType(subExpr))->is<AnyMetatypeType>())\n+      return true;\n+\n+    // Otherwise, check to see if we have a base decl.\n+    if (auto *dre = dyn_cast<DeclRefExpr>(subExpr))\n+      return isValidBaseDecl(dre->getDecl());\n+\n+    // TODO: Handle potentially overloaded decl bases.\n+    return false;\n+  }\n+  case ConversionRestrictionKind::TupleToTuple:\n+  case ConversionRestrictionKind::DeepEquality:\n+  case ConversionRestrictionKind::Superclass:\n+  case ConversionRestrictionKind::LValueToRValue:\n+  case ConversionRestrictionKind::Existential:\n+  case ConversionRestrictionKind::MetatypeToExistentialMetatype:\n+  case ConversionRestrictionKind::ExistentialMetatypeToMetatype:\n+  case ConversionRestrictionKind::ValueToOptional:\n+  case ConversionRestrictionKind::OptionalToOptional:\n+  case ConversionRestrictionKind::ClassMetatypeToAnyObject:\n+  case ConversionRestrictionKind::ExistentialMetatypeToAnyObject:\n+  case ConversionRestrictionKind::ProtocolMetatypeToProtocolClass:\n+  case ConversionRestrictionKind::PointerToPointer:\n+  case ConversionRestrictionKind::ArrayUpcast:\n+  case ConversionRestrictionKind::DictionaryUpcast:\n+  case ConversionRestrictionKind::SetUpcast:\n+  case ConversionRestrictionKind::HashableToAnyHashable:\n+  case ConversionRestrictionKind::CFTollFreeBridgeToObjC:\n+  case ConversionRestrictionKind::ObjCTollFreeBridgeToCF:","path":"lib/Sema/ConstraintSystem.cpp","position":107,"original_position":107,"commit_id":"4e5a2da64993ef7567ac7ac7a9b2228a3a961a5a","original_commit_id":"47e8120c25d96b28f62da90a6dbb7b98749430dd","user":{"login":"hamishknight","id":14794099,"node_id":"MDQ6VXNlcjE0Nzk0MDk5","avatar_url":"https://avatars0.githubusercontent.com/u/14794099?v=4","gravatar_id":"","url":"https://api.github.com/users/hamishknight","html_url":"https://github.com/hamishknight","followers_url":"https://api.github.com/users/hamishknight/followers","following_url":"https://api.github.com/users/hamishknight/following{/other_user}","gists_url":"https://api.github.com/users/hamishknight/gists{/gist_id}","starred_url":"https://api.github.com/users/hamishknight/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hamishknight/subscriptions","organizations_url":"https://api.github.com/users/hamishknight/orgs","repos_url":"https://api.github.com/users/hamishknight/repos","events_url":"https://api.github.com/users/hamishknight/events{/privacy}","received_events_url":"https://api.github.com/users/hamishknight/received_events","type":"User","site_admin":false},"body":"In this patch it could be, although IMO it should it be reasonable for the function to take an arbitrary conversion and answer the question \"is this something that we could pass to a `@_nonEphemeral` parameter?\" – which is true for the rest of these conversions, as they're not things that `@_nonEphemeral` restricts.","created_at":"2018-11-15T14:13:20Z","updated_at":"2018-11-15T14:13:20Z","html_url":"https://github.com/apple/swift/pull/20467#discussion_r233855951","pull_request_url":"https://api.github.com/repos/apple/swift/pulls/20467","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/apple/swift/pulls/comments/233855951"},"html":{"href":"https://github.com/apple/swift/pull/20467#discussion_r233855951"},"pull_request":{"href":"https://api.github.com/repos/apple/swift/pulls/20467"}},"in_reply_to_id":232868535},"pull_request":{"url":"https://api.github.com/repos/apple/swift/pulls/20467","id":229789505,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI5Nzg5NTA1","html_url":"https://github.com/apple/swift/pull/20467","diff_url":"https://github.com/apple/swift/pull/20467.diff","patch_url":"https://github.com/apple/swift/pull/20467.patch","issue_url":"https://api.github.com/repos/apple/swift/issues/20467","number":20467,"state":"open","locked":false,"title":"[Sema] Warn on unsound pointer conversions","user":{"login":"hamishknight","id":14794099,"node_id":"MDQ6VXNlcjE0Nzk0MDk5","avatar_url":"https://avatars0.githubusercontent.com/u/14794099?v=4","gravatar_id":"","url":"https://api.github.com/users/hamishknight","html_url":"https://github.com/hamishknight","followers_url":"https://api.github.com/users/hamishknight/followers","following_url":"https://api.github.com/users/hamishknight/following{/other_user}","gists_url":"https://api.github.com/users/hamishknight/gists{/gist_id}","starred_url":"https://api.github.com/users/hamishknight/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hamishknight/subscriptions","organizations_url":"https://api.github.com/users/hamishknight/orgs","repos_url":"https://api.github.com/users/hamishknight/repos","events_url":"https://api.github.com/users/hamishknight/events{/privacy}","received_events_url":"https://api.github.com/users/hamishknight/received_events","type":"User","site_admin":false},"body":"In this PR is the logic to emit a warning on unsound array-to-pointer, string-to-pointer, and inout-to-pointer conversions. This is done through the introduction of an underscored attribute `@_nonEphemeral` which denotes a pointer parameter which cannot accept pointer conversions that are only valid for the duration of the call they're passed to.\r\n\r\nThis includes all array-to-pointer and string-to-pointer conversions, and most inout-to-pointer conversions with the exception of:\r\n- Global and static variables\r\n- Stored properties on such variables that are accessed directly (e.g excluding ones with property observers, ones on non-final classes and resilient types in general)\r\n- Force unwraps of any of the above\r\n\r\nVarious pointer parameters in the stdlib have been marked as `@_nonEphemeral`, primarily pointer parameters for initialisers on pointer types. In addition, this PR infers `@_nonEphemeral` on pointer parameters for memberwise initialisers and enum case constructors.\r\n\r\nEssentially, this is the warning logic of #20070 plus:\r\n- The allowing of stored properties on final class global/static vars to be treated as non-ephemeral.\r\n- An additional note that suggests that the user use `withUnsafe[Mutable][Bytes/Pointer]`, or for arrays, `withUnsafe[Mutable][Bytes/BufferPointer]`, or for strings, `withCString`.\r\n- The inferring of `@_nonEphemeral` for enum case constructors.\r\n- More tests.\r\n\r\nIf possible, I'd like to get this into Swift 5, allowing us to transition to an error for Swift 6. I do appreciate how late we are into the release cycle for such a (relatively big) change though.\r\n\r\nI'm unsure if this PR requires Swift evolution discussion – I'm happy to start up a thread if it's felt that it does.\r\n\r\nResolves [SR-2790].\r\n\r\n  [SR-2790]: https://bugs.swift.org/browse/SR-2790","created_at":"2018-11-09T19:04:19Z","updated_at":"2018-11-15T14:13:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"40f51c571f45c3795b7ec1d309bdce799f879c5e","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/apple/swift/pulls/20467/commits","review_comments_url":"https://api.github.com/repos/apple/swift/pulls/20467/comments","review_comment_url":"https://api.github.com/repos/apple/swift/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apple/swift/issues/20467/comments","statuses_url":"https://api.github.com/repos/apple/swift/statuses/4e5a2da64993ef7567ac7ac7a9b2228a3a961a5a","head":{"label":"hamishknight:health-and-safety-pointers-ep1","ref":"health-and-safety-pointers-ep1","sha":"4e5a2da64993ef7567ac7ac7a9b2228a3a961a5a","user":{"login":"hamishknight","id":14794099,"node_id":"MDQ6VXNlcjE0Nzk0MDk5","avatar_url":"https://avatars0.githubusercontent.com/u/14794099?v=4","gravatar_id":"","url":"https://api.github.com/users/hamishknight","html_url":"https://github.com/hamishknight","followers_url":"https://api.github.com/users/hamishknight/followers","following_url":"https://api.github.com/users/hamishknight/following{/other_user}","gists_url":"https://api.github.com/users/hamishknight/gists{/gist_id}","starred_url":"https://api.github.com/users/hamishknight/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hamishknight/subscriptions","organizations_url":"https://api.github.com/users/hamishknight/orgs","repos_url":"https://api.github.com/users/hamishknight/repos","events_url":"https://api.github.com/users/hamishknight/events{/privacy}","received_events_url":"https://api.github.com/users/hamishknight/received_events","type":"User","site_admin":false},"repo":{"id":106924558,"node_id":"MDEwOlJlcG9zaXRvcnkxMDY5MjQ1NTg=","name":"swift","full_name":"hamishknight/swift","private":false,"owner":{"login":"hamishknight","id":14794099,"node_id":"MDQ6VXNlcjE0Nzk0MDk5","avatar_url":"https://avatars0.githubusercontent.com/u/14794099?v=4","gravatar_id":"","url":"https://api.github.com/users/hamishknight","html_url":"https://github.com/hamishknight","followers_url":"https://api.github.com/users/hamishknight/followers","following_url":"https://api.github.com/users/hamishknight/following{/other_user}","gists_url":"https://api.github.com/users/hamishknight/gists{/gist_id}","starred_url":"https://api.github.com/users/hamishknight/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hamishknight/subscriptions","organizations_url":"https://api.github.com/users/hamishknight/orgs","repos_url":"https://api.github.com/users/hamishknight/repos","events_url":"https://api.github.com/users/hamishknight/events{/privacy}","received_events_url":"https://api.github.com/users/hamishknight/received_events","type":"User","site_admin":false},"html_url":"https://github.com/hamishknight/swift","description":"The Swift Programming Language","fork":true,"url":"https://api.github.com/repos/hamishknight/swift","forks_url":"https://api.github.com/repos/hamishknight/swift/forks","keys_url":"https://api.github.com/repos/hamishknight/swift/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hamishknight/swift/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hamishknight/swift/teams","hooks_url":"https://api.github.com/repos/hamishknight/swift/hooks","issue_events_url":"https://api.github.com/repos/hamishknight/swift/issues/events{/number}","events_url":"https://api.github.com/repos/hamishknight/swift/events","assignees_url":"https://api.github.com/repos/hamishknight/swift/assignees{/user}","branches_url":"https://api.github.com/repos/hamishknight/swift/branches{/branch}","tags_url":"https://api.github.com/repos/hamishknight/swift/tags","blobs_url":"https://api.github.com/repos/hamishknight/swift/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hamishknight/swift/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hamishknight/swift/git/refs{/sha}","trees_url":"https://api.github.com/repos/hamishknight/swift/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hamishknight/swift/statuses/{sha}","languages_url":"https://api.github.com/repos/hamishknight/swift/languages","stargazers_url":"https://api.github.com/repos/hamishknight/swift/stargazers","contributors_url":"https://api.github.com/repos/hamishknight/swift/contributors","subscribers_url":"https://api.github.com/repos/hamishknight/swift/subscribers","subscription_url":"https://api.github.com/repos/hamishknight/swift/subscription","commits_url":"https://api.github.com/repos/hamishknight/swift/commits{/sha}","git_commits_url":"https://api.github.com/repos/hamishknight/swift/git/commits{/sha}","comments_url":"https://api.github.com/repos/hamishknight/swift/comments{/number}","issue_comment_url":"https://api.github.com/repos/hamishknight/swift/issues/comments{/number}","contents_url":"https://api.github.com/repos/hamishknight/swift/contents/{+path}","compare_url":"https://api.github.com/repos/hamishknight/swift/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hamishknight/swift/merges","archive_url":"https://api.github.com/repos/hamishknight/swift/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hamishknight/swift/downloads","issues_url":"https://api.github.com/repos/hamishknight/swift/issues{/number}","pulls_url":"https://api.github.com/repos/hamishknight/swift/pulls{/number}","milestones_url":"https://api.github.com/repos/hamishknight/swift/milestones{/number}","notifications_url":"https://api.github.com/repos/hamishknight/swift/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hamishknight/swift/labels{/name}","releases_url":"https://api.github.com/repos/hamishknight/swift/releases{/id}","deployments_url":"https://api.github.com/repos/hamishknight/swift/deployments","created_at":"2017-10-14T12:05:30Z","updated_at":"2018-11-12T00:09:37Z","pushed_at":"2018-11-13T15:50:30Z","git_url":"git://github.com/hamishknight/swift.git","ssh_url":"git@github.com:hamishknight/swift.git","clone_url":"https://github.com/hamishknight/swift.git","svn_url":"https://github.com/hamishknight/swift","homepage":"https://swift.org/","size":345375,"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","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"apple:master","ref":"master","sha":"735b6ea1427ebf7aa7961501c8d1a4f7bb3e5aea","user":{"login":"apple","id":10639145,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEwNjM5MTQ1","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,"node_id":"MDEwOlJlcG9zaXRvcnk0NDgzODk0OQ==","name":"swift","full_name":"apple/swift","private":false,"owner":{"login":"apple","id":10639145,"node_id":"MDEyOk9yZ2FuaXphdGlvbjEwNjM5MTQ1","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},"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-11-15T13:09:22Z","pushed_at":"2018-11-15T13:31:47Z","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":364907,"stargazers_count":45767,"watchers_count":45767,"language":"C++","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":7259,"mirror_url":null,"archived":false,"open_issues_count":431,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":7259,"open_issues":431,"watchers":45767,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apple/swift/pulls/20467"},"html":{"href":"https://github.com/apple/swift/pull/20467"},"issue":{"href":"https://api.github.com/repos/apple/swift/issues/20467"},"comments":{"href":"https://api.github.com/repos/apple/swift/issues/20467/comments"},"review_comments":{"href":"https://api.github.com/repos/apple/swift/pulls/20467/comments"},"review_comment":{"href":"https://api.github.com/repos/apple/swift/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apple/swift/pulls/20467/commits"},"statuses":{"href":"https://api.github.com/repos/apple/swift/statuses/4e5a2da64993ef7567ac7ac7a9b2228a3a961a5a"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"hamishknight"}}