Skip to content

Commit

Permalink
Do not allow typeck children items to constrain outer RPITs
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jul 19, 2022
1 parent 8bd12e8 commit e8d9f38
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 0 deletions.
29 changes: 29 additions & 0 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/impl-trait/issue-99073-2.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions src/test/ui/impl-trait/issue-99073-2.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 8 additions & 0 deletions src/test/ui/impl-trait/issue-99073.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 14 additions & 0 deletions src/test/ui/impl-trait/issue-99073.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit e8d9f38

Please sign in to comment.