reduce false positives of tail-expr-drop-order from consumed values
take 2 open up coroutines tweak the wordings the lint works up until 2021 We were missing one case, for ADTs, which was causing `Result` to yield incorrect results. only include field spans with significant types deduplicate and eliminate field spans switch to emit spans to impl Drops Co-authored-by: Niko Matsakis <nikomat@amazon.com> collect drops instead of taking liveness diff apply some suggestions and add explantory notes small fix on the cache let the query recurse through coroutine new suggestion format with extracted variable name fine-tune the drop span and messages bugfix on runtime borrows tweak message wording filter out ecosystem types earlier apply suggestions clippy check lint level at session level further restrict applicability of the lint translate bid into nop for stable mir detect cycle in type structure
This commit is contained in:
parent
70e814bd9e
commit
297b618944
58 changed files with 2015 additions and 538 deletions
|
@ -1,6 +1,5 @@
|
|||
//! See docs in build/expr/mod.rs
|
||||
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::*;
|
||||
use tracing::{debug, instrument};
|
||||
|
@ -9,6 +8,12 @@ use crate::build::expr::category::Category;
|
|||
use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
|
||||
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// Construct a temporary lifetime restricted to just the local scope
|
||||
pub(crate) fn local_temp_lifetime(&self) -> TempLifetime {
|
||||
let local_scope = self.local_scope();
|
||||
TempLifetime { temp_lifetime: Some(local_scope), backwards_incompatible: None }
|
||||
}
|
||||
|
||||
/// Returns an operand suitable for use until the end of the current
|
||||
/// scope expression.
|
||||
///
|
||||
|
@ -21,8 +26,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
block: BasicBlock,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<Operand<'tcx>> {
|
||||
let local_scope = self.local_scope();
|
||||
self.as_operand(block, Some(local_scope), expr_id, LocalInfo::Boring, NeedsTemporary::Maybe)
|
||||
self.as_operand(
|
||||
block,
|
||||
self.local_temp_lifetime(),
|
||||
expr_id,
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::Maybe,
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns an operand suitable for use until the end of the current scope expression and
|
||||
|
@ -80,8 +90,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
block: BasicBlock,
|
||||
expr: ExprId,
|
||||
) -> BlockAnd<Operand<'tcx>> {
|
||||
let local_scope = self.local_scope();
|
||||
self.as_call_operand(block, Some(local_scope), expr)
|
||||
self.as_call_operand(block, self.local_temp_lifetime(), expr)
|
||||
}
|
||||
|
||||
/// Compile `expr` into a value that can be used as an operand.
|
||||
|
@ -102,7 +111,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
pub(crate) fn as_operand(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
scope: Option<region::Scope>,
|
||||
scope: TempLifetime,
|
||||
expr_id: ExprId,
|
||||
local_info: LocalInfo<'tcx>,
|
||||
needs_temporary: NeedsTemporary,
|
||||
|
@ -146,7 +155,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
pub(crate) fn as_call_operand(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
scope: Option<region::Scope>,
|
||||
scope: TempLifetime,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<Operand<'tcx>> {
|
||||
let this = self;
|
||||
|
|
|
@ -6,7 +6,6 @@ use std::iter;
|
|||
use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::hir::place::{Projection as HirProjection, ProjectionKind as HirProjectionKind};
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::AssertKind::BoundsCheck;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::*;
|
||||
|
@ -598,7 +597,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
index: ExprId,
|
||||
mutability: Mutability,
|
||||
fake_borrow_temps: Option<&mut Vec<Local>>,
|
||||
temp_lifetime: Option<region::Scope>,
|
||||
temp_lifetime: TempLifetime,
|
||||
expr_span: Span,
|
||||
source_info: SourceInfo,
|
||||
) -> BlockAnd<PlaceBuilder<'tcx>> {
|
||||
|
|
|
@ -33,14 +33,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
expr_id: ExprId,
|
||||
) -> BlockAnd<Rvalue<'tcx>> {
|
||||
let local_scope = self.local_scope();
|
||||
self.as_rvalue(block, Some(local_scope), expr_id)
|
||||
self.as_rvalue(
|
||||
block,
|
||||
TempLifetime { temp_lifetime: Some(local_scope), backwards_incompatible: None },
|
||||
expr_id,
|
||||
)
|
||||
}
|
||||
|
||||
/// Compile `expr`, yielding an rvalue.
|
||||
pub(crate) fn as_rvalue(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
scope: Option<region::Scope>,
|
||||
scope: TempLifetime,
|
||||
expr_id: ExprId,
|
||||
) -> BlockAnd<Rvalue<'tcx>> {
|
||||
let this = self;
|
||||
|
@ -171,7 +175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
source_info,
|
||||
kind: StatementKind::StorageLive(result),
|
||||
});
|
||||
if let Some(scope) = scope {
|
||||
if let Some(scope) = scope.temp_lifetime {
|
||||
// schedule a shallow free of that memory, lest we unwind:
|
||||
this.schedule_drop_storage_and_value(expr_span, scope, result);
|
||||
}
|
||||
|
@ -445,7 +449,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
block = this.limit_capture_mutability(
|
||||
upvar_expr.span,
|
||||
upvar_expr.ty,
|
||||
scope,
|
||||
scope.temp_lifetime,
|
||||
block,
|
||||
arg,
|
||||
)
|
||||
|
@ -705,7 +709,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
value: ExprId,
|
||||
scope: Option<region::Scope>,
|
||||
scope: TempLifetime,
|
||||
outer_source_info: SourceInfo,
|
||||
) -> BlockAnd<Rvalue<'tcx>> {
|
||||
let this = self;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::middle::region::{Scope, ScopeData};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::*;
|
||||
|
@ -17,7 +16,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
pub(crate) fn as_temp(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
temp_lifetime: Option<region::Scope>,
|
||||
temp_lifetime: TempLifetime,
|
||||
expr_id: ExprId,
|
||||
mutability: Mutability,
|
||||
) -> BlockAnd<Local> {
|
||||
|
@ -31,7 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
fn as_temp_inner(
|
||||
&mut self,
|
||||
mut block: BasicBlock,
|
||||
temp_lifetime: Option<region::Scope>,
|
||||
temp_lifetime: TempLifetime,
|
||||
expr_id: ExprId,
|
||||
mutability: Mutability,
|
||||
) -> BlockAnd<Local> {
|
||||
|
@ -47,8 +46,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let expr_ty = expr.ty;
|
||||
let deduplicate_temps =
|
||||
this.fixed_temps_scope.is_some() && this.fixed_temps_scope == temp_lifetime;
|
||||
let deduplicate_temps = this.fixed_temps_scope.is_some()
|
||||
&& this.fixed_temps_scope == temp_lifetime.temp_lifetime;
|
||||
let temp = if deduplicate_temps && let Some(temp_index) = this.fixed_temps.get(&expr_id) {
|
||||
*temp_index
|
||||
} else {
|
||||
|
@ -76,7 +75,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
LocalInfo::BlockTailTemp(tail_info)
|
||||
}
|
||||
|
||||
_ if let Some(Scope { data: ScopeData::IfThenRescope, id }) = temp_lifetime => {
|
||||
_ if let Some(Scope { data: ScopeData::IfThenRescope, id }) =
|
||||
temp_lifetime.temp_lifetime =>
|
||||
{
|
||||
LocalInfo::IfThenRescopeTemp {
|
||||
if_then: HirId { owner: this.hir_id.owner, local_id: id },
|
||||
}
|
||||
|
@ -117,7 +118,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// Anything with a shorter lifetime (e.g the `&foo()` in
|
||||
// `bar(&foo())` or anything within a block will keep the
|
||||
// regular drops just like runtime code.
|
||||
if let Some(temp_lifetime) = temp_lifetime {
|
||||
if let Some(temp_lifetime) = temp_lifetime.temp_lifetime {
|
||||
this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Storage);
|
||||
}
|
||||
}
|
||||
|
@ -125,10 +126,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
|
||||
block = this.expr_into_dest(temp_place, block, expr_id).into_block();
|
||||
|
||||
if let Some(temp_lifetime) = temp_lifetime {
|
||||
if let Some(temp_lifetime) = temp_lifetime.temp_lifetime {
|
||||
this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Value);
|
||||
}
|
||||
|
||||
if let Some(backwards_incompatible) = temp_lifetime.backwards_incompatible {
|
||||
this.schedule_backwards_incompatible_drop(expr_span, backwards_incompatible, temp);
|
||||
}
|
||||
|
||||
block.and(temp)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// (#66975) Source could be a const of type `!`, so has to
|
||||
// exist in the generated MIR.
|
||||
unpack!(
|
||||
block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut)
|
||||
block =
|
||||
this.as_temp(block, this.local_temp_lifetime(), source, Mutability::Mut)
|
||||
);
|
||||
|
||||
// This is an optimization. If the expression was a call then we already have an
|
||||
|
@ -321,7 +322,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let is_union = adt_def.is_union();
|
||||
let active_field_index = is_union.then(|| fields[0].name);
|
||||
|
||||
let scope = this.local_scope();
|
||||
let scope = this.local_temp_lifetime();
|
||||
|
||||
// first process the set of fields that were provided
|
||||
// (evaluating them in order given by user)
|
||||
|
@ -333,7 +334,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
unpack!(
|
||||
block = this.as_operand(
|
||||
block,
|
||||
Some(scope),
|
||||
scope,
|
||||
f.expr,
|
||||
LocalInfo::AggregateTemp,
|
||||
NeedsTemporary::Maybe,
|
||||
|
@ -548,15 +549,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
ExprKind::Yield { value } => {
|
||||
let scope = this.local_scope();
|
||||
let scope = this.local_temp_lifetime();
|
||||
let value = unpack!(
|
||||
block = this.as_operand(
|
||||
block,
|
||||
Some(scope),
|
||||
value,
|
||||
LocalInfo::Boring,
|
||||
NeedsTemporary::No
|
||||
)
|
||||
block =
|
||||
this.as_operand(block, scope, value, LocalInfo::Boring, NeedsTemporary::No)
|
||||
);
|
||||
let resume = this.cfg.start_new_block();
|
||||
this.cfg.terminate(block, source_info, TerminatorKind::Yield {
|
||||
|
|
|
@ -172,8 +172,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
None
|
||||
};
|
||||
|
||||
let temp =
|
||||
unpack!(block = this.as_temp(block, statement_scope, expr_id, Mutability::Not));
|
||||
let temp = unpack!(
|
||||
block = this.as_temp(
|
||||
block,
|
||||
TempLifetime {
|
||||
temp_lifetime: statement_scope,
|
||||
backwards_incompatible: None
|
||||
},
|
||||
expr_id,
|
||||
Mutability::Not
|
||||
)
|
||||
);
|
||||
|
||||
if let Some(span) = adjusted_span {
|
||||
this.local_decls[temp].source_info.span = span;
|
||||
|
|
|
@ -202,8 +202,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// Increment the decision depth, in case we encounter boolean expressions
|
||||
// further down.
|
||||
this.mcdc_increment_depth_if_enabled();
|
||||
let place =
|
||||
unpack!(block = this.as_temp(block, Some(temp_scope), expr_id, mutability));
|
||||
let place = unpack!(
|
||||
block = this.as_temp(
|
||||
block,
|
||||
TempLifetime {
|
||||
temp_lifetime: Some(temp_scope),
|
||||
backwards_incompatible: None
|
||||
},
|
||||
expr_id,
|
||||
mutability
|
||||
)
|
||||
);
|
||||
this.mcdc_decrement_depth_if_enabled();
|
||||
|
||||
let operand = Operand::Move(Place::from(place));
|
||||
|
|
|
@ -89,7 +89,7 @@ use rustc_index::{IndexSlice, IndexVec};
|
|||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::{ExprId, LintLevel};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_middle::{bug, span_bug, ty};
|
||||
use rustc_session::lint::Level;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
|
@ -151,6 +151,9 @@ struct DropData {
|
|||
|
||||
/// Whether this is a value Drop or a StorageDead.
|
||||
kind: DropKind,
|
||||
|
||||
/// Whether this is a backwards-incompatible drop lint
|
||||
backwards_incompatible_lint: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -274,8 +277,12 @@ impl DropTree {
|
|||
// represents the block in the tree that should be jumped to once all
|
||||
// of the required drops have been performed.
|
||||
let fake_source_info = SourceInfo::outermost(DUMMY_SP);
|
||||
let fake_data =
|
||||
DropData { source_info: fake_source_info, local: Local::MAX, kind: DropKind::Storage };
|
||||
let fake_data = DropData {
|
||||
source_info: fake_source_info,
|
||||
local: Local::MAX,
|
||||
kind: DropKind::Storage,
|
||||
backwards_incompatible_lint: false,
|
||||
};
|
||||
let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]);
|
||||
Self { drops, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() }
|
||||
}
|
||||
|
@ -763,7 +770,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let local =
|
||||
place.as_local().unwrap_or_else(|| bug!("projection in tail call args"));
|
||||
|
||||
Some(DropData { source_info, local, kind: DropKind::Value })
|
||||
Some(DropData {
|
||||
source_info,
|
||||
local,
|
||||
kind: DropKind::Value,
|
||||
backwards_incompatible_lint: false,
|
||||
})
|
||||
}
|
||||
Operand::Constant(_) => None,
|
||||
})
|
||||
|
@ -1019,9 +1031,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
if local.index() <= self.arg_count {
|
||||
span_bug!(
|
||||
span,
|
||||
"`schedule_drop` called with local {:?} and arg_count {}",
|
||||
"`schedule_drop` called with body argument {:?} \
|
||||
but its storage does not require a drop",
|
||||
local,
|
||||
self.arg_count,
|
||||
)
|
||||
}
|
||||
false
|
||||
|
@ -1089,6 +1101,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
source_info: SourceInfo { span: scope_end, scope: scope.source_scope },
|
||||
local,
|
||||
kind: drop_kind,
|
||||
backwards_incompatible_lint: false,
|
||||
});
|
||||
|
||||
return;
|
||||
|
@ -1098,6 +1111,45 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
span_bug!(span, "region scope {:?} not in scope to drop {:?}", region_scope, local);
|
||||
}
|
||||
|
||||
/// Schedule emission of a backwards incompatible drop lint hint.
|
||||
/// Applicable only to temporary values for now.
|
||||
pub(crate) fn schedule_backwards_incompatible_drop(
|
||||
&mut self,
|
||||
span: Span,
|
||||
region_scope: region::Scope,
|
||||
local: Local,
|
||||
) {
|
||||
if !self.local_decls[local].ty.has_significant_drop(self.tcx, ty::TypingEnv {
|
||||
typing_mode: ty::TypingMode::non_body_analysis(),
|
||||
param_env: self.param_env,
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
for scope in self.scopes.scopes.iter_mut().rev() {
|
||||
// Since we are inserting linting MIR statement, we have to invalidate the caches
|
||||
scope.invalidate_cache();
|
||||
if scope.region_scope == region_scope {
|
||||
let region_scope_span = region_scope.span(self.tcx, self.region_scope_tree);
|
||||
let scope_end = self.tcx.sess.source_map().end_point(region_scope_span);
|
||||
|
||||
scope.drops.push(DropData {
|
||||
source_info: SourceInfo { span: scope_end, scope: scope.source_scope },
|
||||
local,
|
||||
kind: DropKind::Value,
|
||||
backwards_incompatible_lint: true,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
span_bug!(
|
||||
span,
|
||||
"region scope {:?} not in scope to drop {:?} for linting",
|
||||
region_scope,
|
||||
local
|
||||
);
|
||||
}
|
||||
|
||||
/// Indicates that the "local operand" stored in `local` is
|
||||
/// *moved* at some point during execution (see `local_scope` for
|
||||
/// more information about what a "local operand" is -- in short,
|
||||
|
@ -1378,16 +1430,25 @@ fn build_scope_drops<'tcx>(
|
|||
continue;
|
||||
}
|
||||
|
||||
unwind_drops.add_entry_point(block, unwind_to);
|
||||
|
||||
let next = cfg.start_new_block();
|
||||
cfg.terminate(block, source_info, TerminatorKind::Drop {
|
||||
place: local.into(),
|
||||
target: next,
|
||||
unwind: UnwindAction::Continue,
|
||||
replace: false,
|
||||
});
|
||||
block = next;
|
||||
if drop_data.backwards_incompatible_lint {
|
||||
cfg.push(block, Statement {
|
||||
source_info,
|
||||
kind: StatementKind::BackwardIncompatibleDropHint {
|
||||
place: Box::new(local.into()),
|
||||
reason: BackwardIncompatibleDropReason::Edition2024,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
unwind_drops.add_entry_point(block, unwind_to);
|
||||
let next = cfg.start_new_block();
|
||||
cfg.terminate(block, source_info, TerminatorKind::Drop {
|
||||
place: local.into(),
|
||||
target: next,
|
||||
unwind: UnwindAction::Continue,
|
||||
replace: false,
|
||||
});
|
||||
block = next;
|
||||
}
|
||||
}
|
||||
DropKind::Storage => {
|
||||
if storage_dead_on_unwind {
|
||||
|
|
|
@ -23,7 +23,6 @@ use tracing::{debug, info, instrument, trace};
|
|||
|
||||
use crate::errors;
|
||||
use crate::thir::cx::Cx;
|
||||
use crate::thir::cx::region::Scope;
|
||||
use crate::thir::util::UserAnnotatedTyHelpers;
|
||||
|
||||
impl<'tcx> Cx<'tcx> {
|
||||
|
@ -240,7 +239,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
fn mirror_expr_cast(
|
||||
&mut self,
|
||||
source: &'tcx hir::Expr<'tcx>,
|
||||
temp_lifetime: Option<Scope>,
|
||||
temp_lifetime: TempLifetime,
|
||||
span: Span,
|
||||
) -> ExprKind<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
|
@ -325,7 +324,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let expr_ty = self.typeck_results().expr_ty(expr);
|
||||
let temp_lifetime =
|
||||
let (temp_lifetime, backwards_incompatible) =
|
||||
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
|
||||
|
||||
let kind = match expr.kind {
|
||||
|
@ -361,7 +360,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e));
|
||||
let tupled_args = Expr {
|
||||
ty: Ty::new_tup_from_iter(tcx, arg_tys),
|
||||
temp_lifetime,
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
span: expr.span,
|
||||
kind: ExprKind::Tuple { fields: self.mirror_exprs(args) },
|
||||
};
|
||||
|
@ -391,7 +390,10 @@ impl<'tcx> Cx<'tcx> {
|
|||
&& let [value] = args
|
||||
{
|
||||
return Expr {
|
||||
temp_lifetime,
|
||||
temp_lifetime: TempLifetime {
|
||||
temp_lifetime,
|
||||
backwards_incompatible,
|
||||
},
|
||||
ty: expr_ty,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Box { value: self.mirror_expr(value) },
|
||||
|
@ -811,13 +813,13 @@ impl<'tcx> Cx<'tcx> {
|
|||
},
|
||||
hir::ExprKind::Loop(body, ..) => {
|
||||
let block_ty = self.typeck_results().node_type(body.hir_id);
|
||||
let temp_lifetime = self
|
||||
let (temp_lifetime, backwards_incompatible) = self
|
||||
.rvalue_scopes
|
||||
.temporary_scope(self.region_scope_tree, body.hir_id.local_id);
|
||||
let block = self.mirror_block(body);
|
||||
let body = self.thir.exprs.push(Expr {
|
||||
ty: block_ty,
|
||||
temp_lifetime,
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
span: self.thir[block].span,
|
||||
kind: ExprKind::Block { block },
|
||||
});
|
||||
|
@ -838,13 +840,17 @@ impl<'tcx> Cx<'tcx> {
|
|||
expr, cast_ty.hir_id, user_ty,
|
||||
);
|
||||
|
||||
let cast = self.mirror_expr_cast(source, temp_lifetime, expr.span);
|
||||
let cast = self.mirror_expr_cast(
|
||||
source,
|
||||
TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
expr.span,
|
||||
);
|
||||
|
||||
if let Some(user_ty) = user_ty {
|
||||
// NOTE: Creating a new Expr and wrapping a Cast inside of it may be
|
||||
// inefficient, revisit this when performance becomes an issue.
|
||||
let cast_expr = self.thir.exprs.push(Expr {
|
||||
temp_lifetime,
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
ty: expr_ty,
|
||||
span: expr.span,
|
||||
kind: cast,
|
||||
|
@ -887,7 +893,12 @@ impl<'tcx> Cx<'tcx> {
|
|||
hir::ExprKind::Err(_) => unreachable!("cannot lower a `hir::ExprKind::Err` to THIR"),
|
||||
};
|
||||
|
||||
Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
|
||||
Expr {
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
ty: expr_ty,
|
||||
span: expr.span,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
fn user_args_applied_to_res(
|
||||
|
@ -931,7 +942,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
span: Span,
|
||||
overloaded_callee: Option<Ty<'tcx>>,
|
||||
) -> Expr<'tcx> {
|
||||
let temp_lifetime =
|
||||
let (temp_lifetime, backwards_incompatible) =
|
||||
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
|
||||
let (ty, user_ty) = match overloaded_callee {
|
||||
Some(fn_def) => (fn_def, None),
|
||||
|
@ -952,7 +963,12 @@ impl<'tcx> Cx<'tcx> {
|
|||
)
|
||||
}
|
||||
};
|
||||
Expr { temp_lifetime, ty, span, kind: ExprKind::ZstLiteral { user_ty } }
|
||||
Expr {
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
ty,
|
||||
span,
|
||||
kind: ExprKind::ZstLiteral { user_ty },
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId {
|
||||
|
@ -1025,7 +1041,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
Res::Def(DefKind::Static { .. }, id) => {
|
||||
// this is &raw for extern static or static mut, and & for other statics
|
||||
let ty = self.tcx.static_ptr_ty(id, self.typing_env());
|
||||
let temp_lifetime = self
|
||||
let (temp_lifetime, backwards_incompatible) = self
|
||||
.rvalue_scopes
|
||||
.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
|
||||
let kind = if self.tcx.is_thread_local_static(id) {
|
||||
|
@ -1035,7 +1051,12 @@ impl<'tcx> Cx<'tcx> {
|
|||
ExprKind::StaticRef { alloc_id, ty, def_id: id }
|
||||
};
|
||||
ExprKind::Deref {
|
||||
arg: self.thir.exprs.push(Expr { ty, temp_lifetime, span: expr.span, kind }),
|
||||
arg: self.thir.exprs.push(Expr {
|
||||
ty,
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
span: expr.span,
|
||||
kind,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1106,13 +1127,13 @@ impl<'tcx> Cx<'tcx> {
|
|||
|
||||
// construct the complete expression `foo()` for the overloaded call,
|
||||
// which will yield the &T type
|
||||
let temp_lifetime =
|
||||
let (temp_lifetime, backwards_incompatible) =
|
||||
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
|
||||
let fun = self.method_callee(expr, span, overloaded_callee);
|
||||
let fun = self.thir.exprs.push(fun);
|
||||
let fun_ty = self.thir[fun].ty;
|
||||
let ref_expr = self.thir.exprs.push(Expr {
|
||||
temp_lifetime,
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
ty: ref_ty,
|
||||
span,
|
||||
kind: ExprKind::Call { ty: fun_ty, fun, args, from_hir_call: false, fn_span: span },
|
||||
|
@ -1127,7 +1148,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
closure_expr: &'tcx hir::Expr<'tcx>,
|
||||
place: HirPlace<'tcx>,
|
||||
) -> Expr<'tcx> {
|
||||
let temp_lifetime = self
|
||||
let (temp_lifetime, backwards_incompatible) = self
|
||||
.rvalue_scopes
|
||||
.temporary_scope(self.region_scope_tree, closure_expr.hir_id.local_id);
|
||||
let var_ty = place.base_ty;
|
||||
|
@ -1143,7 +1164,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
};
|
||||
|
||||
let mut captured_place_expr = Expr {
|
||||
temp_lifetime,
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
ty: var_ty,
|
||||
span: closure_expr.span,
|
||||
kind: self.convert_var(var_hir_id),
|
||||
|
@ -1168,8 +1189,12 @@ impl<'tcx> Cx<'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
captured_place_expr =
|
||||
Expr { temp_lifetime, ty: proj.ty, span: closure_expr.span, kind };
|
||||
captured_place_expr = Expr {
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
ty: proj.ty,
|
||||
span: closure_expr.span,
|
||||
kind,
|
||||
};
|
||||
}
|
||||
|
||||
captured_place_expr
|
||||
|
@ -1184,7 +1209,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
let upvar_capture = captured_place.info.capture_kind;
|
||||
let captured_place_expr =
|
||||
self.convert_captured_hir_place(closure_expr, captured_place.place.clone());
|
||||
let temp_lifetime = self
|
||||
let (temp_lifetime, backwards_incompatible) = self
|
||||
.rvalue_scopes
|
||||
.temporary_scope(self.region_scope_tree, closure_expr.hir_id.local_id);
|
||||
|
||||
|
@ -1201,7 +1226,7 @@ impl<'tcx> Cx<'tcx> {
|
|||
}
|
||||
};
|
||||
Expr {
|
||||
temp_lifetime,
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
ty: upvar_ty,
|
||||
span: closure_expr.span,
|
||||
kind: ExprKind::Borrow {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue