Uh oh!
There was an error while loading. Please reload this page.
Only instantiate inline- and const-fns if they are referenced (again). - #45575
Conversation
alexcrichton
commented
Oct 27, 2017
Looks great to me! r=me with passing tests |
kennytm
commented
Oct 27, 2017
CI is still failing. These tests compiled successfully while they should not: |
4f785a5 to
8d4c92fComparealexcrichton
commented
Oct 31, 2017
This looks great to me, thanks @michaelwoerister! I'm a little hesitant to personally r+ due to the change in semantics here. We chatted on IRC and it sounded like you're going to wait for discussion amongst the @rust-lang/compiler team, so I'll tag the PR appropriately for that. |
I should note that this mainly has to do with unstable features (e.g. direct uses of intrinsics).
We could turn these into warnings and generate runtime panics instead, in fact the warnings could be done ahead-of-time and distinct from codegen anyway. |
michaelwoerister
commented
Nov 1, 2017
Yes, I think this should be the preferred way to do it anyway. What does the rest of @rust-lang/compiler say? Can we land this? I think the general goal of being as lazy as possible is worth pursuing. |
There was a problem hiding this comment.
Shouldn't private no_mangle functions always be compiled in?
There was a problem hiding this comment.
Seems like it would be good if that were true.
There was a problem hiding this comment.
Shouldn't we check the inline attribute for functions that aren't translated? I don't want people to create functions with an inline attribute that explode when a child crate finally instantiates them.
I'm not sure this is a difference in kind, merely a difference in degree: even today you can write things that depend on reachability and blow up only when a downstream crate uses them, for example: #![feature(core_intrinsics)]use std::intrinsics;#[inline(fail)]pubfnfoo<T>(_t:T){unsafe{
intrinsics::atomic_load(1as*const[u8;1048576]);}}#[inline(always)]pubfnbar(){unsafe{
intrinsics::atomic_load(1as*const[u8;1048576]);}}fnmain(){}I still think we want to sanitize attributes during type-checking, but intrinsics (which are unstable and intentionally error on monomorphization time) and resource limits (which are always a problem) should be OK. |
michaelwoerister
commented
Nov 3, 2017
Discussed in the @rust-lang/compiler team meeting yesterday and the conclusion was to proceed with this. The main concern was that @bors r=nikomatsakis |
bors
commented
Nov 3, 2017
📌 Commit 8d4c92f has been approved by |
bors
commented
Nov 4, 2017
⌛ Testing commit 8d4c92f80d97bc0e42d935ce7d23f6e3083a4937 with merge df38d994283db81c5176dc109d1894cd5232625f... |
bors
commented
Nov 4, 2017
💔 Test failed - status-travis |
kennytm
commented
Nov 4, 2017
Test failed, |
michaelwoerister
commented
Nov 7, 2017
So I think these new failures are because #45710 got merged in between. The custom allocator implementations in these test cases fail linking because (I assume) the respective functions are not instantiated because they are not considered exported? Does that sound right, @alexcrichton? I don't quite understand where these functions are supposed to come from ( |
alexcrichton
commented
Nov 7, 2017
@michaelwoerister oh dear sorry about that! The staticFOO:MyAllocator = ...;mod some_internal_name {#[std_special_symbol]#[no_mangle]fn__rg_alloc(...) -> ... {FOO.some_method(...)}
...
}So the symbols are injected by the compiler and their attributes are generated here. IIRC the |
michaelwoerister
commented
Nov 7, 2017
Ah ok, the collector does not see the functions generated in librustc_trans/allocator.rs, and since we are creating an executable, these seemingly unreferenced |
michaelwoerister
commented
Nov 7, 2017
@alexcrichton Do you think that there's a case where a |
alexcrichton
commented
Nov 7, 2017
@michaelwoerister nah I think everything tagged with that should be unconditionally instantiated. They're all tiny anyway and will get gc'd by the linker if they're not used. |
michaelwoerister
commented
Nov 7, 2017
678be7d to
d141abfComparemichaelwoerister
commented
Nov 7, 2017
OK, travis looks good. Let's give it another try. @bors r=nikomatsakis |
bors
commented
Nov 7, 2017
📌 Commit d141abf has been approved by |
bors
commented
Nov 8, 2017
⌛ Testing commit d141abf with merge 6dc72035c92f954c39240fbe4eeec544ef159331... |
bors
commented
Nov 8, 2017
💔 Test failed - status-travis |
kennytm
commented
Nov 8, 2017
Details |
michaelwoerister
commented
Nov 8, 2017
Updated test case. @bors r=nikomatsakis |
bors
commented
Nov 8, 2017
📌 Commit 081ef8e has been approved by |
bors
commented
Nov 8, 2017
…ikomatsakis Only instantiate inline- and const-fns if they are referenced (again). It seems that we have regressed on not translating `#[inline]` functions unless they are actually used. This should bring back this optimization. I also added a regression test this time so it doesn't happen again accidentally. Fixes#40392. r? @alexcrichton UPDATE & PSA --------------------- This patch **makes translation very lazy** -- in general this is a good thing (we don't want the compiler to do unnecessary work) but it has two consequences: 1. Some error messages are only generated when an item is actually translated. Consequently, this patch will lead to more cases where the compiler will only start emitting errors when the erroneous function is actually used. This has always been true to some extend (e.g. when passing generic values to an intrinsic) but since this is something user-facing it's worth mentioning. 2. When writing tests, one has to make sure that the functions in question are actually generated. In other words, it must not be dead code. This can usually be achieved by either 1. making sure the function is exported from the resulting binary or 2. by making sure the function is called from something that is exported (or `main()`). Note that it depends on the crate type what functions are exported: 1. For rlibs and dylibs everything that is reachable from the outside is exported. 2. For executables, cdylibs, and staticlibs, items are only exported if they are additionally `#[no_mangle]` or have an `#[export_name]`. The commits in this PR contain many examples of how tests can be updated to comply to the new requirements.
bors
commented
Nov 8, 2017
☀️ Test successful - status-appveyor, status-travis |
michaelwoerister
commented
Nov 8, 2017
Wow, cool |
It seems that we have regressed on not translating
#[inline]functions unless they are actually used. This should bring back this optimization. I also added a regression test this time so it doesn't happen again accidentally.Fixes#40392.
r? @alexcrichton
UPDATE & PSA
This patch makes translation very lazy -- in general this is a good thing (we don't want the compiler to do unnecessary work) but it has two consequences:
main()).Note that it depends on the crate type what functions are exported:
#[no_mangle]or have an#[export_name].The commits in this PR contain many examples of how tests can be updated to comply to the new requirements.