diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 72b33613c66a..5f9f2ad33aa5 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -675,6 +675,17 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { sup, ""); } + infer::Operand(span) => { + self.tcx.sess.span_err( + span, + "lifetime of operand does not outlive \ + the operation"); + note_and_explain_region( + self.tcx, + "the operand is only valid for ", + sup, + ""); + } infer::AddrOf(span) => { self.tcx.sess.span_err( span, @@ -1593,6 +1604,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { span, "...so that return value is valid for the call"); } + infer::Operand(span) => { + self.tcx.sess.span_err( + span, + "...so that operand is valid for operation"); + } infer::AddrOf(span) => { self.tcx.sess.span_note( span, diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 3cffe4c0fda4..b0576ff55ff7 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -210,6 +210,9 @@ pub enum SubregionOrigin<'tcx> { // Region in return type of invoked fn must enclose call CallReturn(Span), + // Operands must be in scope + Operand(Span), + // Region resulting from a `&` expr must enclose the `&` expr AddrOf(Span), @@ -1195,6 +1198,7 @@ impl<'tcx> SubregionOrigin<'tcx> { CallRcvr(a) => a, CallArg(a) => a, CallReturn(a) => a, + Operand(a) => a, AddrOf(a) => a, AutoBorrow(a) => a, SafeDestructor(a) => a, @@ -1258,6 +1262,7 @@ impl<'tcx> Repr<'tcx> for SubregionOrigin<'tcx> { CallRcvr(a) => format!("CallRcvr({})", a.repr(tcx)), CallArg(a) => format!("CallArg({})", a.repr(tcx)), CallReturn(a) => format!("CallReturn({})", a.repr(tcx)), + Operand(a) => format!("Operand({})", a.repr(tcx)), AddrOf(a) => format!("AddrOf({})", a.repr(tcx)), AutoBorrow(a) => format!("AutoBorrow({})", a.repr(tcx)), SafeDestructor(a) => format!("SafeDestructor({})", a.repr(tcx)), diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 17c259e674e9..e50c3b0306ee 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -610,6 +610,20 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { visit::walk_expr(rcx, expr); } + ast::ExprBinary(_, ref lhs, ref rhs) => { + // If you do `x OP y`, then the types of `x` and `y` must + // outlive the operation you are performing. + let lhs_ty = rcx.resolve_expr_type_adjusted(&**lhs); + let rhs_ty = rcx.resolve_expr_type_adjusted(&**rhs); + for &ty in [lhs_ty, rhs_ty].iter() { + type_must_outlive(rcx, + infer::Operand(expr.span), + ty, + ty::ReScope(CodeExtent::from_node_id(expr.id))); + } + visit::walk_expr(rcx, expr); + } + ast::ExprUnary(op, ref lhs) if has_method_map => { let implicitly_ref_args = !ast_util::is_by_value_unop(op); diff --git a/src/test/run-pass/regions-issue-21422.rs b/src/test/run-pass/regions-issue-21422.rs new file mode 100644 index 000000000000..c59bf15afc3b --- /dev/null +++ b/src/test/run-pass/regions-issue-21422.rs @@ -0,0 +1,25 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for issue #21422, which was related to failing to +// add inference constraints that the operands of a binary operator +// should outlive the binary operation itself. + +pub struct P<'a> { + _ptr: *const &'a u8, +} + +impl <'a> PartialEq for P<'a> { + fn eq(&self, other: &P<'a>) -> bool { + (self as *const _) == (other as *const _) + } +} + +fn main() {}