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

Suggest deref when coercing ty::Ref to ty::RawPtr #71540

Merged
merged 3 commits into from
Apr 30, 2020
Merged

Conversation

ldm0
Copy link
Contributor

@ldm0 ldm0 commented Apr 25, 2020

Fixes #32122

Currently we do autoderef when casting ty::Ref ->ty::Ref, but we don't autoderef when casting ty::Ref -> ty::RawPtr. This PR make the compiler suggests deref when coercing ty::Ref to ty::RawPtr

@rust-highfive
Copy link
Collaborator

r? @davidtwco

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 25, 2020
@ldm0 ldm0 force-pushed the ref2ptr branch 2 times, most recently from 43e2c06 to 1e87240 Compare April 25, 2020 01:06
@ldm0
Copy link
Contributor Author

ldm0 commented Apr 25, 2020

cc @oli-obk
Since #32122 (comment)
What do you think?

@davidtwco
Copy link
Member

r? @oli-obk

@rust-highfive rust-highfive assigned oli-obk and unassigned davidtwco Apr 25, 2020
@ldm0 ldm0 force-pushed the ref2ptr branch 2 times, most recently from 3da6ef8 to da61adb Compare April 26, 2020 01:08
@ldm0 ldm0 changed the title Autoderef when casting ty::Ref to ty::RawPtr Autoderef when coercing ty::Ref to ty::RawPtr Apr 26, 2020
@oli-obk
Copy link
Contributor

oli-obk commented Apr 26, 2020

I don't think we should permit it (at least not without an RFC). But you can use your logic to determine whether we could do it and then use a different error variant to signal that a suggestion should be generated to use a user-written deref.

@ldm0
Copy link
Contributor Author

ldm0 commented Apr 26, 2020

I don't think we should permit it (at least not without an RFC). But you can use your logic to determine whether we could do it and then use a different error variant to signal that a suggestion should be generated to use a user-written deref.

Thanks for reviewing! I'll work on it.

Edit: Done!

@ldm0 ldm0 marked this pull request as draft April 26, 2020 15:00
@ldm0 ldm0 changed the title Autoderef when coercing ty::Ref to ty::RawPtr Suggest deref when coercing ty::Ref to ty::RawPtr Apr 29, 2020
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-8 of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
========================== Starting Command Output ===========================
[command]/bin/bash --noprofile --norc /home/vsts/work/_temp/da083453-20dc-4478-90df-111018c3166c.sh

##[section]Finishing: Disable git automatic line ending conversion
##[section]Starting: Checkout rust-lang/rust@refs/pull/71540/merge to s
Task         : Get sources
Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
Version      : 1.0.0
Author       : Microsoft
---
##[command]git remote add origin https://github.com/rust-lang/rust
##[command]git config gc.auto 0
##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
##[command]git config --get-all http.proxy
##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/71540/merge:refs/remotes/pull/71540/merge
---
 ---> cb2676f08729
Step 5/8 : ENV RUST_CONFIGURE_ARGS       --build=x86_64-unknown-linux-gnu       --llvm-root=/usr/lib/llvm-8       --enable-llvm-link-shared       --set rust.thin-lto-import-instr-limit=10
 ---> Using cache
 ---> df25ce111862
Step 6/8 : ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy &&            python2.7 ../x.py test src/test/mir-opt --pass=build                                   --target=armv5te-unknown-linux-gnueabi &&            python2.7 ../x.py test src/tools/tidy
 ---> 599b9ac96b27
Step 7/8 : ENV NO_DEBUG_ASSERTIONS=1
 ---> Using cache
 ---> 091087e35a36
---
Looks like docker image is the same as before, not uploading
[CI_JOB_NAME=x86_64-gnu-llvm-8]
[CI_JOB_NAME=x86_64-gnu-llvm-8]
== clock drift check ==
  local time: Wed Apr 29 04:06:10 UTC 2020
  network time: Wed, 29 Apr 2020 04:06:10 GMT
Starting sccache server...
configure: processing command line
configure: 
configure: rust.dist-src        := False
---
   Compiling unicode-width v0.1.6
   Compiling getopts v0.2.21
   Compiling test v0.0.0 (/checkout/src/libtest)
    Finished release [optimized] target(s) in 1m 02s
{"reason":"build-finished","success":true}
Building stage0 compiler artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
   Compiling cfg-if v0.1.10
   Compiling libc v0.2.69
   Compiling semver-parser v0.7.0
