Skip to content

Commit f781a78

Browse files
committed
Auto merge of #129021 - compiler-errors:ptr-cast-outlives, r=<try>
Check WF of source type's signature on fn pointer cast TODO: description r? lcnr
2 parents e08b80c + aa3574c commit f781a78

11 files changed

+124
-20
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+50-10
Original file line numberDiff line numberDiff line change
@@ -1978,28 +1978,68 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
19781978

19791979
match cast_kind {
19801980
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
1981-
let fn_sig = op.ty(body, tcx).fn_sig(tcx);
1981+
let src_sig = op.ty(body, tcx).fn_sig(tcx);
1982+
1983+
// FIXME: Explained higher-ranked case.
1984+
if src_sig.has_bound_regions()
1985+
&& let ty::FnPtr(target_sig) = *ty.kind()
1986+
&& let Some(target_sig) = target_sig.no_bound_vars()
1987+
{
1988+
let src_sig = self.infcx.instantiate_binder_with_fresh_vars(
1989+
span,
1990+
BoundRegionConversionTime::HigherRankedType,
1991+
src_sig,
1992+
);
1993+
let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig));
1994+
self.prove_predicate(
1995+
ty::ClauseKind::WellFormed(src_ty.into()),
1996+
location.to_locations(),
1997+
ConstraintCategory::Cast { unsize_to: None },
1998+
);
1999+
2000+
let src_ty = self.normalize(src_ty, location);
2001+
if let Err(terr) = self.sub_types(
2002+
src_ty,
2003+
*ty,
2004+
location.to_locations(),
2005+
ConstraintCategory::Cast { unsize_to: None },
2006+
) {
2007+
span_mirbug!(
2008+
self,
2009+
rvalue,
2010+
"equating {:?} with {:?} yields {:?}",
2011+
target_sig,
2012+
src_sig,
2013+
terr
2014+
);
2015+
};
2016+
}
2017+
2018+
let src_ty = Ty::new_fn_ptr(tcx, src_sig);
2019+
// FIXME: Explain why this is needed.
2020+
self.prove_predicate(
2021+
ty::ClauseKind::WellFormed(src_ty.into()),
2022+
location.to_locations(),
2023+
ConstraintCategory::Cast { unsize_to: None },
2024+
);
19822025

19832026
// The type that we see in the fcx is like
19842027
// `foo::<'a, 'b>`, where `foo` is the path to a
19852028
// function definition. When we extract the
19862029
// signature, it comes from the `fn_sig` query,
19872030
// and hence may contain unnormalized results.
1988-
let fn_sig = self.normalize(fn_sig, location);
1989-
1990-
let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig);
1991-
1992-
if let Err(terr) = self.eq_types(
2031+
let src_ty = self.normalize(src_ty, location);
2032+
if let Err(terr) = self.sub_types(
2033+
src_ty,
19932034
*ty,
1994-
ty_fn_ptr_from,
19952035
location.to_locations(),
19962036
ConstraintCategory::Cast { unsize_to: None },
19972037
) {
19982038
span_mirbug!(
19992039
self,
20002040
rvalue,
20012041
"equating {:?} with {:?} yields {:?}",
2002-
ty_fn_ptr_from,
2042+
src_ty,
20032043
ty,
20042044
terr
20052045
);
@@ -2014,9 +2054,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20142054
let ty_fn_ptr_from =
20152055
Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *safety));
20162056

