about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorYuki Okushi <jtitor@2k36.org>2021-07-24 04:31:11 +0900
committerGitHub <noreply@github.com>2021-07-24 04:31:11 +0900
commit3fc79fde63cfa8472e8c867c0a54de58cffb5cd0 (patch)
tree3c2fd5582b70f542e5fb60d4826cb78097efd37a /compiler
parent82a14e57e7754310dd78c08386d801a33555d2f6 (diff)
parenta1518f091552afdf370c699a359af0b7d34e402d (diff)
downloadrust-3fc79fde63cfa8472e8c867c0a54de58cffb5cd0.tar.gz
rust-3fc79fde63cfa8472e8c867c0a54de58cffb5cd0.zip
Rollup merge of #87322 - chazkiker2:fix/suggestion-ref-sync-send, r=estebank
fix: clarify suggestion that `&T` must refer to `T: Sync` for `&T: Send`

### Description

- [x] fix #86507
- [x] add UI test for relevant code from issue
- [x] change `rustc_trait_selection/src/traits/error_reporting/suggestions.rs` to include a more clear suggestion when `&T` fails to satisfy `Send` bounds due to the fact that `T` fails to implement `Sync`
- [x] update UI test in Clippy: `src/tools/tests/ui/future_not_send.stderr`
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs35
1 files changed, 30 insertions, 5 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 1c6a83b5783..9a33875d6e4 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1857,12 +1857,37 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 }
             }
             GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
+                // `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync`
+                let refers_to_non_sync = match target_ty.kind() {
+                    ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) {
+                        Ok(eval) if !eval.may_apply() => Some(ref_ty),
+                        _ => None,
+                    },
+                    _ => None,
+                };
+
+                let (span_label, span_note) = match refers_to_non_sync {
+                    // if `target_ty` is `&T` and `T` fails to impl `Sync`,
+                    // include suggestions to make `T: Sync` so that `&T: Send`
+                    Some(ref_ty) => (
+                        format!(
+                            "has type `{}` which {}, because `{}` is not `Sync`",
+                            target_ty, trait_explanation, ref_ty
+                        ),
+                        format!(
+                            "captured value {} because `&` references cannot be sent unless their referent is `Sync`",
+                            trait_explanation
+                        ),
+                    ),
+                    None => (
+                        format!("has type `{}` which {}", target_ty, trait_explanation),
+                        format!("captured value {}", trait_explanation),
+                    ),
+                };
+
                 let mut span = MultiSpan::from_span(upvar_span);
-                span.push_span_label(
-                    upvar_span,
-                    format!("has type `{}` which {}", target_ty, trait_explanation),
-                );
-                err.span_note(span, &format!("captured value {}", trait_explanation));
+                span.push_span_label(upvar_span, span_label);
+                err.span_note(span, &span_note);
             }
         }