mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Avoid type inference panic on bitslice methods
Should fix #10090, #10046, #10179. This is only a workaround, but the proper fix requires some bigger refactoring (also related to fixing #10058), and this at least prevents the crash.
This commit is contained in:
parent
317059985a
commit
a2d9f7d7bb
6 changed files with 66 additions and 27 deletions
|
@ -2612,7 +2612,7 @@ impl Type {
|
||||||
None,
|
None,
|
||||||
name,
|
name,
|
||||||
method_resolution::LookupMode::MethodCall,
|
method_resolution::LookupMode::MethodCall,
|
||||||
callback,
|
&mut |ty, id| callback(&ty.value, id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2664,7 +2664,7 @@ impl Type {
|
||||||
None,
|
None,
|
||||||
name,
|
name,
|
||||||
method_resolution::LookupMode::Path,
|
method_resolution::LookupMode::Path,
|
||||||
callback,
|
&mut |ty, id| callback(&ty.value, id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let referent_ty = canonicalized.decanonicalize_ty(referent_ty.value);
|
let referent_ty = canonicalized.decanonicalize_ty(&mut self.table, referent_ty);
|
||||||
|
|
||||||
// At this point, we have deref'd `a` to `referent_ty`. So
|
// At this point, we have deref'd `a` to `referent_ty`. So
|
||||||
// imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
|
// imagine we are coercing from `&'a mut Vec<T>` to `&'b mut [T]`.
|
||||||
|
|
|
@ -328,10 +328,8 @@ impl<'a> InferenceContext<'a> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let res = derefs.by_ref().find_map(|(callee_deref_ty, _)| {
|
let res = derefs.by_ref().find_map(|(callee_deref_ty, _)| {
|
||||||
self.callable_sig(
|
let ty = &canonicalized.decanonicalize_ty(&mut self.table, callee_deref_ty);
|
||||||
&canonicalized.decanonicalize_ty(callee_deref_ty.value),
|
self.callable_sig(ty, args.len())
|
||||||
args.len(),
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
let (param_tys, ret_ty): (Vec<Ty>, Ty) = match res {
|
let (param_tys, ret_ty): (Vec<Ty>, Ty) = match res {
|
||||||
Some(res) => {
|
Some(res) => {
|
||||||
|
@ -510,17 +508,20 @@ impl<'a> InferenceContext<'a> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let ty = autoderef.by_ref().find_map(|(derefed_ty, _)| {
|
let ty = autoderef.by_ref().find_map(|(derefed_ty, _)| {
|
||||||
let def_db = self.db.upcast();
|
|
||||||
let module = self.resolver.module();
|
let module = self.resolver.module();
|
||||||
|
let db = self.db;
|
||||||
let is_visible = |field_id: &FieldId| {
|
let is_visible = |field_id: &FieldId| {
|
||||||
module
|
module
|
||||||
.map(|mod_id| {
|
.map(|mod_id| {
|
||||||
self.db.field_visibilities(field_id.parent)[field_id.local_id]
|
db.field_visibilities(field_id.parent)[field_id.local_id]
|
||||||
.is_visible_from(def_db, mod_id)
|
.is_visible_from(db.upcast(), mod_id)
|
||||||
})
|
})
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
};
|
};
|
||||||
match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
|
match canonicalized
|
||||||
|
.decanonicalize_ty(&mut self.table, derefed_ty)
|
||||||
|
.kind(&Interner)
|
||||||
|
{
|
||||||
TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
|
TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
|
||||||
substs
|
substs
|
||||||
.as_slice(&Interner)
|
.as_slice(&Interner)
|
||||||
|
@ -637,7 +638,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Some(derefed_ty) => {
|
Some(derefed_ty) => {
|
||||||
canonicalized.decanonicalize_ty(derefed_ty.value)
|
canonicalized.decanonicalize_ty(&mut self.table, derefed_ty)
|
||||||
}
|
}
|
||||||
None => self.err_ty(),
|
None => self.err_ty(),
|
||||||
}
|
}
|
||||||
|
@ -740,8 +741,9 @@ impl<'a> InferenceContext<'a> {
|
||||||
krate,
|
krate,
|
||||||
index_trait,
|
index_trait,
|
||||||
);
|
);
|
||||||
let self_ty =
|
let self_ty = self_ty.map_or(self.err_ty(), |t| {
|
||||||
self_ty.map_or(self.err_ty(), |t| canonicalized.decanonicalize_ty(t.value));
|
canonicalized.decanonicalize_ty(&mut self.table, t)
|
||||||
|
});
|
||||||
self.resolve_associated_type_with_params(
|
self.resolve_associated_type_with_params(
|
||||||
self_ty,
|
self_ty,
|
||||||
self.resolve_ops_index_output(),
|
self.resolve_ops_index_output(),
|
||||||
|
@ -987,7 +989,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
});
|
});
|
||||||
let (receiver_ty, method_ty, substs) = match resolved {
|
let (receiver_ty, method_ty, substs) = match resolved {
|
||||||
Some((ty, func)) => {
|
Some((ty, func)) => {
|
||||||
let ty = canonicalized_receiver.decanonicalize_ty(ty);
|
let ty = canonicalized_receiver.decanonicalize_ty(&mut self.table, ty);
|
||||||
let generics = generics(self.db.upcast(), func.into());
|
let generics = generics(self.db.upcast(), func.into());
|
||||||
let substs = self.substs_for_method_call(generics, generic_args, &ty);
|
let substs = self.substs_for_method_call(generics, generic_args, &ty);
|
||||||
self.write_method_resolution(tgt_expr, func, substs.clone());
|
self.write_method_resolution(tgt_expr, func, substs.clone());
|
||||||
|
|
|
@ -41,8 +41,13 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
|
impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
|
||||||
pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty {
|
/// this method is wrong and shouldn't exist
|
||||||
chalk_ir::Substitute::apply(&self.free_vars, ty, &Interner)
|
pub(super) fn decanonicalize_ty(&self, table: &mut InferenceTable, ty: Canonical<Ty>) -> Ty {
|
||||||
|
let mut vars = self.free_vars.clone();
|
||||||
|
while ty.binders.len(&Interner) > vars.len() {
|
||||||
|
vars.push(table.new_type_var().cast(&Interner));
|
||||||
|
}
|
||||||
|
chalk_ir::Substitute::apply(&vars, ty.value, &Interner)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn apply_solution(
|
pub(super) fn apply_solution(
|
||||||
|
|
|
@ -380,7 +380,7 @@ pub(crate) fn lookup_method(
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: Option<ModuleId>,
|
||||||
name: &Name,
|
name: &Name,
|
||||||
) -> Option<(Ty, FunctionId)> {
|
) -> Option<(Canonical<Ty>, FunctionId)> {
|
||||||
iterate_method_candidates(
|
iterate_method_candidates(
|
||||||
ty,
|
ty,
|
||||||
db,
|
db,
|
||||||
|
@ -421,7 +421,7 @@ pub fn iterate_method_candidates<T>(
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: Option<ModuleId>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mode: LookupMode,
|
mode: LookupMode,
|
||||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
mut callback: impl FnMut(&Canonical<Ty>, AssocItemId) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
let mut slot = None;
|
let mut slot = None;
|
||||||
iterate_method_candidates_dyn(
|
iterate_method_candidates_dyn(
|
||||||
|
@ -454,7 +454,7 @@ pub fn iterate_method_candidates_dyn(
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: Option<ModuleId>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mode: LookupMode,
|
mode: LookupMode,
|
||||||
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
|
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
match mode {
|
match mode {
|
||||||
LookupMode::MethodCall => {
|
LookupMode::MethodCall => {
|
||||||
|
@ -520,7 +520,7 @@ fn iterate_method_candidates_with_autoref(
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: Option<ModuleId>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
|
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
iterate_method_candidates_by_receiver(
|
iterate_method_candidates_by_receiver(
|
||||||
&deref_chain[0],
|
&deref_chain[0],
|
||||||
|
@ -580,7 +580,7 @@ fn iterate_method_candidates_by_receiver(
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: Option<ModuleId>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
|
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
// We're looking for methods with *receiver* type receiver_ty. These could
|
// We're looking for methods with *receiver* type receiver_ty. These could
|
||||||
// be found in any of the derefs of receiver_ty, so we have to go through
|
// 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(
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: Option<ModuleId>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
|
mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
iterate_inherent_methods(
|
iterate_inherent_methods(
|
||||||
self_ty,
|
self_ty,
|
||||||
|
@ -645,7 +645,7 @@ fn iterate_trait_method_candidates(
|
||||||
traits_in_scope: &FxHashSet<TraitId>,
|
traits_in_scope: &FxHashSet<TraitId>,
|
||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
receiver_ty: Option<&Canonical<Ty>>,
|
receiver_ty: Option<&Canonical<Ty>>,
|
||||||
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
|
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
let receiver_is_array = matches!(self_ty.value.kind(&Interner), chalk_ir::TyKind::Array(..));
|
let receiver_is_array = matches!(self_ty.value.kind(&Interner), chalk_ir::TyKind::Array(..));
|
||||||
// if ty is `dyn Trait`, the trait doesn't need to be in scope
|
// if ty is `dyn Trait`, the trait doesn't need to be in scope
|
||||||
|
@ -697,7 +697,7 @@ fn iterate_trait_method_candidates(
|
||||||
}
|
}
|
||||||
known_implemented = true;
|
known_implemented = true;
|
||||||
// FIXME: we shouldn't be ignoring the binders here
|
// FIXME: we shouldn't be ignoring the binders here
|
||||||
callback(&self_ty.value, *item)?
|
callback(&self_ty, *item)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
|
@ -738,7 +738,7 @@ fn iterate_inherent_methods(
|
||||||
receiver_ty: Option<&Canonical<Ty>>,
|
receiver_ty: Option<&Canonical<Ty>>,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
visible_from_module: Option<ModuleId>,
|
visible_from_module: Option<ModuleId>,
|
||||||
callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>,
|
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
) -> ControlFlow<()> {
|
) -> ControlFlow<()> {
|
||||||
let def_crates = match def_crates(db, &self_ty.value, krate) {
|
let def_crates = match def_crates(db, &self_ty.value, krate) {
|
||||||
Some(k) => k,
|
Some(k) => k,
|
||||||
|
@ -773,7 +773,7 @@ fn iterate_inherent_methods(
|
||||||
cov_mark::hit!(impl_self_type_match_without_receiver);
|
cov_mark::hit!(impl_self_type_match_without_receiver);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let receiver_ty = receiver_ty.map(|x| &x.value).unwrap_or(&self_ty.value);
|
let receiver_ty = receiver_ty.unwrap_or(&self_ty);
|
||||||
callback(receiver_ty, item)?;
|
callback(receiver_ty, item)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1145,3 +1145,35 @@ impl<'a, T, DB: TypeMetadata> Output<'a, T, DB> {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bitslice_panic() {
|
||||||
|
check_no_mismatches(
|
||||||
|
r#"
|
||||||
|
//- minicore: option, deref
|
||||||
|
|
||||||
|
pub trait BitView {
|
||||||
|
type Store;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Lsb0;
|
||||||
|
|
||||||
|
pub struct BitArray<V: BitView> { }
|
||||||
|
|
||||||
|
pub struct BitSlice<T> { }
|
||||||
|
|
||||||
|
impl<V: BitView> core::ops::Deref for BitArray<V> {
|
||||||
|
type Target = BitSlice<V::Store>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> BitSlice<T> {
|
||||||
|
pub fn split_first(&self) -> Option<(T, &Self)> { loop {} }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn multiexp_inner() {
|
||||||
|
let exp: &BitArray<Foo>;
|
||||||
|
exp.split_first();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue