Skip to content

Commit e8d9f38

Browse files
Do not allow typeck children items to constrain outer RPITs
1 parent 8bd12e8 commit e8d9f38

File tree

5 files changed

+83
-0
lines changed

5 files changed

+83
-0
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
2121
use rustc_infer::infer::{
2222
InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
2323
};
24+
use rustc_infer::traits::ObligationCause;
2425
use rustc_middle::mir::tcx::PlaceTy;
2526
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
2627
use rustc_middle::mir::AssertKind;
@@ -224,6 +225,34 @@ pub(crate) fn type_check<'mir, 'tcx>(
224225
)
225226
.unwrap();
226227
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
228+
// Check that RPITs are only constrained in their outermost
229+
// function, otherwise report a mismatched types error.
230+
if let hir::Node::Item(hir::Item {
231+
kind:
232+
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
233+
origin:
234+
hir::OpaqueTyOrigin::AsyncFn(parent)
235+
| hir::OpaqueTyOrigin::FnReturn(parent),
236+
..
237+
}),
238+
..
239+
}) = infcx.tcx.hir().get_by_def_id(opaque_type_key.def_id.expect_local()) &&
240+
parent.to_def_id() != body.source.def_id()
241+
{
242+
infcx
243+
.report_mismatched_types(
244+
&ObligationCause::misc(
245+
hidden_type.span,
246+
infcx.tcx.hir().local_def_id_to_hir_id(
247+
body.source.def_id().expect_local(),
248+
),
249+
),
250+
infcx.tcx.mk_opaque(opaque_type_key.def_id, opaque_type_key.substs),
251+
hidden_type.ty,
252+
ty::error::TypeError::Mismatch,
253+
)
254+
.emit();
255+
}
227256
trace!(
228257
"finalized opaque type {:?} to {:#?}",
229258
opaque_type_key,
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use std::fmt::Display;
2+
3+
fn main() {
4+
test("hi", true);
5+
}
6+
7+
fn test<T: Display>(t: T, recurse: bool) -> impl Display {
8+
let f = || {
9+
let i: u32 = test::<i32>(-1, false);
10+
//~^ ERROR mismatched types
11+
println!("{i}");
12+
};
13+
if recurse {
14+
f();
15+
}
16+
t
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-99073-2.rs:9:22
3+
|
4+
LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
5+
| ------------ the expected opaque type
6+
LL | let f = || {
7+
LL | let i: u32 = test::<i32>(-1, false);
8+
| ^^^^^^^^^^^^^^^^^^^^^^ types differ
9+
|
10+
= note: expected opaque type `impl std::fmt::Display`
11+
found type `u32`
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/impl-trait/issue-99073.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn main() {
2+
let _ = fix(|_: &dyn Fn()| {});
3+
}
4+
5+
fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
6+
move || f(fix(&f))
7+
//~^ ERROR mismatched types
8+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-99073.rs:6:13
3+
|
4+
LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
5+
| --------- the expected opaque type
6+
LL | move || f(fix(&f))
7+
| ^^^^^^^^^^ types differ
8+
|
9+
= note: expected opaque type `impl Fn()`
10+
found type parameter `G`
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)