Rollup merge of #103876 - oli-obk:tait_implications, r=lcnr

type alias impl trait: add tests showing that hidden type only outlives lifetimes that occur in bounds

fixes #103642

https://github.com/rust-lang/rust/pull/102417 only made sure that hidden types cannot outlive lifetimes other than the ones mentioned on bounds, but didn't allow us to actually infer anything from that.

cc `@aliemjay`
This commit is contained in:
Matthias Krüger 2022-11-29 22:43:15 +01:00 committed by GitHub
commit 3617adfaee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 123 additions and 6 deletions

View File

@ -1705,6 +1705,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
});
}
#[instrument(level = "debug", skip(self, infcx, errors_buffer))]
fn check_member_constraints(
&self,
infcx: &InferCtxt<'tcx>,
@ -1712,22 +1713,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) {
let member_constraints = self.member_constraints.clone();
for m_c_i in member_constraints.all_indices() {
debug!("check_member_constraint(m_c_i={:?})", m_c_i);
debug!(?m_c_i);
let m_c = &member_constraints[m_c_i];
let member_region_vid = m_c.member_region_vid;
debug!(
"check_member_constraint: member_region_vid={:?} with value {}",
member_region_vid,
self.region_value_str(member_region_vid),
?member_region_vid,
value = ?self.region_value_str(member_region_vid),
);
let choice_regions = member_constraints.choice_regions(m_c_i);
debug!("check_member_constraint: choice_regions={:?}", choice_regions);
debug!(?choice_regions);
// Did the member region wind up equal to any of the option regions?
if let Some(o) =
choice_regions.iter().find(|&&o_r| self.eval_equal(o_r, m_c.member_region_vid))
{
debug!("check_member_constraint: evaluated as equal to {:?}", o);
debug!("evaluated as equal to {:?}", o);
continue;
}

View File

@ -0,0 +1,25 @@
// check-pass
#![feature(type_alias_impl_trait)]
trait Callable {
type Output;
fn call() -> Self::Output;
}
impl<'a> Callable for &'a () {
type Output = impl Sized;
fn call() -> Self::Output {}
}
fn test<'a>() -> impl Sized {
<&'a () as Callable>::call()
}
fn want_static<T: 'static>(_: T) {}
fn test2<'a>() {
want_static(<&'a () as Callable>::call());
}
fn main() {}

View File

@ -0,0 +1,38 @@
#![feature(type_alias_impl_trait)]
trait Callable {
type Output;
fn call(x: Self) -> Self::Output;
}
trait PlusOne {
fn plus_one(&mut self);
}
impl<'a> PlusOne for &'a mut i32 {
fn plus_one(&mut self) {
**self += 1;
}
}
impl<T: PlusOne> Callable for T {
type Output = impl PlusOne;
fn call(t: T) -> Self::Output { t }
}
fn test<'a>(y: &'a mut i32) -> impl PlusOne {
<&'a mut i32 as Callable>::call(y)
//~^ ERROR hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
}
fn main() {
let mut z = 42;
let mut thing = test(&mut z);
let mut thing2 = test(&mut z);
thing.plus_one();
assert_eq!(z, 43);
thing2.plus_one();
assert_eq!(z, 44);
thing.plus_one();
assert_eq!(z, 45);
}

View File

@ -0,0 +1,16 @@
error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
--> $DIR/imply_bounds_from_bounds_param.rs:24:5
|
LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne {
| -- hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
LL | <&'a mut i32 as Callable>::call(y)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` lifetime bound
|
LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a {
| ++++
error: aborting due to previous error
For more information about this error, try `rustc --explain E0700`.

View File

@ -0,0 +1,38 @@
// check-pass
#![feature(type_alias_impl_trait)]
fn foo() {
struct Foo<'a> {
x: &'a mut u8,
}
impl<'a> Foo<'a> {
fn foo(&self) -> impl Sized {}
}
// use site
let mut x = 5;
let y = Foo { x: &mut x };
let z = y.foo();
let _a = &x; // invalidate the `&'a mut`in `y`
let _b = z; // this should *not* check that `'a` in the type `Foo<'a>::foo::opaque` is live
}
fn bar() {
struct Foo<'a> {
x: &'a mut u8,
}
// desugared
type FooX<'a> = impl Sized;
impl<'a> Foo<'a> {
fn foo(&self) -> FooX<'a> {}
}
// use site
let mut x = 5;
let y = Foo { x: &mut x };
let z = y.foo();
let _a = &x; // invalidate the `&'a mut`in `y`
let _b = z; // this should *not* check that `'a` in the type `Foo<'a>::foo::opaque` is live
}
fn main() {}