Skip to content

Commit a2d9f7d

Browse files
committed
Avoid type inference panic on bitslice methods
Should fix rust-lang#10090, rust-lang#10046, rust-lang#10179. This is only a workaround, but the proper fix requires some bigger refactoring (also related to fixing rust-lang#10058), and this at least prevents the crash.
1 parent 3170599 commit a2d9f7d

File tree

6 files changed

+66
-27
lines changed

6 files changed

+66
-27
lines changed

crates/hir/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2612,7 +2612,7 @@ impl Type {
26122612
None,
26132613
name,
26142614
method_resolution::LookupMode::MethodCall,
2615-
callback,
2615+
&mut |ty, id| callback(&ty.value, id),
26162616
);
26172617
}
26182618

@@ -2664,7 +2664,7 @@ impl Type {
26642664
None,
26652665
name,
26662666
method_resolution::LookupMode::Path,
2667-
callback,
2667+
&mut |ty, id| callback(&ty.value, id),
26682668
);
26692669
}
26702670

crates/hir_ty/src/infer/coerce.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ impl<'a> InferenceContext<'a> {
277277
continue;
278278
}
279279

280-
let referent_ty = canonicalized.decanonicalize_ty(referent_ty.value);
280+
let referent_ty = canonicalized.decanonicalize_ty(&mut self.table, referent_ty);
281281

282282
// At this point, we have deref'd `a` to `referent_ty`. So
283283
// imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.

crates/hir_ty/src/infer/expr.rs

