Skip to content

Commit a27fed7

Browse files
committed
Auto merge of rust-lang#27096 - apasel422:issue-26217, r=nikomatsakis
closes rust-lang#26217 r? @nikomatsakis
2 parents e0e1859 + d088db9 commit a27fed7

File tree

3 files changed

+40
-12
lines changed

3 files changed

+40
-12
lines changed

src/librustc/middle/traits/fulfill.rs

+24-8
Original file line numberDiff line numberDiff line change
@@ -413,17 +413,33 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
413413
}
414414

415415
ty::Predicate::TypeOutlives(ref binder) => {
416-
// For now, we just check that there are no higher-ranked
417-
// regions. If there are, we will call this obligation an
418-
// error. Eventually we should be able to support some
419-
// cases here, I imagine (e.g., `for<'a> int : 'a`).
416+
// Check if there are higher-ranked regions.
420417
match selcx.tcx().no_late_bound_regions(binder) {
418+
// If there are, inspect the underlying type further.
421419
None => {
422-
errors.push(
423-
FulfillmentError::new(
424-
obligation.clone(),
425-
CodeSelectionError(Unimplemented)))
420+
// Convert from `Binder<OutlivesPredicate<Ty, Region>>` to `Binder<Ty>`.
421+
let binder = binder.map_bound_ref(|pred| pred.0);
422+
423+
// Check if the type has any bound regions.
424+
match selcx.tcx().no_late_bound_regions(&binder) {
425+
// If so, this obligation is an error (for now). Eventually we should be
426+
// able to support additional cases here, like `for<'a> &'a str: 'a`.
427+
None => {
428+
errors.push(
429+
FulfillmentError::new(
430+
obligation.clone(),
431+
CodeSelectionError(Unimplemented)))
432+
}
433+
// Otherwise, we have something of the form
434+
// `for<'a> T: 'a where 'a not in T`, which we can treat as `T: 'static`.
435+
Some(t_a) => {
436+
register_region_obligation(t_a, ty::ReStatic,
437+
obligation.cause.clone(),
438+
region_obligations);
439+
}
440+
}
426441
}
442+
// If there aren't, register the obligation.
427443
Some(ty::OutlivesPredicate(t_a, r_b)) => {
428444
register_region_obligation(t_a, r_b,
429445
obligation.cause.clone(),

src/test/compile-fail/issue-26217.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn foo<T>() where for<'a> T: 'a {}
12+
13+
fn main<'a>() {
14+
foo::<&'a i32>();
15+
//~^ ERROR the type `&'a i32` does not fulfill the required lifetime
16+
}

src/test/compile-fail/hrtb-type-outlives.rs renamed to src/test/run-pass/hrtb-type-outlives.rs

-4
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@ impl<'a,X> Foo<&'a isize> for SomeStruct<X>
3434
}
3535

3636
fn one() {
37-
// In fact there is no good reason for this to be an error, but
38-
// whatever, I'm mostly concerned it doesn't ICE right now:
3937
want_foo::<SomeStruct<usize>>();
40-
//~^ ERROR requirement `for<'a> usize : 'a` is not satisfied
4138
}
4239

4340
///////////////////////////////////////////////////////////////////////////
@@ -53,7 +50,6 @@ impl<'a,X:'a> Foo<&'a isize> for AnotherStruct<X>
5350

5451
fn two() {
5552
want_foo::<AnotherStruct<usize>>();
56-
//~^ ERROR requirement `for<'a> usize : 'a` is not satisfied
5753
}
5854

5955
fn main() { }

0 commit comments

Comments
 (0)