Merge pull request #21235 from benodiwal/fix-const-generic-param-env-panic
Some checks are pending
metrics / build_metrics (push) Waiting to run
metrics / other_metrics (diesel-1.4.8) (push) Blocked by required conditions
metrics / other_metrics (hyper-0.14.18) (push) Blocked by required conditions
metrics / other_metrics (ripgrep-13.0.0) (push) Blocked by required conditions
metrics / other_metrics (self) (push) Blocked by required conditions
metrics / other_metrics (webrender-2022) (push) Blocked by required conditions
metrics / generate_final_metrics (push) Blocked by required conditions
rustdoc / rustdoc (push) Waiting to run

fix: resolve const generic param-env panic in type projection
This commit is contained in:
Chayim Refael Friedman 2025-12-09 16:18:15 +00:00 committed by GitHub
commit 7d052bdfe0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 73 additions and 7 deletions

View file

@ -43,6 +43,7 @@ impl<'db> HirPlace<'db> {
for p in &self.projections {
ty = p.projected_ty(
&ctx.table.infer_ctxt,
ctx.table.param_env,
ty,
|_, _, _| {
unreachable!("Closure field only happens in MIR");
@ -839,6 +840,7 @@ impl<'db> InferenceContext<'_, 'db> {
for (i, p) in capture.place.projections.iter().enumerate() {
ty = p.projected_ty(
&self.table.infer_ctxt,
self.table.param_env,
ty,
|_, _, _| {
unreachable!("Closure field only happens in MIR");

View file

@ -25,7 +25,7 @@ use crate::{
consteval::try_const_usize,
db::HirDatabase,
next_solver::{
DbInterner, GenericArgs, ParamEnv, Ty, TyKind, TypingMode,
DbInterner, GenericArgs, Ty, TyKind, TypingMode,
infer::{DbInternerInferExt, traits::ObligationCause},
},
};
@ -170,7 +170,7 @@ pub fn layout_of_ty_query<'db>(
let cx = LayoutCx::new(dl);
let infer_ctxt = interner.infer_ctxt().build(TypingMode::PostAnalysis);
let cause = ObligationCause::dummy();
let ty = infer_ctxt.at(&cause, ParamEnv::empty()).deeply_normalize(ty).unwrap_or(ty);
let ty = infer_ctxt.at(&cause, trait_env.param_env).deeply_normalize(ty).unwrap_or(ty);
let result = match ty.kind() {
TyKind::Adt(def, args) => {
match def.inner().id {

View file

@ -157,6 +157,7 @@ impl<'db, V: PartialEq> ProjectionElem<'db, V> {
pub fn projected_ty(
&self,
infcx: &InferCtxt<'db>,
env: ParamEnv<'db>,
mut base: Ty<'db>,
closure_field: impl FnOnce(InternedClosureId, GenericArgs<'db>, usize) -> Ty<'db>,
krate: Crate,
@ -173,8 +174,6 @@ impl<'db, V: PartialEq> ProjectionElem<'db, V> {
if matches!(base.kind(), TyKind::Alias(..)) {
let mut ocx = ObligationCtxt::new(infcx);
// FIXME: we should get this from caller
let env = ParamEnv::empty();
match ocx.structurally_normalize_ty(&ObligationCause::dummy(), env, base) {
Ok(it) => base = it,
Err(_) => return Ty::new_error(interner, ErrorGuaranteed),

View file

@ -106,7 +106,7 @@ pub fn borrowck_query<'db>(
// FIXME(next-solver): Opaques.
let infcx = interner.infer_ctxt().build(typing_mode);
res.push(BorrowckResult {
mutability_of_locals: mutability_of_locals(&infcx, &body),
mutability_of_locals: mutability_of_locals(&infcx, env, &body),
moved_out_of_ref: moved_out_of_ref(&infcx, env, &body),
partially_moved: partially_moved(&infcx, env, &body),
borrow_regions: borrow_regions(db, &body),
@ -146,6 +146,7 @@ fn moved_out_of_ref<'db>(
}
ty = proj.projected_ty(
infcx,
env,
ty,
make_fetch_closure_field(db),
body.owner.module(db).krate(db),
@ -242,6 +243,7 @@ fn partially_moved<'db>(
for proj in p.projection.lookup(&body.projection_store) {
ty = proj.projected_ty(
infcx,
env,
ty,
make_fetch_closure_field(db),
body.owner.module(db).krate(db),
@ -374,6 +376,7 @@ enum ProjectionCase {
fn place_case<'db>(
infcx: &InferCtxt<'db>,
env: ParamEnv<'db>,
body: &MirBody<'db>,
lvalue: &Place<'db>,
) -> ProjectionCase {
@ -395,6 +398,7 @@ fn place_case<'db>(
}
ty = proj.projected_ty(
infcx,
env,
ty,
make_fetch_closure_field(db),
body.owner.module(db).krate(db),
@ -535,6 +539,7 @@ fn record_usage_for_operand<'db>(
fn mutability_of_locals<'db>(
infcx: &InferCtxt<'db>,
env: ParamEnv<'db>,
body: &MirBody<'db>,
) -> ArenaMap<LocalId<'db>, MutabilityReason> {
let db = infcx.interner.db;
@ -547,7 +552,7 @@ fn mutability_of_locals<'db>(
for statement in &block.statements {
match &statement.kind {
StatementKind::Assign(place, value) => {
match place_case(infcx, body, place) {
match place_case(infcx, env, body, place) {
ProjectionCase::Direct => {
if ever_init_map.get(place.local).copied().unwrap_or_default() {
push_mut_span(place.local, statement.span, &mut result);
@ -596,7 +601,7 @@ fn mutability_of_locals<'db>(
},
p,
) = value
&& place_case(infcx, body, p) != ProjectionCase::Indirect
&& place_case(infcx, env, body, p) != ProjectionCase::Indirect
{
push_mut_span(p.local, statement.span, &mut result);
}

View file

@ -722,6 +722,7 @@ impl<'db> Evaluator<'db> {
let (ty, proj) = pair;
let r = proj.projected_ty(
&self.infcx,
self.param_env.param_env,
ty,
|c, subst, f| {
let InternedClosure(def, _) = self.db.lookup_intern_closure(c);

View file

@ -1,3 +1,4 @@
use hir_def::DefWithBodyId;
use test_fixture::WithFixture;
use crate::{db::HirDatabase, setup_tracing, test_db::TestDB};
@ -49,3 +50,61 @@ fn foo() {
"#,
);
}
fn check_borrowck(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
let _tracing = setup_tracing();
let (db, file_ids) = TestDB::with_many_files(ra_fixture);
crate::attach_db(&db, || {
let file_id = *file_ids.last().unwrap();
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 mut bodies: Vec<DefWithBodyId> = Vec::new();
for decl in scope.declarations() {
if let hir_def::ModuleDefId::FunctionId(f) = decl {
bodies.push(f.into());
}
}
for impl_id in scope.impls() {
let impl_items = impl_id.impl_items(&db);
for (_, item) in impl_items.items.iter() {
if let hir_def::AssocItemId::FunctionId(f) = item {
bodies.push((*f).into());
}
}
}
for body in bodies {
let _ = db.borrowck(body);
}
})
}
#[test]
fn regression_21173_const_generic_impl_with_assoc_type() {
check_borrowck(
r#"
pub trait Tr {
type Assoc;
fn f(&self, handle: Self::Assoc) -> i32;
}
pub struct ConstGeneric<const N: usize>;
impl<const N: usize> Tr for &ConstGeneric<N> {
type Assoc = AssocTy;
fn f(&self, a: Self::Assoc) -> i32 {
a.x
}
}
pub struct AssocTy {
x: i32,
}
"#,
);
}