diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2018-09-29 00:22:35 +0300 |
|---|---|---|
| committer | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2018-10-01 22:44:45 +0300 |
| commit | 1069c0e38f28539ab29c32921435b3f28eb63808 (patch) | |
| tree | e013610f0cc2eec2807baa30beebadb8a16da024 | |
| parent | 9d44e9eb7ce65d1ae13db56c56713de4f4ef95bd (diff) | |
add a special case for literal `'static: 'a` where-clauses
This makes evaluation more consistent with fulfillment.
| -rw-r--r-- | src/librustc/traits/select.rs | 46 | ||||
| -rw-r--r-- | src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs | 33 |
2 files changed, 64 insertions, 15 deletions
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 0e087153673..860914d1984 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -727,26 +727,42 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { if r_a == r_b { // for<'a> 'a: 'a. OK Ok(EvaluatedToOk) + } else if **r_a == ty::ReStatic { + // 'static: 'x always holds. + // + // This special case is handled somewhat inconsistently - if we + // have an inference variable that is supposed to be equal to + // `'static`, then we don't allow it to be equated to an LBR, + // but if we have a literal `'static`, then we *do*. + // + // This is actually consistent with how our region inference works. + // + // It would appear that this sort of inconsistency would + // cause "instability" problems with evaluation caching. However, + // evaluation caching is only for trait predicates, and when + // trait predicates create nested obligations, they contain + // inference variables for all the regions in the trait - the + // only way this codepath can be reached from trait predicate + // evaluation is when the user typed an explicit `where 'static: 'a` + // lifetime bound (in which case we want to return EvaluatedToOk). + // + // If we ever want to handle inference variables that might be + // equatable with ReStatic, we need to make sure we are not confused by + // technically-allowed-by-RFC-447-but-probably-should-not-be + // impls such as + // ```Rust + // impl<'a, 's, T> X<'s> for T where T: Debug + 'a, 'a: 's + // ``` + Ok(EvaluatedToOk) } else if r_a.is_late_bound() || r_b.is_late_bound() { // There is no current way to prove `for<'a> 'a: 'x` // unless `'a = 'x`, because there are no bounds involving // lifetimes. - // It is possible to solve `for<'a> 'x: 'a` where `'x` - // is a free region by forcing `'x = 'static`. However, - // fulfillment does not *quite* do this ATM (it calls - // `region_outlives_predicate`, which is OK if `'x` is - // literally ReStatic, but is *not* OK if `'x` is any - // sort of inference variable, even if it *is* equal - // to `'static`). - - // If we ever want to handle that sort of obligations, - // we need to make sure we are not confused by - // technically-allowed-by-RFC-447-but-probably-should-not-be - // impls such as - // ```Rust - // impl<'a, 's, T> X<'s> for T where T: Debug + 's, 'a: 's - // ``` + // It might be possible to prove `for<'a> 'x: 'a` by forcing `'x` + // to be `'static`. However, this is not currently done by type + // inference unless `'x` is literally ReStatic. See the comment + // above. // We don't want to allow this sort of reasoning in intercrate // mode, for backwards-compatibility reasons. diff --git a/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs b/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs new file mode 100644 index 00000000000..1051bec6307 --- /dev/null +++ b/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs @@ -0,0 +1,33 @@ +// Copyright 2018 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-pass + +trait Foo<'a> { + fn xyz(self); +} +impl<'a, T> Foo<'a> for T where 'static: 'a { + fn xyz(self) {} +} + +trait Bar { + fn uvw(self); +} +impl<T> Bar for T where for<'a> T: Foo<'a> { + fn uvw(self) { self.xyz(); } +} + +fn foo<T>(t: T) where T: Bar { + t.uvw(); +} + +fn main() { + foo(0); +} |
