Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f44b09f

Browse files
committed
Initial UnsafePinned impl [Part 2: Lowering]
1 parent 40dacd5 commit f44b09f

16 files changed

+899
-13
lines changed

‎compiler/rustc_ast_ir/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContex
1717
pub mod visit;
1818

1919
/// The movability of a coroutine / closure literal:
20-
/// whether a coroutine contains self-references, causing it to be `!Unpin`.
20+
/// whether a coroutine contains self-references, causing it to be `![Unsafe]Unpin`.
2121
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
2222
#[cfg_attr(
2323
feature = "nightly",
2424
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
2525
)]
2626
pub enum Movability {
27-
/// May contain self-references, `!Unpin`.
27+
/// May contain self-references, `!Unpin + !UnsafeUnpin`.
2828
Static,
29-
/// Must not contain self-references, `Unpin`.
29+
/// Must not contain self-references, `Unpin + UnsafeUnpin`.
3030
Movable,
3131
}
3232

‎compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3385,7 +3385,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
33853385
Some(3)
33863386
} else if string.starts_with("static") {
33873387
// `static` is 6 chars long
3388-
// This is used for `!Unpin` coroutines
3388+
// This is used for immovable (self-referential) coroutines
33893389
Some(6)
33903390
} else {
33913391
None

‎compiler/rustc_middle/src/mir/query.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ pub struct CoroutineSavedTy<'tcx> {
2929
pub source_info: SourceInfo,
3030
/// Whether the local should be ignored for trait bound computations.
3131
pub ignore_for_traits: bool,
32+
/// If this local is borrowed across a suspension point and thus is
33+
/// "wrapped" in `UnsafePinned`. Always false for movable coroutines.
34+
pub pinned: bool,
3235
}
3336

3437
/// The layout of coroutine state.

‎compiler/rustc_middle/src/ty/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,7 @@ bidirectional_lang_item_map! {
734734
TransmuteTrait,
735735
Tuple,
736736
Unpin,
737+
UnsafeUnpin,
737738
Unsize,
738739
// tidy-alphabetical-end
739740
}

‎compiler/rustc_mir_transform/src/coroutine.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,15 @@ struct LivenessInfo {
639639
/// Parallel vec to the above with SourceInfo for each yield terminator.
640640
source_info_at_suspension_points: Vec<SourceInfo>,
641641

642+
/// Coroutine saved locals that are borrowed across a suspension point.
643+
/// This corresponds to locals that are "wrapped" with `UnsafePinned`.
644+
///
645+
/// Note that movable coroutines do not allow borrowing locals across
646+
/// suspension points and thus will always have this set empty.
647+
///
648+
/// For more information, see [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html).
649+
saved_locals_borrowed_across_suspension_points: DenseBitSet<CoroutineSavedLocal>,
650+
642651
/// For every saved local, the set of other saved locals that are
643652
/// storage-live at the same time as this local. We cannot overlap locals in
644653
/// the layout which have conflicting storage.
@@ -690,6 +699,8 @@ fn locals_live_across_suspend_points<'tcx>(
690699
let mut live_locals_at_suspension_points = Vec::new();
691700
let mut source_info_at_suspension_points = Vec::new();
692701
let mut live_locals_at_any_suspension_point = DenseBitSet::new_empty(body.local_decls.len());
702+
let mut locals_borrowed_across_any_suspension_point =
703+
DenseBitSet::new_empty(body.local_decls.len());
693704

694705
for (block, data) in body.basic_blocks.iter_enumerated() {
695706
if let TerminatorKind::Yield { .. } = data.terminator().kind {
@@ -711,6 +722,7 @@ fn locals_live_across_suspend_points<'tcx>(
711722
// of the local, which happens using the `intersect` operation below.
712723
borrowed_locals_cursor.seek_before_primary_effect(loc);
713724
live_locals.union(borrowed_locals_cursor.get());
725+
locals_borrowed_across_any_suspension_point.union(borrowed_locals_cursor.get());
714726
}
715727

716728
// Store the storage liveness for later use so we can restore the state
@@ -726,6 +738,7 @@ fn locals_live_across_suspend_points<'tcx>(
726738

727739
// The coroutine argument is ignored.
728740
live_locals.remove(SELF_ARG);
741+
locals_borrowed_across_any_suspension_point.remove(SELF_ARG);
729742

730743
debug!("loc = {:?}, live_locals = {:?}", loc, live_locals);
731744

@@ -741,13 +754,18 @@ fn locals_live_across_suspend_points<'tcx>(
741754
debug!("live_locals_anywhere = {:?}", live_locals_at_any_suspension_point);
742755
let saved_locals = CoroutineSavedLocals(live_locals_at_any_suspension_point);
743756

757+
debug!("borrowed_locals = {:?}", locals_borrowed_across_any_suspension_point);
758+
744759
// Renumber our liveness_map bitsets to include only the locals we are
745760
// saving.
746761
let live_locals_at_suspension_points = live_locals_at_suspension_points
747762
.iter()
748763
.map(|live_here| saved_locals.renumber_bitset(live_here))
749764
.collect();
750765

766+
let saved_locals_borrowed_across_suspension_points =
767+
saved_locals.renumber_bitset(&locals_borrowed_across_any_suspension_point);
768+
751769
let storage_conflicts = compute_storage_conflicts(
752770
body,
753771
&saved_locals,
@@ -759,6 +777,7 @@ fn locals_live_across_suspend_points<'tcx>(
759777
saved_locals,
760778
live_locals_at_suspension_points,
761779
source_info_at_suspension_points,
780+
saved_locals_borrowed_across_suspension_points,
762781
storage_conflicts,
763782
storage_liveness: storage_liveness_map,
764783
}
@@ -931,6 +950,7 @@ fn compute_layout<'tcx>(
931950
saved_locals,
932951
live_locals_at_suspension_points,
933952
source_info_at_suspension_points,
953+
saved_locals_borrowed_across_suspension_points,
934954
storage_conflicts,
935955
storage_liveness,
936956
} = liveness;
@@ -960,8 +980,14 @@ fn compute_layout<'tcx>(
960980
ClearCrossCrate::Set(box LocalInfo::FakeBorrow) => true,
961981
_ => false,
962982
};
963-
let decl =
964-
CoroutineSavedTy { ty: decl.ty, source_info: decl.source_info, ignore_for_traits };
983+
let pinned = saved_locals_borrowed_across_suspension_points.contains(saved_local);
984+
985+
let decl = CoroutineSavedTy {
986+
ty: decl.ty,
987+
source_info: decl.source_info,
988+
ignore_for_traits,
989+
pinned,
990+
};
965991
debug!(?decl);
966992

