Skip to content

Commit 19a54e8

Browse files
committed
Type check pointer comparisons
1 parent 7d01aa8 commit 19a54e8

File tree

3 files changed

+134
-1
lines changed

3 files changed

+134
-1
lines changed

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+39-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc::hir::def_id::DefId;
2727
use rustc::infer::canonical::QueryRegionConstraint;
2828
use rustc::infer::outlives::env::RegionBoundPairs;
2929
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
30+
use rustc::infer::type_variable::TypeVariableOrigin;
3031
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
3132
use rustc::mir::tcx::PlaceTy;
3233
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
@@ -2103,7 +2104,44 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
21032104
self.add_reborrow_constraint(location, region, borrowed_place);
21042105
}
21052106

2106-
// FIXME: These other cases have to be implemented in future PRs
2107+
Rvalue::BinaryOp(BinOp::Eq, left, right)
2108+
| Rvalue::BinaryOp(BinOp::Ne, left, right)
2109+
| Rvalue::BinaryOp(BinOp::Lt, left, right)
2110+
| Rvalue::BinaryOp(BinOp::Le, left, right)
2111+
| Rvalue::BinaryOp(BinOp::Gt, left, right)
2112+
| Rvalue::BinaryOp(BinOp::Ge, left, right) => {
2113+
let ty_left = left.ty(mir, tcx);
2114+
if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.sty {
2115+
let ty_right = right.ty(mir, tcx);
2116+
let common_ty = self.infcx.next_ty_var(
2117+
TypeVariableOrigin::MiscVariable(mir.source_info(location).span),
2118+
);
2119+
self.sub_types(
2120+
common_ty,
2121+
ty_left,
2122+
location.to_locations(),
2123+
ConstraintCategory::Boring
2124+
).unwrap_or_else(|err| {
2125+
bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
2126+
});
2127+
if let Err(terr) = self.sub_types(
2128+
common_ty,
2129+
ty_right,
2130+
location.to_locations(),
2131+
ConstraintCategory::Boring
2132+
) {
2133+
span_mirbug!(
2134+
self,
2135+
rvalue,
2136+
"unexpected comparison types {:?} and {:?} yields {:?}",
2137+
ty_left,
2138+
ty_right,
2139+
terr
2140+
)
2141+
}
2142+
}
2143+
}
2144+
21072145
Rvalue::Use(..)
21082146
| Rvalue::Len(..)
21092147
| Rvalue::BinaryOp(..)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#![feature(nll)]
2+
3+
// Check that we assert that pointers have a common subtype for comparisons
4+
5+
fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
6+
x == y;
7+
//~^ ERROR lifetime may not live long enough
8+
//~| ERROR lifetime may not live long enough
9+
}
10+
11+
fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
12+
x == y;
13+
//~^ ERROR lifetime may not live long enough
14+
//~| ERROR lifetime may not live long enough
15+
}
16+
17+
fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
18+
f == g;
19+
//~^ ERROR lifetime may not live long enough
20+
//~| ERROR lifetime may not live long enough
21+
}
22+
23+
fn compare_hr_fn_ptr<'a>(f: fn(&'a i32), g: fn(&i32)) {
24+
// Ideally this should compile with the operands swapped as well, but HIR
25+
// type checking prevents it (and stops compilation) for now.
26+
f == g; // OK
27+
}
28+
29+
fn compare_const_fn_ptr<'a>(f: *const fn(&'a i32), g: *const fn(&i32)) {
30+
f == g; // OK
31+
}
32+
33+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/type-check-pointer-comparisons.rs:6:5
3+
|
4+
LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
LL | x == y;
9+
| ^ requires that `'a` must outlive `'b`
10+
11+
error: lifetime may not live long enough
12+
--> $DIR/type-check-pointer-comparisons.rs:6:10
13+
|
14+
LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
15+
| -- -- lifetime `'b` defined here
16+
| |
17+
| lifetime `'a` defined here
18+
LL | x == y;
19+
| ^ requires that `'b` must outlive `'a`
20+
21+
error: lifetime may not live long enough
22+
--> $DIR/type-check-pointer-comparisons.rs:12:5
23+
|
24+
LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
25+
| -- -- lifetime `'b` defined here
26+
| |
27+
| lifetime `'a` defined here
28+
LL | x == y;
29+
| ^ requires that `'a` must outlive `'b`
30+
31+
error: lifetime may not live long enough
32+
--> $DIR/type-check-pointer-comparisons.rs:12:10
33+
|
34+
LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
35+
| -- -- lifetime `'b` defined here
36+
| |
37+
| lifetime `'a` defined here
38+
LL | x == y;
39+
| ^ requires that `'b` must outlive `'a`
40+
41+
error: lifetime may not live long enough
42+
--> $DIR/type-check-pointer-comparisons.rs:18:5
43+
|
44+
LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
45+
| -- -- lifetime `'b` defined here
46+
| |
47+
| lifetime `'a` defined here
48+
LL | f == g;
49+
| ^ requires that `'a` must outlive `'b`
50+
51+
error: lifetime may not live long enough
52+
--> $DIR/type-check-pointer-comparisons.rs:18:10
53+
|
54+
LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
55+
| -- -- lifetime `'b` defined here
56+
| |
57+
| lifetime `'a` defined here
58+
LL | f == g;
59+
| ^ requires that `'b` must outlive `'a`
60+
61+
error: aborting due to 6 previous errors
62+

0 commit comments

Comments
 (0)