change equate for binders to not rely on subtyping#118247
change equate for binders to not rely on subtyping#118247bors merged 3 commits intorust-lang:masterfrom
Conversation
This comment has been minimized.
This comment has been minimized.
90695a5 to
b882e13
Compare
This comment has been minimized.
This comment has been minimized.
b882e13 to
3679fde
Compare
…r=<try> Fix for TypeId exposes equality-by-subtyping vs normal-form-syntactic-equality unsoundness Fixes rust-lang#97156 This PR revives rust-lang#97427 idea, it sits on top of rust-lang#118118 because the idea uncovered some problems with IATs. r? `@lcnr` This is ICEing yet for `tests/ui/traits/new-solver/escaping-bound-vars-in-writeback-normalization.rs` using the new trait solver. After rust-lang#118118 and this ICE is fixed, we would need a rebase and a crater run. Opening as a WIP for now.
This comment has been minimized.
This comment has been minimized.
|
☀️ Try build successful - checks-actions |
|
@craterbot check |
|
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
3679fde to
d3841fb
Compare
|
@bors try |
…r=<try> Fix for TypeId exposes equality-by-subtyping vs normal-form-syntactic-equality unsoundness Fixes rust-lang#97156 This PR revives rust-lang#97427 idea, it sits on top of rust-lang#118118 because the idea uncovered some problems with IATs. r? `@lcnr` This is ICEing yet for `tests/ui/traits/new-solver/escaping-bound-vars-in-writeback-normalization.rs` using the new trait solver. After rust-lang#118118 and this ICE is fixed, we would need a rebase and a crater run. Opening as a WIP for now.
|
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
☀️ Try build successful - checks-actions |
|
@craterbot cancel |
|
🗑️ Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
@craterbot check |
|
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
☔ The latest upstream changes (presumably #120500) made this pull request unmergeable. Please resolve the merge conflicts. |
e89a213 to
8efd236
Compare
|
🔔 This is now entering its final comment period, as per the review above. 🔔 |
|
☔ The latest upstream changes (presumably #120881) made this pull request unmergeable. Please resolve the merge conflicts. |
|
☔ The latest upstream changes (presumably #121321) made this pull request unmergeable. Please resolve the merge conflicts. |
This comment has been minimized.
This comment has been minimized.
|
☔ The latest upstream changes (presumably #119106) made this pull request unmergeable. Please resolve the merge conflicts. |
|
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs
Show resolved
Hide resolved
|
@bors r=lcnr rollup=never |
|
☀️ Test successful - checks-actions |
|
Finished benchmarking commit (878c8a2): comparison URL. Overall result: ❌ regressions - no action needed@rustbot label: -perf-regression Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)This benchmark run did not return any relevant results for this metric. CyclesThis benchmark run did not return any relevant results for this metric. Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 650.957s -> 651.156s (0.03%) |
| = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details | ||
|
|
||
| error: aborting due to 1 previous error | ||
| error[E0277]: the trait bound `for<'a, 'b> fn(&'a (), &'b ()): WithAssoc<T>` is not satisfied |
There was a problem hiding this comment.
@spastorino sorry to necro this PR, but this test is (even still on master today) labeled as known-bug and those should have been removed.(at least for 97156, not sure what's going on with the other)...
summary by @spastorino and @lcnr
Context
The following code:
has UB from hitting the
unreachable_unchecked. This happens becauseTypeId::of::<One>()is not the same asTypeId::of::<Two>()despite them being considered the same types by the type checker.Currently the type checker considers binders to be equal if subtyping succeeds in both directions:
for<'a> T<'a> eq for<'b> U<'b>holds iffor<'a> exists<'b> T<'b> <: T'<a> AND for<'b> exists<'a> T<'a> <: T<'b>holds. This results infor<'a> fn(&'a (), &'a ())andfor<'a, 'b> fn(&'a (), &'b ())being equal in the type system.TypeIdis computed by looking at the structure of a type. Even though these types are semantically equal, they have a different structure resulting in them having differentTypeId. This can break invariants of unsafe code at runtime and is unsound when happening at compile time, e.g. when using const generics.So as seen in
main, we can assign a value of typeFoo::<One>to a binding of typeFoo<Two>given those are considered the same type but then when we callderef, it callsdowncast_refthat relies onTypeIdand we would hit theNonearm as these have differentTypeIds.As stated in #97156 (comment), this causes the API of existing crates to be unsound.
What should we do about this
The same type resulting in different
TypeIds is a significant footgun, breaking a very reasonable assumptions by authors of unsafe code. It will also be unsound by itself once they are usable in generic contexts with const generics.There are two options going forward here:
for<'a> fn(&'a (), &'a ())andfor<'a, 'b> fn(&'a (), &'b ())to be equal, but normalize them to a common representation so that theirTypeIdare also the same.for<'a> fn(&'a (), &'a ())andfor<'a, 'b> fn(&'a (), &'b ())still have differentTypeIds but are now also considered to not be semantically equal.Advantages of the first approach:
General thoughts:
Advantages of the second approach:
This PR goes with the second approach. A crater run did not result in any regressions. I am personally very hesitant about trying the first approach due to the above reasons. It feels like there are more unknowns when going that route.
Changing the way we equate binders
Relating bound variables from different depths already results in a universe error in equate. We therefore only need to make sure that there is 1-to-1 correspondence between bound variables when relating binders. This results in concrete types being structurally equal after anonymizing their bound variables.
We implement this by instantiating one of the binder with placeholders and the other with inference variables and then equating the instantiated types. We do so in both directions.
More formally, we change the typing rules as follows:
to
Fixes #97156
r? @lcnr