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

RFC: Allow a re-export for main #1260

Merged
merged 3 commits into from
Oct 13, 2015
Merged

Conversation

tbu-
Copy link
Contributor

@tbu- tbu- commented Aug 19, 2015

@tbu-
Copy link
Contributor Author

tbu- commented Aug 19, 2015

As requested by @steveklabnik in rust-lang/rust#27640 (comment).

@alexcrichton
Copy link
Member

I think that this RFC probably wants to be expanded at least a little bit more, for example it may wish to consider the #[main] attribute in tandem with this. Additionally, does it suffice to say use foo::main? Or do you have to pub use foo::main at the top of the program? In general an RFC should be as thorough and complete as possible to serve as a reference for an implementation wherever possible.

@tbu-
Copy link
Contributor Author

tbu- commented Aug 19, 2015

@alexcrichton Nothing really changes, everything behaves as would be consistent with other behavior: Re-exports behave the same as if the function was declared in that place.

To expand on that: The attribute #[main] works just as before. Whether the symbol needs to be public works just as before.

Can you clarify what you think is missing?

@nrc nrc added the T-lang Relevant to the language team, which will review and decide on the RFC. label Aug 20, 2015
@pnkfelix
Copy link
Member

@tbu- there are no concrete examples given in the RFC. The phrase "pub use bleah as bazzle" (for appropriate "bleah" and "bazzle") do not occur anywhere in the RFC -- it is crying out for a concrete example.

@pnkfelix
Copy link
Member

