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

Fix indeterminism in ty::TraitObject representation. #36425

Merged
merged 7 commits into from
Sep 15, 2016

Conversation

michaelwoerister
Copy link
Member

Make sure that projection bounds in ty::TraitObject are sorted in a way that is stable across compilation sessions and crate boundaries.

This PR

  • moves DefPathHashes up into librustc so it can be used there to create a stable sort key for DefIds,
  • changes PolyExistentialProjection::sort_key() to take advantage of the above,
  • and removes the unused PolyProjectionPredicate::sort_key() and ProjectionTy::sort_key() methods.

Fixes #36155

@rust-highfive
Copy link
Collaborator

r? @nrc

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

@@ -1303,7 +1303,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}

pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> {
obj.projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: extra whitespace

@eddyb
Copy link
Member

eddyb commented Sep 12, 2016

@michaelwoerister I believe the extra logic in tyencode can be removed with this change.

@alexcrichton
Copy link
Member

Thanks for the investigation and fix @michaelwoerister!

@michaelwoerister
Copy link
Member Author

I believe the extra logic in tyencode can be removed with this change.

Yes.

@michaelwoerister
Copy link
Member Author

I followed @arielb1's suggestion and made TraitDef cache the DefPath hash. No need to move DefPathHashes into librustc anymore. I also removed the sorting logic from tyencode as @eddyb suggested.

@eddyb
Copy link
Member

eddyb commented Sep 12, 2016

@michaelwoerister It might be a good idea at this point to fix TypeId trait object handling and the general TypeId hashing of DefId if you have a working solution, otherwise they risk getting left behind and causing subtle bugs.

@michaelwoerister
Copy link
Member Author

@eddyb Can't we just do exactly the same as we do when computing the symbol hash? That seems to work pretty well, so far. I'll look into it tomorrow.

@eddyb
Copy link
Member

eddyb commented Sep 12, 2016

@michaelwoerister The symbol hash is a gross hack that dumps type metadata into strings and hashes that with sha2. The new TypeId hasher is much simpler and more thorough.
I've successfully replaced the symbol hash with a generic version of the TypeId hasher in a WIP branch with no trouble, but I used a stringified version of the DefPath instead of a proper hash.
That part is not very relevant to this PR though.

The immediate result of this PR is that the sorting of trait object projections is no longer necessary, and since I believe that all TyTrait with the same principal trait have the exact same projection bounds, that whole arm can be just:

            TyTrait(ref data) => {
                self.def_id(data.principal.def_id());
                self.hash(data.builtin_bounds);
            }

@michaelwoerister
Copy link
Member Author

I don't think it's 'gross' :) It's rather DRY actually (at the expense
of some computational overhead).

Sha2 is not necessary, probably, but how is it more thorough?

On 12.09.2016 19:22, Eduard-Mihai Burtescu wrote:

@michaelwoerister https://github.com/michaelwoerister The symbol
hash is a gross hack that dumps type metadata into strings and hashes
that with sha2. The new |TypeId| hasher is much simpler and more thorough.
I've successfully replaced the symbol hash with a generic version of
the |TypeId| hasher in a WIP branch with no trouble, but I used a
stringified version of the |DefPath| instead of a proper hash.
That part is not very relevant to this PR though.

The immediate result of this PR is that the sorting of trait object
projections

// Only projection bounds are left, sort and hash them.
let mut projection_bounds: Vec<_> = data.projection_bounds
.iter()
.map(|b| (b.item_name().as_str(), b))
.collect();
projection_bounds.sort_by_key(|&(ref name, _)| name.clone());

is no longer necessary, and since I believe that all |TyTrait| with
the same principal trait have the exact same projection bounds, that
whole arm can be just:

         TyTrait(ref  data)=>  {
             self.def_id(data.principal.def_id());
             self.hash(data.builtin_bounds);
         }


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#36425 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABvcZg9Dy0bWjxLk1btyfyms9v81MW8lks5qpd7EgaJpZM4J6_gh.

@eddyb
Copy link
Member

eddyb commented Sep 12, 2016

@michaelwoerister I only meant that the new TypeId hasher is more thorough than the old one, sorry.

@michaelwoerister
Copy link
Member Author

@eddyb I'd be all for consolidating the various type-id/type-hash implementations we have in the compiler (and get rid of this shit for example :)

@@ -453,17 +453,6 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> {
// Hash region and builtin bounds.
data.region_bound.visit_with(self);
Copy link
Member

Choose a reason for hiding this comment

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

This and data.principal.visit_with(self); above it are unnecessary because automatic recursion will hit them anyway.

@michaelwoerister
Copy link
Member Author

r? @eddyb

@rust-highfive rust-highfive assigned eddyb and unassigned nrc Sep 13, 2016
@eddyb
Copy link
Member

eddyb commented Sep 13, 2016

@bors r+

@bors
Copy link
Contributor

bors commented Sep 13, 2016

📌 Commit 7ec9b81 has been approved by eddyb

@bors
Copy link
Contributor

bors commented Sep 14, 2016

⌛ Testing commit 7ec9b81 with merge fdb4f63...

@bors
Copy link
Contributor

bors commented Sep 14, 2016

💔 Test failed - auto-win-msvc-64-opt-rustbuild

@alexcrichton
Copy link
Member

@bors: retry

On Tue, Sep 13, 2016 at 7:33 PM, bors notifications@github.com wrote:

💔 Test failed - auto-win-msvc-64-opt-rustbuild
https://buildbot.rust-lang.org/builders/auto-win-msvc-64-opt-rustbuild/builds/2489


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#36425 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAD95JIcM3in_wsv7KS34pNWA7pzzicaks5qp10XgaJpZM4J6_gh
.

Manishearth added a commit to Manishearth/rust that referenced this pull request Sep 15, 2016
…bounds, r=eddyb

Fix indeterminism in ty::TraitObject representation.

Make sure that projection bounds in `ty::TraitObject` are sorted in a way that is stable across compilation sessions and crate boundaries.

This PR
+  moves `DefPathHashes` up into `librustc` so it can be used there to create a stable sort key for `DefId`s,
+ changes `PolyExistentialProjection::sort_key()` to take advantage of the above,
+ and removes the unused `PolyProjectionPredicate::sort_key()` and `ProjectionTy::sort_key()` methods.

Fixes rust-lang#36155
bors added a commit that referenced this pull request Sep 15, 2016
Rollup of 9 pull requests

- Successful merges: #36384, #36405, #36425, #36429, #36438, #36454, #36459, #36461, #36463
- Failed merges: #36444
@bors bors merged commit 7ec9b81 into rust-lang:master Sep 15, 2016
Sign up for free to 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