]> git.lizzy.rs Git - rust.git/commitdiff
Do not allow typeck children items to constrain outer RPITs
authorMichael Goulet <michael@errs.io>
Sat, 16 Jul 2022 20:08:04 +0000 (20:08 +0000)
committerMichael Goulet <michael@errs.io>
Tue, 19 Jul 2022 16:22:33 +0000 (16:22 +0000)
compiler/rustc_borrowck/src/type_check/mod.rs
src/test/ui/impl-trait/issue-99073-2.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-99073-2.stderr [new file with mode: 0644]
src/test/ui/impl-trait/issue-99073.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-99073.stderr [new file with mode: 0644]

index 8e763a02af33f11b13726a65a77a0b014d0440eb..4776c11e309082d90a229fde4c696e56b3b83af0 100644 (file)
@@ -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 (file)
index 0000000..bebd828
--- /dev/null
@@ -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
+}
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 (file)
index 0000000..c1e4b82
--- /dev/null
@@ -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`.
diff --git a/src/test/ui/impl-trait/issue-99073.rs b/src/test/ui/impl-trait/issue-99073.rs
new file mode 100644 (file)
index 0000000..1d75f60
--- /dev/null
@@ -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
+}
diff --git a/src/test/ui/impl-trait/issue-99073.stderr b/src/test/ui/impl-trait/issue-99073.stderr
new file mode 100644 (file)
index 0000000..b35d580
--- /dev/null
@@ -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`.