mirror of https://github.com/rust-lang/rust.git
simplify check_unique
This commit is contained in:
parent
6b6ed2ea28
commit
7c6876f9a9
|
@ -9,7 +9,6 @@ use rustc_infer::traits::{Obligation, ObligationCause};
|
|||
use rustc_macros::extension;
|
||||
use rustc_middle::traits::DefiningAnchor;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::RegionVid;
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{GenericArgKind, GenericArgs};
|
||||
use rustc_span::Span;
|
||||
|
@ -23,73 +22,6 @@ use crate::universal_regions::RegionClassification;
|
|||
use super::RegionInferenceContext;
|
||||
|
||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
fn universal_name(&self, vid: ty::RegionVid) -> Option<ty::Region<'tcx>> {
|
||||
let scc = self.constraint_sccs.scc(vid);
|
||||
self.scc_values
|
||||
.universal_regions_outlived_by(scc)
|
||||
.find_map(|lb| self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?))
|
||||
}
|
||||
|
||||
fn generic_arg_to_region(&self, arg: ty::GenericArg<'tcx>) -> Option<RegionVid> {
|
||||
let region = arg.as_region()?;
|
||||
|
||||
if let ty::RePlaceholder(..) = region.kind() {
|
||||
None
|
||||
} else {
|
||||
Some(self.to_region_vid(region))
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that all opaque types have the same region parameters if they have the same
|
||||
/// non-region parameters. This is necessary because within the new solver we perform various query operations
|
||||
/// modulo regions, and thus could unsoundly select some impls that don't hold.
|
||||
fn check_unique(
|
||||
&self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
opaque_ty_decls: &FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
) {
|
||||
for (i, (a, a_ty)) in opaque_ty_decls.iter().enumerate() {
|
||||
for (b, b_ty) in opaque_ty_decls.iter().skip(i + 1) {
|
||||
if a.def_id != b.def_id {
|
||||
continue;
|
||||
}
|
||||
// Non-lifetime params differ -> ok
|
||||
if infcx.tcx.erase_regions(a.args) != infcx.tcx.erase_regions(b.args) {
|
||||
continue;
|
||||
}
|
||||
trace!(?a, ?b);
|
||||
for (a, b) in a.args.iter().zip(b.args) {
|
||||
trace!(?a, ?b);
|
||||
let Some(r1) = self.generic_arg_to_region(a) else {
|
||||
continue;
|
||||
};
|
||||
let Some(r2) = self.generic_arg_to_region(b) else {
|
||||
continue;
|
||||
};
|
||||
if self.eval_equal(r1, r2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore non-universal regions because they result in an error eventually.
|
||||
// FIXME(aliemjay): This logic will be rewritten in a later commit.
|
||||
let Some(r1) = self.universal_name(r1) else {
|
||||
continue;
|
||||
};
|
||||
let Some(r2) = self.universal_name(r2) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
|
||||
arg: r1.into(),
|
||||
prev: r2.into(),
|
||||
span: a_ty.span,
|
||||
prev_span: b_ty.span,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve any opaque types that were encountered while borrow checking
|
||||
/// this item. This is then used to get the type in the `type_of` query.
|
||||
///
|
||||
|
@ -139,9 +71,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
infcx: &InferCtxt<'tcx>,
|
||||
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
|
||||
self.check_unique(infcx, &opaque_ty_decls);
|
||||
|
||||
let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
|
||||
let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
|
||||
FxIndexMap::default();
|
||||
|
||||
for (opaque_type_key, concrete_type) in opaque_ty_decls {
|
||||
debug!(?opaque_type_key, ?concrete_type);
|
||||
|
@ -228,6 +160,29 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
OpaqueHiddenType { ty, span: concrete_type.span },
|
||||
);
|
||||
}
|
||||
|
||||
// Check that all opaque types have the same region parameters if they have the same
|
||||
// non-region parameters. This is necessary because within the new solver we perform
|
||||
// various query operations modulo regions, and thus could unsoundly select some impls
|
||||
// that don't hold.
|
||||
if !ty.references_error()
|
||||
&& let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
|
||||
infcx.tcx.erase_regions(opaque_type_key),
|
||||
(opaque_type_key, concrete_type.span),
|
||||
)
|
||||
&& let Some((arg1, arg2)) = std::iter::zip(
|
||||
prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
|
||||
opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
|
||||
)
|
||||
.find(|(arg1, arg2)| arg1 != arg2)
|
||||
{
|
||||
infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
|
||||
arg: arg1,
|
||||
prev: arg2,
|
||||
span: prev_span,
|
||||
prev_span: concrete_type.span,
|
||||
});
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0792]: expected generic lifetime parameter, found `'_`
|
||||
--> $DIR/defining-use-captured-non-universal-region.rs:15:18
|
||||
--> $DIR/defining-use-captured-non-universal-region.rs:14:18
|
||||
|
|
||||
LL | fn foo<'a>() -> impl Sized + 'a {
|
||||
| -- this generic parameter must be used with a generic lifetime parameter
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
fn foo<'a>() -> impl Sized + 'a {
|
||||
#[cfg(statik)]
|
||||
let i: i32 = foo::<'static>();
|
||||
//[statik]~^ ERROR opaque type used twice with different lifetimes
|
||||
//[statik]~| ERROR opaque type used twice with different lifetimes
|
||||
//[statik]~^ ERROR expected generic lifetime parameter, found `'static`
|
||||
|
||||
#[cfg(infer)]
|
||||
let i: i32 = foo::<'_>();
|
||||
|
|
|
@ -1,33 +1,12 @@
|
|||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
|
||||
|
|
||||
LL | let i: i32 = foo::<'static>();
|
||||
| ^^^^^^^^^^^^^^^^ lifetime `'static` used here
|
||||
...
|
||||
LL | i
|
||||
| - lifetime `'a` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
error[E0792]: expected generic lifetime parameter, found `'static`
|
||||
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
|
||||
|
|
||||
LL | fn foo<'a>() -> impl Sized + 'a {
|
||||
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
|
||||
LL | #[cfg(statik)]
|
||||
LL | let i: i32 = foo::<'static>();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
|
||||
|
|
||||
LL | let i: i32 = foo::<'static>();
|
||||
| ^^^^^^^^^^^^^^^^ lifetime `'static` used here
|
||||
...
|
||||
LL | i
|
||||
| - lifetime `'a` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
--> $DIR/defining-use-captured-non-universal-region.rs:10:18
|
||||
|
|
||||
LL | let i: i32 = foo::<'static>();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
||||
|
|
|
@ -12,7 +12,7 @@ mod statik {
|
|||
// invalid defining use: Opaque<'static> := ()
|
||||
fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
|
||||
let _: () = foo(Lt::<'static>::None);
|
||||
//~^ ERROR opaque type used twice with different lifetimes
|
||||
//~^ ERROR expected generic lifetime parameter, found `'static`
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ mod equal {
|
|||
// because of the use of equal lifetimes in args
|
||||
fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
|
||||
let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
|
||||
//~^ ERROR opaque type used twice with different lifetimes
|
||||
//~^ ERROR non-defining opaque type use in defining scope
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,8 @@
|
|||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/non-defining-use-lifetimes.rs:14:16
|
||||
|
|
||||
LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
|
||||
| ______________________________________________-
|
||||
LL | | let _: () = foo(Lt::<'static>::None);
|
||||
| | ^^ lifetime `'static` used here
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____- lifetime `'a` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
error[E0792]: expected generic lifetime parameter, found `'static`
|
||||
--> $DIR/non-defining-use-lifetimes.rs:14:16
|
||||
|
|
||||
LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
|
||||
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
|
||||
LL | let _: () = foo(Lt::<'static>::None);
|
||||
| ^^
|
||||
|
||||
|
@ -23,22 +14,17 @@ LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
|
|||
LL | let _: () = foo(Lt::<'_>::None);
|
||||
| ^^
|
||||
|
||||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/non-defining-use-lifetimes.rs:33:16
|
||||
|
|
||||
LL | fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
|
||||
| __________________________________________________________________-
|
||||
LL | | let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
|
||||
| | ^^ lifetime `'a` used here
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____- lifetime `'b` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
error: non-defining opaque type use in defining scope
|
||||
--> $DIR/non-defining-use-lifetimes.rs:33:16
|
||||
|
|
||||
LL | let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
|
||||
| ^^
|
||||
|
|
||||
note: lifetime used multiple times
|
||||
--> $DIR/non-defining-use-lifetimes.rs:32:58
|
||||
|
|
||||
LL | fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
|
||||
| ^^ ^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ type Foo<'a> = impl Sized;
|
|||
fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (Foo<'a>, Foo<'b>) {
|
||||
(x, y)
|
||||
//~^ ERROR opaque type used twice with different lifetimes
|
||||
//~| ERROR opaque type used twice with different lifetimes
|
||||
}
|
||||
|
||||
type Bar<'a, 'b> = impl std::fmt::Debug;
|
||||
|
@ -13,9 +12,6 @@ type Bar<'a, 'b> = impl std::fmt::Debug;
|
|||
fn bar<'x, 'y>(i: &'x i32, j: &'y i32) -> (Bar<'x, 'y>, Bar<'y, 'x>) {
|
||||
(i, j)
|
||||
//~^ ERROR opaque type used twice with different lifetimes
|
||||
//~| ERROR opaque type used twice with different lifetimes
|
||||
//~| ERROR opaque type used twice with different lifetimes
|
||||
//~| ERROR opaque type used twice with different lifetimes
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -14,23 +14,7 @@ LL | (x, y)
|
|||
| ^^^^^^
|
||||
|
||||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/lifetime_mismatch.rs:6:5
|
||||
|
|
||||
LL | (x, y)
|
||||
| ^^^^^^
|
||||
| |
|
||||
| lifetime `'a` used here
|
||||
| lifetime `'b` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
--> $DIR/lifetime_mismatch.rs:6:5
|
||||
|
|
||||
LL | (x, y)
|
||||
| ^^^^^^
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/lifetime_mismatch.rs:14:5
|
||||
--> $DIR/lifetime_mismatch.rs:13:5
|
||||
|
|
||||
LL | (i, j)
|
||||
| ^^^^^^
|
||||
|
@ -39,57 +23,10 @@ LL | (i, j)
|
|||
| lifetime `'y` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
--> $DIR/lifetime_mismatch.rs:14:5
|
||||
--> $DIR/lifetime_mismatch.rs:13:5
|
||||
|
|
||||
LL | (i, j)
|
||||
| ^^^^^^
|
||||
|
||||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/lifetime_mismatch.rs:14:5
|
||||
|
|
||||
LL | (i, j)
|
||||
| ^^^^^^
|
||||
| |
|
||||
| lifetime `'y` used here
|
||||
| lifetime `'x` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
--> $DIR/lifetime_mismatch.rs:14:5
|
||||
|
|
||||
LL | (i, j)
|
||||
| ^^^^^^
|
||||
|
||||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/lifetime_mismatch.rs:14:5
|
||||
|
|
||||
LL | (i, j)
|
||||
| ^^^^^^
|
||||
| |
|
||||
| lifetime `'x` used here
|
||||
| lifetime `'y` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
--> $DIR/lifetime_mismatch.rs:14:5
|
||||
|
|
||||
LL | (i, j)
|
||||
| ^^^^^^
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/lifetime_mismatch.rs:14:5
|
||||
|
|
||||
LL | (i, j)
|
||||
| ^^^^^^
|
||||
| |
|
||||
| lifetime `'y` used here
|
||||
| lifetime `'x` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
--> $DIR/lifetime_mismatch.rs:14:5
|
||||
|
|
||||
LL | (i, j)
|
||||
| ^^^^^^
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -3,11 +3,8 @@
|
|||
type Foo<'a, 'b> = impl std::fmt::Debug;
|
||||
|
||||
fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
|
||||
(i, i)
|
||||
(i, j)
|
||||
//~^ ERROR opaque type used twice with different lifetimes
|
||||
//~| ERROR opaque type used twice with different lifetimes
|
||||
//~| ERROR opaque type used twice with different lifetimes
|
||||
//~| ERROR opaque type used twice with different lifetimes
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
|
||||
|
|
||||
LL | (i, i)
|
||||
LL | (i, j)
|
||||
| ^^^^^^
|
||||
| |
|
||||
| lifetime `'x` used here
|
||||
|
@ -10,55 +10,8 @@ LL | (i, i)
|
|||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
--> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
|
||||
|
|
||||
LL | (i, i)
|
||||
LL | (i, j)
|
||||
| ^^^^^^
|
||||
|
||||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
|
||||
|
|
||||
LL | (i, i)
|
||||
| ^^^^^^
|
||||
| |
|
||||
| lifetime `'y` used here
|
||||
| lifetime `'x` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
--> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
|
||||
|
|
||||
LL | (i, i)
|
||||
| ^^^^^^
|
||||
|
||||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
|
||||
|
|
||||
LL | (i, i)
|
||||
| ^^^^^^
|
||||
| |
|
||||
| lifetime `'x` used here
|
||||
| lifetime `'y` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
--> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
|
||||
|
|
||||
LL | (i, i)
|
||||
| ^^^^^^
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: opaque type used twice with different lifetimes
|
||||
--> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
|
||||
|
|
||||
LL | (i, i)
|
||||
| ^^^^^^
|
||||
| |
|
||||
| lifetime `'y` used here
|
||||
| lifetime `'x` previously used here
|
||||
|
|
||||
note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
|
||||
--> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
|
||||
|
|
||||
LL | (i, i)
|
||||
| ^^^^^^
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
Loading…
Reference in New Issue