Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rust-lang/rust
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: pnkfelix/rust
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: experiment-future-growth-89213
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
  • 14 commits
  • 18 files changed
  • 1 contributor

Commits on Nov 30, 2022

  1. Copy the full SHA
    0f7aa7a View commit details
  2. Copy the full SHA
    3293fab View commit details

Commits on Dec 1, 2022

  1. start establishing the path working backwards from the MIR local back…

    … up to the experimental attribute.
    pnkfelix committed Dec 1, 2022
    Copy the full SHA
    e816665 View commit details

Commits on Dec 2, 2022

  1. Copy the full SHA
    c38f239 View commit details
  2. Copy the full SHA
    04c80d1 View commit details

Commits on Dec 3, 2022

  1. Copy the full SHA
    79fc6d6 View commit details
  2. MERGEME

    1. Changed the reuse-upvar state to hold a Place rather than the former
       (placeholder) raw index.
    
    2. Attempted to connect the THIR state up to the MIR state.
    
    (I am not yet certain how successful the wiring was. We will see; I just wanted
    to checkpoint my current state.)
    pnkfelix committed Dec 3, 2022
    Copy the full SHA
    cdf1204 View commit details
  3. Copy the full SHA
    190a9d6 View commit details
  4. experiment: try treating reuse_upvar-marked local as always live.

    (does not work yet; looks like reuse_upvar state is not yet threaded through
    completely.)
    pnkfelix committed Dec 3, 2022
    Copy the full SHA
    d5ddea7 View commit details

Commits on Dec 6, 2022

  1. Empty commit to mark current state.

    An example input file, example-89213-c.rs:
    
    ```rust
    
    pub const LEN: usize = 100000;
    
    pub fn wait(an_upvar: [u8; LEN]) -> impl core::future::Future<Output = ()> {
        async move {
            #[rustc_reuse_upvar_slot] let a_let_local = an_upvar;
            no_op().await;
            drop(a_let_local);
        }
    }
    
    async fn no_op() { }
    fn drop<T>(_x: T) { }
    ```
    
    A compilation-buffer invocation (will need to be updated for other non Apple arch):
    
      KKEEP_STAGE="--keep-stage=1" ; time ../x.py build library $KEEP_STAGE && RUSTC_LOG=rustc_ast_lowering,rustc_middle::hir,rustc_parse::parser,rustc_hir,rustc_mir_build,rustc_mir_transform::generator,rustc_mir_dataflow ./build/aarch64-apple-darwin/stage1/bin/rustc --edition 2021 example-89213-c.rs > rustc_log.log 2>&1
    
    Some Elisp code
    
    (defun some-highlights ()
      (interactive)
      (highlight-regexp "a_let_local")
      (highlight-regexp "an_upvar" 'hi-pink)
      (highlight-regexp "reuse_slot" 'hi-green))
    pnkfelix committed Dec 6, 2022
    Copy the full SHA
    ed227a6 View commit details

Commits on Dec 7, 2022

  1. Update static asserts to accommodate the (hopefully temporary) size b…

    …loat pnkfelix has injected.
    pnkfelix committed Dec 7, 2022
    Copy the full SHA
    8804534 View commit details
  2. Copy the full SHA
    4131e16 View commit details
  3. expanded debug instrumentation to include the local key for the Local…

    …Decl under inspection.
    pnkfelix committed Dec 7, 2022
    Copy the full SHA
    3e5abc1 View commit details

Commits on Dec 17, 2022

  1. Copy the full SHA
    c23b2c8 View commit details
34 changes: 32 additions & 2 deletions compiler/rustc_ast_lowering/src/block.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind};
use rustc_hir as hir;
use rustc_span::symbol::sym;

use smallvec::SmallVec;

@@ -96,8 +97,37 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
};
let span = self.lower_span(l.span);
let source = hir::LocalSource::Normal;
self.lower_attrs(hir_id, &l.attrs);
self.arena.alloc(hir::Local { hir_id, ty, pat, init, els, span, source })
let attrs = self.lower_attrs(hir_id, &l.attrs);
debug!("lower_local hir_id={hir_id:?} attrs={attrs:?}");
let reuse_slot = attrs
.map(|attrs| attrs.iter().any(|attr| attr.has_name(sym::rustc_reuse_upvar_slot)))
.unwrap_or(false);
let reuse_slot = if reuse_slot {
if let Some(hir::Expr {
kind: hir::ExprKind::Path(hir::QPath::Resolved(
None, hir::Path { res: hir::def::Res::Local(hir_id), .. })), .. }) = init
{
Some(*hir_id)
} else {
if init.is_some() {
panic!("init fed to let was not a simple upvar");
} else {
panic!("with no init expression I cannot know what slot to use");
}
}
} else {
None
};
/*
Some(Expr { hir_id: HirId { owner: OwnerId { def_id: DefId(0:5 ~ example_89213_c[f670]::wait) }, local_id: 8 },
kind: Path(Resolved(None, Path { span: example-89213-c.rs:9:53: 9:61 (#0), res: Local(HirId { owner: OwnerId { def_id: DefId(0:5 ~ example_89213_c[f670]::wait) }, local_id: 2 }), segments: [PathSegment { ident: an_upvar#0, hir_id: HirId { owner: OwnerId { def_id: DefId(0:5 ~ example_89213_c[f670]::wait) }, local_id: 7 }, res: Local(HirId { owner: OwnerId { def_id: DefId(0:5 ~ example_89213_c[f670]::wait) }, local_id: 2 }), args: None, infer_args: true }] })),
span: example-89213-c.rs:9:53: 9:61 (#0) })
*/
debug!("lower_local reuse_slot={reuse_slot:?} init={init:?}");
let local = self.arena.alloc(hir::Local { hir_id, ty, pat, init, els, reuse_slot, span, source });
debug!(?local);
local
}

fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -2362,6 +2362,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
init,
pat,
els: None,
reuse_slot: None,
source,
span: self.lower_span(span),
ty: None,
6 changes: 6 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
@@ -741,6 +741,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
"the `#[rustc_reservation_impl]` attribute is internally used \
for reserving for `for<T> From<!> for T` impl"
),
rustc_attr!(
rustc_reuse_upvar_slot, Normal,
template!(Word), WarnFollowing,
"the `#[rustc_reuse_upvar_slot]` attribute is used to experiment with \
generator layout strategies"
),
rustc_attr!(
rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing,
"the `#[rustc_test_marker]` attribute is used internally to track tests",
3 changes: 2 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -1355,6 +1355,7 @@ pub struct Local<'hir> {
pub init: Option<&'hir Expr<'hir>>,
/// Else block for a `let...else` binding.
pub els: Option<&'hir Block<'hir>>,
pub reuse_slot: Option<HirId>,
pub hir_id: HirId,
pub span: Span,
/// Can be `ForLoopDesugar` if the `let` statement is part of a `for` loop
@@ -3598,7 +3599,7 @@ mod size_asserts {
static_assert_size!(ImplItemKind<'_>, 32);
static_assert_size!(Item<'_>, 80);
static_assert_size!(ItemKind<'_>, 48);
static_assert_size!(Local<'_>, 64);
static_assert_size!(Local<'_>, 72); // FIXME: add separate side-table and bring this back to 64
static_assert_size!(Param<'_>, 32);
static_assert_size!(Pat<'_>, 72);
static_assert_size!(Path<'_>, 40);
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/gather_locals.rs
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ pub(super) struct Declaration<'a> {

impl<'a> From<&'a hir::Local<'a>> for Declaration<'a> {
fn from(local: &'a hir::Local<'a>) -> Self {
let hir::Local { hir_id, pat, ty, span, init, els, source: _ } = *local;
let hir::Local { hir_id, pat, ty, span, init, els, reuse_slot: _, source: _ } = *local;
Declaration { hir_id, pat, ty, span, init, els }
}
}
13 changes: 11 additions & 2 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -812,6 +812,8 @@ pub struct LocalDecl<'tcx> {
/// generator.
pub internal: bool,

pub reuse_upvar: Option<Place<'tcx>>,

/// If this local is a temporary and `is_block_tail` is `Some`,
/// then it is a temporary created for evaluation of some
/// subexpression of some block's tail expression (with no
@@ -1025,16 +1027,23 @@ impl<'tcx> LocalDecl<'tcx> {
/// Creates a new `LocalDecl` for a temporary: mutable, non-internal.
#[inline]
pub fn new(ty: Ty<'tcx>, span: Span) -> Self {
Self::with_source_info(ty, SourceInfo::outermost(span))
Self::with_source_info_core(ty, SourceInfo::outermost(span))
}

/// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`.
#[inline]
pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
Self::with_source_info_core(ty, source_info)
}

/// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`.
#[inline]
fn with_source_info_core(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
LocalDecl {
mutability: Mutability::Mut,
local_info: None,
internal: false,
reuse_upvar: None,
is_block_tail: None,
ty,
user_ty: None,
@@ -3092,7 +3101,7 @@ mod size_asserts {
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
static_assert_size!(BasicBlockData<'_>, 144);
static_assert_size!(LocalDecl<'_>, 56);
static_assert_size!(LocalDecl<'_>, 72); // FIXME: add separate side-table and bring this back to 56
static_assert_size!(Statement<'_>, 32);
static_assert_size!(StatementKind<'_>, 16);
static_assert_size!(Terminator<'_>, 112);
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
@@ -811,6 +811,7 @@ macro_rules! make_mir_visitor {
user_ty,
source_info,
internal: _,
reuse_upvar: _,
local_info: _,
is_block_tail: _,
} = local_decl;
15 changes: 13 additions & 2 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
@@ -205,11 +205,22 @@ pub enum StmtKind<'tcx> {
/// `let pat: ty = <INIT> else { <ELSE> }`
else_block: Option<BlockId>,

reuse_upvar_slot: Option<UpvarRef>,

/// The lint level for this `let` statement.
lint_level: LintLevel,
},
}

#[derive(Copy, Clone, Debug, HashStable)]
pub struct UpvarRef {
/// DefId of the closure/generator
pub closure_def_id: DefId,

/// HirId of the root variable
pub var_hir_id: LocalVarId,
}

#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct LocalVarId(pub hir::HirId);
@@ -853,7 +864,7 @@ mod size_asserts {
static_assert_size!(ExprKind<'_>, 40);
static_assert_size!(Pat<'_>, 72);
static_assert_size!(PatKind<'_>, 56);
static_assert_size!(Stmt<'_>, 48);
static_assert_size!(StmtKind<'_>, 40);
static_assert_size!(Stmt<'_>, 64); // FIXME: add separate side-table and bring this back to 48
static_assert_size!(StmtKind<'_>, 56); // FIXME: add separate side table and bring this back to 40.
// tidy-alphabetical-end
}
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/thir/visit.rs
Original file line number Diff line number Diff line change
@@ -173,6 +173,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm
remainder_scope: _,
init_scope: _,
ref pattern,
reuse_upvar_slot: _,
lint_level: _,
else_block,
} => {
8 changes: 8 additions & 0 deletions compiler/rustc_mir_build/src/build/block.rs
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ use rustc_middle::{mir::*, ty};
use rustc_span::Span;

impl<'a, 'tcx> Builder<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub(crate) fn ast_block(
&mut self,
destination: Place<'tcx>,
@@ -115,6 +116,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
initializer: Some(initializer),
lint_level,
else_block: Some(else_block),
reuse_upvar_slot: _,
} => {
// When lowering the statement `let <pat> = <expr> else { <else> };`,
// the `<else>` block is nested in the parent scope enclosing this statement.
@@ -232,6 +234,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
pattern,
None,
Some((None, initializer_span)),
None,
);
this.visit_primary_bindings(
pattern,
@@ -278,7 +281,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
initializer,
lint_level,
else_block: None,
reuse_upvar_slot,
} => {
debug!("ast_block_stmts StmtKind::Let pattern: {pattern:?} reuse_upvar_slot: {reuse_upvar_slot:?}");
let ignores_expr_result = matches!(pattern.kind, PatKind::Wild);
this.block_context.push(BlockFrame::Statement { ignores_expr_result });

@@ -309,6 +314,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
pattern,
None,
Some((None, initializer_span)),
*reuse_upvar_slot,
);
this.expr_into_pattern(block, &pattern, init)
// irrefutable pattern
@@ -317,6 +323,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
)
)
} else {
assert!(reuse_upvar_slot.is_none());
let scope = (*init_scope, source_info);
unpack!(this.in_scope(scope, *lint_level, |this| {
this.declare_bindings(
@@ -325,6 +332,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
pattern,
None,
None,
None,
);
block.unit()
}));
3 changes: 2 additions & 1 deletion compiler/rustc_mir_build/src/build/expr/into.rs
Original file line number Diff line number Diff line change
@@ -108,7 +108,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ExprKind::Let { expr, ref pat } => {
let scope = this.local_scope();
let (true_block, false_block) = this.in_if_then_scope(scope, expr_span, |this| {
this.lower_let_expr(block, &this.thir[expr], pat, scope, None, expr_span, true)
this.lower_let_expr(
block, &this.thir[expr], pat, scope, None, expr_span, true, None)
});

this.cfg.push_assign_constant(
29 changes: 25 additions & 4 deletions compiler/rustc_mir_build/src/build/matches/mod.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
//! This also includes code for pattern bindings in `let` statements and
//! function parameters.
use crate::build::expr::as_place::PlaceBuilder;
use crate::build::expr::as_place::{PlaceBase, PlaceBuilder};
use crate::build::scope::DropKind;
use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
use crate::build::{BlockAnd, BlockAndExtension, Builder};
@@ -85,6 +85,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Some(variable_source_info.scope),
variable_source_info.span,
true,
None,
),
_ => {
let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
@@ -354,6 +355,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&arm.pattern,
arm.guard.as_ref(),
opt_scrutinee_place,
None,
);

let arm_block = this.bind_pattern(
@@ -640,6 +642,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
pattern: &Pat<'tcx>,
guard: Option<&Guard<'tcx>>,
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
opt_reuse_upvar_slot: Option<UpvarRef>,
) -> Option<SourceScope> {
self.visit_primary_bindings(
&pattern,
@@ -663,12 +666,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ArmHasGuard(guard.is_some()),
opt_match_place.map(|(x, y)| (x.cloned(), y)),
pattern.span,
opt_reuse_upvar_slot,
);
},
);
if let Some(Guard::IfLet(guard_pat, _)) = guard {
// FIXME: pass a proper `opt_match_place`
self.declare_bindings(visibility_scope, scope_span, guard_pat, None, None);
self.declare_bindings(visibility_scope, scope_span, guard_pat, None, None, None);
}
visibility_scope
}
@@ -1772,7 +1776,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
source_scope: Option<SourceScope>,
span: Span,
declare_bindings: bool,
// FIXME does this need a potential reuse_var_slot parameter? When is this lowering path used?
reuse_upvar_slot: Option<UpvarRef>,
) -> BlockAnd<()> {
debug!("lower_let_expr expr: {expr:?} pat: {pat:?} reuse_upvar_slot: {reuse_upvar_slot:?}");
let expr_span = expr.span;
let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
let wildcard = Pat::wildcard_from_ty(pat.ty);
@@ -1792,7 +1799,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span));

if declare_bindings {
self.declare_bindings(source_scope, pat.span.to(span), pat, None, opt_expr_place);
self.declare_bindings(
source_scope,
pat.span.to(span),
pat,
None,
opt_expr_place,
reuse_upvar_slot
);
}

let post_guard_block = self.bind_pattern(
@@ -1974,7 +1988,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Guard::IfLet(ref pat, scrutinee) => {
let s = &this.thir[scrutinee];
guard_span = s.span;
this.lower_let_expr(block, s, pat, match_scope, None, arm.span, false)
this.lower_let_expr(block, s, pat, match_scope, None, arm.span, false, None)
}
});

@@ -2204,7 +2218,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
has_guard: ArmHasGuard,
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
pat_span: Span,
reuse_upvar: Option<UpvarRef>,
) {
debug!("declare_binding var_id: {var_id:?} var_ty: {var_ty:?} reuse_upvar: {reuse_upvar:?}");
let tcx = self.tcx;
let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope };
let binding_mode = match mode {
@@ -2217,6 +2233,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) },
source_info,
internal: false,
reuse_upvar: reuse_upvar.map(|thir::UpvarRef { closure_def_id, var_hir_id }| {
let closure_def_id = closure_def_id.expect_local();
PlaceBuilder::from(PlaceBase::Upvar { var_hir_id, closure_def_id }).to_place(self)
}),
is_block_tail: None,
local_info: Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
VarBindingForm {
@@ -2246,6 +2266,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
user_ty: None,
source_info,
internal: false,
reuse_upvar: None,
is_block_tail: None,
local_info: Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(
BindingForm::RefForGuard,
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/build/mod.rs
Original file line number Diff line number Diff line change
@@ -926,6 +926,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&pat,
None,
Some((Some(&place), span)),
None,
);
let place_builder = PlaceBuilder::from(local);
unpack!(block = self.place_into_pattern(block, &pat, place_builder, false));
15 changes: 15 additions & 0 deletions compiler/rustc_mir_build/src/thir/cx/block.rs
Original file line number Diff line number Diff line change
@@ -116,6 +116,21 @@ impl<'tcx> Cx<'tcx> {
initializer: local.init.map(|init| self.mirror_expr(init)),
else_block,
lint_level: LintLevel::Explicit(local.hir_id),
reuse_upvar_slot: {
let tcx = self.tcx;
let body_owner = self.body_owner;
local.reuse_slot.map(|hir_id| {
tcx.upvars_mentioned(body_owner)
.iter()
.for_each(|upvars| {
assert!(upvars.contains_key(&hir_id));
});
UpvarRef {
closure_def_id: self.body_owner,
var_hir_id: LocalVarId(hir_id),
}
})
},
},
opt_destruction_scope: opt_dxn_ext,
};
Loading