(the RFC text probably would also have benefited from referencing the rust-lang/rust#27640 )

@nikomatsakis
Copy link
Contributor

I agree with @pnkfelix that a bit more detail would be nice -- I found it a bit hard to figure out what this RFC was even requesting. IIUC, this RFC is basically saying "you should be able to do pub use foo::bar as main at the top level of a crate, instead of writing fn main() { foo::bar() }? This seems reasonable -- I can see why one might expect it -- but also fairly low priority. After all, fn main isn't really much longer or anything.

Do you have an implementation of this? Or was it merely that you opened an issue because it seemed surprising and wrong, but didn't actually plan to fix it in the short term? (I have no objection to the latter, to be clear, just want to understand the state here.)

I'm trying to imagine what complications might arise from being more general? I don't know enough about linkers etc to know if there is somehow a problem where ultimately the compiler would have to synthesize the main function you didn't write? For example, if an extern crate is dynamically linked or something like that? Given that (IIRC) we are already synthesizing an init (or something similar) that calls main, I don't think so, but worth double checking.

UPDATE: tweaked wording.

@tbu- tbu- force-pushed the rfc_main_reexport branch 3 times, most recently from 9148a3b to 89c91f6 Compare August 21, 2015 10:12
@Ericson2314
Copy link
Contributor

+1. Seems completely reasonable.

@tbu-
Copy link
Contributor Author

tbu- commented Aug 24, 2015

Forgot to click the 'comment' button:

I'm sorry that I rushed this RFC in this way, updated it with examples and a link to the issue discussion, thanks for the hints.

@steveklabnik I don't have an implementation of this, this was merely ment as a bug report, "it seemed surprising to me, I didn't plan to fix it in the sort term". I totally see why this is low-priority, because you can work around very easily and without much typing.

@pnkfelix
Copy link
Member

pnkfelix commented Oct 1, 2015

I was going to post something here about this potentially breaking certain workflows with debuggers (along the lines about whether one could assume that certain functions named main always existed in binary programs). The draft comment was essentially echoing @nikomatsakis 's point above about there being low-level details that we might be missing here.

But then while making a concrete example of the point, I realized that the #[main] attribute already breaks whatever work-flows I was talking about in my previously drafted comment. So, I don't have any objections to the heart of what this RFC is proposing.


@tbu- Here are some updates I suggest:

  1. can you incorporate your feedback to @alexcrichton 's question into the RFC text.

    That is, if your intention is that one does not need to make the rexport pub, then say so, or at least make one of your examples reflect that generality.

  2. Can you mention #[main] in the RFC text, and point out why it is not sufficiently expressive?

    (In particular, if I understand correctly, your first example could easily be re-expressed by using #[main], while your second example could not be encoded so trivially.)

@nikomatsakis
Copy link
Contributor

Hear ye, hear ye. This RFC is entering final comment period.

@tbu- It still seems like a good idea to incorporate @pnkfelix's suggestions, but given that they don't change the functionality, we don't need to block FCP on it, I don't think.

@nikomatsakis nikomatsakis added the final-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. label Oct 2, 2015
@tbu-
Copy link
Contributor Author

tbu- commented Oct 2, 2015

Note: I'm still not sure why this even warrants an RFC. Re-exports and functions do not behave differently in other places.

@pnkfelix
Copy link
Member

pnkfelix commented Oct 2, 2015

@tbu- part of the reason for the RFC process is to vet changes to the language and have them go through a review process that is independent of the implementation of the change.

I can understand your view that this perhaps could have been categorized as "just a bug" to be fixed, and not a "change to the language per se."

But then again, the question about whether the re-exported main needs to be pub or not is an example of the kind of detail that I think the RFC process is meant to tease out before we commit to an implementation.

In this case the change is relatively small and seems pretty straight-forward (in terms of its specification -- I am not considering difficulty of implementation here). I assume there won't be any hurdles for acceptance, assuming no one points out any critical flaws during the FCP.

@Ericson2314
Copy link
Contributor

I'm confused, I thought pub use was a rexport, and use was merely an import. What's a private re-export?

Also doesn't main normally need to be public?

@tbu-
Copy link
Contributor Author

tbu- commented Oct 3, 2015

Also doesn't main normally need to be public?

No, it doesn't.

@Ericson2314
Copy link
Contributor

Wat. Why on earth do we allow that? Can't declare main to be static in C (https://goo.gl/L6D1gB).

I think my first point still stands however: http://is.gd/8Vt2Cq. Now arguably there should be such a notion of a private re-export, so things like that can work, but as it stands the language doesn't have one.

@Kimundi
Copy link
Member

Kimundi commented Oct 3, 2015

In my humble opinion non-pub use items should just behave like any other private item: Not special.

So any private use would be a re-export for all module below it.

(See also #1289)

@pnkfelix
Copy link
Member

pnkfelix commented Oct 4, 2015

@Ericson2314 For what its worth, I meant to write "re-naming import" when I originally wrote "re-export."

@Ericson2314
Copy link
Contributor

@pnkfelix ah, ok.

@Kimundi, I was going to ask would this cause an explosion of extra symbols, but then I remembered (I think correctly) that items' names match the original location they are defined in, and that their aren't extra symbols for each re-export.

But this also explains why this problem exists in the first place: The imported main doesn't get a new symbol for it's top-level status. edit

I see these options:

  1. Just pub use introduces re-exports. We add extra symbols for re-exports, but they are more rare, so probably OK. pub use foo::main; should now work for free. Downside is main-needs to be pub.
  2. Like 1, but add a new syntax for private re-exports. Rexported main can now need not be pub, but I am sympathetic to Kimundi's proposal that imports and private re-exports should be the same, if for no other reason than our existing syntax implies that pub use and use are the same but for privacy.
  3. Kimundi's plan, and all re-exports get new symbols. Again solve the main problem for free, but way too many symbols.
  4. Kimundi's plan, just introduce extra symbol for imported-main-as-entry point. Solves one inconsistency with another.
  5. We don't make re-exports introduce new symbols, and instead redefined the entry point to match the symbol of main (be it re-exported or not) in the top module. Exactly what qualifies as a re-export is an orthogonal question.

@nikomatsakis
Copy link
Contributor

In the case of main, don't we always synthesize the start point anyhow?
That is, I think that the symbol name rust would normally generate for
main in the root crate is not main, but rather a mangled form thereof.

On Sun, Oct 4, 2015 at 12:11 PM, John Ericson notifications@github.com
wrote:

@pnkfelix https://github.com/pnkfelix ah, ok.

@Kimundi https://github.com/Kimundi, I was going to ask would this
cause an explosion of extra symbols, but then I remembered (I think
correctly) that items' names match the original location they are defined
in, and that their aren't extra symbols for each re-export.

But this also explains why this problem exists in the first place: the
imported main doesn't get a new symbol for it's top-level status.

I see these options:

Just pub use introduces re-exports. We add extra symbols for
re-exports, but they are more rare, so probably OK. pub use foo::main;
should now work for free. Downside is main-needs to be pub.
2.

Like 1, but add a new syntax for private re-exports. Rexported main
can now need not be pub, but I am sympathetic to Kimundi's proposal that
imports and private re-exports should be the same, if for no other reason
than our existing syntax implies that pub use and use are the same but
for privacy.
3.

Kimundi's plan, and all re-exports get new symbols. Again solve the
main problem for free, but way too many symbols.
4.

Kimundi's plan, just introduce extra symbol for imported-main-as-entry
point. Solves one inconsistency with another.
5.

We don't make re-exports introduce new symbols, and instead redefined
the entry point to match the symbol of main (be it re-exported or not) in
the top module. Exactly what qualifies as a re-export is an orthogonal
question.


Reply to this email directly or view it on GitHub
#1260 (comment).

@Ericson2314
Copy link
Contributor

@nikomatsakis You are correct that there is a generated stub (lang_start maybe from looking at play pen?). That "the imported main doesn't get a new symbol for it's top-level status" isn't causing any problem right now as the error comes before anything tries to link the generated stub, but it's still something to keep in mind.

The mangled name for a normal main is roughly ::main : () -> () [I don't know exactly how the C++ mangling scheme works nor how we map our types onto it]. Generated entry points or not, that is what I'd expect. But, depending on which of the choices I enumerate above is taken, if one does use foo::main, the symbol for main will be ::foo::main : () -> (). Certainly, that is what the only symbol for it would be today.

tl;dr, generated name or no generated name, still worthwhile to think about symbol names.

@aturon
Copy link
Member

aturon commented Oct 9, 2015

This RFC has been merged.

The lang team discussed this RFC, and while no one felt strongly that it was important to tackle, it's a relatively minor detail that we would accept a PR to change.

@aturon aturon removed the final-comment-period Will be merged/postponed/closed in ~10 calendar days unless new substational objections are raised. label Oct 9, 2015
@jethrogb
Copy link
Contributor

It seems like this was not an actual merge? 411daab is the relevant commit. This PR should not be open anymore?

@aturon aturon merged commit aa533f9 into rust-lang:master Oct 13, 2015
@aturon
Copy link
Member

aturon commented Oct 13, 2015

@jethrogb Fixed, thanks.

@nikomatsakis
Copy link
Contributor

On Thu, Oct 08, 2015 at 07:34:54PM -0700, John Ericson wrote:

tl;dr, generated name or no generated name, still worthwhile to think about symbol names.

I think my point was us that the symbol name of interest is probably
lang_start, not the Rust main function. But yes, given this PR,
there is no Rust symbol name we can use.

@Centril Centril added A-main Proposals relating to program entrypoints. A-modules Proposals relating to modules. labels Nov 23, 2018
@nikomatsakis
Copy link
Contributor

We discussed this in the @rust-lang/lang meeting. We are generally "fine" with stabilizing this, but we would like to know whether it's in use. Can anybody identify a crate that is using it, or vouch that they would like to use it and have tried it, but are blocked on it not being stable?

@nagisa
Copy link
Member

nagisa commented Mar 9, 2022

I have tried to write code using functionality like this in the past. Intuitively I expected use foo::main to work just as fine as a regular function definition. I recall having a good reason for wanting to do so, which involved some conditional use statements, which IIRC in the end I replaced with

fn main() {
    #[cfg(test)] // harness=false test runner
    tests::main();
    #[cfg(not(test))]
    app::main();
}

kinda thing. I imagine anybody doing something like this would be surprised to find out main at the crate root is special but only if it refers to a canonical function definition.

@tbu-
Copy link
Contributor Author

tbu- commented Mar 10, 2022

I don't remember my use case anymore. I think I remember that I created the issue because I wanted to use it (and expected it to work), not specifically only because I found it inconsistent.

@nikomatsakis
Copy link
Contributor

I think @nagisa identified the use case -- and yes, I imagine the argument in favor of this is basically 'it would be nice if the model is just "we call crate::main, whatever that is"'.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-main Proposals relating to program entrypoints. A-modules Proposals relating to modules. T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

Successfully merging this pull request may close these issues.