---
   Compiling rustc_feature v0.0.0 (/checkout/src/librustc_feature)
   Compiling fmt_macros v0.0.0 (/checkout/src/libfmt_macros)
   Compiling rustc_ast_pretty v0.0.0 (/checkout/src/librustc_ast_pretty)
   Compiling rustc_hir v0.0.0 (/checkout/src/librustc_hir)
   Compiling rustc_query_system v0.0.0 (/checkout/src/librustc_query_system)
   Compiling rustc_hir_pretty v0.0.0 (/checkout/src/librustc_hir_pretty)
   Compiling rustc_attr v0.0.0 (/checkout/src/librustc_attr)
   Compiling rustc_parse v0.0.0 (/checkout/src/librustc_parse)
   Compiling rustc_ast_lowering v0.0.0 (/checkout/src/librustc_ast_lowering)
---
   Compiling rustc_mir v0.0.0 (/checkout/src/librustc_mir)
   Compiling rustc_plugin_impl v0.0.0 (/checkout/src/librustc_plugin_impl)
   Compiling rustc_privacy v0.0.0 (/checkout/src/librustc_privacy)
   Compiling rustc-main v0.0.0 (/checkout/src/rustc)
{"reason":"build-finished","success":true}
Copying stage0 rustc from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Assembling stage1 compiler (x86_64-unknown-linux-gnu)
Building stage1 std artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
   Compiling cc v1.0.50
---
   Compiling unicode-width v0.1.6
   Compiling getopts v0.2.21
   Compiling test v0.0.0 (/checkout/src/libtest)
    Finished release [optimized] target(s) in 1m 13s
{"reason":"build-finished","success":true}
Building stage1 compiler artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
   Compiling cfg-if v0.1.10
   Compiling libc v0.2.69
   Compiling semver-parser v0.7.0
---
   Compiling rustc_feature v0.0.0 (/checkout/src/librustc_feature)
   Compiling fmt_macros v0.0.0 (/checkout/src/libfmt_macros)
   Compiling rustc_ast_pretty v0.0.0 (/checkout/src/librustc_ast_pretty)
   Compiling rustc_hir v0.0.0 (/checkout/src/librustc_hir)
   Compiling rustc_query_system v0.0.0 (/checkout/src/librustc_query_system)
   Compiling rustc_hir_pretty v0.0.0 (/checkout/src/librustc_hir_pretty)
   Compiling rustc_attr v0.0.0 (/checkout/src/librustc_attr)
   Compiling rustc_parse v0.0.0 (/checkout/src/librustc_parse)
   Compiling rustc_ast_lowering v0.0.0 (/checkout/src/librustc_ast_lowering)
