提交 8430042a 编写于 作者: B bors

Auto merge of #39066 - arielb1:lifetime-extension-test, r=nikomatsakis

End temporary lifetimes being extended by `let X: &_` hints

cc #39283

r? @nikomatsakis
......@@ -23,7 +23,6 @@
use middle::free_region::FreeRegionMap;
use middle::mem_categorization as mc;
use middle::mem_categorization::McResult;
use middle::region::CodeExtent;
use middle::lang_items;
use mir::tcx::LvalueTy;
use ty::subst::{Kind, Subst, Substs};
......@@ -1622,10 +1621,6 @@ pub fn is_method_call(&self, id: ast::NodeId) -> bool {
self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
}
pub fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
self.tcx.region_maps.temporary_scope(rvalue_id)
}
pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
}
......
......@@ -296,6 +296,7 @@ pub fn consume_body(&mut self, body: &hir::Body) {
arg.id,
arg.pat.span,
fn_body_scope_r, // Args live only as long as the fn body.
fn_body_scope_r,
arg_ty);
self.walk_irrefutable_pat(arg_cmt, &arg.pat);
......
......@@ -88,7 +88,8 @@
#[derive(Clone, PartialEq)]
pub enum Categorization<'tcx> {
Rvalue(&'tcx ty::Region), // temporary val, argument is its scope
// temporary val, argument is its scope
Rvalue(&'tcx ty::Region, &'tcx ty::Region),
StaticItem,
Upvar(Upvar), // upvar referenced by closure env
Local(ast::NodeId), // local variable
......@@ -760,11 +761,18 @@ fn env_deref(&self,
/// Returns the lifetime of a temporary created by expr with id `id`.
/// This could be `'static` if `id` is part of a constant expression.
pub fn temporary_scope(&self, id: ast::NodeId) -> &'tcx ty::Region {
self.tcx().mk_region(match self.infcx.temporary_scope(id) {
pub fn temporary_scope(&self, id: ast::NodeId) -> (&'tcx ty::Region, &'tcx ty::Region)
{
let (scope, old_scope) =
self.tcx().region_maps.old_and_new_temporary_scope(id);
(self.tcx().mk_region(match scope {
Some(scope) => ty::ReScope(scope),
None => ty::ReStatic
}),
self.tcx().mk_region(match old_scope {
Some(scope) => ty::ReScope(scope),
None => ty::ReStatic
})
}))
}
pub fn cat_rvalue_node(&self,
......@@ -785,12 +793,13 @@ pub fn cat_rvalue_node(&self,
// Compute maximum lifetime of this rvalue. This is 'static if
// we can promote to a constant, otherwise equal to enclosing temp
// lifetime.
let re = if promotable {
self.tcx().mk_region(ty::ReStatic)
let (re, old_re) = if promotable {
(self.tcx().mk_region(ty::ReStatic),
self.tcx().mk_region(ty::ReStatic))
} else {
self.temporary_scope(id)
};
let ret = self.cat_rvalue(id, span, re, expr_ty);
let ret = self.cat_rvalue(id, span, re, old_re, expr_ty);
debug!("cat_rvalue_node ret {:?}", ret);
ret
}
......@@ -799,11 +808,12 @@ pub fn cat_rvalue(&self,
cmt_id: ast::NodeId,
span: Span,
temp_scope: &'tcx ty::Region,
old_temp_scope: &'tcx ty::Region,
expr_ty: Ty<'tcx>) -> cmt<'tcx> {
let ret = Rc::new(cmt_ {
id:cmt_id,
span:span,
cat:Categorization::Rvalue(temp_scope),
cat:Categorization::Rvalue(temp_scope, old_temp_scope),
mutbl:McDeclared,
ty:expr_ty,
note: NoteNone
......@@ -1386,7 +1396,9 @@ impl<'tcx> fmt::Debug for Categorization<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Categorization::StaticItem => write!(f, "static"),
Categorization::Rvalue(r) => write!(f, "rvalue({:?})", r),
Categorization::Rvalue(r, or) => {
write!(f, "rvalue({:?}, {:?})", r, or)
}
Categorization::Local(id) => {
let name = ty::tls::with(|tcx| tcx.local_var_name_str(id));
write!(f, "local({})", name)
......
......@@ -272,6 +272,13 @@ pub struct RegionMaps {
/// block (see `terminating_scopes`).
rvalue_scopes: RefCell<NodeMap<CodeExtent>>,
/// Records the value of rvalue scopes before they were shrunk by
/// #36082, for error reporting.
///
/// FIXME: this should be temporary. Remove this by 1.18.0 or
/// so.
shrunk_rvalue_scopes: RefCell<NodeMap<CodeExtent>>,
/// Encodes the hierarchy of fn bodies. Every fn body (including
/// closures) forms its own distinct region hierarchy, rooted in
/// the block that is the fn body. This map points from the id of
......@@ -419,11 +426,7 @@ pub fn each_var_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, &CodeExten
e(child, parent)
}
}
pub fn each_rvalue_scope<E>(&self, mut e:E) where E: FnMut(&ast::NodeId, &CodeExtent) {
for (child, parent) in self.rvalue_scopes.borrow().iter() {
e(child, parent)
}
}
/// Records that `sub_fn` is defined within `sup_fn`. These ids
/// should be the id of the block that is the fn body, which is
/// also the root of the region hierarchy for that fn.
......@@ -457,6 +460,12 @@ fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) {
self.rvalue_scopes.borrow_mut().insert(var, lifetime);
}
fn record_shrunk_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) {
debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.node_id(self));
self.shrunk_rvalue_scopes.borrow_mut().insert(var, lifetime);
}
pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
//! Returns the narrowest scope that encloses `id`, if any.
self.scope_map.borrow()[id.0 as usize].into_option()
......@@ -476,6 +485,30 @@ pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent {
}
}
pub fn temporary_scope2(&self, expr_id: ast::NodeId) -> (Option<CodeExtent>, bool) {
let temporary_scope = self.temporary_scope(expr_id);
let was_shrunk = match self.shrunk_rvalue_scopes.borrow().get(&expr_id) {
Some(&s) => {
info!("temporary_scope2({:?}, scope={:?}, shrunk={:?})",
expr_id, temporary_scope, s);
temporary_scope != Some(s)
}
_ => false
};
info!("temporary_scope2({:?}) - was_shrunk={:?}", expr_id, was_shrunk);
(temporary_scope, was_shrunk)
}
pub fn old_and_new_temporary_scope(&self, expr_id: ast::NodeId) ->
(Option<CodeExtent>, Option<CodeExtent>)
{
let temporary_scope = self.temporary_scope(expr_id);
(temporary_scope,
self.shrunk_rvalue_scopes
.borrow().get(&expr_id).cloned()
.or(temporary_scope))
}
pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option<CodeExtent> {
//! Returns the scope when temp created by expr_id will be cleaned up
......@@ -929,8 +962,10 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>,
let is_borrow =
if let Some(ref ty) = local.ty { is_borrowed_ty(&ty) } else { false };
if is_binding_pat(&local.pat) || is_borrow {
record_rvalue_scope(visitor, &expr, blk_scope);
if is_binding_pat(&local.pat) {
record_rvalue_scope(visitor, &expr, blk_scope, false);
} else if is_borrow {
record_rvalue_scope(visitor, &expr, blk_scope, true);
}
}
......@@ -995,7 +1030,7 @@ fn record_rvalue_scope_if_borrow_expr(visitor: &mut RegionResolutionVisitor,
match expr.node {
hir::ExprAddrOf(_, ref subexpr) => {
record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id);
record_rvalue_scope(visitor, &subexpr, blk_id);
record_rvalue_scope(visitor, &subexpr, blk_id, false);
}
hir::ExprStruct(_, ref fields, _) => {
for field in fields {
......@@ -1040,7 +1075,8 @@ fn record_rvalue_scope_if_borrow_expr(visitor: &mut RegionResolutionVisitor,
/// Note: ET is intended to match "rvalues or lvalues based on rvalues".
fn record_rvalue_scope<'a>(visitor: &mut RegionResolutionVisitor,
expr: &'a hir::Expr,
blk_scope: CodeExtent) {
blk_scope: CodeExtent,
is_shrunk: bool) {
let mut expr = expr;
loop {
// Note: give all the expressions matching `ET` with the
......@@ -1048,7 +1084,12 @@ fn record_rvalue_scope<'a>(visitor: &mut RegionResolutionVisitor,
// because in trans if we must compile e.g. `*rvalue()`
// into a temporary, we request the temporary scope of the
// outer expression.
visitor.region_maps.record_rvalue_scope(expr.id, blk_scope);
if is_shrunk {
// this changed because of #36082
visitor.region_maps.record_shrunk_rvalue_scope(expr.id, blk_scope);
} else {
visitor.region_maps.record_rvalue_scope(expr.id, blk_scope);
}
match expr.node {
hir::ExprAddrOf(_, ref subexpr) |
......@@ -1225,6 +1266,7 @@ pub fn resolve_crate(sess: &Session, map: &hir_map::Map) -> RegionMaps {
scope_map: RefCell::new(vec![]),
var_map: RefCell::new(NodeMap()),
rvalue_scopes: RefCell::new(NodeMap()),
shrunk_rvalue_scopes: RefCell::new(NodeMap()),
fn_tree: RefCell::new(NodeMap()),
};
let root_extent = maps.bogus_code_extent(
......
......@@ -108,7 +108,7 @@ fn scope(&self, cmt: &mc::cmt<'tcx>) -> &'tcx ty::Region {
//! rooting etc, and presuming `cmt` is not mutated.
match cmt.cat {
Categorization::Rvalue(temp_scope) => {
Categorization::Rvalue(temp_scope, _) => {
temp_scope
}
Categorization::Upvar(..) => {
......
......@@ -967,7 +967,7 @@ pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<
err_mutbl => self.note_and_explain_mutbl_error(db, &err, &error_span),
err_out_of_scope(super_scope, sub_scope, cause) => {
let (value_kind, value_msg) = match err.cmt.cat {
mc::Categorization::Rvalue(_) =>
mc::Categorization::Rvalue(..) =>
("temporary value", "temporary value created here"),
_ =>
("borrowed value", "borrow occurs here")
......@@ -1061,6 +1061,17 @@ pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<
if let Some(_) = statement_scope_span(self.tcx, super_scope) {
db.note("consider using a `let` binding to increase its lifetime");
}
match err.cmt.cat {
mc::Categorization::Rvalue(r, or) if r != or => {
db.note("\
before rustc 1.16, this temporary lived longer - see issue #39283 \
(https://github.com/rust-lang/rust/issues/39283)");
}
_ => {}
}
}
err_borrowed_pointer_too_short(loan_scope, ptr_scope) => {
......
......@@ -26,7 +26,8 @@ pub fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> {
let this = self;
let Expr { ty, temp_lifetime: _, span, kind } = expr;
let Expr { ty, temp_lifetime: _, temp_lifetime_was_shrunk: _, span, kind }
= expr;
match kind {
ExprKind::Scope { extent: _, value } =>
this.as_constant(value),
......
......@@ -39,6 +39,13 @@ fn expr_as_temp(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<
let expr_span = expr.span;
let source_info = this.source_info(expr_span);
if expr.temp_lifetime_was_shrunk && this.hir.needs_drop(expr_ty) {
this.hir.tcx().sess.span_warn(
expr_span,
"this temporary used to live longer - see issue #39283 \
(https://github.com/rust-lang/rust/issues/39283)");
}
if temp_lifetime.is_some() {
this.cfg.push(block, Statement {
source_info: source_info,
......
......@@ -83,10 +83,11 @@ pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
block: &'tcx hir::Block)
-> ExprRef<'tcx> {
let block_ty = cx.tables().node_id_to_type(block.id);
let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id);
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps.temporary_scope2(block.id);
let expr = Expr {
ty: block_ty,
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
span: block.span,
kind: ExprKind::Block { body: block },
};
......
......@@ -27,7 +27,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
type Output = Expr<'tcx>;
fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
let temp_lifetime = cx.tcx.region_maps.temporary_scope(self.id);
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps.temporary_scope2(self.id);
let expr_extent = cx.tcx.region_maps.node_extent(self.id);
debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
......@@ -45,6 +45,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
Some((ty::adjustment::Adjust::ReifyFnPointer, adjusted_ty)) => {
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: adjusted_ty,
span: self.span,
kind: ExprKind::ReifyFnPointer { source: expr.to_ref() },
......@@ -53,6 +54,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
Some((ty::adjustment::Adjust::UnsafeFnPointer, adjusted_ty)) => {
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: adjusted_ty,
span: self.span,
kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() },
......@@ -61,6 +63,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
Some((ty::adjustment::Adjust::NeverToAny, adjusted_ty)) => {
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: adjusted_ty,
span: self.span,
kind: ExprKind::NeverToAny { source: expr.to_ref() },
......@@ -69,6 +72,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
Some((ty::adjustment::Adjust::MutToConstPointer, adjusted_ty)) => {
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: adjusted_ty,
span: self.span,
kind: ExprKind::Cast { source: expr.to_ref() },
......@@ -98,6 +102,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: cx.tcx.mk_ref(region,
ty::TypeAndMut {
ty: expr.ty,
......@@ -123,6 +128,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
};
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: adjusted_ty,
span: self.span,
kind: kind,
......@@ -135,6 +141,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
ty::adjustment::AutoBorrow::Ref(r, m) => {
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: adjusted_ty,
span: self.span,
kind: ExprKind::Borrow {
......@@ -152,6 +159,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
let region = cx.tcx.mk_region(region);
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: cx.tcx.mk_ref(region,
ty::TypeAndMut {
ty: expr.ty,
......@@ -166,6 +174,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
};
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: adjusted_ty,
span: self.span,
kind: ExprKind::Cast { source: expr.to_ref() },
......@@ -177,6 +186,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
if unsize {
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: adjusted_ty,
span: self.span,
kind: ExprKind::Unsize { source: expr.to_ref() },
......@@ -188,6 +198,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
// Next, wrap this up in the expr's scope.
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: expr.ty,
span: self.span,
kind: ExprKind::Scope {
......@@ -200,6 +211,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> {
if let Some(extent) = cx.tcx.region_maps.opt_destruction_extent(self.id) {
expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: expr.ty,
span: self.span,
kind: ExprKind::Scope {
......@@ -218,7 +230,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr)
-> Expr<'tcx> {
let expr_ty = cx.tables().expr_ty(expr);
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps.temporary_scope2(expr.id);
let kind = match expr.node {
// Here comes the interesting stuff:
......@@ -260,6 +272,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
let tupled_args = Expr {
ty: sig.inputs()[1],
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
span: expr.span,
kind: ExprKind::Tuple { fields: args.iter().map(ToRef::to_ref).collect() },
};
......@@ -670,6 +683,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: expr_ty,
span: expr.span,
kind: kind,
......@@ -681,9 +695,10 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
method_call: ty::MethodCall)
-> Expr<'tcx> {
let callee = cx.tables().method_map[&method_call];
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps.temporary_scope2(expr.id);
Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: callee.ty,
span: expr.span,
kind: ExprKind::Literal {
......@@ -761,7 +776,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr,
def: Def)
-> ExprKind<'tcx> {
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps.temporary_scope2(expr.id);
match def {
Def::Local(def_id) => {
......@@ -813,15 +828,17 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
Expr {
ty: closure_ty,
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
span: expr.span,
kind: ExprKind::Deref {
arg: Expr {
ty: ref_closure_ty,
temp_lifetime: temp_lifetime,
span: expr.span,
kind: ExprKind::SelfRef,
}
.to_ref(),
ty: ref_closure_ty,
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
span: expr.span,
kind: ExprKind::SelfRef,
}
.to_ref(),
},
}
}
......@@ -834,15 +851,16 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
Expr {
ty: closure_ty,
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
span: expr.span,
kind: ExprKind::Deref {
arg: Expr {
ty: ref_closure_ty,
temp_lifetime: temp_lifetime,
span: expr.span,
kind: ExprKind::SelfRef,
}
.to_ref(),
ty: ref_closure_ty,
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
span: expr.span,
kind: ExprKind::SelfRef,
}.to_ref(),
},
}
}
......@@ -850,6 +868,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
Expr {
ty: closure_ty,
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
span: expr.span,
kind: ExprKind::SelfRef,
}
......@@ -879,16 +898,16 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
ty::UpvarCapture::ByRef(borrow) => {
ExprKind::Deref {
arg: Expr {
temp_lifetime: temp_lifetime,
ty: cx.tcx.mk_ref(borrow.region,
ty::TypeAndMut {
ty: var_ty,
mutbl: borrow.kind.to_mutbl_lossy(),
}),
span: expr.span,
kind: field_kind,
}
.to_ref(),
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: cx.tcx.mk_ref(borrow.region,
ty::TypeAndMut {
ty: var_ty,
mutbl: borrow.kind.to_mutbl_lossy(),
}),
span: expr.span,
kind: field_kind,
}.to_ref(),
}
}
}
......@@ -944,7 +963,8 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
PassArgs::ByRef => {
let region = cx.tcx.node_scope_region(expr.id);
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
let (temp_lifetime, was_shrunk) =
cx.tcx.region_maps.temporary_scope2(expr.id);
argrefs.extend(args.iter()
.map(|arg| {
let arg_ty = cx.tables().expr_ty_adjusted(arg);
......@@ -954,16 +974,17 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
mutbl: hir::MutImmutable,
});
Expr {
temp_lifetime: temp_lifetime,
ty: adjusted_ty,
span: expr.span,
kind: ExprKind::Borrow {
region: region,
borrow_kind: BorrowKind::Shared,
arg: arg.to_ref(),
},
}
.to_ref()
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: adjusted_ty,
span: expr.span,
kind: ExprKind::Borrow {
region: region,
borrow_kind: BorrowKind::Shared,
arg: arg.to_ref(),
},
}
.to_ref()
}))
}
}
......@@ -995,10 +1016,11 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// construct the complete expression `foo()` for the overloaded call,
// which will yield the &T type
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps.temporary_scope2(expr.id);
let ref_kind = overloaded_operator(cx, expr, method_call, pass_args, receiver, args);
let ref_expr = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: ref_ty,
span: expr.span,
kind: ref_kind,
......@@ -1019,10 +1041,11 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
closure_expr_id: closure_expr.id,
};
let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap();
let temp_lifetime = cx.tcx.region_maps.temporary_scope(closure_expr.id);
let (temp_lifetime, was_shrunk) = cx.tcx.region_maps.temporary_scope2(closure_expr.id);
let var_ty = cx.tables().node_id_to_type(id_var);
let captured_var = Expr {
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: var_ty,
span: closure_expr.span,
kind: convert_var(cx, closure_expr, freevar.def),
......@@ -1036,16 +1059,16 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
ty::BorrowKind::MutBorrow => BorrowKind::Mut,
};
Expr {
temp_lifetime: temp_lifetime,
ty: freevar_ty,
span: closure_expr.span,
kind: ExprKind::Borrow {
region: upvar_borrow.region,
borrow_kind: borrow_kind,
arg: captured_var.to_ref(),
},
}
.to_ref()
temp_lifetime: temp_lifetime,
temp_lifetime_was_shrunk: was_shrunk,
ty: freevar_ty,
span: closure_expr.span,
kind: ExprKind::Borrow {
region: upvar_borrow.region,
borrow_kind: borrow_kind,
arg: captured_var.to_ref(),
},
}.to_ref()
}
}
}
......
......@@ -97,6 +97,9 @@ pub struct Expr<'tcx> {
/// temporary; should be None only if in a constant context
pub temp_lifetime: Option<CodeExtent>,
/// whether this temp lifetime was shrunk by #36082.
pub temp_lifetime_was_shrunk: bool,
/// span of the expression in the source
pub span: Span,
......
......@@ -996,7 +996,7 @@ fn check_safety_of_rvalue_destructor_if_necessary(&mut self,
cmt: mc::cmt<'tcx>,
span: Span) {
match cmt.cat {
Categorization::Rvalue(region) => {
Categorization::Rvalue(region, _) => {
match *region {
ty::ReScope(rvalue_scope) => {
let typ = self.resolve_type(cmt.ty);
......@@ -1113,7 +1113,8 @@ fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
for arg in args {
let arg_ty = self.node_ty(arg.id);
let re_scope = self.tcx.mk_region(ty::ReScope(body_scope));
let arg_cmt = mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty);
let arg_cmt = mc.cat_rvalue(
arg.id, arg.pat.span, re_scope, re_scope, arg_ty);
debug!("arg_ty={:?} arg_cmt={:?} arg={:?}",
arg_ty,
arg_cmt,
......
......@@ -339,7 +339,7 @@ fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: mc::cmt<'tcx>) {
Categorization::Deref(.., mc::UnsafePtr(..)) |
Categorization::StaticItem |
Categorization::Rvalue(_) |
Categorization::Rvalue(..) |
Categorization::Local(_) |
Categorization::Upvar(..) => {
return;
......@@ -371,7 +371,7 @@ fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: mc::cmt<'tcx>) {
Categorization::Deref(.., mc::UnsafePtr(..)) |
Categorization::StaticItem |
Categorization::Rvalue(_) |
Categorization::Rvalue(..) |
Categorization::Local(_) |
Categorization::Upvar(..) => {
}
......
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::cell::RefCell;
fn main() {
let mut r = 0;
let s = 0;
let x = RefCell::new((&mut r,s));
let val: &_ = x.borrow().0;
//~^ WARNING this temporary used to live longer - see issue #39283
//~^^ ERROR borrowed value does not live long enough
//~| temporary value dropped here while still borrowed
//~| temporary value created here
//~| consider using a `let` binding to increase its lifetime
//~| before rustc 1.16, this temporary lived longer - see issue #39283
println!("{}", val);
}
//~^ temporary value needs to live until here
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册