mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
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
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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…
Reference in New Issue
Block a user