From 7d01aa8a4815207d83664353895ac168b7564e4b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 23 Feb 2019 14:25:03 +0000 Subject: Type check coercions to pointer types --- src/test/ui/nll/type-check-pointer-coercions.rs | 39 ++++++++++ .../ui/nll/type-check-pointer-coercions.stderr | 87 ++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 src/test/ui/nll/type-check-pointer-coercions.rs create mode 100644 src/test/ui/nll/type-check-pointer-coercions.stderr (limited to 'src/test') diff --git a/src/test/ui/nll/type-check-pointer-coercions.rs b/src/test/ui/nll/type-check-pointer-coercions.rs new file mode 100644 index 00000000000..b6a25eddb86 --- /dev/null +++ b/src/test/ui/nll/type-check-pointer-coercions.rs @@ -0,0 +1,39 @@ +#![feature(nll)] + +fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 { + x //~ ERROR +} + +fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 { + x //~ ERROR +} + +fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 { + // Two errors because *mut is invariant + x //~ ERROR + //~| ERROR +} + +fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 { + x //~ ERROR +} + +fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 { + let z = &[x; 3]; + let y = z as *const &i32; + y //~ ERROR +} + +fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] { + let z = &[x; 3]; + let y = z as *const [&i32; 3]; + y //~ ERROR +} + +fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] { + let z = &[[x; 2]; 3]; + let y = z as *const [&i32; 2]; + y //~ ERROR +} + +fn main() {} diff --git a/src/test/ui/nll/type-check-pointer-coercions.stderr b/src/test/ui/nll/type-check-pointer-coercions.stderr new file mode 100644 index 00000000000..3b8d9942124 --- /dev/null +++ b/src/test/ui/nll/type-check-pointer-coercions.stderr @@ -0,0 +1,87 @@ +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:4:5 + | +LL | fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x //~ ERROR + | ^ returning this value requires that `'a` must outlive `'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:8:5 + | +LL | fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x //~ ERROR + | ^ returning this value requires that `'a` must outlive `'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:13:5 + | +LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Two errors because *mut is invariant +LL | x //~ ERROR + | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:13:5 + | +LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Two errors because *mut is invariant +LL | x //~ ERROR + | ^ returning this value requires that `'a` must outlive `'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:18:5 + | +LL | fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | x //~ ERROR + | ^ returning this value requires that `'a` must outlive `'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:24:5 + | +LL | fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | y //~ ERROR + | ^ returning this value requires that `'a` must outlive `'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:30:5 + | +LL | fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | y //~ ERROR + | ^ returning this value requires that `'a` must outlive `'b` + +error: lifetime may not live long enough + --> $DIR/type-check-pointer-coercions.rs:36:5 + | +LL | fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | y //~ ERROR + | ^ returning this value requires that `'a` must outlive `'b` + +error: aborting due to 8 previous errors + -- cgit 1.4.1-3-g733a5 From 19a54e80934c802109ae7175cc824c22c672caa6 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 24 Feb 2019 12:54:45 +0000 Subject: Type check pointer comparisons --- .../borrow_check/nll/type_check/mod.rs | 40 +++++++++++++- src/test/ui/nll/type-check-pointer-comparisons.rs | 33 ++++++++++++ .../ui/nll/type-check-pointer-comparisons.stderr | 62 ++++++++++++++++++++++ 3 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/nll/type-check-pointer-comparisons.rs create mode 100644 src/test/ui/nll/type-check-pointer-comparisons.stderr (limited to 'src/test') diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 6b948e40bfb..ef0f11ecfb9 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -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(..) diff --git a/src/test/ui/nll/type-check-pointer-comparisons.rs b/src/test/ui/nll/type-check-pointer-comparisons.rs new file mode 100644 index 00000000000..3c900356fab --- /dev/null +++ b/src/test/ui/nll/type-check-pointer-comparisons.rs @@ -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() {} diff --git a/src/test/ui/nll/type-check-pointer-comparisons.stderr b/src/test/ui/nll/type-check-pointer-comparisons.stderr new file mode 100644 index 00000000000..c0a994cfb63 --- /dev/null +++ b/src/test/ui/nll/type-check-pointer-comparisons.stderr @@ -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 + -- cgit 1.4.1-3-g733a5