Change:
Messing around with a Haskell-like implementation of , I encountered two presumably similar ICEs (would think they're the same, but the error messages are obviously different). The other one is . I'm pretty sure this should be an error, based on the reasoning that returns an opaque type, so, while the output of might be , it also might not (and in this case, isn't), and since only accepts s, should be an error. Note that this implementation throws the ICE even without the main method, but I'm leaving it there for contrast to the other ICE. : Same ICE on nightly: <details<summary<strongBacktrace</strong</summary<p</p</details
This regressed in
I was able to "weaponize" this into a transmute, lol: So the issue here is that, at least in the case of RPITs, we are not checking for opaque type mismatches in closures correctly. The closure, in this example, is able to incorrectly constrain even though in the enclosing function, we define . During mir borrowck, we never check these two together, so we never report a type mismatch. I think I have a fix, though.
WG-prioritization assigning priority (). label -I-prioritize +P-critical

Discussion:
use rustc_infer::infer::{ InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin, }; <ins> use rustc_infer::traits::ObligationCause; </ins> use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::AssertKind;

) .unwrap(); let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); <ins> // Check that RPITs are only constrained in their outermost // function, otherwise report a mismatched types error. 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( &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.to_def_id(), opaque_type_key.substs), hidden_type.ty, ty::error::TypeError::Mismatch, ) .emit(); } </ins> trace!( "finalized opaque type {:?} to {:#?}", opaque_type_key,

} #[instrument(skip(self), level = "trace")] <del> fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin { </del> <ins> pub fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin { </ins> let origin = match self.tcx.hir().expect_item(def_id).kind { hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin, ref itemkind => {

<ins> 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 } </ins>

<ins> 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`. </ins>

<ins> fn main() { let _ = fix(|_: &dyn Fn()| {}); } fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() { move || f(fix(&f)) //~^ ERROR mismatched types } </ins>

<ins> 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`. </ins>