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.
This commit is contained in:
Niko Matsakis 2018-03-15 10:49:05 -04:00
parent fc3c90cf8a
commit f71de45b23
3 changed files with 35 additions and 4 deletions

View File

@ -217,7 +217,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
.upvar_tys(closure_def_id, self.tcx)
.zip(final_upvar_tys)
{
self.demand_eqtype(span, final_upvar_ty, upvar_ty);
self.demand_suptype(span, upvar_ty, final_upvar_ty);
}
// If we are also inferred the closure kind here,

View File

@ -1,15 +1,15 @@
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, ()}]`
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, ()}]`
--> $DIR/auto-trait-regions.rs:40:5
|
LL | assert_foo(gen); //~ ERROR the trait bound `No: Foo` is not satisfied
| ^^^^^^^^^^ 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`
| ^^^^^^^^^^ 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`
|
= help: the following implementations were found:
<No as Foo>
= note: required because it appears within the type `OnlyFooIfStaticRef`
= note: required because it appears within the type `&OnlyFooIfStaticRef`
= note: required because it appears within the type `for<'r> {&'r OnlyFooIfStaticRef, ()}`
= 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, ()}]`
= note: required because it appears within the type `[generator@$DIR/auto-trait-regions.rs:35:15: 39:6 x:&&OnlyFooIfStaticRef for<'r> {&'r OnlyFooIfStaticRef, ()}]`
note: required by `assert_foo`
--> $DIR/auto-trait-regions.rs:30:1
|

View File

@ -0,0 +1,31 @@
// Copyright 2016 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.
// In contrast to `region-escape-via-bound-invariant`, in this case we
// *can* return a value of type `&'x u32`, even though `'x` does not
// appear in the bounds. This is because `&` is contravariant, and so
// we are *actually* returning a `&'y u32`.
//
// See https://github.com/rust-lang/rust/issues/46541 for more details.
// run-pass
#![allow(dead_code)]
#![feature(conservative_impl_trait)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
fn foo(x: &'x u32) -> impl Fn() -> &'y u32
where 'x: 'y
{
move || x
}
fn main() { }