Unnamed repository; edit this file 'description' to name the repository.
Fix late params overlapping
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 10 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/fold.rs | 2 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/region.rs | 14 | ||||
| -rw-r--r-- | crates/hir-ty/src/tests/regression/new_solver.rs | 51 |
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() { |