Make pin!() more foolproof.#158061
Conversation
There was a problem hiding this comment.
sgtm
i consider this to properly fix #153438. I don't worry about us adding random coercions inside of user defined types causing problems here, as that should also cause problems for abstractions outside of stdlib
3f561c7 to
609617c
Compare
|
This should hopefully be ready to merge now. @lcnr |
There was a problem hiding this comment.
I've messed around with this some more and discovered that you can do this (no need for the custom error reporting code)
pub struct PinMacroHelper<T> {
pub value: T,
}
impl<T> PinMacroHelper<T> {
pub const unsafe fn pin_new_unchecked<'a>(&'a mut self) -> Pin<&'a mut T> {
// SAFETY: Ensured by the caller.
unsafe { Pin::new_unchecked(&mut self.value) }
}
}and then you get the error:
error[E0308]: mismatched types
--> $DIR/dont-deref-coerce-pinned-value.rs:9:14
|
LL | fn wrong_pin<T>(data: &mut T, callback: impl FnOnce(Pin<&mut T>)) {
| - expected this type parameter
LL | callback(pin!(data));
| ^^^^^^^^^^ expected `Pin<&mut T>`, found `Pin<&mut &mut T>`
|
= note: expected struct `Pin<&mut _>`
found struct `Pin<&mut &mut _>`
error: aborting due to 1 previous errorAnyway while I was messing around I noticed that the test passed while the error message changed. Can you add an explicit HELP/NOTE annotation so it doesn't regress?
|
@mejrs I avoided using the method call syntax because I didn't want to deal with autoref/autoderef. Do you think it's worth slightly complicating the soundness reasoning for the sake of diagnostics? |
It would be nice to not have to put these hacks in the error reporting code... 🤔 |
Previously, the soundness argument for the `pin!()` macro relied on very complicated conditions on what coercions are possible. As a result, it was not obvious whether the macro was sound or not, and the macro was potentially fragile to changes in how coercions work. Therefore, we change the `pin!()` macro so that it relies on less subtle properties of coercions. In particular: * The soundness argument now only relies on enumerating the possible types that a coercion could produce, as opposed to relying on details about how coercion expectations are propagated. * The soundness argument now only requires reasoning about possible coercions between a single pair of types defined in the standard library, as opposed to reasoning about two pairs of types, with some involved types being defined by the user. Fixes <rust-lang#153438>
is your concern that resolving method calls might have unintended behavior (e.g. preferring a trait method in scope or sth) I do prefer not using method call syntax here I think. The diagnostics hack is somewhat ugly, but fine imo |
c1f7194 to
f0c86f6
Compare
This comment was marked as resolved.
This comment was marked as resolved.
|
@bors r+ rollup |
…uwer Rollup of 18 pull requests Successful merges: - #159600 (`rust-analyzer` subtree update) - #158046 (proc_macro: preserve file module spans for inner attrs) - #159000 (Small cleanups to the incr comp session code) - #159189 (Account for type alias projections in E0308 "expected/found" shortening logic) - #159449 (Enable single Location to issue multiple borrows) - #159544 (Suggest valid command-line crate names) - #159587 (Improve `AttrItem::span`) - #159594 (feat(rustc_hir_typeck): suggest `impl Fn` return for capturing closures) - #159597 (std: use `arc4random_buf` from libc) - #159599 (Resolver: Record at least 1 ambiguous trait if main decl is not a trait.) - #158061 (Make `pin!()` more foolproof.) - #159460 (Do not mark unnormalized const aliases as rigid when normalizing param env) - #159529 (Add regression test for nested replacement ranges in `collect_tokens`) - #159571 (Remove unused bundled library lookup for the local crate) - #159585 (Minor `TokenStream` improvements) - #159586 (Separate `InterpCx` usage by `ConstAnalysis` phases) - #159602 (Remove `ItemLike`) - #159603 (Clarify `push_stream`/`push_tree`) Failed merges: - #159590 (Remove some dead code)
Rollup merge of #158061 - theemathas:pin-foolproof, r=lcnr Make `pin!()` more foolproof. Previously, the soundness argument for the `pin!()` macro relied on very complicated conditions on what coercions are possible. As a result, it was not obvious whether the macro was sound or not, and the macro was potentially fragile to changes in how coercions work. Therefore, we change the `pin!()` macro so that it relies on less subtle properties of coercions. In particular: * The soundness argument now only relies on enumerating the possible types that a coercion could produce, as opposed to relying on details about how coercion expectations are propagated. * The soundness argument now only requires reasoning about possible coercions between a single pair of types defined in the standard library, as opposed to reasoning about two pairs of types, with some involved types being defined by the user. Fixes <#153438>. This PR supersedes the proposed FCP on that issue. cc @dianne r? types
View all comments
Previously, the soundness argument for the
pin!()macro relied on very complicated conditions on what coercions are possible. As a result, it was not obvious whether the macro was sound or not, and the macro was potentially fragile to changes in how coercions work.Therefore, we change the
pin!()macro so that it relies on less subtle properties of coercions. In particular:Fixes #153438. This PR supersedes the proposed FCP on that issue.
cc @dianne
r? types