Skip to content

Commit 3c3c5da

Browse files
authored
Rollup merge of rust-lang#99345 - compiler-errors:issue-99073-redux, r=oli-obk
Do not allow typeck children items to constrain outer RPITs Fixes rust-lang#99073 in a simpler and more conservative way than rust-lang#99079. Simply raise a mismatched types error if we try to constrain an RPIT in an item that isn't the RPIT's parent. r? `@oli-obk`
2 parents 90c59e7 + 5a4601f commit 3c3c5da

File tree

6 files changed

+76
-1
lines changed

6 files changed

+76
-1
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+21
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
2121
use rustc_infer::infer::{
2222
InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
2323
};
24+
use rustc_infer::traits::ObligationCause;
2425
use rustc_middle::mir::tcx::PlaceTy;
2526
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
2627
use rustc_middle::mir::AssertKind;
@@ -224,6 +225,26 @@ pub(crate) fn type_check<'mir, 'tcx>(
224225
)
225226
.unwrap();
226227
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
228+
// Check that RPITs are only constrained in their outermost
229+
// function, otherwise report a mismatched types error.
230+
if let OpaqueTyOrigin::FnReturn(parent) | OpaqueTyOrigin::AsyncFn(parent)
231+
= infcx.opaque_ty_origin_unchecked(opaque_type_key.def_id, hidden_type.span)
232+
&& parent.to_def_id() != body.source.def_id()
233+
{
234+
infcx
235+
.report_mismatched_types(
236+
&ObligationCause::misc(
237+
hidden_type.span,
238+
infcx.tcx.hir().local_def_id_to_hir_id(
239+
body.source.def_id().expect_local(),
240+
),
241+
),
242+
infcx.tcx.mk_opaque(opaque_type_key.def_id.to_def_id(), opaque_type_key.substs),
243+
hidden_type.ty,
244+
ty::error::TypeError::Mismatch,
245+
)
246+
.emit();
247+
}
227248
trace!(
228249
"finalized opaque type {:?} to {:#?}",
229250
opaque_type_key,

compiler/rustc_infer/src/infer/opaque_types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
433433
}
434434

435435
#[instrument(skip(self), level = "trace")]
436-
fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin {
436+
pub fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin {
437437
let origin = match self.tcx.hir().expect_item(def_id).kind {
438438
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
439439
ref itemkind => {
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use std::fmt::Display;
2+
3+
fn main() {
4+
test("hi", true);
5+
}
6+
7+
fn test<T: Display>(t: T, recurse: bool) -> impl Display {
8+
let f = || {
9+
let i: u32 = test::<i32>(-1, false);
10+
//~^ ERROR mismatched types
11+
println!("{i}");
12+
};
13+
if recurse {
14+
f();
15+
}
16+
t
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-99073-2.rs:9:22
3+
|
4+
LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
5+
| ------------ the expected opaque type
6+
LL | let f = || {
7+
LL | let i: u32 = test::<i32>(-1, false);
8+
| ^^^^^^^^^^^^^^^^^^^^^^ types differ
9+
|
10+
= note: expected opaque type `impl std::fmt::Display`
11+
found type `u32`
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/impl-trait/issue-99073.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn main() {
2+
let _ = fix(|_: &dyn Fn()| {});
3+
}
4+
5+
fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
6+
move || f(fix(&f))
7+
//~^ ERROR mismatched types
8+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-99073.rs:6:13
3+
|
4+
LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
5+
| --------- the expected opaque type
6+
LL | move || f(fix(&f))
7+
| ^^^^^^^^^^ types differ
8+
|
9+
= note: expected opaque type `impl Fn()`
10+
found type parameter `G`
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)