Do not allow typeck children items to constrain outer RPITs
This commit is contained in:
@@ -21,6 +21,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
|
||||
use rustc_infer::infer::{
|
||||
InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
|
||||
};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::AssertKind;
|
||||
@@ -224,6 +225,34 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
)
|
||||
.unwrap();
|
||||
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
|
||||
// Check that RPITs are only constrained in their outermost
|
||||
// function, otherwise report a mismatched types error.
|
||||
if let hir::Node::Item(hir::Item {
|
||||
kind:
|
||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
origin:
|
||||
hir::OpaqueTyOrigin::AsyncFn(parent)
|
||||
| hir::OpaqueTyOrigin::FnReturn(parent),
|
||||
..
|
||||
}),
|
||||
..
|
||||
}) = infcx.tcx.hir().get_by_def_id(opaque_type_key.def_id.expect_local()) &&
|
||||
parent.to_def_id() != body.source.def_id()
|
||||
{
|
||||
infcx
|
||||
.report_mismatched_types(
|
||||
&ObligationCause::misc(
|
||||
hidden_type.span,
|
||||
infcx.tcx.hir().local_def_id_to_hir_id(
|
||||
body.source.def_id().expect_local(),
|
||||
),
|
||||
),
|
||||
infcx.tcx.mk_opaque(opaque_type_key.def_id, opaque_type_key.substs),
|
||||
hidden_type.ty,
|
||||
ty::error::TypeError::Mismatch,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
trace!(
|
||||
"finalized opaque type {:?} to {:#?}",
|
||||
opaque_type_key,
|
||||
|
||||
17
src/test/ui/impl-trait/issue-99073-2.rs
Normal file
17
src/test/ui/impl-trait/issue-99073-2.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
fn main() {
|
||||
test("hi", true);
|
||||
}
|
||||
|
||||
fn test<T: Display>(t: T, recurse: bool) -> impl Display {
|
||||
let f = || {
|
||||
let i: u32 = test::<i32>(-1, false);
|
||||
//~^ ERROR mismatched types
|
||||
println!("{i}");
|
||||
};
|
||||
if recurse {
|
||||
f();
|
||||
}
|
||||
t
|
||||
}
|
||||
15
src/test/ui/impl-trait/issue-99073-2.stderr
Normal file
15
src/test/ui/impl-trait/issue-99073-2.stderr
Normal file
@@ -0,0 +1,15 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-99073-2.rs:9:22
|
||||
|
|
||||
LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
|
||||
| ------------ the expected opaque type
|
||||
LL | let f = || {
|
||||
LL | let i: u32 = test::<i32>(-1, false);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
|
||||
= note: expected opaque type `impl std::fmt::Display`
|
||||
found type `u32`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
8
src/test/ui/impl-trait/issue-99073.rs
Normal file
8
src/test/ui/impl-trait/issue-99073.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
let _ = fix(|_: &dyn Fn()| {});
|
||||
}
|
||||
|
||||
fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
|
||||
move || f(fix(&f))
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
14
src/test/ui/impl-trait/issue-99073.stderr
Normal file
14
src/test/ui/impl-trait/issue-99073.stderr
Normal file
@@ -0,0 +1,14 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-99073.rs:6:13
|
||||
|
|
||||
LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
|
||||
| --------- the expected opaque type
|
||||
LL | move || f(fix(&f))
|
||||
| ^^^^^^^^^^ types differ
|
||||
|
|
||||
= note: expected opaque type `impl Fn()`
|
||||
found type parameter `G`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
Reference in New Issue
Block a user