Skip to content

Commit 379ef9b

Browse files
authored
Rollup merge of #121386 - oli-obk:no_higher_ranked_opaques, r=lcnr
test that we do not support higher-ranked regions in opaque type inference We already do all the right checks in `check_opaque_type_parameter_valid`, and we have done so since at least 2 years. I collected the tests from #116935 and #100503 and added some more cc #96146 r? `@lcnr`
2 parents 702225e + 1efb747 commit 379ef9b

File tree

19 files changed

+451
-34
lines changed

19 files changed

+451
-34
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
153153
if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
154154
if prev.ty != ty {
155155
let guar = ty.error_reported().err().unwrap_or_else(|| {
156-
prev.report_mismatch(
157-
&OpaqueHiddenType { ty, span: concrete_type.span },
158-
opaque_type_key.def_id,
159-
infcx.tcx,
160-
)
161-
.emit()
156+
let (Ok(e) | Err(e)) = prev
157+
.build_mismatch_error(
158+
&OpaqueHiddenType { ty, span: concrete_type.span },
159+
opaque_type_key.def_id,
160+
infcx.tcx,
161+
)
162+
.map(|d| d.emit());
163+
e
162164
});
163165
prev.ty = Ty::new_error(infcx.tcx, guar);
164166
}

compiler/rustc_hir_analysis/src/check/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ fn sanity_check_found_hidden_type<'tcx>(
477477
} else {
478478
let span = tcx.def_span(key.def_id);
479479
let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
480-
Err(ty.report_mismatch(&other, key.def_id, tcx).emit())
480+
Err(ty.build_mismatch_error(&other, key.def_id, tcx)?.emit())
481481
}
482482
}
483483

compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs

+25-18
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
5858
// Only check against typeck if we didn't already error
5959
if !hidden.ty.references_error() {
6060
for concrete_type in locator.typeck_types {
61-
if concrete_type.ty != tcx.erase_regions(hidden.ty)
62-
&& !(concrete_type, hidden).references_error()
63-
{
64-
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
61+
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
62+
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
63+
d.emit();
64+
}
6565
}
6666
}
6767
}
@@ -134,10 +134,10 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
134134
// Only check against typeck if we didn't already error
135135
if !hidden.ty.references_error() {
136136
for concrete_type in locator.typeck_types {
137-
if concrete_type.ty != tcx.erase_regions(hidden.ty)
138-
&& !(concrete_type, hidden).references_error()
139-
{
140-
hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
137+
if concrete_type.ty != tcx.erase_regions(hidden.ty) {
138+
if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) {
139+
d.emit();
140+
}
141141
}
142142
}
143143
}
@@ -287,8 +287,10 @@ impl TaitConstraintLocator<'_> {
287287
if let Some(&concrete_type) = borrowck_results.concrete_opaque_types.get(&self.def_id) {
288288
debug!(?concrete_type, "found constraint");
289289
if let Some(prev) = &mut self.found {
290-
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
291-
let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
290+
if concrete_type.ty != prev.ty {
291+
let (Ok(guar) | Err(guar)) = prev
292+
.build_mismatch_error(&concrete_type, self.def_id, self.tcx)
293+
.map(|d| d.emit());
292294
prev.ty = Ty::new_error(self.tcx, guar);
293295
}
294296
} else {
@@ -361,11 +363,13 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
361363
hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
362364
);
363365
if let Some(prev) = &mut hir_opaque_ty {
364-
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
365-
prev.report_mismatch(&concrete_type, def_id, tcx).stash(
366-
tcx.def_span(opaque_type_key.def_id),
367-
StashKey::OpaqueHiddenTypeMismatch,
368-
);
366+
if concrete_type.ty != prev.ty {
367+
if let Ok(d) = prev.build_mismatch_error(&concrete_type, def_id, tcx) {
368+
d.stash(
369+
tcx.def_span(opaque_type_key.def_id),
370+
StashKey::OpaqueHiddenTypeMismatch,
371+
);
372+
}
369373
}
370374
} else {
371375
hir_opaque_ty = Some(concrete_type);
@@ -436,9 +440,12 @@ impl RpitConstraintChecker<'_> {
436440

437441
debug!(?concrete_type, "found constraint");
438442

439-
if concrete_type.ty != self.found.ty && !(concrete_type, self.found).references_error()
440-
{
441-
self.found.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
443+
if concrete_type.ty != self.found.ty {
444+
if let Ok(d) =
445+
self.found.build_mismatch_error(&concrete_type, self.def_id, self.tcx)
446+
{
447+
d.emit();
448+
}
442449
}
443450
}
444451
}

compiler/rustc_hir_typeck/src/writeback.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -589,12 +589,16 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
589589
&& last_opaque_ty.ty != hidden_type.ty
590590
{
591591
assert!(!self.fcx.next_trait_solver());
592-
hidden_type
593-
.report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
594-
.stash(
592+
if let Ok(d) = hidden_type.build_mismatch_error(
593+
&last_opaque_ty,
594+
opaque_type_key.def_id,
595+
self.tcx(),
596+
) {
597+
d.stash(
595598
self.tcx().def_span(opaque_type_key.def_id),
596599
StashKey::OpaqueHiddenTypeMismatch,
597600
);
601+
}
598602
}
599603
}
600604
}

compiler/rustc_middle/src/ty/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -840,31 +840,32 @@ pub struct OpaqueHiddenType<'tcx> {
840840
}
841841

842842
impl<'tcx> OpaqueHiddenType<'tcx> {
843-
pub fn report_mismatch(
843+
pub fn build_mismatch_error(
844844
&self,
845845
other: &Self,
846846
opaque_def_id: LocalDefId,
847847
tcx: TyCtxt<'tcx>,
848-
) -> DiagnosticBuilder<'tcx> {
848+
) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed> {
849849
if let Some(diag) = tcx
850850
.sess
851851
.dcx()
852852
.steal_diagnostic(tcx.def_span(opaque_def_id), StashKey::OpaqueHiddenTypeMismatch)
853853
{
854854
diag.cancel();
855855
}
856+
(self.ty, other.ty).error_reported()?;
856857
// Found different concrete types for the opaque type.
857858
let sub_diag = if self.span == other.span {
858859
TypeMismatchReason::ConflictType { span: self.span }
859860
} else {
860861
TypeMismatchReason::PreviousUse { span: self.span }
861862
};
862-
tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
863+
Ok(tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
863864
self_ty: self.ty,
864865
other_ty: other.ty,
865866
other_span: other.span,
866867
sub: sub_diag,
867-
})
868+
}))
868869
}
869870

870871
#[instrument(level = "debug", skip(tcx), ret)]

compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
9898
query_key: ParamEnvAnd<'tcx, Self>,
9999
infcx: &InferCtxt<'tcx>,
100100
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
101+
span: Span,
101102
) -> Result<
102103
(
103104
Self::QueryResponse,
@@ -118,7 +119,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
118119

119120
let InferOk { value, obligations } = infcx
120121
.instantiate_nll_query_response_and_region_obligations(
121-
&ObligationCause::dummy(),
122+
&ObligationCause::dummy_with_span(span),
122123
old_param_env,
123124
&canonical_var_values,
124125
canonical_result,
@@ -160,7 +161,7 @@ where
160161

161162
let mut region_constraints = QueryRegionConstraints::default();
162163
let (output, error_info, mut obligations, _) =
163-
Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
164+
Q::fully_perform_into(self, infcx, &mut region_constraints, span).map_err(|_| {
164165
infcx.dcx().span_delayed_bug(span, format!("error performing {self:?}"))
165166
})?;
166167

@@ -178,6 +179,7 @@ where
178179
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
179180
infcx,
180181
&mut region_constraints,
182+
span,
181183
) {
182184
Ok(((), _, new, certainty)) => {
183185
obligations.extend(new);

tests/ui/generic-associated-types/issue-90014-tait2.stderr

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
error[E0792]: expected generic lifetime parameter, found `'a`
2+
--> $DIR/issue-90014-tait2.rs:27:9
3+
|
4+
LL | type Fut<'a> = impl Future<Output = ()>;
5+
| -- this generic parameter must be used with a generic lifetime parameter
6+
...
7+
LL | Box::new((async { () },))
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
29

310
error: aborting due to 1 previous error
411

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Regression test for #97099.
2+
// This was an ICE because `impl Sized` captures the lifetime 'a.
3+
4+
trait Trait<E> {
5+
type Assoc;
6+
}
7+
8+
struct Foo;
9+
10+
impl<'a> Trait<&'a ()> for Foo {
11+
type Assoc = ();
12+
}
13+
14+
fn foo() -> impl for<'a> Trait<&'a ()> {
15+
Foo
16+
}
17+
18+
fn bar() -> impl for<'a> Trait<&'a (), Assoc = impl Sized> {
19+
foo()
20+
//~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds
21+
}
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
2+
--> $DIR/higher-ranked-regions-diag.rs:19:5
3+
|
4+
LL | fn bar() -> impl for<'a> Trait<&'a (), Assoc = impl Sized> {
5+
| -- ---------- opaque type defined here
6+
| |
7+
| hidden type `<impl for<'a> Trait<&'a ()> as Trait<&'a ()>>::Assoc` captures the lifetime `'a` as defined here
8+
LL | foo()
9+
| ^^^^^
10+
11+
error: aborting due to 1 previous error
12+
13+
For more information about this error, try `rustc --explain E0700`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Basic tests for opaque type inference under for<_> binders.
2+
3+
#![feature(type_alias_impl_trait)]
4+
5+
trait Trait<'a> {
6+
type Ty;
7+
}
8+
impl<'a, T> Trait<'a> for T {
9+
type Ty = &'a ();
10+
}
11+
12+
mod basic_pass {
13+
use super::*;
14+
type Opq<'a> = impl Sized + 'a;
15+
fn test() -> impl for<'a> Trait<'a, Ty = Opq<'a>> {}
16+
//~^ ERROR: expected generic lifetime parameter, found `'a`
17+
}
18+
19+
mod capture_rpit {
20+
use super::*;
21+
fn test() -> impl for<'a> Trait<'a, Ty = impl Sized> {}
22+
//~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds
23+
}
24+
25+
mod capture_tait {
26+
use super::*;
27+
type Opq0 = impl Sized;
28+
type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0>;
29+
type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
30+
fn test() -> Opq2 {}
31+
//~^ ERROR hidden type for `capture_tait::Opq0` captures lifetime that does not appear in bounds
32+
}
33+
34+
mod capture_tait_complex_pass {
35+
use super::*;
36+
type Opq0<'a> = impl Sized;
37+
type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'b>>; // <- Note 'b
38+
type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
39+
fn test() -> Opq2 {}
40+
//~^ ERROR: expected generic lifetime parameter, found `'a`
41+
}
42+
43+
// Same as the above, but make sure that different placeholder regions are not equal.
44+
mod capture_tait_complex_fail {
45+
use super::*;
46+
type Opq0<'a> = impl Sized;
47+
type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a>>; // <- Note 'a
48+
type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
49+
fn test() -> Opq2 {}
50+
//~^ ERROR hidden type for `capture_tait_complex_fail::Opq0<'a>` captures lifetime that does not appear in bounds
51+
}
52+
53+
// non-defining use because 'static is used.
54+
mod constrain_fail0 {
55+
use super::*;
56+
type Opq0<'a, 'b> = impl Sized;
57+
fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
58+
//~^ ERROR non-defining opaque type use in defining scope
59+
//~| ERROR: expected generic lifetime parameter, found `'a`
60+
}
61+
62+
// non-defining use because generic lifetime is used multiple times.
63+
mod constrain_fail {
64+
use super::*;
65+
type Opq0<'a, 'b> = impl Sized;
66+
fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
67+
//~^ ERROR non-defining opaque type use in defining scope
68+
//~| ERROR: expected generic lifetime parameter, found `'a`
69+
}
70+
71+
mod constrain_pass {
72+
use super::*;
73+
type Opq0<'a, 'b> = impl Sized;
74+
type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a, 'b>>;
75+
type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
76+
fn test() -> Opq2 {}
77+
//~^ ERROR: expected generic lifetime parameter, found `'a`
78+
}
79+
80+
fn main() {}

0 commit comments

Comments
 (0)