From e8d9f38141a0ee8ac5484783e1fb5c218f9d2eee Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 16 Jul 2022 20:08:04 +0000 Subject: [PATCH] Do not allow typeck children items to constrain outer RPITs --- compiler/rustc_borrowck/src/type_check/mod.rs | 29 +++++++++++++++++++ src/test/ui/impl-trait/issue-99073-2.rs | 17 +++++++++++ src/test/ui/impl-trait/issue-99073-2.stderr | 15 ++++++++++ src/test/ui/impl-trait/issue-99073.rs | 8 +++++ src/test/ui/impl-trait/issue-99073.stderr | 14 +++++++++ 5 files changed, 83 insertions(+) create mode 100644 src/test/ui/impl-trait/issue-99073-2.rs create mode 100644 src/test/ui/impl-trait/issue-99073-2.stderr create mode 100644 src/test/ui/impl-trait/issue-99073.rs create mode 100644 src/test/ui/impl-trait/issue-99073.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 8e763a02af3..4776c11e309 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -21,6 +21,7 @@ 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, diff --git a/src/test/ui/impl-trait/issue-99073-2.rs b/src/test/ui/impl-trait/issue-99073-2.rs new file mode 100644 index 00000000000..bebd8286de9 --- /dev/null +++ b/src/test/ui/impl-trait/issue-99073-2.rs @@ -0,0 +1,17 @@ +use std::fmt::Display; + +fn main() { + test("hi", true); +} + +fn test(t: T, recurse: bool) -> impl Display { + let f = || { + let i: u32 = test::(-1, false); + //~^ ERROR mismatched types + println!("{i}"); + }; + if recurse { + f(); + } + t +} diff --git a/src/test/ui/impl-trait/issue-99073-2.stderr b/src/test/ui/impl-trait/issue-99073-2.stderr new file mode 100644 index 00000000000..c1e4b823c08 --- /dev/null +++ b/src/test/ui/impl-trait/issue-99073-2.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-99073-2.rs:9:22 + | +LL | fn test(t: T, recurse: bool) -> impl Display { + | ------------ the expected opaque type +LL | let f = || { +LL | let i: u32 = test::(-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`. diff --git a/src/test/ui/impl-trait/issue-99073.rs b/src/test/ui/impl-trait/issue-99073.rs new file mode 100644 index 00000000000..1d75f608666 --- /dev/null +++ b/src/test/ui/impl-trait/issue-99073.rs @@ -0,0 +1,8 @@ +fn main() { + let _ = fix(|_: &dyn Fn()| {}); +} + +fn fix(f: F) -> impl Fn() { + move || f(fix(&f)) + //~^ ERROR mismatched types +} diff --git a/src/test/ui/impl-trait/issue-99073.stderr b/src/test/ui/impl-trait/issue-99073.stderr new file mode 100644 index 00000000000..b35d58093d5 --- /dev/null +++ b/src/test/ui/impl-trait/issue-99073.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-99073.rs:6:13 + | +LL | fn fix(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`. -- 2.44.0