967993
tys.push(decl);

‎compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,13 +1148,16 @@ where
11481148

11491149
ty::Infer(_) | ty::Bound(_, _) => panic!("unexpected type `{self_ty:?}`"),
11501150

1151-
// Coroutines have one special built-in candidate, `Unpin`, which
1152-
// takes precedence over the structural auto trait candidate being
1153-
// assembled.
1151+
// Coroutines have two special built-in candidates, `Unpin` and `UnsafeUnpin`.
1152+
// These take precedence over the structural auto trait candidate being assembled.
11541153
ty::Coroutine(def_id, _)
1155-
if self.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::Unpin) =>
1154+
if matches!(
1155+
self.cx().as_lang_item(goal.predicate.def_id()),
1156+
Some(TraitSolverLangItem::Unpin | TraitSolverLangItem::UnsafeUnpin)
1157+
) =>
11561158
{
11571159
match self.cx().coroutine_movability(def_id) {
1160+
// immovable coroutines are *never* [Unsafe]Unpin
11581161
Movability::Static => Some(Err(NoSolution)),
11591162
Movability::Movable => Some(
11601163
self.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {

‎compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -752,15 +752,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
752752
candidates.ambiguous = true;
753753
}
754754
ty::Coroutine(coroutine_def_id, _)
755-
if self.tcx().is_lang_item(def_id, LangItem::Unpin) =>
755+
if self.tcx().is_lang_item(def_id, LangItem::Unpin)
756+
|| self.tcx().is_lang_item(def_id, LangItem::UnsafeUnpin) =>
756757
{
757758
match self.tcx().coroutine_movability(coroutine_def_id) {
758759
hir::Movability::Static => {
759-
// Immovable coroutines are never `Unpin`, so
760+
// Immovable coroutines are never `[Unsafe]Unpin`, so
760761
// suppress the normal auto-impl candidate for it.
761762
}
762763
hir::Movability::Movable => {
763-
// Movable coroutines are always `Unpin`, so add an
764+
// Movable coroutines are always `[Unsafe]Unpin`, so add an
764765
// unconditional builtin candidate.
765766
candidates.vec.push(BuiltinCandidate { has_nested: false });
766767
}

‎compiler/rustc_type_ir/src/lang_items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub enum TraitSolverLangItem {
3838
TransmuteTrait,
3939
Tuple,
4040
Unpin,
41+
UnsafeUnpin,
4142
Unsize,
4243
// tidy-alphabetical-end
4344
}

‎tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
scope: scope[0],
2222
},
2323
ignore_for_traits: false,
24+
pinned: true,
2425
},
2526
_1: CoroutineSavedTy {
2627
ty: Coroutine(
@@ -42,6 +43,7 @@
4243
scope: scope[0],
4344
},
4445
ignore_for_traits: false,
46+
pinned: true,
4547
},
4648
},
4749
variant_fields: {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /