Skip to content

Commit 3617adf

Browse files
authored
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 #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`
2 parents e0098a5 + ca57832 commit 3617adf

File tree

5 files changed

+123
-6
lines changed

5 files changed

+123
-6
lines changed

compiler/rustc_borrowck/src/region_infer/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1705,29 +1705,29 @@ impl<'tcx> RegionInferenceContext<'tcx> {
17051705
});
17061706
}
17071707

1708+
#[instrument(level = "debug", skip(self, infcx, errors_buffer))]
17081709
fn check_member_constraints(
17091710
&self,
17101711
infcx: &InferCtxt<'tcx>,
17111712
errors_buffer: &mut RegionErrors<'tcx>,
17121713
) {
17131714
let member_constraints = self.member_constraints.clone();
17141715
for m_c_i in member_constraints.all_indices() {
1715-
debug!("check_member_constraint(m_c_i={:?})", m_c_i);
1716+
debug!(?m_c_i);
17161717
let m_c = &member_constraints[m_c_i];
17171718
let member_region_vid = m_c.member_region_vid;
17181719
debug!(
1719-
"check_member_constraint: member_region_vid={:?} with value {}",
1720-
member_region_vid,
1721-
self.region_value_str(member_region_vid),
1720+
?member_region_vid,
1721+
value = ?self.region_value_str(member_region_vid),
17221722
);
17231723
let choice_regions = member_constraints.choice_regions(m_c_i);
1724-
debug!("check_member_constraint: choice_regions={:?}", choice_regions);
1724+
debug!(?choice_regions);
17251725

17261726
// Did the member region wind up equal to any of the option regions?
17271727
if let Some(o) =
17281728
choice_regions.iter().find(|&&o_r| self.eval_equal(o_r, m_c.member_region_vid))
17291729
{
1730-
debug!("check_member_constraint: evaluated as equal to {:?}", o);
1730+
debug!("evaluated as equal to {:?}", o);
17311731
continue;
17321732
}
17331733

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// check-pass
2+
3+
#![feature(type_alias_impl_trait)]
4+
5+
trait Callable {
6+
type Output;
7+
fn call() -> Self::Output;
8+
}
9+
10+
impl<'a> Callable for &'a () {
11+
type Output = impl Sized;
12+
fn call() -> Self::Output {}
13+
}
14+
15+
fn test<'a>() -> impl Sized {
16+
<&'a () as Callable>::call()
17+
}
18+
19+
fn want_static<T: 'static>(_: T) {}
20+
21+
fn test2<'a>() {
22+
want_static(<&'a () as Callable>::call());
23+
}
24+
25+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#![feature(type_alias_impl_trait)]
2+
3+
trait Callable {
4+
type Output;
5+
fn call(x: Self) -> Self::Output;
6+
}
7+
8+
trait PlusOne {
9+
fn plus_one(&mut self);
10+
}
11+
12+
impl<'a> PlusOne for &'a mut i32 {
13+
fn plus_one(&mut self) {
14+
**self += 1;
15+
}
16+
}
17+
18+
impl<T: PlusOne> Callable for T {
19+
type Output = impl PlusOne;
20+
fn call(t: T) -> Self::Output { t }
21+
}
22+
23+
fn test<'a>(y: &'a mut i32) -> impl PlusOne {
24+
<&'a mut i32 as Callable>::call(y)
25+
//~^ ERROR hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
26+
}
27+
28+
fn main() {
29+
let mut z = 42;
30+
let mut thing = test(&mut z);
31+
let mut thing2 = test(&mut z);
32+
thing.plus_one();
33+
assert_eq!(z, 43);
34+
thing2.plus_one();
35+
assert_eq!(z, 44);
36+
thing.plus_one();
37+
assert_eq!(z, 45);
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
2+
--> $DIR/imply_bounds_from_bounds_param.rs:24:5
3+
|
4+
LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne {
5+
| -- hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
6+
LL | <&'a mut i32 as Callable>::call(y)
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8+
|
9+
help: to declare that `impl PlusOne` captures `'a`, you can add an explicit `'a` lifetime bound
10+
|
11+
LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + 'a {
12+
| ++++
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0700`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// check-pass
2+
3+
#![feature(type_alias_impl_trait)]
4+
fn foo() {
5+
struct Foo<'a> {
6+
x: &'a mut u8,
7+
}
8+
impl<'a> Foo<'a> {
9+
fn foo(&self) -> impl Sized {}
10+
}
11+
// use site
12+
let mut x = 5;
13+
let y = Foo { x: &mut x };
14+
let z = y.foo();
15+
let _a = &x; // invalidate the `&'a mut`in `y`
16+
let _b = z; // this should *not* check that `'a` in the type `Foo<'a>::foo::opaque` is live
17+
}
18+
19+
fn bar() {
20+
struct Foo<'a> {
21+
x: &'a mut u8,
22+
}
23+
24+
// desugared
25+
type FooX<'a> = impl Sized;
26+
impl<'a> Foo<'a> {
27+
fn foo(&self) -> FooX<'a> {}
28+
}
29+
30+
// use site
31+
let mut x = 5;
32+
let y = Foo { x: &mut x };
33+
let z = y.foo();
34+
let _a = &x; // invalidate the `&'a mut`in `y`
35+
let _b = z; // this should *not* check that `'a` in the type `Foo<'a>::foo::opaque` is live
36+
}
37+
38+
fn main() {}

0 commit comments

Comments
 (0)