+14-12
Original file line numberDiff line numberDiff line change
@@ -328,10 +328,8 @@ impl<'a> InferenceContext<'a> {
328328
},
329329
);
330330
let res = derefs.by_ref().find_map(|(callee_deref_ty, _)| {
331-
self.callable_sig(
332-
&canonicalized.decanonicalize_ty(callee_deref_ty.value),
333-
args.len(),
334-
)
331+
let ty = &canonicalized.decanonicalize_ty(&mut self.table, callee_deref_ty);
332+
self.callable_sig(ty, args.len())
335333
});
336334
let (param_tys, ret_ty): (Vec<Ty>, Ty) = match res {
337335
Some(res) => {
@@ -510,17 +508,20 @@ impl<'a> InferenceContext<'a> {
510508
},
511509
);
512510
let ty = autoderef.by_ref().find_map(|(derefed_ty, _)| {
513-
let def_db = self.db.upcast();
514511
let module = self.resolver.module();
512+
let db = self.db;
515513
let is_visible = |field_id: &FieldId| {
516514
module
517515
.map(|mod_id| {
518-
self.db.field_visibilities(field_id.parent)[field_id.local_id]
519-
.is_visible_from(def_db, mod_id)
516+
db.field_visibilities(field_id.parent)[field_id.local_id]
517+
.is_visible_from(db.upcast(), mod_id)
520518
})
521519
.unwrap_or(true)
522520
};
523-
match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
521+
match canonicalized
522+
.decanonicalize_ty(&mut self.table, derefed_ty)
523+
.kind(&Interner)
524+
{
524525
TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
525526
substs
526527
.as_slice(&Interner)
@@ -637,7 +638,7 @@ impl<'a> InferenceContext<'a> {
637638
},
638639
) {
639640
Some(derefed_ty) => {
640-
canonicalized.decanonicalize_ty(derefed_ty.value)
641+
canonicalized.decanonicalize_ty(&mut self.table, derefed_ty)
641642
}
642643
None => self.err_ty(),
643644
}
@@ -740,8 +741,9 @@ impl<'a> InferenceContext<'a> {
740741
krate,
741742
index_trait,
742743
);
743-
let self_ty =
744-
self_ty.map_or(self.err_ty(), |t| canonicalized.decanonicalize_ty(t.value));
744+
let self_ty = self_ty.map_or(self.err_ty(), |t| {
745+
canonicalized.decanonicalize_ty(&mut self.table, t)
746+
});
745747
self.resolve_associated_type_with_params(
746748
self_ty,
747749
self.resolve_ops_index_output(),
@@ -987,7 +989,7 @@ impl<'a> InferenceContext<'a> {
987989
});
988990
let (receiver_ty, method_ty, substs) = match resolved {
989991
Some((ty, func)) => {
990-
let ty = canonicalized_receiver.decanonicalize_ty(ty);
992+
let ty = canonicalized_receiver.decanonicalize_ty(&mut self.table, ty);
991993
let generics = generics(self.db.upcast(), func.into());
992994
let substs = self.substs_for_method_call(generics, generic_args, &ty);
993995
self.write_method_resolution(tgt_expr, func, substs.clone());

crates/hir_ty/src/infer/unify.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,13 @@ where
4141
}
4242

4343
impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
44-
pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty {
45-
chalk_ir::Substitute::apply(&self.free_vars, ty, &Interner)
44+
/// this method is wrong and shouldn't exist
45+
pub(super) fn decanonicalize_ty(&self, table: &mut InferenceTable, ty: Canonical<Ty>) -> Ty {
46+
let mut vars = self.free_vars.clone();
47+
while ty.binders.len(&Interner) > vars.len() {
48+
vars.push(table.new_type_var().cast(&Interner));
49+
}
50+
chalk_ir::Substitute::apply(&vars, ty.value, &Interner)
4651
}
4752

4853
pub(super) fn apply_solution(

crates/hir_ty/src/method_resolution.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ pub(crate) fn lookup_method(
380380
traits_in_scope: &FxHashSet<TraitId>,
381381
visible_from_module: Option<ModuleId>,
382382
name: &Name,
383-
) -> Option<(Ty, FunctionId)> {
383+
) -> Option<(Canonical<Ty>, FunctionId)> {
384384
iterate_method_candidates(
385385
ty,
386386
db,
@@ -421,7 +421,7 @@ pub fn iterate_method_candidates<T>(
421421
visible_from_module: Option<ModuleId>,
422422
name: Option<&Name>,
423423
mode: LookupMode,
424-
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
424+
mut callback: impl FnMut(&Canonical<Ty>, AssocItemId) -> Option<T>,
425425
) -> Option<T> {
426426
let mut slot = None;
427427
iterate_method_candidates_dyn(
@@ -454,7 +454,7 @@ pub fn iterate_method_candidates_dyn(
454454
visible_from_module: Option<ModuleId>,
455455
name: Option<&Name>,
456456
mode: LookupMode,
457-
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
457+
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
458458
) -> ControlFlow<()> {
459459
match mode {
460460
LookupMode::MethodCall => {
@@ -520,7 +520,7 @@ fn iterate_method_candidates_with_autoref(
520520
traits_in_scope: &FxHashSet<TraitId>,
521521
visible_from_module: Option<ModuleId>,
522522
name: Option<&Name>,
523-
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
523+
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
524524
) -> ControlFlow<()> {
525525
iterate_method_candidates_by_receiver(
526526
&deref_chain[0],
@@ -580,7 +580,7 @@ fn iterate_method_candidates_by_receiver(
580580
traits_in_scope: &FxHashSet<TraitId>,
581581
visible_from_module: Option<ModuleId>,
582582
name: Option<&Name>,
583-
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
583+
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
584584
) -> ControlFlow<()> {
585585
// We're looking for methods with *receiver* type receiver_ty. These could
586586
// be found in any of the derefs of receiver_ty, so we have to go through
@@ -622,7 +622,7 @@ fn iterate_method_candidates_for_self_ty(
622622
traits_in_scope: &FxHashSet<TraitId>,
623623
visible_from_module: Option<ModuleId>,
624624
name: Option<&Name>,
625-
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
625+
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
626626
) -> ControlFlow<()> {
627627
iterate_inherent_methods(
628628
self_ty,
@@ -645,7 +645,7 @@ fn iterate_trait_method_candidates(
645645
traits_in_scope: &FxHashSet<TraitId>,
646646
name: Option<&Name>,
647647
receiver_ty: Option<&Canonical<Ty>>,
648-
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
648+
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
649649
) -> ControlFlow<()> {
650650
let receiver_is_array = matches!(self_ty.value.kind(&Interner), chalk_ir::TyKind::Array(..));
651651
// if ty is `dyn Trait`, the trait doesn't need to be in scope
@@ -697,7 +697,7 @@ fn iterate_trait_method_candidates(
697697
}
698698
known_implemented = true;
699699
// FIXME: we shouldn't be ignoring the binders here
700-
callback(&self_ty.value, *item)?
700+
callback(&self_ty, *item)?
701701
}
702702
}
703703
ControlFlow::Continue(())
@@ -738,7 +738,7 @@ fn iterate_inherent_methods(
738738
receiver_ty: Option<&Canonical<Ty>>,
739739
krate: CrateId,
740740
visible_from_module: Option<ModuleId>,
741-
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
741+
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
742742
) -> ControlFlow<()> {
743743
let def_crates = match def_crates(db, &self_ty.value, krate) {
744744
Some(k) => k,
@@ -773,7 +773,7 @@ fn iterate_inherent_methods(
773773
cov_mark::hit!(impl_self_type_match_without_receiver);
774774
continue;
775775
}
776-
let receiver_ty = receiver_ty.map(|x| &x.value).unwrap_or(&self_ty.value);
776+
let receiver_ty = receiver_ty.unwrap_or(&self_ty);
777777
callback(receiver_ty, item)?;
778778
}
779779
}

crates/hir_ty/src/tests/regression.rs

+32
Original file line numberDiff line numberDiff line change
@@ -1145,3 +1145,35 @@ impl<'a, T, DB: TypeMetadata> Output<'a, T, DB> {
11451145
"#,
11461146
);
11471147
}
1148+
1149+
#[test]
1150+
fn bitslice_panic() {
1151+
check_no_mismatches(
1152+
r#"
1153+
//- minicore: option, deref
1154+
1155+
pub trait BitView {
1156+
type Store;
1157+
}
1158+
1159+
pub struct Lsb0;
1160+
1161+
pub struct BitArray<V: BitView> { }
1162+
1163+
pub struct BitSlice<T> { }
1164+
1165+
impl<V: BitView> core::ops::Deref for BitArray<V> {
1166+
type Target = BitSlice<V::Store>;
1167+
}
1168+
1169+
impl<T> BitSlice<T> {
1170+
pub fn split_first(&self) -> Option<(T, &Self)> { loop {} }
1171+
}
1172+
1173+
fn multiexp_inner() {
1174+
let exp: &BitArray<Foo>;
1175+
exp.split_first();
1176+
}
1177+
"#,
1178+
);
1179+
}

0 commit comments

Comments
 (0)