Skip to content

Commit 99b01b8

Browse files
committed
Gate direct pin-borrow ADT diagnostic on !Unpin
1 parent d7f4bbd commit 99b01b8

3 files changed

Lines changed: 72 additions & 18 deletions

File tree

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
3636
use rustc_span::hygiene::DesugaringKind;
3737
use rustc_span::{Ident, Span, Spanned, Symbol, kw, sym};
3838
use rustc_trait_selection::infer::InferCtxtExt;
39+
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
3940
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
4041
use tracing::{debug, instrument, trace};
4142

@@ -531,6 +532,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
531532
let ty = self.structurally_resolve_type(span, ty);
532533
if let Some(adt) = ty.ty_adt_def()
533534
&& !adt.is_pin_project()
535+
&& self.type_known_to_not_be_unpin(ty, span)
534536
{
535537
let def_span = self.tcx.hir_span_if_local(adt.did());
536538
let sugg_span = def_span.map(|span| span.shrink_to_lo());
@@ -542,6 +544,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
542544
}
543545
}
544546

547+
fn type_known_to_not_be_unpin(&self, ty: Ty<'tcx>, span: Span) -> bool {
548+
if ty.has_param() || ty.has_infer() || ty.has_aliases() || ty.has_placeholders() {
549+
return false;
550+
}
551+
552+
let unpin_def_id = self.tcx.require_lang_item(LangItem::Unpin, span);
553+
let trait_ref = ty::TraitRef::new(self.tcx, unpin_def_id, [ty]);
554+
let obligation =
555+
traits::Obligation::new(self.tcx, self.misc(span), self.param_env, trait_ref);
556+
self.evaluate_obligation(&obligation).is_ok_and(|result| !result.may_apply())
557+
}
558+
545559
/// Does this expression refer to a place that either:
546560
/// * Is based on a local or static.
547561
/// * Contains a dereference
Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,57 @@
11
#![feature(pin_ergonomics)]
2-
#![allow(incomplete_features)]
2+
#![allow(dead_code, incomplete_features)]
33
//@ normalize-stderr: "\n\n\z" -> "\n"
44

5-
struct NotPinV2;
5+
use std::marker::PhantomPinned;
6+
use std::pin::Pin;
67

7-
fn direct_pin_mut(mut value: NotPinV2) {
8-
let _ = &pin mut value;
8+
struct UnpinAdt;
9+
10+
struct NotUnpin {
11+
_pin: PhantomPinned,
12+
}
13+
14+
#[pin_v2]
15+
struct PinV2NotUnpin {
16+
_pin: PhantomPinned,
17+
}
18+
19+
struct GenericAdt<T> {
20+
value: T,
21+
}
22+
23+
fn direct_pin_mut_unpin() {
24+
let _: Pin<&mut _> = &pin mut UnpinAdt;
25+
}
26+
27+
fn direct_pin_const_unpin() {
28+
let _: Pin<&_> = &pin const UnpinAdt;
29+
}
30+
31+
fn direct_pin_mut_not_unpin() {
32+
let _ = &pin mut NotUnpin { _pin: PhantomPinned };
933
//~^ ERROR cannot directly pin an ADT that is not `#[pin_v2]`
1034
}
1135

12-
fn direct_pin_const(value: NotPinV2) {
13-
let _ = &pin const value;
36+
fn direct_pin_const_not_unpin() {
37+
let _ = &pin const NotUnpin { _pin: PhantomPinned };
1438
//~^ ERROR cannot directly pin an ADT that is not `#[pin_v2]`
1539
}
1640

41+
fn direct_pin_mut_pin_v2_not_unpin() {
42+
let _: Pin<&mut _> = &pin mut PinV2NotUnpin { _pin: PhantomPinned };
43+
}
44+
45+
fn direct_pin_const_pin_v2_not_unpin() {
46+
let _: Pin<&_> = &pin const PinV2NotUnpin { _pin: PhantomPinned };
47+
}
48+
49+
fn direct_pin_mut_generic<T>(mut value: GenericAdt<T>) {
50+
let _ = &pin mut value;
51+
}
52+
53+
fn direct_pin_const_generic<T>(value: GenericAdt<T>) {
54+
let _ = &pin const value;
55+
}
56+
1757
fn main() {}
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
error: cannot directly pin an ADT that is not `#[pin_v2]`
2-
--> $DIR/direct-borrow-requires-pin-v2.rs:8:13
2+
--> $DIR/direct-borrow-requires-pin-v2.rs:32:13
33
|
4-
LL | let _ = &pin mut value;
5-
| ^^^^^^^^^^^^^^
4+
LL | let _ = &pin mut NotUnpin { _pin: PhantomPinned };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
note: type defined here
8-
--> $DIR/direct-borrow-requires-pin-v2.rs:5:1
8+
--> $DIR/direct-borrow-requires-pin-v2.rs:10:1
99
|
10-
LL | struct NotPinV2;
10+
LL | struct NotUnpin {
1111
| ^^^^^^^^^^^^^^^
1212
help: add `#[pin_v2]` here
1313
|
1414
LL + #[pin_v2]
15-
LL | struct NotPinV2;
15+
LL | struct NotUnpin {
1616
|
1717

1818
error: cannot directly pin an ADT that is not `#[pin_v2]`
19-
--> $DIR/direct-borrow-requires-pin-v2.rs:13:13
19+
--> $DIR/direct-borrow-requires-pin-v2.rs:37:13
2020
|
21-
LL | let _ = &pin const value;
22-
| ^^^^^^^^^^^^^^^^
21+
LL | let _ = &pin const NotUnpin { _pin: PhantomPinned };
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2323
|
2424
note: type defined here
25-
--> $DIR/direct-borrow-requires-pin-v2.rs:5:1
25+
--> $DIR/direct-borrow-requires-pin-v2.rs:10:1
2626
|
27-
LL | struct NotPinV2;
27+
LL | struct NotUnpin {
2828
| ^^^^^^^^^^^^^^^
2929
help: add `#[pin_v2]` here
3030
|
3131
LL + #[pin_v2]
32-
LL | struct NotPinV2;
32+
LL | struct NotUnpin {
3333
|
3434

3535
error: aborting due to 2 previous errors

0 commit comments

Comments
 (0)