Skip to content

Commit 2f1b7ce

Browse files
committed
Auto merge of rust-lang#14971 - lowr:fix/captured-item-ty-outer-binder, r=HKalbasi
fix: consider outer binders when folding captured items' type Fixes rust-lang#14966 Basically, the crash is caused by us producing a broken type and passing it to chalk: `&dyn for<type> [for<> Implemented(^1.0: A<^0.0>)]` (notice the innermost bound var `^0.0` has no corresponding binder). It's created in `CapturedItemWithoutTy::with_ty()`, which didn't consider outer binders when folding types to replace placeholders with bound variables. The fix is one-liner, but I've also refactored the surrounding code a little.
2 parents 5545961 + f549cac commit 2f1b7ce

File tree

4 files changed

+102
-68
lines changed

4 files changed

+102
-68
lines changed

crates/hir-ty/src/infer.rs

+39-11
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,10 @@ pub enum PointerCast {
367367
}
368368

369369
/// The result of type inference: A mapping from expressions and patterns to types.
370+
///
371+
/// When you add a field that stores types (including `Substitution` and the like), don't forget
372+
/// `resolve_completely()`'ing them in `InferenceContext::resolve_all()`. Inference variables must
373+
/// not appear in the final inference result.
370374
#[derive(Clone, PartialEq, Eq, Debug, Default)]
371375
pub struct InferenceResult {
372376
/// For each method call expr, records the function it resolves to.
@@ -576,6 +580,30 @@ impl<'a> InferenceContext<'a> {
576580
// there is no problem in it being `pub(crate)`, remove this comment.
577581
pub(crate) fn resolve_all(self) -> InferenceResult {
578582
let InferenceContext { mut table, mut result, .. } = self;
583+
// Destructure every single field so whenever new fields are added to `InferenceResult` we
584+
// don't forget to handle them here.
585+
let InferenceResult {
586+
method_resolutions,
587+
field_resolutions: _,
588+
variant_resolutions: _,
589+
assoc_resolutions,
590+
diagnostics,
591+
type_of_expr,
592+
type_of_pat,
593+
type_of_binding,
594+
type_of_rpit,
595+
type_of_for_iterator,
596+
type_mismatches,
597+
standard_types: _,
598+
pat_adjustments,
599+
binding_modes: _,
600+
expr_adjustments,
601+
// Types in `closure_info` have already been `resolve_completely()`'d during
602+
// `InferenceContext::infer_closures()` (in `HirPlace::ty()` specifically), so no need
603+
// to resolve them here.
604+
closure_info: _,
605+
mutated_bindings_in_closure: _,
606+
} = &mut result;
579607

580608
table.fallback_if_possible();
581609

@@ -584,26 +612,26 @@ impl<'a> InferenceContext<'a> {
584612

585613
// make sure diverging type variables are marked as such
586614
table.propagate_diverging_flag();
587-
for ty in result.type_of_expr.values_mut() {
615+
for ty in type_of_expr.values_mut() {
588616
*ty = table.resolve_completely(ty.clone());
589617
}
590-
for ty in result.type_of_pat.values_mut() {
618+
for ty in type_of_pat.values_mut() {
591619
*ty = table.resolve_completely(ty.clone());
592620
}
593-
for ty in result.type_of_binding.values_mut() {
621+
for ty in type_of_binding.values_mut() {
594622
*ty = table.resolve_completely(ty.clone());
595623
}
596-
for ty in result.type_of_rpit.values_mut() {
624+
for ty in type_of_rpit.values_mut() {
597625
*ty = table.resolve_completely(ty.clone());
598626
}
599-
for ty in result.type_of_for_iterator.values_mut() {
627+
for ty in type_of_for_iterator.values_mut() {
600628
*ty = table.resolve_completely(ty.clone());
601629
}
602-
for mismatch in result.type_mismatches.values_mut() {
630+
for mismatch in type_mismatches.values_mut() {
603631
mismatch.expected = table.resolve_completely(mismatch.expected.clone());
604632
mismatch.actual = table.resolve_completely(mismatch.actual.clone());
605633
}
606-
result.diagnostics.retain_mut(|diagnostic| {
634+
diagnostics.retain_mut(|diagnostic| {
607635
use InferenceDiagnostic::*;
608636
match diagnostic {
609637
ExpectedFunction { found: ty, .. }
@@ -631,16 +659,16 @@ impl<'a> InferenceContext<'a> {
631659
}
632660
true
633661
});
634-
for (_, subst) in result.method_resolutions.values_mut() {
662+
for (_, subst) in method_resolutions.values_mut() {
635663
*subst = table.resolve_completely(subst.clone());
636664
}
637-
for (_, subst) in result.assoc_resolutions.values_mut() {
665+
for (_, subst) in assoc_resolutions.values_mut() {
638666
*subst = table.resolve_completely(subst.clone());
639667
}
640-
for adjustment in result.expr_adjustments.values_mut().flatten() {
668+
for adjustment in expr_adjustments.values_mut().flatten() {
641669
adjustment.target = table.resolve_completely(adjustment.target.clone());
642670
}
643-
for adjustment in result.pat_adjustments.values_mut().flatten() {
671+
for adjustment in pat_adjustments.values_mut().flatten() {
644672
*adjustment = table.resolve_completely(adjustment.clone());
645673
}
646674
result

crates/hir-ty/src/infer/closure.rs

+26-36
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{cmp, collections::HashMap, convert::Infallible, mem};
55
use chalk_ir::{
66
cast::Cast,
77
fold::{FallibleTypeFolder, TypeFoldable},
8-
AliasEq, AliasTy, BoundVar, ConstData, DebruijnIndex, FnSubst, Mutability, TyKind, WhereClause,
8+
AliasEq, AliasTy, BoundVar, DebruijnIndex, FnSubst, Mutability, TyKind, WhereClause,
99
};
1010
use hir_def::{
1111
data::adt::VariantData,
@@ -26,8 +26,8 @@ use crate::{
2626
static_lifetime, to_chalk_trait_id,
2727
traits::FnTrait,
2828
utils::{self, generics, Generics},
29-
Adjust, Adjustment, Binders, BindingMode, ChalkTraitId, ClosureId, ConstValue, DynTy,
30-
FnPointer, FnSig, Interner, Substitution, Ty, TyExt,
29+
Adjust, Adjustment, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, FnPointer, FnSig,
30+
Interner, Substitution, Ty, TyExt,
3131
};
3232

3333
use super::{Expectation, InferenceContext};
@@ -236,6 +236,24 @@ pub(crate) struct CapturedItemWithoutTy {
236236

237237
impl CapturedItemWithoutTy {
238238
fn with_ty(self, ctx: &mut InferenceContext<'_>) -> CapturedItem {
239+
let ty = self.place.ty(ctx).clone();
240+
let ty = match &self.kind {
241+
CaptureKind::ByValue => ty,
242+
CaptureKind::ByRef(bk) => {
243+
let m = match bk {
244+
BorrowKind::Mut { .. } => Mutability::Mut,
245+
_ => Mutability::Not,
246+
};
247+
TyKind::Ref(m, static_lifetime(), ty).intern(Interner)
248+
}
249+
};
250+
return CapturedItem {
251+
place: self.place,
252+
kind: self.kind,
253+
span: self.span,
254+
ty: replace_placeholder_with_binder(ctx.db, ctx.owner, ty),
255+
};
256+
239257
fn replace_placeholder_with_binder(
240258
db: &dyn HirDatabase,
241259
owner: DefWithBodyId,
@@ -266,56 +284,28 @@ impl CapturedItemWithoutTy {
266284
let Some(idx) = self.generics.param_idx(x) else {
267285
return Err(());
268286
};
269-
Ok(ConstData {
270-
ty,
271-
value: ConstValue::BoundVar(BoundVar::new(outer_binder, idx)),
272-
}
273-
.intern(Interner))
287+
Ok(BoundVar::new(outer_binder, idx).to_const(Interner, ty))
274288
}
275289

276290
fn try_fold_free_placeholder_ty(
277291
&mut self,
278292
idx: chalk_ir::PlaceholderIndex,
279-
_outer_binder: DebruijnIndex,
293+
outer_binder: DebruijnIndex,
280294
) -> std::result::Result<Ty, Self::Error> {
281295
let x = from_placeholder_idx(self.db, idx);
282296
let Some(idx) = self.generics.param_idx(x) else {
283297
return Err(());
284298
};
285-
Ok(TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx))
286-
.intern(Interner))
299+
Ok(BoundVar::new(outer_binder, idx).to_ty(Interner))
287300
}
288301
}
289-
let g_def = match owner {
290-
DefWithBodyId::FunctionId(f) => Some(f.into()),
291-
DefWithBodyId::StaticId(_) => None,
292-
DefWithBodyId::ConstId(f) => Some(f.into()),
293-
DefWithBodyId::VariantId(f) => Some(f.into()),
294-
};
295-
let Some(generics) = g_def.map(|g_def| generics(db.upcast(), g_def)) else {
302+
let Some(generic_def) = owner.as_generic_def_id() else {
296303
return Binders::empty(Interner, ty);
297304
};
298-
let filler = &mut Filler { db, generics };
305+
let filler = &mut Filler { db, generics: generics(db.upcast(), generic_def) };
299306
let result = ty.clone().try_fold_with(filler, DebruijnIndex::INNERMOST).unwrap_or(ty);
300307
make_binders(db, &filler.generics, result)
301308
}
302-
let ty = self.place.ty(ctx).clone();
303-
let ty = match &self.kind {
304-
CaptureKind::ByValue => ty,
305-
CaptureKind::ByRef(bk) => {
306-
let m = match bk {
307-
BorrowKind::Mut { .. } => Mutability::Mut,
308-
_ => Mutability::Not,
309-
};
310-
TyKind::Ref(m, static_lifetime(), ty).intern(Interner)
311-
}
312-
};
313-
CapturedItem {
314-
place: self.place,
315-
kind: self.kind,
316-
span: self.span,
317-
ty: replace_placeholder_with_binder(ctx.db, ctx.owner, ty),
318-
}
319309
}
320310
}
321311

crates/hir-ty/src/mir/eval/tests.rs

+34
Original file line numberDiff line numberDiff line change
@@ -640,3 +640,37 @@ fn main() {
640640
"#,
641641
);
642642
}
643+
644+
#[test]
645+
fn regression_14966() {
646+
check_pass(
647+
r#"
648+
//- minicore: fn, copy, coerce_unsized
649+
trait A<T> {
650+
fn a(&self) {}
651+
}
652+
impl A<()> for () {}
653+
654+
struct B;
655+
impl B {
656+
pub fn b<T>(s: &dyn A<T>) -> Self {
657+
B
658+
}
659+
}
660+
struct C;
661+
impl C {
662+
fn c<T>(a: &dyn A<T>) -> Self {
663+
let mut c = C;
664+
let b = B::b(a);
665+
c.d(|| a.a());
666+
c
667+
}
668+
fn d(&mut self, f: impl FnOnce()) {}
669+
}
670+
671+
fn main() {
672+
C::c(&());
673+
}
674+
"#,
675+
);
676+
}

crates/hir-ty/src/mir/monomorphization.rs

+3-21
Original file line numberDiff line numberDiff line change
@@ -303,13 +303,7 @@ pub fn monomorphized_mir_body_query(
303303
subst: Substitution,
304304
trait_env: Arc<crate::TraitEnvironment>,
305305
) -> Result<Arc<MirBody>, MirLowerError> {
306-
let g_def = match owner {
307-
DefWithBodyId::FunctionId(f) => Some(f.into()),
308-
DefWithBodyId::StaticId(_) => None,
309-
DefWithBodyId::ConstId(f) => Some(f.into()),
310-
DefWithBodyId::VariantId(f) => Some(f.into()),
311-
};
312-
let generics = g_def.map(|g_def| generics(db.upcast(), g_def));
306+
let generics = owner.as_generic_def_id().map(|g_def| generics(db.upcast(), g_def));
313307
let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner };
314308
let body = db.mir_body(owner)?;
315309
let mut body = (*body).clone();
@@ -334,13 +328,7 @@ pub fn monomorphized_mir_body_for_closure_query(
334328
trait_env: Arc<crate::TraitEnvironment>,
335329
) -> Result<Arc<MirBody>, MirLowerError> {
336330
let (owner, _) = db.lookup_intern_closure(closure.into());
337-
let g_def = match owner {
338-
DefWithBodyId::FunctionId(f) => Some(f.into()),
339-
DefWithBodyId::StaticId(_) => None,
340-
DefWithBodyId::ConstId(f) => Some(f.into()),
341-
DefWithBodyId::VariantId(f) => Some(f.into()),
342-
};
343-
let generics = g_def.map(|g_def| generics(db.upcast(), g_def));
331+
let generics = owner.as_generic_def_id().map(|g_def| generics(db.upcast(), g_def));
344332
let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner };
345333
let body = db.mir_body_for_closure(closure)?;
346334
let mut body = (*body).clone();
@@ -356,13 +344,7 @@ pub fn monomorphize_mir_body_bad(
356344
trait_env: Arc<crate::TraitEnvironment>,
357345
) -> Result<MirBody, MirLowerError> {
358346
let owner = body.owner;
359-
let g_def = match owner {
360-
DefWithBodyId::FunctionId(f) => Some(f.into()),
361-
DefWithBodyId::StaticId(_) => None,
362-
DefWithBodyId::ConstId(f) => Some(f.into()),
363-
DefWithBodyId::VariantId(f) => Some(f.into()),
364-
};
365-
let generics = g_def.map(|g_def| generics(db.upcast(), g_def));
347+
let generics = owner.as_generic_def_id().map(|g_def| generics(db.upcast(), g_def));
366348
let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner };
367349
filler.fill_body(&mut body)?;
368350
Ok(body)

0 commit comments

Comments
 (0)