---
   Compiling rustc_plugin_impl v0.0.0 (/checkout/src/librustc_plugin_impl)
   Compiling rustc_privacy v0.0.0 (/checkout/src/librustc_privacy)
   Compiling rustc-main v0.0.0 (/checkout/src/rustc)
    Finished release [optimized] target(s) in 23m 14s
{"reason":"build-finished","success":true}
Assembling stage2 compiler (x86_64-unknown-linux-gnu)
Uplifting stage1 std (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage2 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
Building test helpers
---
   Compiling serde_derive v1.0.81
   Compiling serde_json v1.0.40
   Compiling rustfix v0.5.0
   Compiling compiletest v0.0.0 (/checkout/src/tools/compiletest)
{"reason":"build-finished","success":true}
Check compiletest suite=ui mode=ui (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)

running 9941 tests
.................................................................................................... 100/9941
---
.................................................................................................... 1800/9941
.................................................................................................... 1900/9941
..............i..................................................................................... 2000/9941
.................................................................................................... 2100/9941
....iiiii........................................................................................... 2200/9941
.................................................................................................... 2400/9941
.................................................................................................... 2500/9941
.................................................................................................... 2600/9941
.................................................................................................... 2700/9941
---
....i............................................................................................... 5100/9941
.................................................................................................... 5200/9941
..................................i................................................................. 5300/9941
.........................i.......................................................................... 5400/9941
..........................ii.ii........i...i........................................................ 5500/9941
.........................................................................i.......................... 5700/9941
.................................................................................................... 5800/9941
......ii.....................................i...................................................... 5900/9941
.................................................................................................... 6000/9941
.................................................................................................... 6000/9941
.................................................................................................... 6100/9941
.......................................ii...i..ii...........i....................................... 6200/9941
.................................................................................................... 6400/9941
.................................................................................................... 6500/9941
.................................................................................................... 6500/9941
.....................................................................i..ii.......................... 6600/9941
.................................................................................................... 6800/9941
......................................................................i............................. 6900/9941
.................................................................................................... 7000/9941
.................................................................................................... 7100/9941
---
.................................................................................................... 7900/9941
.................................................................................................... 8000/9941
................................................................................i................... 8100/9941
.................................................................................................... 8200/9941
..............................iiiiiiiiiii.i......................................................... 8300/9941
.................................................................................................... 8500/9941
.................................................................................................... 8600/9941
.................................................................................................... 8700/9941
.................................................................................................... 8800/9941
---
---- [ui] ui/issues/issue-32122-1.rs stdout ----

error: fixed code is still producing diagnostics
status: exit code: 0
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/issues/issue-32122-1.fixed" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-32122-1/a" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-32122-1/auxiliary"
------------------------------------------

------------------------------------------
stderr:
stderr:
------------------------------------------
warning: unused variable: `b`
  --> /checkout/src/test/ui/issues/issue-32122-1.fixed:16:9
   |
LL |     let b: *const u8 = &*a; //~ ERROR mismatched types
   |         ^ help: if this is intentional, prefix it with an underscore: `_b`
   = note: `#[warn(unused_variables)]` on by default

warning: 1 warning emitted

---
---- [ui] ui/issues/issue-32122-2.rs stdout ----

error: failed to compile fixed code
status: exit code: 1
command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/issues/issue-32122-2.fixed" "-Zthreads=1" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "--emit" "metadata" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-32122-2/a" "-Crpath" "-O" "-Cdebuginfo=0" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/issues/issue-32122-2/auxiliary"
------------------------------------------

------------------------------------------
stderr:
stderr:
------------------------------------------
error[E0308]: mismatched types
  --> /checkout/src/test/ui/issues/issue-32122-2.fixed:27:24
   |
LL |     let b: *const u8 = &*a; //~ ERROR mismatched types
   |            |           |
   |            |           expected `u8`, found struct `Foo`
   |            |           expected `u8`, found struct `Foo`
   |            |           help: consider using `&*` rather than `&`: `&**a`
   |
   |
   = note: expected raw pointer `*const u8`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
---
thread 'main' panicked at 'Some tests failed', src/tools/compiletest/src/main.rs:348:22
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/ui" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-8/bin/FileCheck" "--nodejs" "/usr/bin/node" "--host-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--target-rustcflags" "-Crpath -O -Cdebuginfo=0 -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "8.0.0" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"


failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test --exclude src/tools/tidy
Build completed unsuccessfully in 1:01:44
Build completed unsuccessfully in 1:01:44
== clock drift check ==
  local time: Wed Apr 29 05:09:32 UTC 2020
  network time: Wed, 29 Apr 2020 05:09:32 GMT


##[error]Bash exited with code '1'.
##[section]Finishing: Run build
##[section]Starting: Checkout rust-lang/rust@refs/pull/71540/merge to s
Task         : Get sources
Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
Version      : 1.0.0
Author       : Microsoft
Author       : Microsoft
Help         : [More Information](https://go.microsoft.com/fwlink/?LinkId=798199)
==============================================================================
Cleaning any cached credential from repository: rust-lang/rust (GitHub)
##[section]Finishing: Checkout rust-lang/rust@refs/pull/71540/merge to s
Cleaning up task key
Start cleaning up orphan processes.
Terminate orphan process: pid (4244) (python)
##[section]Finishing: Finalize Job

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @rust-lang/infra. (Feature Requests)

@ldm0 ldm0 marked this pull request as ready for review April 29, 2020 05:59
@ldm0
Copy link
Contributor Author

ldm0 commented Apr 29, 2020

Now it can even suggest &*******var! XD

Comment on lines 555 to 565
Some(steps).filter(|_| {
coerce
.unify(
coerce.tcx.mk_ptr(ty::TypeAndMut {
mutbl: hir::Mutability::Not,
ty: referent_ty,
}),
expected,
)
.is_ok()
})
Copy link
Contributor

Choose a reason for hiding this comment

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

This took me a moment to untangle. The filter is always executed, so I think it would be better formulated as

Suggested change
Some(steps).filter(|_| {
coerce
.unify(
coerce.tcx.mk_ptr(ty::TypeAndMut {
mutbl: hir::Mutability::Not,
ty: referent_ty,
}),
expected,
)
.is_ok()
})
coerce
.unify(
coerce.tcx.mk_ptr(ty::TypeAndMut {
mutbl: hir::Mutability::Not,
ty: referent_ty,
}),
expected,
)
.ok().map(|_| steps)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice! I didn't expect to write like that.

(
_,
&ty::RawPtr(TypeAndMut { ty: _, mutbl: hir::Mutability::Not }),
&ty::Ref(_, _, hir::Mutability::Not),
Copy link
Contributor

Choose a reason for hiding this comment

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

While I believe we could also do something for mutable references (both for staying in the same mutability and moving to const), this requires some care to get right without false positives, so maybe just leave a FIXME or open an issue?

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, I missed the mutable references situation. I'll open another issue.

@oli-obk
Copy link
Contributor

oli-obk commented Apr 29, 2020

This is great! just an impl nit then this lgtm

@oli-obk
Copy link
Contributor

oli-obk commented Apr 29, 2020

@bors r+

@bors
Copy link
Contributor

bors commented Apr 29, 2020

📌 Commit a985879 has been approved by oli-obk

@bors bors 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 Apr 29, 2020
RalfJung added a commit to RalfJung/rust that referenced this pull request Apr 30, 2020
Suggest deref when coercing `ty::Ref` to `ty::RawPtr`

Fixes rust-lang#32122

Currently we do autoderef when casting `ty::Ref` ->`ty::Ref`, but we don't autoderef when casting `ty::Ref` -> `ty::RawPtr`. This PR make the compiler suggests deref when coercing `ty::Ref` to `ty::RawPtr`
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 30, 2020
Rollup of 5 pull requests

Successful merges:

 - rust-lang#71205 (rustc: fix check_attr() for methods, closures and foreign functions)
 - rust-lang#71540 (Suggest deref when coercing `ty::Ref` to `ty::RawPtr`)
 - rust-lang#71655 (Miri: better document and fix dynamic const pattern soundness checks)
 - rust-lang#71672 (document missing stable counterparts of intrinsics)
 - rust-lang#71692 (Add clarification on std::cfg macro docs v. #[cfg] attribute)

Failed merges:

r? @ghost
@bors bors merged commit 58d955e into rust-lang:master Apr 30, 2020
@carlpaten
Copy link

Thank you @ldm0 for getting around to this!!

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request May 2, 2020
Suggest deref when coercing `ty::Ref` to `ty::RawPtr` with arbitrary mutability

Fixes rust-lang#71676
1. Implement dereference suggestion when coercing `ty::Ref` to `ty::RawPtr` with arbitrary mutability.
2. Extract the dereference steps into `deref_steps()`, which removes all the `use` and `pub` noise introduced by last PR rust-lang#71540, and makes the code more readable.
3. Use the `remove_prefix()` closure which makes the prefix removal more readable.
4. Introduce `Applicability` as a return value of `check_ref` to suggest `Applicability::Unspecified` suggestion.

**Special**: I found it is not possible to genereate `Applicability::MachineApplicable` suggestion for situation like this:
```rust
use std::ops::Deref;
use std::ops::DerefMut;
struct Bar(u8);
struct Foo(Bar);
struct Emm(Foo);
impl Deref for Bar{
    type Target = u8;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl Deref for Foo {
    type Target = Bar;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl Deref for Emm {
    type Target = Foo;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl DerefMut for Bar{
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl DerefMut for Foo {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl DerefMut for Emm {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
fn main() {
    let a = Emm(Foo(Bar(0)));
    let _: *mut u8 = &a; //~ ERROR mismatched types
}
```
We may suggest `&mut ***a` here, but the `a` is not declared as mutable variable. And also when processing HIR, it's not possible to check if `a` is declared as a mutable variable (currently we do borrow checking with MIR). So we cannot ensure that suggestion when coercing immutable reference to mutable pointer is always machine applicable. Therefore I added a `Applicability` return value in `check_ref()`. And move the `immutable reference -> mutable pointer` situation into a sperate test file without `run-rustfix`. (It seems that `run-rustfix` will also adopt `Applicability::Unspecified` suggestion, which is strange)
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request May 3, 2020
Suggest deref when coercing `ty::Ref` to `ty::RawPtr` with arbitrary mutability

Fixes rust-lang#71676
1. Implement dereference suggestion when coercing `ty::Ref` to `ty::RawPtr` with arbitrary mutability.
2. Extract the dereference steps into `deref_steps()`, which removes all the `use` and `pub` noise introduced by last PR rust-lang#71540, and makes the code more readable.
3. Use the `remove_prefix()` closure which makes the prefix removal more readable.
4. Introduce `Applicability` as a return value of `check_ref` to suggest `Applicability::Unspecified` suggestion.

**Special**: I found it is not possible to genereate `Applicability::MachineApplicable` suggestion for situation like this:
```rust
use std::ops::Deref;
use std::ops::DerefMut;
struct Bar(u8);
struct Foo(Bar);
struct Emm(Foo);
impl Deref for Bar{
    type Target = u8;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl Deref for Foo {
    type Target = Bar;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl Deref for Emm {
    type Target = Foo;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl DerefMut for Bar{
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl DerefMut for Foo {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl DerefMut for Emm {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
fn main() {
    let a = Emm(Foo(Bar(0)));
    let _: *mut u8 = &a; //~ ERROR mismatched types
}
```
We may suggest `&mut ***a` here, but the `a` is not declared as mutable variable. And also when processing HIR, it's not possible to check if `a` is declared as a mutable variable (currently we do borrow checking with MIR). So we cannot ensure that suggestion when coercing immutable reference to mutable pointer is always machine applicable. Therefore I added a `Applicability` return value in `check_ref()`. And move the `immutable reference -> mutable pointer` situation into a sperate test file without `run-rustfix`. (It seems that `run-rustfix` will also adopt `Applicability::Unspecified` suggestion, which is strange)
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request May 3, 2020
Suggest deref when coercing `ty::Ref` to `ty::RawPtr` with arbitrary mutability

Fixes rust-lang#71676
1. Implement dereference suggestion when coercing `ty::Ref` to `ty::RawPtr` with arbitrary mutability.
2. Extract the dereference steps into `deref_steps()`, which removes all the `use` and `pub` noise introduced by last PR rust-lang#71540, and makes the code more readable.
3. Use the `remove_prefix()` closure which makes the prefix removal more readable.
4. Introduce `Applicability` as a return value of `check_ref` to suggest `Applicability::Unspecified` suggestion.

**Special**: I found it is not possible to genereate `Applicability::MachineApplicable` suggestion for situation like this:
```rust
use std::ops::Deref;
use std::ops::DerefMut;
struct Bar(u8);
struct Foo(Bar);
struct Emm(Foo);
impl Deref for Bar{
    type Target = u8;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl Deref for Foo {
    type Target = Bar;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl Deref for Emm {
    type Target = Foo;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl DerefMut for Bar{
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl DerefMut for Foo {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl DerefMut for Emm {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
fn main() {
    let a = Emm(Foo(Bar(0)));
    let _: *mut u8 = &a; //~ ERROR mismatched types
}
```
We may suggest `&mut ***a` here, but the `a` is not declared as mutable variable. And also when processing HIR, it's not possible to check if `a` is declared as a mutable variable (currently we do borrow checking with MIR). So we cannot ensure that suggestion when coercing immutable reference to mutable pointer is always machine applicable. Therefore I added a `Applicability` return value in `check_ref()`. And move the `immutable reference -> mutable pointer` situation into a sperate test file without `run-rustfix`. (It seems that `run-rustfix` will also adopt `Applicability::Unspecified` suggestion, which is strange)
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request May 3, 2020
Suggest deref when coercing `ty::Ref` to `ty::RawPtr` with arbitrary mutability

Fixes rust-lang#71676
1. Implement dereference suggestion when coercing `ty::Ref` to `ty::RawPtr` with arbitrary mutability.
2. Extract the dereference steps into `deref_steps()`, which removes all the `use` and `pub` noise introduced by last PR rust-lang#71540, and makes the code more readable.
3. Use the `remove_prefix()` closure which makes the prefix removal more readable.
4. Introduce `Applicability` as a return value of `check_ref` to suggest `Applicability::Unspecified` suggestion.

**Special**: I found it is not possible to genereate `Applicability::MachineApplicable` suggestion for situation like this:
```rust
use std::ops::Deref;
use std::ops::DerefMut;
struct Bar(u8);
struct Foo(Bar);
struct Emm(Foo);
impl Deref for Bar{
    type Target = u8;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl Deref for Foo {
    type Target = Bar;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl Deref for Emm {
    type Target = Foo;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl DerefMut for Bar{
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl DerefMut for Foo {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl DerefMut for Emm {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
fn main() {
    let a = Emm(Foo(Bar(0)));
    let _: *mut u8 = &a; //~ ERROR mismatched types
}
```
We may suggest `&mut ***a` here, but the `a` is not declared as mutable variable. And also when processing HIR, it's not possible to check if `a` is declared as a mutable variable (currently we do borrow checking with MIR). So we cannot ensure that suggestion when coercing immutable reference to mutable pointer is always machine applicable. Therefore I added a `Applicability` return value in `check_ref()`. And move the `immutable reference -> mutable pointer` situation into a sperate test file without `run-rustfix`. (It seems that `run-rustfix` will also adopt `Applicability::Unspecified` suggestion, which is strange)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

Deref coercions and &-to-* coercions don't compose
7 participants