about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-01-25 04:42:56 +0000
committerbors <bors@rust-lang.org>2020-01-25 04:42:56 +0000
commit8bf17584e01d85c631bcb19b7cd0f95e84c9a9b1 (patch)
tree9c7deec833818c906f8663b4bbb24fdc7ad74254
parent8647aa1a2ce279f8ec7cc5252d10b8cb9ea504eb (diff)
parentcd7b5edc2cac3fa0db6b464a6e94edd8f334274d (diff)
downloadrust-8bf17584e01d85c631bcb19b7cd0f95e84c9a9b1.tar.gz
rust-8bf17584e01d85c631bcb19b7cd0f95e84c9a9b1.zip
Auto merge of #68269 - csmoe:temp, r=estebank
Suggest to shorten temporary borrow from raw pointer

Closes https://github.com/rust-lang/rust/issues/65436
r? @estebank
cc @tmandry
-rw-r--r--src/librustc/traits/error_reporting/suggestions.rs37
-rw-r--r--src/test/ui/async-await/issue-64130-4-async-move.stderr2
-rw-r--r--src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs16
-rw-r--r--src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr26
4 files changed, 75 insertions, 6 deletions
diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs
index 4559007ea42..aa5e9f65d2b 100644
--- a/src/librustc/traits/error_reporting/suggestions.rs
+++ b/src/librustc/traits/error_reporting/suggestions.rs
@@ -12,6 +12,7 @@ use rustc_errors::{
     error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
 };
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::Node;
@@ -1366,14 +1367,40 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         if let Some(expr_id) = expr {
             let expr = hir.expect_expr(expr_id);
-            let is_ref = tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
+            debug!("target_ty evaluated from {:?}", expr);
+
             let parent = hir.get_parent_node(expr_id);
             if let Some(hir::Node::Expr(e)) = hir.find(parent) {
-                let method_span = hir.span(parent);
-                if tables.is_method_call(e) && is_ref {
+                let parent_span = hir.span(parent);
+                let parent_did = parent.owner_def_id();
+                // ```rust
+                // impl T {
+                //     fn foo(&self) -> i32 {}
+                // }
+                // T.foo();
+                // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
+                // ```
+                //
+                let is_region_borrow =
+                    tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
+
+                // ```rust
+                // struct Foo(*const u8);
+                // bar(Foo(std::ptr::null())).await;
+                //     ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
+                // ```
+                debug!("parent_def_kind: {:?}", self.tcx.def_kind(parent_did));
+                let is_raw_borrow_inside_fn_like_call = match self.tcx.def_kind(parent_did) {
+                    Some(DefKind::Fn) | Some(DefKind::Ctor(..)) => target_ty.is_unsafe_ptr(),
+                    _ => false,
+                };
+
+                if (tables.is_method_call(e) && is_region_borrow)
+                    || is_raw_borrow_inside_fn_like_call
+                {
                     err.span_help(
-                        method_span,
-                        "consider moving this method call into a `let` \
+                        parent_span,
+                        "consider moving this into a `let` \
                         binding to create a shorter lived borrow",
                     );
                 }
diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr
index f59dbc26384..1e52d74f155 100644
--- a/src/test/ui/async-await/issue-64130-4-async-move.stderr
+++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr
@@ -25,7 +25,7 @@ LL |                 let _x = get().await;
 ...
 LL |     }
    |     - `client` is later dropped here
-help: consider moving this method call into a `let` binding to create a shorter lived borrow
+help: consider moving this into a `let` binding to create a shorter lived borrow
   --> $DIR/issue-64130-4-async-move.rs:19:15
    |
 LL |         match client.status() {
diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs
new file mode 100644
index 00000000000..3a814b47517
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs
@@ -0,0 +1,16 @@
+// edition:2018
+
+struct Foo(*const u8);
+
+unsafe impl Send for Foo {}
+
+async fn bar(_: Foo) {}
+
+fn assert_send<T: Send>(_: T) {}
+
+fn main() {
+    assert_send(async {
+    //~^ ERROR future cannot be sent between threads safely
+        bar(Foo(std::ptr::null())).await;
+    })
+}
diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr
new file mode 100644
index 00000000000..7638ba1fe7d
--- /dev/null
+++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr
@@ -0,0 +1,26 @@
+error: future cannot be sent between threads safely
+  --> $DIR/issue-65436-raw-ptr-not-send.rs:12:5
+   |
+LL | fn assert_send<T: Send>(_: T) {}
+   |    -----------    ---- required by this bound in `assert_send`
+...
+LL |     assert_send(async {
+   |     ^^^^^^^^^^^ future returned by `main` is not `Send`
+   |
+   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `*const u8`
+note: future is not `Send` as this value is used across an await
+  --> $DIR/issue-65436-raw-ptr-not-send.rs:14:9
+   |
+LL |         bar(Foo(std::ptr::null())).await;
+   |         ^^^^^^^^----------------^^^^^^^^- `std::ptr::null()` is later dropped here
+   |         |       |
+   |         |       has type `*const u8`
+   |         await occurs here, with `std::ptr::null()` maybe used later
+help: consider moving this into a `let` binding to create a shorter lived borrow
+  --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13
+   |
+LL |         bar(Foo(std::ptr::null())).await;
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+