Do not allow typeck children items to constrain outer RPITs

This commit is contained in:
Michael Goulet
2022-07-16 20:08:04 +00:00
parent 8bd12e8cca
commit e8d9f38141
5 changed files with 83 additions and 0 deletions

View File

@@ -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,

View 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
}

View 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`.

View 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
}

View 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`.