From 27188bbefe5efbbb8c11464457ce90edf24ac17f Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Fri, 17 Jul 2015 13:46:33 -0400 Subject: [PATCH] treat `for<'a> T: 'a` as `T: 'static` closes #26217 --- src/librustc/middle/traits/fulfill.rs | 32 ++++++++++++++----- src/test/compile-fail/issue-26217.rs | 16 ++++++++++ .../hrtb-type-outlives.rs | 4 --- 3 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 src/test/compile-fail/issue-26217.rs rename src/test/{compile-fail => run-pass}/hrtb-type-outlives.rs (82%) diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index 08cb3e5701569..e06333114f520 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/issue-26217.rs b/src/test/compile-fail/issue-26217.rs new file mode 100644 index 0000000000000..06a8fe525889b --- /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/compile-fail/hrtb-type-outlives.rs b/src/test/run-pass/hrtb-type-outlives.rs similarity index 82% rename from src/test/compile-fail/hrtb-type-outlives.rs rename to src/test/run-pass/hrtb-type-outlives.rs index 7bb74d6b03a33..083f042fec265 100644 --- a/src/test/compile-fail/hrtb-type-outlives.rs +++ b/src/test/run-pass/hrtb-type-outlives.rs @@ -34,10 +34,7 @@ impl<'a,X> Foo<&'a isize> for SomeStruct } 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 } /////////////////////////////////////////////////////////////////////////// @@ -53,7 +50,6 @@ impl<'a,X:'a> Foo<&'a isize> for AnotherStruct fn two() { want_foo::>(); - //~^ ERROR requirement `for<'a> usize : 'a` is not satisfied } fn main() { }