{"action":"created","issue":{"url":"https://api.github.com/repos/JuliaLang/julia/issues/23721","repository_url":"https://api.github.com/repos/JuliaLang/julia","labels_url":"https://api.github.com/repos/JuliaLang/julia/issues/23721/labels{/name}","comments_url":"https://api.github.com/repos/JuliaLang/julia/issues/23721/comments","events_url":"https://api.github.com/repos/JuliaLang/julia/issues/23721/events","html_url":"https://github.com/JuliaLang/julia/issues/23721","id":258026361,"number":23721,"title":"RFC: Get rid of #undef and replace it with null in Array{Union{Null, T}}","user":{"login":"nalimilan","id":1120448,"avatar_url":"https://avatars3.githubusercontent.com/u/1120448?v=4","gravatar_id":"","url":"https://api.github.com/users/nalimilan","html_url":"https://github.com/nalimilan","followers_url":"https://api.github.com/users/nalimilan/followers","following_url":"https://api.github.com/users/nalimilan/following{/other_user}","gists_url":"https://api.github.com/users/nalimilan/gists{/gist_id}","starred_url":"https://api.github.com/users/nalimilan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nalimilan/subscriptions","organizations_url":"https://api.github.com/users/nalimilan/orgs","repos_url":"https://api.github.com/users/nalimilan/repos","events_url":"https://api.github.com/users/nalimilan/events{/privacy}","received_events_url":"https://api.github.com/users/nalimilan/received_events","type":"User","site_admin":false},"labels":[{"id":62693664,"url":"https://api.github.com/repos/JuliaLang/julia/labels/arrays","name":"arrays","color":"006b75","default":false},{"id":1363386,"url":"https://api.github.com/repos/JuliaLang/julia/labels/breaking","name":"breaking","color":"800000","default":false},{"id":688843543,"url":"https://api.github.com/repos/JuliaLang/julia/labels/triage","name":"triage","color":"f00040","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":13,"created_at":"2017-09-15T12:40:50Z","updated_at":"2017-09-20T11:57:34Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"I mentioned this idea at https://github.com/JuliaLang/julia/issues/16029#issuecomment-327420330 but I thought this proposal entails large enough changes that it deserves its own issue. The idea is to get rid of `#undef` entries in non-`isbits` arrays, and replace it with `null`(from #23642). This would have several advantages:\r\n- Use a single representation for missing values everywhere: currently `#undef` is kind of weird since you can get this value, but never set it again, and having multiple notions of missing/uninitialized value increases the complexity of the language.\r\n- Guarantee that an `Array{T}` always contains valid values of type `T`: currently there's always the possibility that indexing into a non-`isbits` array throws an `UndefRefError`, which is akin to the \"billion dollar mistake\" (though in a less severe form since it only affects arrays).\r\n\r\nConcretely, in order to be able to set uninitialized values to `null`, we must force all uninitialized array constructors to create `Array{Union{Null, T}}` rather than `Array{T}` objects.  For non-`isbits` arrays, this is not a problem since there is room to store the type tag already, or a `NULL` pointer can be translated to `null` as a built-in special case. For `isbits` arrays, with @quinnj's recent work to optimize `Union`s (https://github.com/JuliaLang/julia/pull/22441), the performance impact is limited: it is equivalent to allocating an `Array{T}` plus an `Array{UInt8}` (the latter storing the type, i.e. whether the value is initialized or not). Moreover, with `Union{Null, T}` the type tag for `Null` is equal to `0`, which means the `Array{UInt8}` part can be allocated directly and efficiently using `calloc`. But of course for `isbits` arrays it would be more common to create an initialized `Array{T}` directly using `zeros` or `fill` (which would be the recommended constructors).\r\n\r\nOnce all entries in an unitialized `Array{Union{Null, T}}` have been replaced with valid objects, the array can be turned into an `Array{T}` via a simple call to `convert`. This never requires making a copy, so it's very efficient. Then the `Array{T}` can safely be passed to functions which expect it to contain only valid `T` objects, which is now always guaranteed.\r\n\r\nIf it turns out that creating the `Array{UInt8}` type tag part is too costly in some very particular cases, an `unsafe_array` function could be provided, which would allow creating uninitialized `Array{T}` objects for `isbits` types. This should probably not be allowed for non-`isbits` types (though if it was the current behavior of `#undef` could possibly be retained, with the expectation that most users would never see it).\r\n\r\nSince it forces filling arrays with valid values on construction, this proposal effectively amounts to forbidding uninitialized arrays (https://github.com/JuliaLang/julia/issues/9147)."},"comment":{"url":"https://api.github.com/repos/JuliaLang/julia/issues/comments/330829417","html_url":"https://github.com/JuliaLang/julia/issues/23721#issuecomment-330829417","issue_url":"https://api.github.com/repos/JuliaLang/julia/issues/23721","id":330829417,"user":{"login":"nalimilan","id":1120448,"avatar_url":"https://avatars3.githubusercontent.com/u/1120448?v=4","gravatar_id":"","url":"https://api.github.com/users/nalimilan","html_url":"https://github.com/nalimilan","followers_url":"https://api.github.com/users/nalimilan/followers","following_url":"https://api.github.com/users/nalimilan/following{/other_user}","gists_url":"https://api.github.com/users/nalimilan/gists{/gist_id}","starred_url":"https://api.github.com/users/nalimilan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nalimilan/subscriptions","organizations_url":"https://api.github.com/users/nalimilan/orgs","repos_url":"https://api.github.com/users/nalimilan/repos","events_url":"https://api.github.com/users/nalimilan/events{/privacy}","received_events_url":"https://api.github.com/users/nalimilan/received_events","type":"User","site_admin":false},"created_at":"2017-09-20T11:57:34Z","updated_at":"2017-09-20T11:57:34Z","author_association":"CONTRIBUTOR","body":"> One way to accommodate this might be to have a \"construction\" phase followed by a \"publishing\" step where all refs are validated to be defined (and perhaps that any user defined invariants are followed)? It's a bit of an odd idea, I admit.\r\n\r\nThat's more or less what this proposal suggests, by requiring a call to `convert(Array{T}, x)` once initialization is done, which would guarantee early failures if there are nulls."}}
{"actor":{"display_login":"nalimilan"}}