2017-
if let Err(terr) = self.eq_types(
2018-
*ty,
2057+
if let Err(terr) = self.sub_types(
20192058
ty_fn_ptr_from,
2059+
*ty,
20202060
location.to_locations(),
20212061
ConstraintCategory::Cast { unsize_to: None },
20222062
) {

compiler/rustc_hir_typeck/src/coercion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
137137
at.lub(DefineOpaqueTypes::Yes, b, a)
138138
} else {
139139
at.sup(DefineOpaqueTypes::Yes, b, a)
140-
.map(|InferOk { value: (), obligations }| InferOk { value: a, obligations })
140+
.map(|InferOk { value: (), obligations }| InferOk { value: b, obligations })
141141
};
142142

143143
// In the new solver, lazy norm may allow us to shallowly equate

tests/ui/impl-trait/recursive-ice-101862.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ LL | vec![].append(&mut ice(x.as_ref()));
1111
= note: `#[warn(unconditional_recursion)]` on by default
1212

1313
error[E0792]: expected generic type parameter, found `&str`
14-
--> $DIR/recursive-ice-101862.rs:6:5
14+
--> $DIR/recursive-ice-101862.rs:6:19
1515
|
1616
LL | pub fn ice(x: impl AsRef<str>) -> impl IntoIterator<Item = ()> {
1717
| --------------- this generic parameter must be used with a generic type parameter
1818
LL |
1919
LL | vec![].append(&mut ice(x.as_ref()));
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
| ^^^^^^^^^^^^^^^^^^^^
2121

2222
error: aborting due to 1 previous error; 1 warning emitted
2323

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
static UNIT: &'static &'static () = &&();
2+
3+
fn foo<'a: 'a, 'b: 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
4+
5+
fn bad<'a, T>(x: &'a T) -> &'static T {
6+
let f: fn(_, &'a T) -> &'static T = foo;
7+
//~^ ERROR lifetime may not live long enough
8+
f(UNIT, x)
9+
}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/implied-bounds-on-nested-references-plus-variance-early-bound.rs:6:12
3+
|
4+
LL | fn bad<'a, T>(x: &'a T) -> &'static T {
5+
| -- lifetime `'a` defined here
6+
LL | let f: fn(_, &'a T) -> &'static T = foo;
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
8+
9+
error: aborting due to 1 previous error
10+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
trait ToArg<T> {
2+
type Arg;
3+
}
4+
impl<T, U> ToArg<T> for U {
5+
type Arg = T;
6+
}
7+
8+
fn extend_inner<'a, 'b>(x: &'a str) -> <&'b &'a () as ToArg<&'b str>>::Arg { x }
9+
fn extend<'a, 'b>(x: &'a str) -> &'b str {
10+
(extend_inner as fn(_) -> _)(x)
11+
//~^ ERROR lifetime may not live long enough
12+
}
13+
14+
fn main() {
15+
let y = extend(&String::from("Hello World"));
16+
println!("{}", y);
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/implied-bounds-on-nested-references-plus-variance-unnormalized.rs:10:5
3+
|
4+
LL | fn extend<'a, 'b>(x: &'a str) -> &'b str {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
LL | (extend_inner as fn(_) -> _)(x)
9+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
10+
|
11+
= help: consider adding the following bound: `'a: 'b`
12+
13+
error: aborting due to 1 previous error
14+

tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
1-
//@ check-pass
2-
//@ known-bug: #25860
3-
4-
// Should fail. The combination of variance and implied bounds for nested
5-
// references allows us to infer a longer lifetime than we can prove.
6-
71
static UNIT: &'static &'static () = &&();
82

93
fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
104

115
fn bad<'a, T>(x: &'a T) -> &'static T {
126
let f: fn(_, &'a T) -> &'static T = foo;
7+
//~^ ERROR lifetime may not live long enough
138
f(UNIT, x)
149
}
1510

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/implied-bounds-on-nested-references-plus-variance.rs:6:12
3+
|
4+
LL | fn bad<'a, T>(x: &'a T) -> &'static T {
5+
| -- lifetime `'a` defined here
6+
LL | let f: fn(_, &'a T) -> &'static T = foo;
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
8+
9+
error: aborting due to 1 previous error
10+

tests/ui/traits/next-solver/alias-bound-unsound.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,6 @@ fn main() {
2727
//~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
2828
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
2929
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
30+
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
3031
println!("{x}");
3132
}

tests/ui/traits/next-solver/alias-bound-unsound.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ LL | drop(<() as Foo>::copy_me(&x));
4444
|
4545
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
4646

47-
error: aborting due to 6 previous errors
47+
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
48+
--> $DIR/alias-bound-unsound.rs:24:31
49+
|
50+
LL | drop(<() as Foo>::copy_me(&x));
51+
| ^^
52+
53+
error: aborting due to 7 previous errors
4854

4955
For more information about this error, try `rustc --explain E0275`.

0 commit comments

Comments
 (0)