Skip to content

cycles creating new placeholders result in overflow #209

Open
rust-lang/rust
#140208
@lcnr

Description

@lcnr

cc rust-lang/rust#141125

fn build_multiple<'a>() -> impl Sized {
    spawn(async { build_dependencies().await });
}

// Adding an explicit `Send` bound fixes it.
// Proving `build_dependencies(): Send` in `build_multiple` adds
// addiitional defining uses/placeholders.
fn build_dependencies() -> impl Future<Output = ()> /* + Send */ {
    async {
        Box::pin(build_dependencies()).await;
        async { build_multiple() }.await;
    }
}

fn spawn<F: Send>(_: F) {}

this is breaking werk, cc #199


pub struct Bar
where
    for<'a> &'a mut Self:;

fn main() {}

results in overflow in the new solver when checking WF(Bar) or `for<'a> WF(&'a mut Bar). The issue is as follows:

pub struct Bar
where
    for<'a> &'a mut Bar:;
  • for<'a> WF(&'a mut Bar) (attempt 0)
    • WF(&'a.1 mut Bar)
      • outlives(Bar, 'a.1) OK [Bar: 'a.1]
      • WF(Bar)
        • for<'a> WF(&'a mut Bar) cycle OK []
    • RESULT: OK [Bar: 'a.1]
  • for<'a> WF(&'a mut Bar) (attempt 1)
    • WF(&'a.1 mut Bar)
      • outlives(Bar, 'a.1) OK [Bar: 'a.1]
      • WF(Bar)
        • for<'a> WF(&'a mut Bar) cycle OK [Bar: 'a.2] (create new universe)
    • RESULT: OK [Bar: 'a.1, Bar: 'a.2]
  • for<'a> WF(&'a mut Bar) (attempt 2)
    • WF(&'a.1 mut Bar)
      • outlives(Bar, 'a.1) OK [Bar: 'a.1]
      • WF(Bar)
        • for<'a> WF(&'a mut Bar) cycle OK [Bar: 'a.2, Bar: 'a.3] (create new universe)
    • RESULT: OK [Bar: 'a.1, Bar: 'a.2, Bar: 'a.3]

starting with WF(BAR)

  • WF(Bar) iteration 0
    • for<'a> WF(&'a mut Bar)
      • WF(&'a.1 mut Bar)
        • outlives(Bar, 'a.1) OK [Bar: 'a.1]
        • WF(Bar) cycle OK []
  • WF(Bar) iteration 1
    • for<'a> WF(&'a mut Bar)
      • WF(&'a.1 mut Bar)
        • outlives(Bar, 'a.1) OK [Bar: 'a.1]
        • WF(Bar) cycle OK [Bar: 'a.?]

a similar issue is:

struct Foo
where
    Foo:,
    for<'a> &'a ():;
  • WF(Foo) iteration 0
    • WF(Foo) cycle OK []
    • for<'a> WF(&'a ()) OK [(): 'a.1] (new universe for unnameable placeholder)
    • result OK [(): 'a.1]
  • WF(Foo) iteration 1 (in new infcx)
    • WF(Foo) cycle OK [(): 'a.1] (new universe for unnameable placeholder)
    • for<'a> WF(&'a ()) OK [(): 'a.2] (new universe for unnameable placeholder)
    • result OK [(): 'a.1, (): 'a.2] yikes (have to rerun again)

The long term plan to solve this is to eagerly deal with new placeholders in the solver, short term we probably want to somehow deduplicate new placeholder constraints when creating the query response we're going to ignore this because hopefully this pattern does not exist in user-code.

Metadata

Metadata

Assignees

Type

No type

Projects

Status

potentially irrelevant

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions