Type check pointer comparisons
This commit is contained in:
parent
7d01aa8a48
commit
19a54e8093
3 changed files with 134 additions and 1 deletions
|
|
@ -27,6 +27,7 @@ use rustc::hir::def_id::DefId;
|
|||
use rustc::infer::canonical::QueryRegionConstraint;
|
||||
use rustc::infer::outlives::env::RegionBoundPairs;
|
||||
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
|
||||
use rustc::mir::tcx::PlaceTy;
|
||||
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
|
||||
|
|
@ -2103,7 +2104,44 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
self.add_reborrow_constraint(location, region, borrowed_place);
|
||||
}
|
||||
|
||||
// FIXME: These other cases have to be implemented in future PRs
|
||||
Rvalue::BinaryOp(BinOp::Eq, left, right)
|
||||
| Rvalue::BinaryOp(BinOp::Ne, left, right)
|
||||
| Rvalue::BinaryOp(BinOp::Lt, left, right)
|
||||
| Rvalue::BinaryOp(BinOp::Le, left, right)
|
||||
| Rvalue::BinaryOp(BinOp::Gt, left, right)
|
||||
| Rvalue::BinaryOp(BinOp::Ge, left, right) => {
|
||||
let ty_left = left.ty(mir, tcx);
|
||||
if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.sty {
|
||||
let ty_right = right.ty(mir, tcx);
|
||||
let common_ty = self.infcx.next_ty_var(
|
||||
TypeVariableOrigin::MiscVariable(mir.source_info(location).span),
|
||||
);
|
||||
self.sub_types(
|
||||
common_ty,
|
||||
ty_left,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring
|
||||
).unwrap_or_else(|err| {
|
||||
bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
|
||||
});
|
||||
if let Err(terr) = self.sub_types(
|
||||
common_ty,
|
||||
ty_right,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"unexpected comparison types {:?} and {:?} yields {:?}",
|
||||
ty_left,
|
||||
ty_right,
|
||||
terr
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rvalue::Use(..)
|
||||
| Rvalue::Len(..)
|
||||
| Rvalue::BinaryOp(..)
|
||||
|
|
|
|||
33
src/test/ui/nll/type-check-pointer-comparisons.rs
Normal file
33
src/test/ui/nll/type-check-pointer-comparisons.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#![feature(nll)]
|
||||
|
||||
// Check that we assert that pointers have a common subtype for comparisons
|
||||
|
||||
fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
|
||||
x == y;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
//~| ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
|
||||
x == y;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
//~| ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
|
||||
f == g;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
//~| ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn compare_hr_fn_ptr<'a>(f: fn(&'a i32), g: fn(&i32)) {
|
||||
// Ideally this should compile with the operands swapped as well, but HIR
|
||||
// type checking prevents it (and stops compilation) for now.
|
||||
f == g; // OK
|
||||
}
|
||||
|
||||
fn compare_const_fn_ptr<'a>(f: *const fn(&'a i32), g: *const fn(&i32)) {
|
||||
f == g; // OK
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
62
src/test/ui/nll/type-check-pointer-comparisons.stderr
Normal file
62
src/test/ui/nll/type-check-pointer-comparisons.stderr
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/type-check-pointer-comparisons.rs:6:5
|
||||
|
|
||||
LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | x == y;
|
||||
| ^ requires that `'a` must outlive `'b`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/type-check-pointer-comparisons.rs:6:10
|
||||
|
|
||||
LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | x == y;
|
||||
| ^ requires that `'b` must outlive `'a`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/type-check-pointer-comparisons.rs:12:5
|
||||
|
|
||||
LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | x == y;
|
||||
| ^ requires that `'a` must outlive `'b`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/type-check-pointer-comparisons.rs:12:10
|
||||
|
|
||||
LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | x == y;
|
||||
| ^ requires that `'b` must outlive `'a`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/type-check-pointer-comparisons.rs:18:5
|
||||
|
|
||||
LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | f == g;
|
||||
| ^ requires that `'a` must outlive `'b`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/type-check-pointer-comparisons.rs:18:10
|
||||
|
|
||||
LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | f == g;
|
||||
| ^ requires that `'b` must outlive `'a`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue