Unnamed repository; edit this file 'description' to name the repository.
Fix late params overlapping
Lukas Wirth 4 weeks ago
parent e9a723b · commit 5f0eb33
-rw-r--r--crates/hir-ty/src/lower.rs10
-rw-r--r--crates/hir-ty/src/next_solver/fold.rs2
-rw-r--r--crates/hir-ty/src/next_solver/region.rs14
-rw-r--r--crates/hir-ty/src/tests/regression/new_solver.rs51
4 files changed, 64 insertions, 13 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index b252f8dac1..656d39e5ad 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -542,7 +542,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
Region::new_late_param(
self.interner,
solver_def_id,
- BoundRegionKind::Named(solver_def_id),
+ BoundRegion {
+ var: BoundVar::from_u32(index),
+ kind: BoundRegionKind::Named(solver_def_id),
+ },
)
}
} else {
@@ -665,7 +668,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
LifetimeLoweringMode::LateParam => Region::new_late_param(
interner,
self.generic_def.into(),
- bound_region_kind,
+ BoundRegion {
+ var: BoundVar::from_u32(late_bound_index),
+ kind: bound_region_kind,
+ },
),
};
late_bound_index += 1;
diff --git a/crates/hir-ty/src/next_solver/fold.rs b/crates/hir-ty/src/next_solver/fold.rs
index 7db7b44727..0a41874374 100644
--- a/crates/hir-ty/src/next_solver/fold.rs
+++ b/crates/hir-ty/src/next_solver/fold.rs
@@ -232,7 +232,7 @@ impl<'db> DbInterner<'db> {
T: TypeFoldable<DbInterner<'db>>,
{
self.instantiate_bound_regions_uncached(value, |br| {
- Region::new_late_param(self, all_outlive_scope, br.kind)
+ Region::new_late_param(self, all_outlive_scope, br)
})
}
}
diff --git a/crates/hir-ty/src/next_solver/region.rs b/crates/hir-ty/src/next_solver/region.rs
index 317aaa9c57..dc753a1b47 100644
--- a/crates/hir-ty/src/next_solver/region.rs
+++ b/crates/hir-ty/src/next_solver/region.rs
@@ -78,7 +78,7 @@ impl<'db> Region<'db> {
pub fn new_late_param(
interner: DbInterner<'db>,
scope: SolverDefId,
- bound_region: BoundRegionKind<'db>,
+ bound_region: BoundRegion<'db>,
) -> Region<'db> {
let late_bound_region = LateParamRegion { scope, bound_region };
Region::new(interner, RegionKind::ReLateParam(late_bound_region))
@@ -164,17 +164,13 @@ pub struct EarlyParamRegion {
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, GenericTypeVisitable)]
-/// The parameter representation of late-bound function parameters, "some region
-/// at least as big as the scope `fr.scope`".
+/// Represents a liberated late-bound function lifetime parameter.
///
-/// Similar to a placeholder region as we create `LateParam` regions when entering a binder
-/// except they are always in the root universe and instead of using a boundvar to distinguish
-/// between others we use the `DefId` of the parameter. For this reason the `bound_region` field
-/// should basically always be `BoundRegionKind::Named` as otherwise there is no way of telling
-/// different parameters apart.
+/// This denotes some region at least as big as `scope`. It is similar to a placeholder region
+/// created when entering a binder, except it always lives in the root universe.
pub struct LateParamRegion<'db> {
pub scope: SolverDefId,
- pub bound_region: BoundRegionKind<'db>,
+ pub bound_region: BoundRegion<'db>,
}
impl std::fmt::Debug for LateParamRegion<'_> {
diff --git a/crates/hir-ty/src/tests/regression/new_solver.rs b/crates/hir-ty/src/tests/regression/new_solver.rs
index fb00a755fa..121e3959ce 100644
--- a/crates/hir-ty/src/tests/regression/new_solver.rs
+++ b/crates/hir-ty/src/tests/regression/new_solver.rs
@@ -1,6 +1,55 @@
use expect_test::expect;
+use hir_def::ModuleDefId;
+use rustc_type_ir::inherent::IntoKind as _;
+use test_fixture::WithFixture;
-use crate::tests::{check_infer, check_no_mismatches, check_types};
+use crate::{
+ db::HirDatabase,
+ next_solver::{DbInterner, RegionKind, TyKind},
+ test_db::TestDB,
+ tests::{check_infer, check_no_mismatches, check_types},
+};
+
+#[test]
+fn liberating_distinct_late_bound_lifetimes_preserves_identity() {
+ let (db, file_id) = TestDB::with_single_file(
+ r#"
+fn f<'a, 'b>(x: &'a u8, y: &'b u8) {}
+"#,
+ );
+
+ crate::attach_db(&db, || {
+ let module_id = db.module_for_file(file_id.file_id(&db));
+ let def_map = module_id.def_map(&db);
+ let scope = &def_map[module_id].scope;
+ let func = scope
+ .declarations()
+ .find_map(
+ |decl| {
+ if let ModuleDefId::FunctionId(func) = decl { Some(func) } else { None }
+ },
+ )
+ .unwrap();
+ let interner = DbInterner::new_with(&db, module_id.krate(&db));
+ let sig = db.callable_item_signature(func.into()).instantiate_identity().skip_norm_wip();
+ let sig = interner.liberate_late_bound_regions(func.into(), sig);
+ let inputs = sig.inputs();
+ let TyKind::Ref(first_region, _first_ty, _first_mutability) = inputs[0].kind() else {
+ panic!("expected reference input, got {:?}", inputs[0]);
+ };
+ let TyKind::Ref(second_region, _second_ty, _second_mutability) = inputs[1].kind() else {
+ panic!("expected reference input, got {:?}", inputs[1]);
+ };
+ let RegionKind::ReLateParam(_first_late_param) = first_region.kind() else {
+ panic!("expected late parameter region, got {first_region:?}");
+ };
+ let RegionKind::ReLateParam(_second_late_param) = second_region.kind() else {
+ panic!("expected late parameter region, got {second_region:?}");
+ };
+
+ assert_ne!(first_region, second_region);
+ });
+}
#[test]
fn regression_20365() {