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

move closure kind, signature into ClosureSubsts #45879

Merged
merged 26 commits into from
Nov 22, 2017

Conversation

nikomatsakis
Copy link
Contributor

Instead of using side-tables, store the closure-kind and signature in the substitutions themselves. This has two key effects:

  • It means that the closure's type changes as inference finds out more things, which is very nice.
    • As a result, it avoids the need for the freshen_closure_like code (though we still use it for generators).
  • It avoids cyclic closures calls.
    • These were never meant to be supported, precisely because they make a lot of the fancy inference that we do much more complicated. However, due to an oversight, it was previously possible -- if challenging -- to create a setup where a closure directly called itself (see e.g. Stack overflow in rustc using unboxed closure bounds #21410).

We have to see what the effect of this change is, though. Needs a crater run. Marking as [WIP] until that has been assessed.

r? @arielb1

@nikomatsakis nikomatsakis added the relnotes Marks issues that should be documented in the release notes of the next release. label Nov 8, 2017
@nikomatsakis
Copy link
Contributor Author

cc @Mark-Simulacrum -- potential breaking change

|substs| tcx.mk_closure(def_id, substs)
)
}

ty::TyGenerator(def_id, substs, interior) => {
Copy link
Contributor

@arielb1 arielb1 Nov 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you want to do this change for generators too? Generators referencing themselves are just as bad as closures doing so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but for purposes of getting crater results, not really needed. Will do, however.

@nikomatsakis
Copy link
Contributor Author

Hmm, the mir-opt tests seem... maybe real? Will have to investigate later.

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 9, 2017
@nikomatsakis
Copy link
Contributor Author

The mir-opt problem turns out to be an existing bug in inlining.

@nikomatsakis
Copy link
Contributor Author

So should we do a crater run here? In that case, do we want to do a try build?

@bors
Copy link
Contributor

bors commented Nov 10, 2017

☔ The latest upstream changes (presumably #45785) made this pull request unmergeable. Please resolve the merge conflicts.

@nikomatsakis nikomatsakis force-pushed the nll-kill-cyclic-closures branch from 3a1134d to d5a54a9 Compare November 11, 2017 11:02
@nikomatsakis
Copy link
Contributor Author

cc @rust-lang/infra -- what is the procedure for doing a crater run here?

@nikomatsakis
Copy link
Contributor Author

@bors try

@bors
Copy link
Contributor

bors commented Nov 11, 2017

⌛ Trying commit d5a54a9 with merge fb88d08...

bors added a commit that referenced this pull request Nov 11, 2017
[WIP] move closure kind, signature into `ClosureSubsts`

Instead of using side-tables, store the closure-kind and signature in the substitutions themselves. This has two key effects:

- It means that the closure's type changes as inference finds out more things, which is very nice.
    - As a result, it avoids the need for the `freshen_closure_like` code (though we still use it for generators).
- It avoids cyclic closures calls.
    - These were never meant to be supported, precisely because they make a lot of the fancy inference that we do much more complicated. However, due to an oversight, it was previously possible -- if challenging -- to create a setup where a closure *directly* called itself (see e.g. #21410).

We have to see what the effect of this change is, though. Needs a crater run. Marking as [WIP] until that has been assessed.

r? @arielb1
@kennytm kennytm added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 11, 2017
@bors
Copy link
Contributor

bors commented Nov 11, 2017

☀️ Test successful - status-travis
State: approved= try=True

@alexcrichton
Copy link
Member

r? @arielb1

(assigning a reviewer)

@nikomatsakis
Copy link
Contributor Author

Rebased.

@nikomatsakis nikomatsakis force-pushed the nll-kill-cyclic-closures branch from d5a54a9 to 0f6bd17 Compare November 13, 2017 14:35
@nikomatsakis
Copy link
Contributor Author

nikomatsakis commented Nov 13, 2017

I also decided to start an "old school" crater run.

Root regressions, sorted by rank:

@nikomatsakis
Copy link
Contributor Author

@bors try

@bors
Copy link
Contributor

bors commented Nov 13, 2017

⌛ Trying commit 0f6bd17 with merge e3645b5...

bors added a commit that referenced this pull request Nov 13, 2017
[WIP] move closure kind, signature into `ClosureSubsts`

Instead of using side-tables, store the closure-kind and signature in the substitutions themselves. This has two key effects:

- It means that the closure's type changes as inference finds out more things, which is very nice.
    - As a result, it avoids the need for the `freshen_closure_like` code (though we still use it for generators).
- It avoids cyclic closures calls.
    - These were never meant to be supported, precisely because they make a lot of the fancy inference that we do much more complicated. However, due to an oversight, it was previously possible -- if challenging -- to create a setup where a closure *directly* called itself (see e.g. #21410).

We have to see what the effect of this change is, though. Needs a crater run. Marking as [WIP] until that has been assessed.

r? @arielb1
@bors
Copy link
Contributor

bors commented Nov 13, 2017

☀️ Test successful - status-travis
State: approved= try=True

@aidanhs
Copy link
Member

aidanhs commented Nov 14, 2017

@nikomatsakis just pinging rust-lang/infra and saying "requesting crater run" will (eventually) get a crater run done.

@nikomatsakis
Copy link
Contributor Author

@aidanhs thanks =)

@nikomatsakis
Copy link
Contributor Author

So, based on the "old school" crater results (no regressions), I see three paths forward:

  • Improve this branch to issue a nicer error (i.e., one that says "this is a result of a recent fix" and points to an issue describing what happened and how to fix it) and land it. This approach is a good thing for the code but cannot accommodate a warning period.
  • Close this PR and open another that adds a warning period. Once that is out in the next beta, re-open this PR.
  • Wait for the "full crater" and then decide.

I'm leaning mildly towards path 2, but we'll see how much time I get for it. I just prefer to give warnings if we can.

// not known to hold in the creator's context (and
// indeed the closure may not be invoked by its
// creator, but rather turned to someone who *can*
// verify that).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also doesn't check captured variables from the parent function's generics.

Maybe these don't matter, because within a function the generics are always the function's own - and therefore WF, and outside of it a TyClosure should not appear in the wild. So I'll either add the generics in, or be sure they don't matter and add a comment..

EntryKind::Generator(self.lazy(&data))
}

ty::TyClosure(def_id, substs) => {
Copy link
Contributor

@arielb1 arielb1 Nov 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: isn't a closure's signature stored in the closure's item type? storing the data separately feels like it's only likely to cause mimsmatches and trouble (aka can't CrateMetadata::fn_sig call tcx.item_type(def_id).closure_sig(def_id, tcx)?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does seem silly. Let me see if it can be readily purged.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not really obvious to me how to do this. I'm sure it can be done, but I don't think that item_type will do it. I believe that gives back something with "identity" substitutions, which isn't really what we want here (i.e., the closure_sig parameter will be an unsubstituted type parameter). The other definition of fn_sig uses the typeck_tables to get what we want, but for that we need the HirId of the closure, and I'm not sure how to get that from another crate.

@arielb1
Copy link
Contributor

arielb1 commented Nov 18, 2017

r=me mod. comments

also, apparently MIR inlining is still somewhat broken with closures. I'll try to open an issue.

[00:57:59] ---- [mir-opt] mir-opt/validate_1.rs stdout ----
[00:57:59] 	
[00:57:59] error: compilation failed!
[00:57:59] status: exit code: 101
[00:57:59] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/mir-opt/validate_1.rs" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/mir-opt" "--target=x86_64-unknown-linux-gnu" "-Zdump-mir=all" "-Zmir-opt-level=3" "-Zdump-mir-exclude-pass-number" "-Zdump-mir-dir=/checkout/obj/build/x86_64-unknown-linux-gnu/test/mir-opt/validate_1" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/mir-opt/validate_1.stage2-x86_64-unknown-linux-gnu" "-Crpath" "-O" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-Z" "verbose" "-Z" "mir-emit-validate=1" "-Z" "span_free_formats" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/mir-opt/validate_1.stage2-x86_64-unknown-linux-gnu.aux"
[00:57:59] stdout:
[00:57:59] ------------------------------------------
[00:57:59] 
[00:57:59] ------------------------------------------
[00:57:59] stderr:
[00:57:59] ------------------------------------------
[00:57:59] error: internal compiler error: /checkout/src/librustc_mir/transform/inline.rs:715: Arg operand `1` is (_10.0: &ReErased mut i32), not local

@arielb1
Copy link
Contributor

arielb1 commented Nov 18, 2017

this is #46086

@nikomatsakis nikomatsakis force-pushed the nll-kill-cyclic-closures branch from c490241 to df6fdbc Compare November 19, 2017 10:37
@arielb1
Copy link
Contributor

arielb1 commented Nov 19, 2017

Test problem:

[01:06:03] ---- /checkout/obj/build/x86_64-unknown-linux-gnu/test/error-index.md - Rust_Compiler_Error_Index::E0644 (line 11807) stdout ----
[01:06:03] 	error[E0631]: type mismatch in closure arguments
[01:06:03]   --> /checkout/obj/build/x86_64-unknown-linux-gnu/test/error-index.md:12:3
[01:06:03]    |
[01:06:03] 9  |     let x = |y| {
[01:06:03]    |  ___________-
[01:06:03] 10 | |     // Here, when `x` is called, the parameter `y` is equal to `x`.
[01:06:03] 11 | |   };
[01:06:03]    | |___- found signature of `fn(_) -> _`
[01:06:03] 12 |     fix(&x);
[01:06:03]    |     ^^^ expected signature of `for<'r> fn(&'r [closure@/checkout/obj/build/x86_64-unknown-linux-gnu/test/error-index.md:9:11: 11:4]) -> _`
[01:06:03]    |
[01:06:03]    = note: required by `fix`
[01:06:03] 
[01:06:03] thread 'rustc' panicked at 'couldn't compile the test', /checkout/src/librustdoc/test.rs:288:12
[01:06:03]
[01:06:03] 
[01:06:03] failures:
[01:06:03]     /checkout/obj/build/x86_64-unknown-linux-gnu/test/error-index.md - Rust_Compiler_Error_Index::E0644 (line 11807)

@arielb1
Copy link
Contributor

arielb1 commented Nov 19, 2017

r=me with test fixed.

@kennytm kennytm added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 19, 2017
@arielb1
Copy link
Contributor

arielb1 commented Nov 20, 2017

@bors r+

@bors
Copy link
Contributor

bors commented Nov 20, 2017

📌 Commit 9af5a06 has been approved by arielb1

@nikomatsakis
Copy link
Contributor Author

@bors r=arielb1

@bors
Copy link
Contributor

bors commented Nov 20, 2017

📌 Commit b9c766c has been approved by arielb1

Before we were assuming that *every* `fn_sig` must pertain to a local
closure.
@nikomatsakis
Copy link
Contributor Author

@bors r=arielb1

@bors
Copy link
Contributor

bors commented Nov 21, 2017

📌 Commit 00732a3 has been approved by arielb1

@bors
Copy link
Contributor

bors commented Nov 21, 2017

⌛ Testing commit 00732a3 with merge d6d09e0...

bors added a commit that referenced this pull request Nov 21, 2017
move closure kind, signature into `ClosureSubsts`

Instead of using side-tables, store the closure-kind and signature in the substitutions themselves. This has two key effects:

- It means that the closure's type changes as inference finds out more things, which is very nice.
    - As a result, it avoids the need for the `freshen_closure_like` code (though we still use it for generators).
- It avoids cyclic closures calls.
    - These were never meant to be supported, precisely because they make a lot of the fancy inference that we do much more complicated. However, due to an oversight, it was previously possible -- if challenging -- to create a setup where a closure *directly* called itself (see e.g. #21410).

We have to see what the effect of this change is, though. Needs a crater run. Marking as [WIP] until that has been assessed.

r? @arielb1
@bors
Copy link
Contributor

bors commented Nov 22, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: arielb1
Pushing d6d09e0 to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants