From 27188bbefe5efbbb8c11464457ce90edf24ac17f Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Fri, 17 Jul 2015 13:46:33 -0400 Subject: treat `for<'a> T: 'a` as `T: 'static` closes #26217 --- src/librustc/middle/traits/fulfill.rs | 32 ++++++++++++---- src/test/compile-fail/hrtb-type-outlives.rs | 59 ----------------------------- src/test/compile-fail/issue-26217.rs | 16 ++++++++ src/test/run-pass/hrtb-type-outlives.rs | 55 +++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 67 deletions(-) delete mode 100644 src/test/compile-fail/hrtb-type-outlives.rs create mode 100644 src/test/compile-fail/issue-26217.rs create mode 100644 src/test/run-pass/hrtb-type-outlives.rs diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index 08cb3e57015..e06333114f5 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -413,17 +413,33 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, } ty::Predicate::TypeOutlives(ref binder) => { - // For now, we just check that there are no higher-ranked - // regions. If there are, we will call this obligation an - // error. Eventually we should be able to support some - // cases here, I imagine (e.g., `for<'a> int : 'a`). + // Check if there are higher-ranked regions. match selcx.tcx().no_late_bound_regions(binder) { + // If there are, inspect the underlying type further. None => { - errors.push( - FulfillmentError::new( - obligation.clone(), - CodeSelectionError(Unimplemented))) + // Convert from `Binder>` to `Binder`. + let binder = binder.map_bound_ref(|pred| pred.0); + + // Check if the type has any bound regions. + match selcx.tcx().no_late_bound_regions(&binder) { + // If so, this obligation is an error (for now). Eventually we should be + // able to support additional cases here, like `for<'a> &'a str: 'a`. + None => { + errors.push( + FulfillmentError::new( + obligation.clone(), + CodeSelectionError(Unimplemented))) + } + // Otherwise, we have something of the form `for<'a> T: 'a`, which + // we can treat as `T: 'static`. + Some(t_a) => { + register_region_obligation(t_a, ty::ReStatic, + obligation.cause.clone(), + region_obligations); + } + } } + // If there aren't, register the obligation. Some(ty::OutlivesPredicate(t_a, r_b)) => { register_region_obligation(t_a, r_b, obligation.cause.clone(), diff --git a/src/test/compile-fail/hrtb-type-outlives.rs b/src/test/compile-fail/hrtb-type-outlives.rs deleted file mode 100644 index 7bb74d6b03a..00000000000 --- a/src/test/compile-fail/hrtb-type-outlives.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2014 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. - -// Test what happens when a HR obligation is applied to an impl with -// "outlives" bounds. Currently we're pretty conservative here; this -// will probably improve in time. - -trait Foo { - fn foo(&self, x: X) { } -} - -fn want_foo() - where T : for<'a> Foo<&'a isize> -{ -} - -/////////////////////////////////////////////////////////////////////////// -// Expressed as a where clause - -struct SomeStruct { - x: X -} - -impl<'a,X> Foo<&'a isize> for SomeStruct - where X : 'a -{ -} - -fn one() { - // In fact there is no good reason for this to be an error, but - // whatever, I'm mostly concerned it doesn't ICE right now: - want_foo::>(); - //~^ ERROR requirement `for<'a> usize : 'a` is not satisfied -} - -/////////////////////////////////////////////////////////////////////////// -// Expressed as shorthand - -struct AnotherStruct { - x: X -} - -impl<'a,X:'a> Foo<&'a isize> for AnotherStruct -{ -} - -fn two() { - want_foo::>(); - //~^ ERROR requirement `for<'a> usize : 'a` is not satisfied -} - -fn main() { } diff --git a/src/test/compile-fail/issue-26217.rs b/src/test/compile-fail/issue-26217.rs new file mode 100644 index 00000000000..06a8fe52588 --- /dev/null +++ b/src/test/compile-fail/issue-26217.rs @@ -0,0 +1,16 @@ +// 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. + +fn foo() where for<'a> T: 'a {} + +fn main<'a>() { + foo::<&'a i32>(); + //~^ ERROR the type `&'a i32` does not fulfill the required lifetime +} diff --git a/src/test/run-pass/hrtb-type-outlives.rs b/src/test/run-pass/hrtb-type-outlives.rs new file mode 100644 index 00000000000..083f042fec2 --- /dev/null +++ b/src/test/run-pass/hrtb-type-outlives.rs @@ -0,0 +1,55 @@ +// Copyright 2014 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. + +// Test what happens when a HR obligation is applied to an impl with +// "outlives" bounds. Currently we're pretty conservative here; this +// will probably improve in time. + +trait Foo { + fn foo(&self, x: X) { } +} + +fn want_foo() + where T : for<'a> Foo<&'a isize> +{ +} + +/////////////////////////////////////////////////////////////////////////// +// Expressed as a where clause + +struct SomeStruct { + x: X +} + +impl<'a,X> Foo<&'a isize> for SomeStruct + where X : 'a +{ +} + +fn one() { + want_foo::>(); +} + +/////////////////////////////////////////////////////////////////////////// +// Expressed as shorthand + +struct AnotherStruct { + x: X +} + +impl<'a,X:'a> Foo<&'a isize> for AnotherStruct +{ +} + +fn two() { + want_foo::>(); +} + +fn main() { } -- cgit 1.4.1-3-g733a5 From d088db99a7c67bebb00c2d66bfaf9cb64298fba2 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Fri, 17 Jul 2015 16:02:43 -0400 Subject: clarify that `T` does not contain `'a` --- src/librustc/middle/traits/fulfill.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index e06333114f5..44fc6b6b8ab 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -430,8 +430,8 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, obligation.clone(), CodeSelectionError(Unimplemented))) } - // Otherwise, we have something of the form `for<'a> T: 'a`, which - // we can treat as `T: 'static`. + // Otherwise, we have something of the form + // `for<'a> T: 'a where 'a not in T`, which we can treat as `T: 'static`. Some(t_a) => { register_region_obligation(t_a, ty::ReStatic, obligation.cause.clone(), -- cgit 1.4.1-3-g733a5