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:
commit
3617adfaee
5 changed files with 123 additions and 6 deletions
|
@ -1705,6 +1705,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self, infcx, errors_buffer))]
|
||||||
fn check_member_constraints(
|
fn check_member_constraints(
|
||||||
&self,
|
&self,
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
|
@ -1712,22 +1713,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
) {
|
) {
|
||||||
let member_constraints = self.member_constraints.clone();
|
let member_constraints = self.member_constraints.clone();
|
||||||
for m_c_i in member_constraints.all_indices() {
|
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 m_c = &member_constraints[m_c_i];
|
||||||
let member_region_vid = m_c.member_region_vid;
|
let member_region_vid = m_c.member_region_vid;
|
||||||
debug!(
|
debug!(
|
||||||
"check_member_constraint: member_region_vid={:?} with value {}",
|
?member_region_vid,
|
||||||
member_region_vid,
|
value = ?self.region_value_str(member_region_vid),
|
||||||
self.region_value_str(member_region_vid),
|
|
||||||
);
|
);
|
||||||
let choice_regions = member_constraints.choice_regions(m_c_i);
|
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?
|
// Did the member region wind up equal to any of the option regions?
|
||||||
if let Some(o) =
|
if let Some(o) =
|
||||||
choice_regions.iter().find(|&&o_r| self.eval_equal(o_r, m_c.member_region_vid))
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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`.
|
38
src/test/ui/type-alias-impl-trait/self_implication.rs
Normal file
38
src/test/ui/type-alias-impl-trait/self_implication.rs
Normal 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() {}
|
Loading…
Add table
Add a link
Reference in a new issue