Skip to content

Commit f2529ac

Browse files
committed
Constrain operands to outlive the operation. Fixes #21422.
1 parent 801bc48 commit f2529ac

File tree

4 files changed

+60
-0
lines changed

4 files changed

+60
-0
lines changed

src/librustc/middle/infer/error_reporting.rs

+16
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,17 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
675675
sup,
676676
"");
677677
}
678+
infer::Operand(span) => {
679+
self.tcx.sess.span_err(
680+
span,
681+
"lifetime of operand does not outlive \
682+
the operation");
683+
note_and_explain_region(
684+
self.tcx,
685+
"the operand is only valid for ",
686+
sup,
687+
"");
688+
}
678689
infer::AddrOf(span) => {
679690
self.tcx.sess.span_err(
680691
span,
@@ -1593,6 +1604,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
15931604
span,
15941605
"...so that return value is valid for the call");
15951606
}
1607+
infer::Operand(span) => {
1608+
self.tcx.sess.span_err(
1609+
span,
1610+
"...so that operand is valid for operation");
1611+
}
15961612
infer::AddrOf(span) => {
15971613
self.tcx.sess.span_note(
15981614
span,

src/librustc/middle/infer/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ pub enum SubregionOrigin<'tcx> {
210210
// Region in return type of invoked fn must enclose call
211211
CallReturn(Span),
212212

213+
// Operands must be in scope
214+
Operand(Span),
215+
213216
// Region resulting from a `&` expr must enclose the `&` expr
214217
AddrOf(Span),
215218

@@ -1195,6 +1198,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
11951198
CallRcvr(a) => a,
11961199
CallArg(a) => a,
11971200
CallReturn(a) => a,
1201+
Operand(a) => a,
11981202
AddrOf(a) => a,
11991203
AutoBorrow(a) => a,
12001204
SafeDestructor(a) => a,
@@ -1258,6 +1262,7 @@ impl<'tcx> Repr<'tcx> for SubregionOrigin<'tcx> {
12581262
CallRcvr(a) => format!("CallRcvr({})", a.repr(tcx)),
12591263
CallArg(a) => format!("CallArg({})", a.repr(tcx)),
12601264
CallReturn(a) => format!("CallReturn({})", a.repr(tcx)),
1265+
Operand(a) => format!("Operand({})", a.repr(tcx)),
12611266
AddrOf(a) => format!("AddrOf({})", a.repr(tcx)),
12621267
AutoBorrow(a) => format!("AutoBorrow({})", a.repr(tcx)),
12631268
SafeDestructor(a) => format!("SafeDestructor({})", a.repr(tcx)),

src/librustc_typeck/check/regionck.rs

+14
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,20 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
610610
visit::walk_expr(rcx, expr);
611611
}
612612

613+
ast::ExprBinary(_, ref lhs, ref rhs) => {
614+
// If you do `x OP y`, then the types of `x` and `y` must
615+
// outlive the operation you are performing.
616+
let lhs_ty = rcx.resolve_expr_type_adjusted(&**lhs);
617+
let rhs_ty = rcx.resolve_expr_type_adjusted(&**rhs);
618+
for &ty in [lhs_ty, rhs_ty].iter() {
619+
type_must_outlive(rcx,
620+
infer::Operand(expr.span),
621+
ty,
622+
ty::ReScope(CodeExtent::from_node_id(expr.id)));
623+
}
624+
visit::walk_expr(rcx, expr);
625+
}
626+
613627
ast::ExprUnary(op, ref lhs) if has_method_map => {
614628
let implicitly_ref_args = !ast_util::is_by_value_unop(op);
615629

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Regression test for issue #21422, which was related to failing to
12+
// add inference constraints that the operands of a binary operator
13+
// should outlive the binary operation itself.
14+
15+
pub struct P<'a> {
16+
_ptr: *const &'a u8,
17+
}
18+
19+
impl <'a> PartialEq for P<'a> {
20+
fn eq(&self, other: &P<'a>) -> bool {
21+
(self as *const _) == (other as *const _)
22+
}
23+
}
24+
25+
fn main() {}

0 commit comments

Comments
 (0)