Skip to content
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

Rename isleaftype() to isconcrete() #20709

Closed
wants to merge 5 commits into from
Closed

Rename isleaftype() to isconcrete() #20709

wants to merge 5 commits into from

Conversation

nalimilan
Copy link
Member

@nalimilan nalimilan commented Feb 21, 2017

For consistency, also change the C function jl_is_leaf_type() to
jl_is_concrete_type(). Replace (almost) all uses of "leaf" which mean
"concrete".

I have left unchanged several functions in src/typemap.c (sig_match_leaf, sig_match_by_type_leaf, is_cache_leaf, is_leaf_bound) and the leaf field of _jl_typemap_entry_t, since the "leaf" term seemed to make more sense there in the context of a type tree. Suggestions welcome.

Fixes #17086.

@StefanKarpinski
Copy link
Sponsor Member

To be completely explicit about it, I'd like to propose that we officially define concrete to mean the following: a type T is concrete if and only if there can exist an object x such that typeof(x) == T. There are some corner cases where x could exist but is not constructible (still counts for the sake of this definition), but I still think that's a pretty clear definition.

@omus
Copy link
Member

omus commented Feb 21, 2017

Related to #17086

@nalimilan
Copy link
Member Author

Thanks. Regarding the definition of "concrete", see in particular the table at #17086 (comment).

@@ -264,8 +264,8 @@ First, a review of some relevant Julia type terminology:

| Syntax / Keyword | Example | Description |
|:----------------------------- |:------------------------------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `mutable struct` | `String` | "Leaf Type" :: A group of related data that includes a type-tag, is managed by the Julia GC, and is defined by object-identity. The type parameters of a leaf type must be fully defined (no `TypeVars` are allowed) in order for the instance to be constructed. |
| `abstract type` | `Any`, `AbstractArray{T, N}`, `Complex{T}` | "Super Type" :: A super-type (not a leaf-type) that cannot be instantiated, but can be used to describe a group of types. |
| `mutable struct` | `String` | "Leaf Type" :: A group of related data that includes a type-tag, is managed by the Julia GC, and is defined by object-identity. The type parameters of a concrete type must be fully defined (no `TypeVars` are allowed) in order for the instance to be constructed. |
Copy link
Member Author

Choose a reason for hiding this comment

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

Looks like I missed non-lowercase occurrences of "lift". Will fix later, after leaving time for other comments.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed. Though I've noticed that table is almost impossible to read online. Any ideas how to improve it? Is it possible to force text to wrap instead of going beyond the page limits? Or should we move to a bullet list instead?

@tkoolen
Copy link
Contributor

tkoolen commented Feb 21, 2017

I happened to notice yesterday that the jldoctest example is missing the closing ```: http://docs.julialang.org/en/latest/stdlib/base.html#Base.isleaftype.

@JeffBezanson
Copy link
Sponsor Member

see in particular the table at #17086 (comment).

Looking at that table is a good way to waste time and become confused.

@kshyatt kshyatt added the domain:types and dispatch Types, subtyping and method dispatch label Feb 21, 2017
@StefanKarpinski
Copy link
Sponsor Member

Is there any practical reason to need to distinguish any other meaning of "concrete"? The meaning I've proposed maps well onto whether a field of a type can be stored inline assuming it is a bits type. When would you need any of the other meanings? In particular, the meaning by which Complex is "concrete". Is there any useful, non-internal application of that meaning?

@JeffBezanson
Copy link
Sponsor Member

I'm fine with this renaming, but note that as it is we'd have isconcrete(Type{Int}). Changing that would require a detailed review of all uses to see which ones care about this.

@StefanKarpinski
Copy link
Sponsor Member

Under what theory of concreteness is isconcrete(Type{Int}) true? I'm just curious.

true

julia> isleaftype(Vector{Complex{Float32}})
julia> isconcrete(Vector{Complex{Float32}})
true
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

closing triple backtick missing here, as mentioned by @tkoolen

Copy link
Member Author

Choose a reason for hiding this comment

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

See new commit.

@JeffBezanson
Copy link
Sponsor Member

It's concrete in the sense that you have enough information about the value to do dispatch. Type{Int} is not itself the tag of a value, but the tag can be determined from it. Or put differently, it's the maximum amount of information about a value the type system can express.

This is probably part of why we used the term "leaf type"; if not for that we might have called this "concrete" all along.

@TotalVerb
Copy link
Contributor

TotalVerb commented Feb 22, 2017

But aren't Union, UnionAll, and DataType concrete though, despite not always being enough information to do dispatch?

For consistency, also change the C function jl_is_leaf_type() to
jl_is_concrete_type(). Replace (almost) all uses of "leaf" which mean
"concrete".
@JeffBezanson
Copy link
Sponsor Member

JeffBezanson commented Feb 22, 2017

Unfortunately it is a bit context-dependent. If you want to know the memory layout of a value, then knowing that it's a DataType is sufficient. But if you pass a type to a function that has ::Type{T} selectors, it's not sufficient for dispatch. This is a long-term issue we'll have to fully resolve eventually.

Here, we can only make sense of isleaftype if we look at what it's used for. The basic use is to ask "do I know exactly what kind of value I'd have, or only some approximation?" We can decide what counts as "exact enough". In most cases we consider DataType "exact enough", e.g.

julia> typeof((Int,Int8))
Tuple{DataType,DataType}

We have a lot of experience with the isleaftype function, and in almost all cases we've wanted both DataType and Type{Int} to give true. Returning false tends to send you to a slow path.

For an example library use, consider the Set constructor on a Generator. If we can infer an isleaftype element type, that's precise enough so we directly use it as the Set's element type. Otherwise we examine the types of everything to pick a result type. For this purpose, clearly both DataType and Type{Int} are acceptable. If we know every element is Type{Int} then we know the exact identity of every value, so examining all of them would be silly. If we know DataType, we consider that good enough for a collection like Set; we don't want to bother checking whether every element is actually the same type. So the current somewhat fuzzy definition of isleaftype has proven itself useful.

@StefanKarpinski
Copy link
Sponsor Member

StefanKarpinski commented Feb 23, 2017

I propose having isconcrete and isfinal where the former means that it could be the tag of an object and the latter means that we can do dispatch (i.e. has non-empty intersection with exactly one concrete type). If isleaftype were not exported, the naming wouldn't matter, but it is exported so bikeshedding the name and semantics is fair game.

@JeffBezanson
Copy link
Sponsor Member

What is an example use case where you need to know that something could be the direct tag of an object? Or, put differently, an example of where calling Type{Int} leaf or concrete has caused a problem?

@felixrehren
Copy link
Contributor

(Cf. #20555 "A publicly facing reflection API" -> knowing which types you can dispatch on?)

@nalimilan
Copy link
Member Author

Bump. Should I rebase this so that it can be merged?

@nalimilan
Copy link
Member Author

Rebased and added a NEWS.md entry.

@@ -1595,6 +1595,8 @@ end
# issue #6466
# `write` on non-isbits arrays is deprecated in io.jl.

@deprecate isconcrete isconcrete
Copy link
Contributor

@pabloferz pabloferz Aug 4, 2017

Choose a reason for hiding this comment

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

@deprecate isleaftype isconcrete? Or are you trying to deprecate what you just introduced?... by what you just introduced.

Copy link
Contributor

Choose a reason for hiding this comment

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

fixed in 3813421 - I think this was a mistake during the conflict resolution in fd4283c

@StefanKarpinski
Copy link
Sponsor Member

I still much prefer "concrete" to "leaf type" but there's a bit of a fundamental terminology decision to be made here. Does this function actually compute the property that we want to call "concrete"?

@omus omus added this to the 1.0 milestone Sep 8, 2017
@omus
Copy link
Member

omus commented Sep 8, 2017

I added the 1.0 milestone as we should probably make a final decision on this before release

@StefanKarpinski
Copy link
Sponsor Member

@JeffBezanson would you be happier calling this isfinal? The terminology isleaftype is pretty jargony and not entirely accurate since these types are not really the leaves of a tree in any case.

@JeffBezanson
Copy link
Sponsor Member

One good option might be to un-export isleaftype and add isconcrete, with the tag-based meaning (basically x isa DataType && x.layout != C_NULL). That's probably the most useful function (all type-related reflection will succeed on such a type). Replacing uses of isleaftype in the compiler will take more time and can be deferred.

@StefanKarpinski
Copy link
Sponsor Member

That's a good plan.

@JeffBezanson
Copy link
Sponsor Member

Done by #23666

@StefanKarpinski StefanKarpinski deleted the nl/isconcrete branch September 14, 2017 22:32
@StefanKarpinski StefanKarpinski restored the nl/isconcrete branch September 14, 2017 22:32
@nalimilan nalimilan deleted the nl/isconcrete branch December 1, 2018 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:types and dispatch Types, subtyping and method dispatch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants