Description
Proposal
One of the main remaining blockers of the next-generation trait solver is our handling of opaque types. The core issue is that there are many existing uses of RPITs which are opaque with the existing impl but will reveal the opaque type with the new solver.
Background
Consider the following example, minimized from the gll
crate:
struct Foo;
impl Foo {
fn defines_rpit(&self) -> impl Sized + '_ {
let _ = || {
let temp = Foo;
temp.defines_rpit();
// desugars to `Foo::defines_rpit(&temp);`
};
self
}
}
The recursive function call currently does not reveal the RPIT. With the new solver we always normalize opaque types in the defining scope, so the recursive call ends up having a defining use of rpit<'temp> = &'unconstrained Foo
. This use then results in an error for two reasons:
- the arguments of the opaque type are not universal (i.e. free regions in the function)
- it's impossible to know how
'unconstrained
and'temp
are related in the general case, especially if the opaque has more than 1 region parameter
To support this I believe that we need to introduce the concept of a revealing use in the defining scope. The idea is that as long as there is one use of the opaque type with universal arguments, we use that defining use to fully infer the hidden type and then only check that the revealing uses are correct.
We currently compute mir_borrowck
separately for closures and their parents. Given a closure with a signature fn(&'0 T) -> &'1 T
borrowck of the closure itself does not know how '0
and '1
are related. It therefore propagates any constraints between these external regions to its parent, see the rustc-dev-guide. Using separate queries here is incompatible with this new design as we need to support revealing uses inside of closures while the defining use in the parent function. This is the case in the above example.
Instead of using a separate mir_borrowck
query for nested bodies, I intend to borrowck nested bodies directly as part of mir_borrowck
of the typeck root. I intend to keep the actual impls mostly separate for now, e.g. continue using a separate InferCtxt
and nll region vars in each body.
We currently apply member constraints while computing the sccs of the region constraint graph in a single pass. This will need to support merging already computed sccs when checking revealing uses.
The exact modifications necessary to support revealing uses are still not totally clear to me and will require us to actually attempt to implement this design.
Mentors or Reviewers
Process
The main points of the Major Change Process are as follows:
- File an issue describing the proposal.
- A types team member or contributor who is knowledgeable in the area can second by writing
@rustbot second
.- Finding a "second" suffices for internal changes. If however, you are proposing a new public-facing feature, such as a
-C flag
, then full team check-off is required. - Types team members can initiate a check-off via
@rfcbot fcp merge
on either the MCP or the PR.
- Finding a "second" suffices for internal changes. If however, you are proposing a new public-facing feature, such as a
- Once an MCP is seconded, the Final Comment Period begins. If no objections are raised after 10 days, the MCP is considered approved.
You can read more about Major Change Proposals on forge.
Comments
This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.