Skip to content

Commit f71de45

Browse files
committed
use subtyping when we create a closure instead of for upvar types
We used to make the upvar types in the closure `==` but that was stronger than we needed. Subtyping suffices, since we are copying the upvar value into the closure field. This in turn allows us to infer smaller lifetimes in captured values in some cases (like the example here), avoiding errors.
1 parent fc3c90c commit f71de45

File tree

3 files changed

+35
-4
lines changed

3 files changed

+35
-4
lines changed

src/librustc_typeck/check/upvar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
217217
.upvar_tys(closure_def_id, self.tcx)
218218
.zip(final_upvar_tys)
219219
{
220-
self.demand_eqtype(span, final_upvar_ty, upvar_ty);
220+
self.demand_suptype(span, upvar_ty, final_upvar_ty);
221221
}
222222

223223
// If we are also inferred the closure kind here,

src/test/ui/generator/auto-trait-regions.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
1+
error[E0277]: the trait bound `No: Foo` is not satisfied in `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
22
--> $DIR/auto-trait-regions.rs:40:5
33
|
44
LL | assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied
5-
| ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No`
5+
| ^^^^^^^^^^ within `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`, the trait `Foo` is not implemented for `No`
66
|
77
= help: the following implementations were found:
88
<No as Foo>
99
= note: required because it appears within the type `OnlyFooIfStaticRef`
1010
= note: required because it appears within the type `&OnlyFooIfStaticRef`
1111
= note: required because it appears within the type `for<'r> {&'r OnlyFooIfStaticRef, ()}`
12-
= note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&'static OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
12+
= note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
1313
note: required by `assert_foo`
1414
--> $DIR/auto-trait-regions.rs:30:1
1515
|
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2016 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+
// In contrast to `region-escape-via-bound-invariant`, in this case we
12+
// *can* return a value of type `&'x u32`, even though `'x` does not
13+
// appear in the bounds. This is because `&` is contravariant, and so
14+
// we are *actually* returning a `&'y u32`.
15+
//
16+
// See https://github.com/rust-lang/rust/issues/46541 for more details.
17+
18+
// run-pass
19+
20+
#![allow(dead_code)]
21+
#![feature(conservative_impl_trait)]
22+
#![feature(in_band_lifetimes)]
23+
#![feature(nll)]
24+
25+
fn foo(x: &'x u32) -> impl Fn() -> &'y u32
26+
where 'x: 'y
27+
{
28+
move || x
29+
}
30+
31+
fn main() { }

0 commit comments

Comments
 (0)