]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/future_not_send.rs
Auto merge of #9148 - arieluy:then_some_unwrap_or, r=Jarcho
[rust.git] / clippy_lints / src / future_not_send.rs
index 515b8887453b92a0d49cebab5f245a4c3d8a4a4b..5c46d6c7df7056856ed7afcd3d37f09b70cd2808 100644 (file)
@@ -5,19 +5,21 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::{Opaque, PredicateKind::Trait};
+use rustc_middle::ty::{EarlyBinder, Opaque, PredicateKind::Trait};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{sym, Span};
 use rustc_trait_selection::traits::error_reporting::suggestions::InferCtxtExt;
 use rustc_trait_selection::traits::{self, FulfillmentError, TraitEngine};
 
 declare_clippy_lint! {
-    /// **What it does:** This lint requires Future implementations returned from
+    /// ### What it does
+    /// This lint requires Future implementations returned from
     /// functions and methods to implement the `Send` marker trait. It is mostly
     /// used by library authors (public and internal) that target an audience where
     /// multithreaded executors are likely to be used for running these Futures.
     ///
-    /// **Why is this bad?** A Future implementation captures some state that it
+    /// ### Why is this bad?
+    /// A Future implementation captures some state that it
     /// needs to eventually produce its final value. When targeting a multithreaded
     /// executor (which is the norm on non-embedded devices) this means that this
     /// state may need to be transported to other threads, in other words the
     /// modifying the library where the offending Future implementation is
     /// produced.
     ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    ///
+    /// ### Example
     /// ```rust
     /// async fn not_send(bytes: std::rc::Rc<[u8]>) {}
     /// ```
@@ -42,6 +41,7 @@
     /// ```rust
     /// async fn is_send(bytes: std::sync::Arc<[u8]>) {}
     /// ```
+    #[clippy::version = "1.44.0"]
     pub FUTURE_NOT_SEND,
     nursery,
     "public Futures must be Send"
@@ -67,24 +67,24 @@ fn check_fn(
             let preds = cx.tcx.explicit_item_bounds(id);
             let mut is_future = false;
             for &(p, _span) in preds {
-                let p = p.subst(cx.tcx, subst);
-                if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
-                    if Some(trait_ref.value.def_id()) == cx.tcx.lang_items().future_trait() {
+                let p = EarlyBinder(p).subst(cx.tcx, subst);
+                if let Some(trait_pred) = p.to_opt_poly_trait_pred() {
+                    if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() {
                         is_future = true;
                         break;
                     }
                 }
             }
             if is_future {
-                let send_trait = cx.tcx.get_diagnostic_item(sym::send_trait).unwrap();
+                let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
                 let span = decl.output.span();
-                let send_result = cx.tcx.infer_ctxt().enter(|infcx| {
+                let send_errors = cx.tcx.infer_ctxt().enter(|infcx| {
                     let cause = traits::ObligationCause::misc(span, hir_id);
                     let mut fulfillment_cx = traits::FulfillmentContext::new();
                     fulfillment_cx.register_bound(&infcx, cx.param_env, ret_ty, send_trait, cause);
                     fulfillment_cx.select_all_or_error(&infcx)
                 });
-                if let Err(send_errors) = send_result {
+                if !send_errors.is_empty() {
                     span_lint_and_then(
                         cx,
                         FUTURE_NOT_SEND,
@@ -94,7 +94,7 @@ fn check_fn(
                             cx.tcx.infer_ctxt().enter(|infcx| {
                                 for FulfillmentError { obligation, .. } in send_errors {
                                     infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
-                                    if let Trait(trait_pred, _) = obligation.predicate.kind().skip_binder() {
+                                    if let Trait(trait_pred) = obligation.predicate.kind().skip_binder() {
                                         db.note(&format!(
                                             "`{}` doesn't implement `{}`",
                                             trait_pred.self_ty(),