-
Notifications
You must be signed in to change notification settings - Fork 13.3k
experiment with relaxing the orphan rule #136979
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
Comments
@rustbot label +I-lang-nominated +I-types-nominated +A-rust-for-linux |
Note that the Linux kernel would, if it shipped anything with this variant of the compiler, lock us into supporting this code for its LTS lifecycle, no matter how unsound it was. This problem has already occurred with other flags that were proposed for addition "until a better solution was found". Thus this proposed plan, and especially "just provide a modified compiler repo", is in conflict with our proposed project goal for stabilizing tooling for the kernel. A project I support, because then the kernel has less special asks "just for them" in our repository and inflicts less additional maintenance burdens. |
This is the reputation we are getting in the kernel because Ted Ts'o thinks it's okay to bag on us because R4L uses unstable features. And this would be the most unstable of them all, because the flag would be inherently unsound, in this proposed form. I do not think it is a good idea to embark on a project to deliberately increase the amount of libelous accusations directed at our community. |
The nightly compiler flag will not be used in the kernel. It is only to experiment and find a path forward. So essentially, we want a way to eventually have this feature in stable and only then use it in the kernel. |
It shouldn't be too hard to patch rustc yourself to disable the orphan checker. Probably just a matter of adding |
I sadly do not have the bandwidth to hack on the rust compiler. We also need to go through the proper procedure on the Rust side to get it implemented, so I brought this topic up in the RfL sync meeting. TC suggested that I create this issue and so I did. |
I think the right location to add
|
Why do you need proper procedures for an experiment?
Also as seen in bjorn's comment, if you want to do an experiment, people are usually happy to provide a patch under the condition it will never make it into the rustc repo itself. Thus I don't quite understand why this issue exists. |
Thanks for the pointer (I have only hacked twice on the rust compiler and I wouldn't even have had an idea of where to start), I will try it out next week.
All I did was bring this up again in the RfL sync meeting and we talked a bit about how we could start an experiment to find a solution. We've talked about this before (as you can see in the zulip topic). As I wrote above, TC suggested that I create an issue for this. |
What was discussed in the meeting was explicitly about a flag (or fork, or experiment) that would never be used in upstream Linux, as @y86-dev explained.
I made the suggestion of providing the flag outside the usual compiler binaries precisely in case it helped Rust ensure this would never be used in upstream Linux.
I am not sure Ted was talking about unstable features used by Rust for Linux. |
My understanding from our prior discussions was that RfL was looking for some option you could use to relax coherence for your use case, on nightly, so that you could actually merge this work to break things apart into separate crates, with the idea being that, while we would never stabilize the flag or whatever that would relax the rules in a coarse way, that this nightly ability would allow you to hold onto an older MSRV as, when we do later add something we can stabilize, RfL could use build-time logic to move to that conditionally based on the user's toolchain version. @ojeda: Let me know about that. If that's no longer the idea, and testing with some local branch is fine for what you need until we later (maybe much later) work out something that could go on a stabilization path, then we can indeed just close this. |
I'm pretty confident we'll need years to get even an idea of something stabilizable. This is the kind of feature with too many unknowns to actually be on the horizon. I recommend just waiting until there's an impl and then discussing what to actually do. Especially in the light of linux already able to do a trivial backport of a one line |
Agreed it could. As I put it:
|
There have been discussions for many, many years about trying to find ways to relax the orphan rule, and about experimenting with approaches that would allow doing so without introducing soundness issues. This issue was an effort to attempt to turn some of those discussions into low-commitment action and experiment. I'm not sure why this was framed as being a potential out-of-tree rustc experiment. The discussion in the RfL meeting was about something that could appear in rustc. In the RfL meeting, I suggested doing two things:
I think it's reasonably safe to say RfL is not going to push upstream any code depending on |
Yea I think bin crates and wasm cdylibs are a safe place for experimentation. Though I do not see why this should be part of RfL goals or prioritization. It is an issue for everyone, and everyone works around it. So can RfL. There are no blockers or major pain points, just a bit of boilerplate. Or is the issue that such workarounds create an API that will be expensive to migrate due to the guarantees the kernel has? |
In the past we discussed whether we could get a flag in the actual compiler that we could use as a last resort (especially nice if it could be in Debian Trixie's Yesterday, my understanding was that we were discussing other possibilities that are way less adventurous, such as having the flag but not ever use it in Linux. Or, if that is still too risky, having it in a different binary that is not the official |
Thank you, that's really helpful confirmation! I'm assuming this would apply to a C-style For the sake of clarity: I very much understand that large design issues and potential soundness issues definitely apply to any solution that would allow this in library crates. I'd like to get there eventually, but I would not equate that with the much simpler experiment of trying this in top-level bin/cdylib/staticlib crates. (I have some ideas for simplifying the problem for library crates as well, but that's separate.)
Many of the items that get noticed in the course of work on RfL apply to many many other projects as well, and work on them (towards eventual stabilization of them) helps many other projects as well. This one seemed worth bringing up on the basis that many many projects have requested this, not just RfL. It's a regular recurring topic on IRLO, URLO, /r/rust, and many other places.
If you mean workarounds like newtypes: there are no API guarantees inside the kernel, so there's no fundamental concern about migration. But it's the kind of thing where it'd probably produce enough of an "ugh" reaction from people using it that I suspect the RfL folks would likely just not split crates if it'd require that workaround, rather than inflict that on people. |
@ojeda wrote:
I can safely say this isn't going to happen. The compiler version that's likely to ship in Trixie is well past the point where any experimental flag could be added that RfL could or should be relying on.
✋ Confirming that I said that in the meeting. Adding an experimental flag in nightly is a first step towards something you'll eventually be able to use, and that we'll eventually be able to stabilize. |
Exactly, that is the main motivation for the kernel to relax the rule somehow.
Yeah, that was my understanding as well yesterday -- I was trying to describe what we discussed in the past in the first sentence. That is why, since it is not happening, we were suggesting yesterday other options to start the experiment that may not require the flag in the actual Of course, it is still better for us to have it in nightly; and if it is also easier for you, that is great too. And in such a case, we would still discuss with you before actually using it in the kernel for real and so on, i.e. the same still applies. I hope that clarifies. |
I agree, I just don't like that it's being under a RfL umbrella. It seems like a useless burning of priorization points while actual blockers for running on stable have not finished. This is not what is going to make RfL any less likely to succeed, so it's burning sync T-lang meeting time and discussion resources. Let's use those resources to instead actually do the experiment as we always do experiments. No pressure, just figuring out MVPs and incremental steps and stuff |
I think we're broadly in agreement. It is definitely not a "needed for RfL to be on stable" issue, and as such it also isn't part of that project goal. It's something I would advocate prioritizing in lang on the basis of "many people want this, and it's a multi-year arc we should embark upon because the sooner we start the sooner we finish". In any case, 👍 for embarking upon the experiment rather than spending more time evaluating rationale and prioritization. :) |
It is true that it is not important because we have kept a lot of the code in a single crate. However, we will really need to split it soon in many crates, and thus this may become more important soon, i.e. it could become a common pain point mentioned by kernel maintainers. We don't know how bad it will be yet, though. I think we all agree that it is not in the scope of the flagship project goal. Nevertheless, it is something that has been in our radar for a couple years. |
I would love to see some actual examples of such cases.
I’m not sure I follow this argument… well it lacks explicit arguments anyway. I can only assume this argues from a perspective of “orphan rules protect semver-stable interfaces” and “orphan rules protect you from unexpected downstream breakage/overlaps”. But that’s an incomplete picture. I’ve recently written down some of my intuitions of a larger picture here (given this is mostly written from a user’s perspective, I’m not sure every point I’m making is actually correct… but I’m pretty certain with the challenges around vtables). I’m happy to hear any corrections or clarifications if I’m too pessimistic on any aspects. To re-iterate the high-level: The important difficulty with breaking orphan rules is two main aspects:
Now… I’ll come back again to the original point: I’m very curious to see more examples. Examples of that “it won't be feasible to always create a workaround for orphan rule conflicts”. For instance, in my original (linked) internals thread reply I already hadn’t actually thought up the example here at all, with But with this example solved via a Of course a 3rd possible use-case is when you actually want to somehow be like This general pattern can come up with orphan-rules considerations though, because I can imagine applying a “moving the otherwise-orphaned impl somewhere upstream” workaround can be hard when the implementation details use a lot of other stuff only available downstream. Footnotes
|
Thanks @steffahn for all the context and explanations. Quick note...
Even if there happen to be always workarounds (which would already be a nice result), part of the motivation here is to avoid those workarounds, i.e. to improve the language (if possible) so that they are not needed to begin with, thus improving ergonomics and making the crate boundary less special (for projects that may want/need that). |
What steffahn is trying to say is that you're having us poke in the dark. We don't know what you are asking us to experiment with. For that matter, I'm not even sure all the problems being grouped under orphan rules are actually orphan rules. Please provide examples of the different kinds of workarounds you are considering. There are proposals I can think of that can be considered if someone writes a thorough enough analysis of the problems with said proposal (what Jack asks for in https://rust-lang.zulipchat.com/#narrow/channel/326866-t-types.2Fnominated/topic/.23136979.3A.20experiment.20with.20relaxing.20the.20orphan.20rule/near/499848638). And then there are proposals (that have frequently employed workarounds) that to the best of my knowledge have been hard rejected by every lang or compiler dev as long as I've been around rustc. |
I understood -- my reply was just a note on a particular point.
We are not asking Rust to experiment with anything in particular. I think @y86-dev's initial message is quite clear on that. @joshtriplett also framed it well: "The question is more, how might we start figuring out a path to a feature we could feel confident in and stabilize? If it's going to take a while, taking a first step seems like a good idea." We are stating a problem we are facing and we had a suggestion that could perhaps allow us to experiment around how the kernel could potentially look like if some current restrictions (or their workarounds) were not there. The goal of that suggestion is to give you more information about what kind of code we would like to be able to write if possible. The overall goal is to learn more about the problem by using Linux as an example use case where we already collaborate.
Definitely, that is a possibility. What we care about is the problem and whether there is anything that could potentially be done about it to improve how kernel code is written.
That is good to know, thank you. However, to be clear, we are not trying to propose any particular solution. |
By splitting your crates the with the "workarounds" (I disagree they are really workarounds. They make reasoning about what happens where very simple) and reporting actual end user pain points. |
I chatted with @compiler-errors about this a bit. As we talked about during the RfL meeting, what you actually need for this specific issue is the ability to define fundamental types. Now, this is not something we can expose on stable for the foreseeable future because it's a semver hazard, but
So, my recommendation is that you try out this feature in your experiment. No new flags needed. If you decide it would be useful and solve most or all of your problems with crate splitting, let's discuss how to get it to you on stable. Old compilers can then just use the current overly permissive attribute |
We can definitely give that a try, thanks a lot! |
In Rust-for-Linux, we wish to split our single
kernel
crate into many smaller crates. There are various reasons for this:rust/
directory and into their respective subsystems. Then every subsystem should have their own crate(s).While I was splitting off the
pin-init
crate from thekernel
crate in order to keep it in sync with the user-space version, I ran into a problem with the orphan rule. We also had previously anticipated that issues with the orphan rule would pop up if we were to split ourkernel
crate. The issue that I am facing currently is not that bad, as I can solve it with an additional trait. But in the long run, it won't be feasible to always create a workaround for orphan rule conflicts.Note that in the
kernel
crate, we don't need to be protected by the orphan rule, as all 1 dependents (and dependencies exceptcore
) of thekernel
crate are under our control directly in-tree. So we would like to have some way to relax the orphan rule for our kernel crates.Here is the error that I am currently running into.
I have this trait in
pin-init
(or thekernel
crate before splitting):And an impl in the
kernel
crate for our ownBox
type:The error that I get is expected, as neither
Zeroable
norOption<T>
are declared by thekernel
crate:In the latest RfL sync meeting, I brought this up and @ojeda had a good way of highlighting the problem: it's a chicken-and-egg situation, until we can relax the orphan rule, we're not able to split our crate due to these errors. And in order to know how the orphan rule should be relaxed, we have to split our crate. For this reason, it was suggested in the latest RfL sync meeting to use the following approach: introduce a nightly flag that disables the orphan rule wholesale (edit: for binary crates) and add a lint that warns on the orphan rule being violated. This way, we can split the kernel crate and see what types of orphan rule violations we would like to use without actually stabilizing anything. Miguel also added that you do not even need to ship it into nightly, you can just give us a modified compiler repository and we can test locally with that.
So essentially, this issue is for getting the ball rolling and having some nightly-only/custom-compiler-only flag to disable the orphan rule and see what types of violations we would like to have relaxed. Figuring out a stabilizable solution should come later, when we have an overview over all of the different kinds of relaxations we would like to have.
There also has been a zulip discussion about this topic.
cc @rust-lang/lang
Footnotes
while there are out-of-tree modules, they are always built for a pinned kernel version. When updating, they face the same issue on the C side, so it's OK to break them. ↩
The text was updated successfully, but these errors were encountered: