Skip to content

revealing uses in the defining scope: merge borrowck for all typeck children #129

Closed
@lcnr

Description

@lcnr

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

@compiler-errors, @oli-obk

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.
  • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    final-comment-periodThe FCP has started, most (if not all) team members are in agreementmajor-changeA major change proposalto-announceAnnounce this issue on triage meeting

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions