Skip to content

first pass at isolating dep-graph tasks - #40308

Merged
bors merged 2 commits into
rust-lang:masterfrom
nikomatsakis:incr-comp-isolate-task
Mar 11, 2017
Merged

first pass at isolating dep-graph tasks#40308
bors merged 2 commits into
rust-lang:masterfrom
nikomatsakis:incr-comp-isolate-task

Conversation

@nikomatsakis

Copy link
Copy Markdown
Contributor

This intentionally leaves DepGraph::in_task(), the more common form,
alone. Eventually all uses of DepGraph::in_task() should be ported
to with_task(), but I wanted to start with a smaller subset.

I also used AssertDepGraphSafe on the closures that are found in
trans. This is because the types there are non-trivial and I wanted to
lay down the mechanism and come back to the more subtle cases.

The current approach taken in this PR has a downside: it is necessary
to manually "reify" fn types into fn pointers when starting a task,
like so:

dep_graph.with_task(..., task_fn as fn(_))

this is because with_task takes some type T that implements
DepGraphTask rather than taking a fn() type directly. This is so
that we can accept closure and also so that we can accept fns with
multiple arities. I am not sure this is the right approach.

Originally I wanted to use closures bound by an auto trait, but that
approach has some limitations:

  • the trait cannot have a read() method; since the current method
    is unused, that may not be a problem.
  • more importantly, we would want the auto trait to be "undefined" for all types
    by default -- that is, this use case doesn't really fit the typical
    auto trait scenario. For example, imagine that there is a u32 loaded
    out of a hir::Node -- we don't really want to be passing that
    u32 into the task!

@nikomatsakis

Copy link
Copy Markdown
ContributorAuthor

r? @michaelwoerister

cc @eddyb

cc #40304

@rust-highfive

Copy link
Copy Markdown
Contributor

r? @nrc

(rust_highfive has picked a reviewer for you, use r? to override)

@nikomatsakis

nikomatsakis commented Mar 6, 2017

Copy link
Copy Markdown
ContributorAuthor

This is probably not ready to merge quite yet, but I wanted to let people take a look and get some feedback. I'm thinking of experimenting with different forms for more ergonomic APIs. I had thoughts of experimenting with macros that create functions, though it might be better to take advatnage of the new "coerce closure into fn ptr" RFC, once that is implemented. Another possibility is always passing the tcx, which is basically always necessary.

@michaelwoerister

Copy link
Copy Markdown
Member

Another possibility is always passing the tcx, which is basically always necessary.

If that's possible it would make for a rather simple API.

@eddyb

eddyb commented Mar 7, 2017

Copy link
Copy Markdown
Contributor

@nikomatsakis That RFC is already implemented! We'll be able to use it once we bump the beta.

@nikomatsakis

Copy link
Copy Markdown
ContributorAuthor

OK, pushed a revised version that takes a fn with two arguments. This might get mildly cleaner if we had access to the closure-as-fn thing (good to hear that will come soon, @eddyb) but, actually, I think not that much. Declaring a fn item just isn't that bad, and for those cases where it is, it starts to suggest places that we should be employing on-demand, I think.

@nikomatsakisnikomatsakis changed the title WIP: first pass at isolating dep-graph tasksfirst pass at isolating dep-graph tasksMar 7, 2017
@nikomatsakis

Copy link
Copy Markdown
ContributorAuthor

removing "WIP" as I think this is ready for review

r? @michaelwoerister

@michaelwoeristermichaelwoerister left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Seems like a good starting point. Closure-to-fn coercions will certainly make this more ergonomic.

r=me with the comments addressed.

Comment threadsrc/librustc/dep_graph/mod.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't see any macros in that module.

Comment threadsrc/librustc/dep_graph/graph.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A comment explaining the setup would be good here, especially why there's a distinction between cx and arg.

Comment threadsrc/librustc/dep_graph/safe.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's not an auto trait anymore, right?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

good point :)

Comment threadsrc/librustc/lib.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not needed anymore?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

ah yeah all the macro stuff is from an older pass, thanks

Comment threadsrc/librustc_typeck/collect.rs Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This explicit read is not there anymore in the new version. This should be fine -- after all, the new system should guarantee that we cannot do anything with the NodeId without triggering a read -- but I wanted to double check that that is intentional.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

that is intentional -- the newer code no longer "leaks" in a hir::Item (or TraitItem, etc), so there is no need for the "automatic" read.

@nikomatsakis
nikomatsakisforce-pushed the incr-comp-isolate-task branch from 635a4c1 to 19c6bfbCompareMarch 8, 2017 14:15
@nikomatsakis

Copy link
Copy Markdown
ContributorAuthor

@bors r=mw

@bors

bors commented Mar 8, 2017

Copy link
Copy Markdown
Collaborator

📌 Commit 19c6bfb has been approved by mw

@bors

bors commented Mar 9, 2017

Copy link
Copy Markdown
Collaborator

🔒 Merge conflict

@alexcrichton

Copy link
Copy Markdown
Member

@bors: retry

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Mar 10, 2017
…, r=mw
first pass at isolating dep-graph tasks
This intentionally leaves `DepGraph::in_task()`, the more common form,
alone. Eventually all uses of `DepGraph::in_task()` should be ported
to `with_task()`, but I wanted to start with a smaller subset.
I also used `AssertDepGraphSafe` on the closures that are found in
trans. This is because the types there are non-trivial and I wanted to
lay down the mechanism and come back to the more subtle cases.
The current approach taken in this PR has a downside: it is necessary
to manually "reify" fn types into fn pointers when starting a task,
like so:
dep_graph.with_task(..., task_fn as fn(_))
this is because `with_task` takes some type `T` that implements
`DepGraphTask` rather than taking a `fn()` type directly. *This* is so
that we can accept closure and also so that we can accept fns with
multiple arities. I am not sure this is the right approach.
Originally I wanted to use closures bound by an auto trait, but that
approach has some limitations:
- the trait cannot have a `read()` method; since the current method
is unused, that may not be a problem.
- more importantly, we would want the auto trait to be "undefined" for all types
*by default* -- that is, this use case doesn't really fit the typical
auto trait scenario. For example, imagine that there is a `u32` loaded
out of a `hir::Node` -- we don't really want to be passing that
`u32` into the task!
A task function is now given as a `fn` pointer to ensure that it carries
no state. Each fn can take two arguments, because that worked out to be
convenient -- these two arguments must be of some type that is
`DepGraphSafe`, a new trait that is intended to prevent "leaking"
information into the task that was derived from tracked state.
This intentionally leaves `DepGraph::in_task()`, the more common form,
alone. Eventually all uses of `DepGraph::in_task()` should be ported
to `with_task()`, but I wanted to start with a smaller subset.
Originally I wanted to use closures bound by an auto trait, but that
approach has some limitations:
- the trait cannot have a `read()` method; since the current method
is unused, that may not be a problem.
- more importantly, we would want the auto trait to be "undefined" for all types
*by default* -- that is, this use case doesn't really fit the typical
auto trait scenario. For example, imagine that there is a `u32` loaded
out of a `hir::Node` -- we don't really want to be passing that
`u32` into the task!
@alexcrichton
alexcrichtonforce-pushed the incr-comp-isolate-task branch from 19c6bfb to 4d5441fCompareMarch 10, 2017 16:15
@alexcrichton

Copy link
Copy Markdown
Member

@bors: r=mw

@bors

bors commented Mar 10, 2017

Copy link
Copy Markdown
Collaborator

📌 Commit 4d5441f has been approved by mw

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Mar 10, 2017
…, r=mw
first pass at isolating dep-graph tasks
This intentionally leaves `DepGraph::in_task()`, the more common form,
alone. Eventually all uses of `DepGraph::in_task()` should be ported
to `with_task()`, but I wanted to start with a smaller subset.
I also used `AssertDepGraphSafe` on the closures that are found in
trans. This is because the types there are non-trivial and I wanted to
lay down the mechanism and come back to the more subtle cases.
The current approach taken in this PR has a downside: it is necessary
to manually "reify" fn types into fn pointers when starting a task,
like so:
dep_graph.with_task(..., task_fn as fn(_))
this is because `with_task` takes some type `T` that implements
`DepGraphTask` rather than taking a `fn()` type directly. *This* is so
that we can accept closure and also so that we can accept fns with
multiple arities. I am not sure this is the right approach.
Originally I wanted to use closures bound by an auto trait, but that
approach has some limitations:
- the trait cannot have a `read()` method; since the current method
is unused, that may not be a problem.
- more importantly, we would want the auto trait to be "undefined" for all types
*by default* -- that is, this use case doesn't really fit the typical
auto trait scenario. For example, imagine that there is a `u32` loaded
out of a `hir::Node` -- we don't really want to be passing that
`u32` into the task!
@bors

bors commented Mar 11, 2017

Copy link
Copy Markdown
Collaborator

⌛ Testing commit 4d5441f with merge 4b1dfbd...

bors added a commit that referenced this pull request Mar 11, 2017
first pass at isolating dep-graph tasks
This intentionally leaves `DepGraph::in_task()`, the more common form,
alone. Eventually all uses of `DepGraph::in_task()` should be ported
to `with_task()`, but I wanted to start with a smaller subset.
I also used `AssertDepGraphSafe` on the closures that are found in
trans. This is because the types there are non-trivial and I wanted to
lay down the mechanism and come back to the more subtle cases.
The current approach taken in this PR has a downside: it is necessary
to manually "reify" fn types into fn pointers when starting a task,
like so:
dep_graph.with_task(..., task_fn as fn(_))
this is because `with_task` takes some type `T` that implements
`DepGraphTask` rather than taking a `fn()` type directly. *This* is so
that we can accept closure and also so that we can accept fns with
multiple arities. I am not sure this is the right approach.
Originally I wanted to use closures bound by an auto trait, but that
approach has some limitations:
- the trait cannot have a `read()` method; since the current method
is unused, that may not be a problem.
- more importantly, we would want the auto trait to be "undefined" for all types
*by default* -- that is, this use case doesn't really fit the typical
auto trait scenario. For example, imagine that there is a `u32` loaded
out of a `hir::Node` -- we don't really want to be passing that
`u32` into the task!
@bors

bors commented Mar 11, 2017

Copy link
Copy Markdown
Collaborator

☀️ Test successful - status-appveyor, status-travis
Approved by: mw
Pushing 4b1dfbd to master...

@bors
bors merged commit 4d5441f into rust-lang:masterMar 11, 2017
@nikomatsakis
nikomatsakis deleted the incr-comp-isolate-task branch April 14, 2017 10:12
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@nikomatsakis@rust-highfive@michaelwoerister@eddyb@bors@alexcrichton@nrc