Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upSet transmute from fn item to type fn lint a hard error #19925
Comments
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 16, 2014
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 16, 2014
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 19, 2014
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 19, 2014
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 21, 2014
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 21, 2014
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 22, 2014
nikomatsakis
added a commit
to nikomatsakis/rust
that referenced
this issue
Dec 22, 2014
kmcallister
added
the
A-codegen
label
Jan 16, 2015
nikomatsakis
added
the
I-nominated
label
Jan 27, 2015
This comment has been minimized.
This comment has been minimized.
|
Nominating. Not sure how important this is. |
This comment has been minimized.
This comment has been minimized.
|
P-high, not 1.0 milestone. |
pnkfelix
added
P-medium
and removed
I-nominated
labels
Jan 29, 2015
P1start
referenced this issue
Feb 20, 2015
Closed
Make function pointer types look like borrowed pointer types for forwards compatability #883
petrochenkov
referenced this issue
Mar 26, 2015
Closed
Unique function types are not unique enough #23733
This comment has been minimized.
This comment has been minimized.
|
On a related note, the subtyping relation is not quite right. This code should not type check: fn foo<A>(_: A, _: A) { }
fn bar<B>() { }
fn main() {
let x = bar::<u32>;
let y = bar::<i32>;
foo(x, y);
} |
This comment has been minimized.
This comment has been minimized.
|
To elaborate, the type of |
This comment has been minimized.
This comment has been minimized.
|
Put another way, the type of a fn item ought to have the values for all of its substs (sort of like |
nikomatsakis
added
the
I-nominated
label
Apr 1, 2015
This comment has been minimized.
This comment has been minimized.
|
Nominating. Not sure how seriously to take this (but probably not that hard to fix). |
This comment has been minimized.
This comment has been minimized.
|
Classifying even the type-system issue as a "bug that needs fixing" -- thus we can afford to leave this as P-high, not a 1.0-blocker. |
pnkfelix
removed
the
I-nominated
label
Apr 2, 2015
nikomatsakis
added
the
P-backcompat-lang
label
Apr 2, 2015
This comment has been minimized.
This comment has been minimized.
|
Tagging as P-backcompat-lang since compiler incorrectly accepts things it shouldn't accept. |
pnkfelix
removed
the
P-medium
label
Apr 2, 2015
brson
added
P-high
and removed
P-backcompat-lang
labels
Apr 29, 2015
pnkfelix
assigned
nikomatsakis
Apr 30, 2015
This comment has been minimized.
This comment has been minimized.
|
Closing it as in "this has been fully implemented", by merging #34198. |
This comment has been minimized.
This comment has been minimized.
The latter point may be true, but |
This comment has been minimized.
This comment has been minimized.
Yeah...I know. |
This comment has been minimized.
This comment has been minimized.
|
cc @pnkfelix and @withoutboats -- your thoughts here? |
nikomatsakis
closed this
Jan 10, 2017
nikomatsakis
reopened this
Jan 10, 2017
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis can't you always |
This comment has been minimized.
This comment has been minimized.
|
@withoutboats you can, indeed. In any case, the proposal is to remove the special case from transmute (and hence you will get a hard error). What I am saying is merely that I would like a more concise syntax here, since when you actually have to write (e.g.) @eddyb -- one thing, though it has more to do w/ the PR than this, I think we should make sure to give a very clear error message, along with a suggestion of what to write instead. |
This comment has been minimized.
This comment has been minimized.
|
@rfcbot reviewed
Sounds reasonable, just wanted to make sure I understand that this special case is just about concision & not expressibility. |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis In that case, we have to keep the special-casing code where we're not emitting the lint. |
This comment has been minimized.
This comment has been minimized.
Yes, such is life. I left a comment in the PR. |
This comment has been minimized.
This comment has been minimized.
|
Basically nice errors == special-case code. =) |
This comment has been minimized.
This comment has been minimized.
|
@rfcbot reviewed |
This comment has been minimized.
This comment has been minimized.
|
It seems that @rfcbot went on vacation. I will put this into Final Comment Period manually:
|
nikomatsakis
added
the
final-comment-period
label
Jan 17, 2017
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Jan 23, 2017
|
psst @eddyb, I wasn't able to add the |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Feb 2, 2017
|
The final comment period is now complete. |
This comment has been minimized.
This comment has been minimized.
|
Although the FCP is complete, the change has not been finalized, and I want to float one possible tweak to the rules that might go a long way to eliminating the annoyance that these rules can cause. Each function has a unique type, but we could make the unique types for |
This comment has been minimized.
This comment has been minimized.
|
I raised this with @nikomatsakis privately because this broke a significant amount of code I wrote that I just came back to after a number of months. In my view While there may be some cases of extern "C" functions that are only ever called from Rust, this seems exceedingly rare compared to extern "C" functions meant to be called from C. Since pointers are part of the C representation in such an exceedingly large % of cases, the extra type-cast we're imposing here seems inappropriate. |
This comment has been minimized.
This comment has been minimized.
|
@wycats You should never need the |
This comment has been minimized.
This comment has been minimized.
|
@eddyb you don't need the transmute because you can do a manual cast? |
This comment has been minimized.
This comment has been minimized.
|
I suppose we should've been stricter and not allow many type combinations, where a better option exists. |
bors
added a commit
that referenced
this issue
Feb 28, 2017
bors
added a commit
that referenced
this issue
Feb 28, 2017
bors
added a commit
that referenced
this issue
Mar 1, 2017
bors
added a commit
that referenced
this issue
Mar 1, 2017
bors
closed this
in
#34198
Mar 1, 2017
This comment has been minimized.
This comment has been minimized.
|
My take on this proposal that I floated earlier: I still think it's worth considering making |
nikomatsakis
referenced this issue
Mar 22, 2017
Open
Consider changing the representation for `fn`-item types based on their ABI #40744
This comment has been minimized.
This comment has been minimized.
|
The main thing that makes me sad about this is that it seems like a regression. Code that used to work now breaks without a major version change. At least there is a workaround. |
nikomatsakis commentedDec 16, 2014
•
edited by alexcrichton
Original title: Fn item types should be zero-sized
Per RFC 401, every fn in Rust should have its own unique, zero-sized type. This fits with the overall design of closures, which also have their own unique types (but those types are not zero-sized, as they carry the environment). None of these types have any explicit syntax at present. This has been a longstanding plan, but until recently it was not fully implemented. This is changing with PR #31710, which means that some existing code will need to be adjusted to account for the new behavior. This issue attempts to summarize how things work and describe what needs to be changed.
Zero-sized fn types
What all of this means is that, if you have a function declaration
foo:the type of
foois notfn(i32), as one might expect. Rather, it is a unique, zero-sized marker type that I will just write astypeof(foo). However,typeof(foo)can be coerced to a function pointerfn(i32), so you rarely notice this:The reason that this matter is that the type
fn(i32)is not specify to any particular function: it's a function pointer. So callingx()results in a virtual call, whereasfoo()is statically dispatched, because the type offootells us precisely what function is being called.Impact on users
As noted above, coercions mean that most code will continue to work just fine before and after this issue is fully fixed. However, you can tell the difference in a few scenarios. Perhaps the most prominent is using transmute to convert a fn item into a fn pointer. This is often done as part of an FFI:
Here, transmute is being used to convert the types of the fn arguments. This pattern is now incorrect because, because the type of
foois a function item (typeof(foo)), which is zero-sized, and the target type (fn()) is a function pointer, which is not zero-sized. For now, this pattern still works due to some special-cased code in the compiler, but that code is expected to be removed. For future compatibility, this pattern should be rewritten. There are a few possible ways to do this:let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_))let f: extern "C" fn(*mut i32) = transmute(foo as usize) /* works too */The same applies to transmutes to
*mut fn(), which were observed frequently in practice. Note though that use of this type is generally incorrect. The intention is typically to describe a function pointer, but justfn()alone suffices for that.*mut fn()is a pointer to a fn pointer. (Since these values are typically just passed to C code, however, this rarely makes a difference in practice.)Current status and implementation trail