From e8d9f38141a0ee8ac5484783e1fb5c218f9d2eee Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 16 Jul 2022 20:08:04 +0000 Subject: [PATCH 1/2] 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 8e763a02af33f..4776c11e30908 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::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, 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 0000000000000..bebd8286de9fe --- /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 0000000000000..c1e4b823c08e7 --- /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 0000000000000..1d75f6086664f --- /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 0000000000000..b35d58093d5fc --- /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`. From 5a4601fea56502e4f50df046c4205e678397599b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 17 Jul 2022 10:37:23 -0700 Subject: [PATCH 2/2] use opaque_ty_origin_unchecked instead of destructuring HIR --- compiler/rustc_borrowck/src/type_check/mod.rs | 16 ++++------------ compiler/rustc_infer/src/infer/opaque_types.rs | 2 +- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 4776c11e30908..508903049db80 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -227,17 +227,9 @@ pub(crate) fn type_check<'mir, 'tcx>( 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() + if let OpaqueTyOrigin::FnReturn(parent) | OpaqueTyOrigin::AsyncFn(parent) + = infcx.opaque_ty_origin_unchecked(opaque_type_key.def_id, hidden_type.span) + && parent.to_def_id() != body.source.def_id() { infcx .report_mismatched_types( @@ -247,7 +239,7 @@ pub(crate) fn type_check<'mir, 'tcx>( body.source.def_id().expect_local(), ), ), - infcx.tcx.mk_opaque(opaque_type_key.def_id, opaque_type_key.substs), + infcx.tcx.mk_opaque(opaque_type_key.def_id.to_def_id(), opaque_type_key.substs), hidden_type.ty, ty::error::TypeError::Mismatch, ) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 4ee9c4eeda40a..81c3bf5d441f8 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -433,7 +433,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } #[instrument(skip(self), level = "trace")] - fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin { + pub fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin { let origin = match self.tcx.hir().expect_item(def_id).kind { hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin, ref itemkind => {