Skip to content

Commit 7c6876f

Browse files
committed
simplify check_unique
1 parent 6b6ed2e commit 7c6876f

10 files changed

+52
-250
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+25-70
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use rustc_infer::traits::{Obligation, ObligationCause};
99
use rustc_macros::extension;
1010
use rustc_middle::traits::DefiningAnchor;
1111
use rustc_middle::ty::visit::TypeVisitableExt;
12-
use rustc_middle::ty::RegionVid;
1312
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
1413
use rustc_middle::ty::{GenericArgKind, GenericArgs};
1514
use rustc_span::Span;
@@ -23,73 +22,6 @@ use crate::universal_regions::RegionClassification;
2322
use super::RegionInferenceContext;
2423

2524
impl<'tcx> RegionInferenceContext<'tcx> {
26-
fn universal_name(&self, vid: ty::RegionVid) -> Option<ty::Region<'tcx>> {
27-
let scc = self.constraint_sccs.scc(vid);
28-
self.scc_values
29-
.universal_regions_outlived_by(scc)
30-
.find_map(|lb| self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?))
31-
}
32-
33-
fn generic_arg_to_region(&self, arg: ty::GenericArg<'tcx>) -> Option<RegionVid> {
34-
let region = arg.as_region()?;
35-
36-
if let ty::RePlaceholder(..) = region.kind() {
37-
None
38-
} else {
39-
Some(self.to_region_vid(region))
40-
}
41-
}
42-
43-
/// Check that all opaque types have the same region parameters if they have the same
44-
/// non-region parameters. This is necessary because within the new solver we perform various query operations
45-
/// modulo regions, and thus could unsoundly select some impls that don't hold.
46-
fn check_unique(
47-
&self,
48-
infcx: &InferCtxt<'tcx>,
49-
opaque_ty_decls: &FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
50-
) {
51-
for (i, (a, a_ty)) in opaque_ty_decls.iter().enumerate() {
52-
for (b, b_ty) in opaque_ty_decls.iter().skip(i + 1) {
53-
if a.def_id != b.def_id {
54-
continue;
55-
}
56-
// Non-lifetime params differ -> ok
57-
if infcx.tcx.erase_regions(a.args) != infcx.tcx.erase_regions(b.args) {
58-
continue;
59-
}
60-
trace!(?a, ?b);
61-
for (a, b) in a.args.iter().zip(b.args) {
62-
trace!(?a, ?b);
63-
let Some(r1) = self.generic_arg_to_region(a) else {
64-
continue;
65-
};
66-
let Some(r2) = self.generic_arg_to_region(b) else {
67-
continue;
68-
};
69-
if self.eval_equal(r1, r2) {
70-
continue;
71-
}
72-
73-
// Ignore non-universal regions because they result in an error eventually.
74-
// FIXME(aliemjay): This logic will be rewritten in a later commit.
75-
let Some(r1) = self.universal_name(r1) else {
76-
continue;
77-
};
78-
let Some(r2) = self.universal_name(r2) else {
79-
continue;
80-
};
81-
82-
infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
83-
arg: r1.into(),
84-
prev: r2.into(),
85-
span: a_ty.span,
86-
prev_span: b_ty.span,
87-
});
88-
}
89-
}
90-
}
91-
}
92-
9325
/// Resolve any opaque types that were encountered while borrow checking
9426
/// this item. This is then used to get the type in the `type_of` query.
9527
///
@@ -139,9 +71,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
13971
infcx: &InferCtxt<'tcx>,
14072
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
14173
) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
142-
self.check_unique(infcx, &opaque_ty_decls);
143-
14474
let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
75+
let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
76+
FxIndexMap::default();
14577

14678
for (opaque_type_key, concrete_type) in opaque_ty_decls {
14779
debug!(?opaque_type_key, ?concrete_type);
@@ -228,6 +160,29 @@ impl<'tcx> RegionInferenceContext<'tcx> {
228160
OpaqueHiddenType { ty, span: concrete_type.span },
229161
);
230162
}
163+
164+
// Check that all opaque types have the same region parameters if they have the same
165+
// non-region parameters. This is necessary because within the new solver we perform
166+
// various query operations modulo regions, and thus could unsoundly select some impls
167+
// that don't hold.
168+
if !ty.references_error()
169+
&& let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
170+
infcx.tcx.erase_regions(opaque_type_key),
171+
(opaque_type_key, concrete_type.span),
172+
)
173+
&& let Some((arg1, arg2)) = std::iter::zip(
174+
prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
175+
opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
176+
)
177+
.find(|(arg1, arg2)| arg1 != arg2)
178+
{
179+
infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
180+
arg: arg1,
181+
prev: arg2,
182+
span: prev_span,
183+
prev_span: concrete_type.span,
184+
});
185+
}
231186
}
232187
result
233188
}

tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0792]: expected generic lifetime parameter, found `'_`
2-
--> $DIR/defining-use-captured-non-universal-region.rs:15:18
2+
--> $DIR/defining-use-captured-non-universal-region.rs:14:18
33
|
44
LL | fn foo<'a>() -> impl Sized + 'a {
55
| -- this generic parameter must be used with a generic lifetime parameter

tests/ui/impl-trait/defining-use-captured-non-universal-region.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
fn foo<'a>() -> impl Sized + 'a {
99
#[cfg(statik)]
1010
let i: i32 = foo::<'static>();
11-
//[statik]~^ ERROR opaque type used twice with different lifetimes
12-
//[statik]~| ERROR opaque type used twice with different lifetimes
11+
//[statik]~^ ERROR expected generic lifetime parameter, found `'static`
1312

1413
#[cfg(infer)]
1514
let i: i32 = foo::<'_>();
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,12 @@
1-
error: opaque type used twice with different lifetimes
2-
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
3-
|
4-
LL | let i: i32 = foo::<'static>();
5-
| ^^^^^^^^^^^^^^^^ lifetime `'static` used here
6-
...
7-
LL | i
8-
| - lifetime `'a` previously used here
9-
|
10-
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
11-
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
12-
|
13-
LL | let i: i32 = foo::<'static>();
14-
| ^^^^^^^^^^^^^^^^
15-
16-
error: opaque type used twice with different lifetimes
17-
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
18-
|
19-
LL | let i: i32 = foo::<'static>();
20-
| ^^^^^^^^^^^^^^^^ lifetime `'static` used here
21-
...
22-
LL | i
23-
| - lifetime `'a` previously used here
24-
|
25-
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
1+
error[E0792]: expected generic lifetime parameter, found `'static`
262
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
273
|
4+
LL | fn foo<'a>() -> impl Sized + 'a {
5+
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
6+
LL | #[cfg(statik)]
287
LL | let i: i32 = foo::<'static>();
298
| ^^^^^^^^^^^^^^^^
30-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
319

32-
error: aborting due to 2 previous errors
10+
error: aborting due to 1 previous error
3311

12+
For more information about this error, try `rustc --explain E0792`.

tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mod statik {
1212
// invalid defining use: Opaque<'static> := ()
1313
fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
1414
let _: () = foo(Lt::<'static>::None);
15-
//~^ ERROR opaque type used twice with different lifetimes
15+
//~^ ERROR expected generic lifetime parameter, found `'static`
1616
}
1717
}
1818

@@ -31,7 +31,7 @@ mod equal {
3131
// because of the use of equal lifetimes in args
3232
fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
3333
let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
34-
//~^ ERROR opaque type used twice with different lifetimes
34+
//~^ ERROR non-defining opaque type use in defining scope
3535
}
3636
}
3737

tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr

+10-24
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,8 @@
1-
error: opaque type used twice with different lifetimes
2-
--> $DIR/non-defining-use-lifetimes.rs:14:16
3-
|
4-
LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
5-
| ______________________________________________-
6-
LL | | let _: () = foo(Lt::<'static>::None);
7-
| | ^^ lifetime `'static` used here
8-
LL | |
9-
LL | | }
10-
| |_____- lifetime `'a` previously used here
11-
|
12-
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
1+
error[E0792]: expected generic lifetime parameter, found `'static`
132
--> $DIR/non-defining-use-lifetimes.rs:14:16
143
|
4+
LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
5+
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
156
LL | let _: () = foo(Lt::<'static>::None);
167
| ^^
178

@@ -23,22 +14,17 @@ LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
2314
LL | let _: () = foo(Lt::<'_>::None);
2415
| ^^
2516

26-
error: opaque type used twice with different lifetimes
27-
--> $DIR/non-defining-use-lifetimes.rs:33:16
28-
|
29-
LL | fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
30-
| __________________________________________________________________-
31-
LL | | let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
32-
| | ^^ lifetime `'a` used here
33-
LL | |
34-
LL | | }
35-
| |_____- lifetime `'b` previously used here
36-
|
37-
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
17+
error: non-defining opaque type use in defining scope
3818
--> $DIR/non-defining-use-lifetimes.rs:33:16
3919
|
4020
LL | let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
4121
| ^^
22+
|
23+
note: lifetime used multiple times
24+
--> $DIR/non-defining-use-lifetimes.rs:32:58
25+
|
26+
LL | fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
27+
| ^^ ^^
4228

4329
error: aborting due to 3 previous errors
4430

tests/ui/type-alias-impl-trait/lifetime_mismatch.rs

-4
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@ type Foo<'a> = impl Sized;
55
fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (Foo<'a>, Foo<'b>) {
66
(x, y)
77
//~^ ERROR opaque type used twice with different lifetimes
8-
//~| ERROR opaque type used twice with different lifetimes
98
}
109

1110
type Bar<'a, 'b> = impl std::fmt::Debug;
1211

1312
fn bar<'x, 'y>(i: &'x i32, j: &'y i32) -> (Bar<'x, 'y>, Bar<'y, 'x>) {
1413
(i, j)
1514
//~^ ERROR opaque type used twice with different lifetimes
16-
//~| ERROR opaque type used twice with different lifetimes
17-
//~| ERROR opaque type used twice with different lifetimes
18-
//~| ERROR opaque type used twice with different lifetimes
1915
}
2016

2117
fn main() {

tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr

+3-66
Original file line numberDiff line numberDiff line change
@@ -14,53 +14,7 @@ LL | (x, y)
1414
| ^^^^^^
1515

1616
error: opaque type used twice with different lifetimes
17-
--> $DIR/lifetime_mismatch.rs:6:5
18-
|
19-
LL | (x, y)
20-
| ^^^^^^
21-
| |
22-
| lifetime `'a` used here
23-
| lifetime `'b` previously used here
24-
|
25-
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
26-
--> $DIR/lifetime_mismatch.rs:6:5
27-
|
28-
LL | (x, y)
29-
| ^^^^^^
30-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
31-
32-
error: opaque type used twice with different lifetimes
33-
--> $DIR/lifetime_mismatch.rs:14:5
34-
|
35-
LL | (i, j)
36-
| ^^^^^^
37-
| |
38-
| lifetime `'x` used here
39-
| lifetime `'y` previously used here
40-
|
41-
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
42-
--> $DIR/lifetime_mismatch.rs:14:5
43-
|
44-
LL | (i, j)
45-
| ^^^^^^
46-
47-
error: opaque type used twice with different lifetimes
48-
--> $DIR/lifetime_mismatch.rs:14:5
49-
|
50-
LL | (i, j)
51-
| ^^^^^^
52-
| |
53-
| lifetime `'y` used here
54-
| lifetime `'x` previously used here
55-
|
56-
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
57-
--> $DIR/lifetime_mismatch.rs:14:5
58-
|
59-
LL | (i, j)
60-
| ^^^^^^
61-
62-
error: opaque type used twice with different lifetimes
63-
--> $DIR/lifetime_mismatch.rs:14:5
17+
--> $DIR/lifetime_mismatch.rs:13:5
6418
|
6519
LL | (i, j)
6620
| ^^^^^^
@@ -69,27 +23,10 @@ LL | (i, j)
6923
| lifetime `'y` previously used here
7024
|
7125
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
72-
--> $DIR/lifetime_mismatch.rs:14:5
73-
|
74-
LL | (i, j)
75-
| ^^^^^^
76-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
77-
78-
error: opaque type used twice with different lifetimes
79-
--> $DIR/lifetime_mismatch.rs:14:5
80-
|
81-
LL | (i, j)
82-
| ^^^^^^
83-
| |
84-
| lifetime `'y` used here
85-
| lifetime `'x` previously used here
86-
|
87-
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
88-
--> $DIR/lifetime_mismatch.rs:14:5
26+
--> $DIR/lifetime_mismatch.rs:13:5
8927
|
9028
LL | (i, j)
9129
| ^^^^^^
92-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
9330

94-
error: aborting due to 6 previous errors
31+
error: aborting due to 2 previous errors
9532

tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@
33
type Foo<'a, 'b> = impl std::fmt::Debug;
44

55
fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
6-
(i, i)
6+
(i, j)
77
//~^ ERROR opaque type used twice with different lifetimes
8-
//~| ERROR opaque type used twice with different lifetimes
9-
//~| ERROR opaque type used twice with different lifetimes
10-
//~| ERROR opaque type used twice with different lifetimes
118
}
129

1310
fn main() {}

0 commit comments

Comments
 (0)