Skip to content

Commit d089e27

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#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`
2 parents 976d406 + 831ac19 commit d089e27

File tree

3 files changed

+78
-5
lines changed

3 files changed

+78
-5
lines changed

Diff for: compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+30-5
Original file line numberDiff line numberDiff line change
@@ -1857,12 +1857,37 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
18571857
}
18581858
}
18591859
GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
1860+
// `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync`
1861+
let refers_to_non_sync = match target_ty.kind() {
1862+
ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) {
1863+
Ok(eval) if !eval.may_apply() => Some(ref_ty),
1864+
_ => None,
1865+
},
1866+
_ => None,
1867+
};
1868+
1869+
let (span_label, span_note) = match refers_to_non_sync {
1870+
// if `target_ty` is `&T` and `T` fails to impl `Sync`,
1871+
// include suggestions to make `T: Sync` so that `&T: Send`
1872+
Some(ref_ty) => (
1873+
format!(
1874+
"has type `{}` which {}, because `{}` is not `Sync`",
1875+
target_ty, trait_explanation, ref_ty
1876+
),
1877+
format!(
1878+
"captured value {} because `&` references cannot be sent unless their referent is `Sync`",
1879+
trait_explanation
1880+
),
1881+
),
1882+
None => (
1883+
format!("has type `{}` which {}", target_ty, trait_explanation),
1884+
format!("captured value {}", trait_explanation),
1885+
),
1886+
};
1887+
18601888
let mut span = MultiSpan::from_span(upvar_span);
1861-
span.push_span_label(
1862-
upvar_span,
1863-
format!("has type `{}` which {}", target_ty, trait_explanation),
1864-
);
1865-
err.span_note(span, &format!("captured value {}", trait_explanation));
1889+
span.push_span_label(upvar_span, span_label);
1890+
err.span_note(span, &span_note);
18661891
}
18671892
}
18681893

Diff for: src/test/ui/async-await/issue-86507.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// edition:2018
2+
3+
use ::core::pin::Pin;
4+
use ::core::future::Future;
5+
use ::core::marker::Send;
6+
7+
trait Foo {
8+
fn bar<'me, 'async_trait, T: Send>(x: &'me T)
9+
-> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
10+
where 'me: 'async_trait;
11+
}
12+
13+
impl Foo for () {
14+
fn bar<'me, 'async_trait, T: Send>(x: &'me T)
15+
-> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
16+
where 'me:'async_trait {
17+
Box::pin( //~ ERROR future cannot be sent between threads safely
18+
async move {
19+
let x = x;
20+
}
21+
)
22+
}
23+
}
24+
25+
fn main() { }

Diff for: src/test/ui/async-await/issue-86507.stderr

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error: future cannot be sent between threads safely
2+
--> $DIR/issue-86507.rs:17:13
3+
|
4+
LL | / Box::pin(
5+
LL | | async move {
6+
LL | | let x = x;
7+
LL | | }
8+
LL | | )
9+
| |_____________^ future created by async block is not `Send`
10+
|
11+
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
12+
--> $DIR/issue-86507.rs:19:29
13+
|
14+
LL | let x = x;
15+
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
16+
= note: required for the cast to the object type `dyn Future<Output = ()> + Send`
17+
help: consider further restricting type parameter `T`
18+
|
19+
LL | where 'me:'async_trait, T: std::marker::Sync {
20+
| ^^^^^^^^^^^^^^^^^^^^^^
21+
22+
error: aborting due to previous error
23+

0 commit comments

Comments
 (0)