Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions TODO.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- mir tests
- support `async` blocks and `async` closures
7 changes: 7 additions & 0 deletions compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ rustc_index::newtype_index! {
}
}

impl VariantIdx {
/// The second variant, at index 1.
///
/// For use alongside [`VariantIdx::ZERO`].
pub const ONE: VariantIdx = VariantIdx::from_u32(1);
}

// A variant is absent if it's uninhabited and only has ZST fields.
// Present uninhabited variants only require space for their fields,
// but *not* an encoding of the discriminant (e.g., a tag value).
Expand Down
28 changes: 21 additions & 7 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
body,
*fn_decl_span,
*fn_arg_span,
find_attr!(attrs, Fused(_)),
),
None => self.lower_expr_closure(
attrs,
Expand All @@ -250,7 +251,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
},
ExprKind::Gen(capture_clause, block, genblock_kind, decl_span) => {
let desugaring_kind = match genblock_kind {
GenBlockKind::Async => hir::CoroutineDesugaring::Async,
GenBlockKind::Async => {
hir::CoroutineDesugaring::Async { fused: find_attr!(attrs, Fused(_)) }
}
GenBlockKind::Gen => hir::CoroutineDesugaring::Gen,
GenBlockKind::AsyncGen => hir::CoroutineDesugaring::AsyncGen,
};
Expand Down Expand Up @@ -714,7 +717,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// The `async` desugaring takes a resume argument and maintains a `task_context`,
// whereas a generator does not.
let (inputs, params, task_context): (&[_], &[_], _) = match desugaring_kind {
hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::AsyncGen => {
hir::CoroutineDesugaring::Async { fused: _ } | hir::CoroutineDesugaring::AsyncGen => {
// Resume argument type: `ResumeTy`
let unstable_span = self.mark_span_with_reason(
DesugaringKind::Async,
Expand Down Expand Up @@ -850,7 +853,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
let full_span = expr.span.to(await_kw_span);

let is_async_gen = match self.coroutine_kind {
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => false,
Some(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async { fused: _ },
_,
)) => false,
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
Some(hir::CoroutineKind::Coroutine(_))
| Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _))
Expand Down Expand Up @@ -1114,7 +1120,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
Some(
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async { fused: _ }, _)
| hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _),
) => {
panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering");
Expand Down Expand Up @@ -1155,13 +1161,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Expr,
fn_decl_span: Span,
fn_arg_span: Span,
fused: bool,
) -> hir::ExprKind<'hir> {
let closure_def_id = self.local_def_id(closure_id);
let (binder_clause, generic_params) = self.lower_closure_binder(binder);

let coroutine_desugaring = match coroutine_kind {
CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async { fused },
CoroutineKind::Gen { .. } => {
debug_assert!(!fused, "This should have been rejected by attribute parsing");
hir::CoroutineDesugaring::Gen
}
CoroutineKind::AsyncGen { span, .. } => {
span_bug!(span, "only async closures and `iter!` closures are supported currently")
}
Expand All @@ -1181,6 +1191,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
body.span,
coroutine_kind,
hir::CoroutineSource::Closure,
fused,
);

this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id);
Expand Down Expand Up @@ -1706,7 +1717,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
let is_async_gen = match self.coroutine_kind {
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)) => false,
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)) => true,
Some(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)) => {
Some(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async { fused: _ },
_,
)) => {
// Lower to a block `{ EXPR; <error> }` so that the awaited expr
// is not accidentally orphaned.
let stmt_id = self.next_id();
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1484,6 +1484,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
body.span,
coroutine_kind,
hir::CoroutineSource::Fn,
find_attr!(attrs, Fused(_)),
);

// FIXME(async_fn_track_caller): Can this be moved above?
Expand All @@ -1506,6 +1507,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
body_span: Span,
coroutine_kind: CoroutineKind,
coroutine_source: hir::CoroutineSource,
fused: bool,
) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) {
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
Expand Down Expand Up @@ -1665,7 +1667,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
this.expr_block(body)
};
let desugaring_kind = match coroutine_kind {
CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async { fused },
CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen,
};
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,18 @@ impl NoArgsAttributeParser for CoroutineParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]);
const CREATE: fn(rustc_span::Span) -> AttributeKind = |_| AttributeKind::Coroutine;
}

pub(crate) struct FusedParser;

impl NoArgsAttributeParser for FusedParser {
const PATH: &[Symbol] = &[sym::fused];
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Fn),
Allow(Target::Method(MethodKind::TraitImpl)),
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Closure),
Allow(Target::Expression),
]);
const CREATE: fn(rustc_span::Span) -> AttributeKind = |span| AttributeKind::Fused(span);
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ attribute_parsers!(
Single<WithoutArgs<FfiConstParser>>,
Single<WithoutArgs<FfiPureParser>>,
Single<WithoutArgs<FundamentalParser>>,
Single<WithoutArgs<FusedParser>>,
Single<WithoutArgs<LoopMatchParser>>,
Single<WithoutArgs<MacroEscapeParser>>,
Single<WithoutArgs<MarkerParser>>,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3614,7 +3614,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
bug!("gen block/closure expected, but gen function found.")
}
},
CoroutineKind::Desugared(CoroutineDesugaring::Async, async_kind) => {
CoroutineKind::Desugared(CoroutineDesugaring::Async { fused: _ }, async_kind) => {
match async_kind {
CoroutineSource::Block => "async block",
CoroutineSource::Closure => "async closure",
Expand Down Expand Up @@ -3654,7 +3654,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
fr_name.highlight_region_name(&mut err);
if matches!(
use_span.coroutine_kind(),
Some(CoroutineKind::Desugared(CoroutineDesugaring::Async, _))
Some(CoroutineKind::Desugared(CoroutineDesugaring::Async { fused: _ }, _))
) {
err.note(
"async blocks are not executed immediately and must either take a \
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if !matches!(
kind,
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineDesugaring::Async { fused: _ },
_
),)
) {
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_borrowck/src/diagnostics/region_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -807,20 +807,20 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
};
let mir_description = match kind {
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineDesugaring::Async { fused: _ },
hir::CoroutineSource::Block,
)) => " of async block",

hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineDesugaring::Async { fused: _ },
hir::CoroutineSource::Closure,
))
| hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => {
" of async closure"
}
| hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async {
fused: _,
}) => " of async closure",

hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineDesugaring::Async { fused: _ },
hir::CoroutineSource::Fn,
)) => {
let parent_item =
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/type_check/input_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
assert_matches!(
self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(mir_def_id)),
Some(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::Gen,
hir::CoroutineDesugaring::Async { fused: _ } | hir::CoroutineDesugaring::Gen,
hir::CoroutineSource::Closure
)),
"this needs to be modified if we're lowering non-async closures"
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,9 +586,9 @@ fn coroutine_kind_label(coroutine_kind: Option<CoroutineKind>) -> &'static str {
Some(Desugared(Gen, Block)) => "gen_block",
Some(Desugared(Gen, Closure)) => "gen_closure",
Some(Desugared(Gen, Fn)) => "gen_fn",
Some(Desugared(Async, Block)) => "async_block",
Some(Desugared(Async, Closure)) => "async_closure",
Some(Desugared(Async, Fn)) => "async_fn",
Some(Desugared(Async { fused: _ }, Block)) => "async_block",
Some(Desugared(Async { fused: _ }, Closure)) => "async_closure",
Some(Desugared(Async { fused: _ }, Fn)) => "async_fn",
Some(Desugared(AsyncGen, Block)) => "async_gen_block",
Some(Desugared(AsyncGen, Closure)) => "async_gen_closure",
Some(Desugared(AsyncGen, Fn)) => "async_gen_fn",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
match self.0 {
hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineDesugaring::Async { fused: _ },
hir::CoroutineSource::Block,
)
// FIXME(coroutines): eventually we want to gate const coroutine coroutines behind a
Expand Down
10 changes: 4 additions & 6 deletions compiler/rustc_const_eval/src/interpret/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {

// If one variant consists entirely of 1-ZST, then the other variant
// is the only "relevant" one for this check.
let var0 = VariantIdx::from_u32(0);
let var1 = VariantIdx::from_u32(1);
let relevant_variant = if all_fields_1zst(def.variant(var0))? {
def.variant(var1)
} else if all_fields_1zst(def.variant(var1))? {
def.variant(var0)
let relevant_variant = if all_fields_1zst(def.variant(VariantIdx::ZERO))? {
def.variant(VariantIdx::ONE)
} else if all_fields_1zst(def.variant(VariantIdx::ONE))? {
def.variant(VariantIdx::ZERO)
} else {
// No variant is all-1-ZST, so no NPO.
return interp_ok(layout);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// `#[coroutine]` attribute to be applied to closures to make them coroutines instead
gated!(coroutine, coroutines, experimental!(coroutine)),

gated!(fused, fused_attribute, experimental!(fused)),

// RFC 3543
// `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
gated!(patchable_function_entry, experimental!(patchable_function_entry)),
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,8 @@ declare_features! (
(unstable, dropck_eyepatch, "1.10.0", Some(34761)),
/// Allows using the `#[fundamental]` attribute.
(unstable, fundamental, "1.0.0", Some(29635)),
/// Allows using the `#[fused]` attribute.
(unstable, fused_attribute, "CURRENT_RUSTC_VERSION", Some(147129)),
/// Allows using `#[link_name="llvm.*"]`.
(internal, link_llvm_intrinsics, "1.0.0", Some(29602)),
/// Allows using the `#[linkage = ".."]` attribute.
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,9 @@ pub enum AttributeKind {
/// Represents `#[fundamental]`.
Fundamental,

/// Represents `#[fused]`.
Fused(Span),

/// Represents `#[ignore]`
Ignore {
span: Span,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ impl AttributeKind {
FfiConst => No,
FfiPure(..) => No,
Fundamental { .. } => Yes,
Fused(..) => No,
Ignore { .. } => No,
Inline(..) => No,
InstructionSet(..) => No,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2207,7 +2207,7 @@ pub enum CoroutineKind {
impl CoroutineKind {
pub fn movability(self) -> Movability {
match self {
CoroutineKind::Desugared(CoroutineDesugaring::Async, _)
CoroutineKind::Desugared(CoroutineDesugaring::Async { fused: _ }, _)
| CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) => Movability::Static,
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => Movability::Movable,
CoroutineKind::Coroutine(mov) => mov,
Expand Down Expand Up @@ -2271,7 +2271,7 @@ impl fmt::Display for CoroutineSource {
#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash, StableHash, Encodable, Decodable)]
pub enum CoroutineDesugaring {
/// An explicit `async` block or the body of an `async` function.
Async,
Async { fused: bool },

/// An explicit `gen` block or the body of a `gen` function.
Gen,
Expand All @@ -2284,7 +2284,7 @@ pub enum CoroutineDesugaring {
impl fmt::Display for CoroutineDesugaring {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CoroutineDesugaring::Async => {
CoroutineDesugaring::Async { fused: _ } => {
if f.alternate() {
f.write_str("`async` ")?;
} else {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::ExprKind::Closure(&hir::Closure {
kind:
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineDesugaring::Async { fused: _ },
hir::CoroutineSource::Closure,
)),
..
Expand Down
Loading
Loading