diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index b028e76c17a..3b0c29e87e8 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -2612,7 +2612,7 @@ impl Type { None, name, method_resolution::LookupMode::MethodCall, - callback, + &mut |ty, id| callback(&ty.value, id), ); } @@ -2664,7 +2664,7 @@ impl Type { None, name, method_resolution::LookupMode::Path, - callback, + &mut |ty, id| callback(&ty.value, id), ); } diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 0f5859c433f..4d7ac6fd85f 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -277,7 +277,7 @@ impl<'a> InferenceContext<'a> { 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 // imagine we are coercing from `&'a mut Vec` to `&'b mut [T]`. diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index ea71cdd8102..b0306d9148a 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -328,10 +328,8 @@ impl<'a> InferenceContext<'a> { }, ); let res = derefs.by_ref().find_map(|(callee_deref_ty, _)| { - self.callable_sig( - &canonicalized.decanonicalize_ty(callee_deref_ty.value), - args.len(), - ) + let ty = &canonicalized.decanonicalize_ty(&mut self.table, callee_deref_ty); + self.callable_sig(ty, args.len()) }); let (param_tys, ret_ty): (Vec, Ty) = match res { Some(res) => { @@ -510,17 +508,20 @@ impl<'a> InferenceContext<'a> { }, ); let ty = autoderef.by_ref().find_map(|(derefed_ty, _)| { - let def_db = self.db.upcast(); let module = self.resolver.module(); + let db = self.db; let is_visible = |field_id: &FieldId| { module .map(|mod_id| { - self.db.field_visibilities(field_id.parent)[field_id.local_id] - .is_visible_from(def_db, mod_id) + db.field_visibilities(field_id.parent)[field_id.local_id] + .is_visible_from(db.upcast(), mod_id) }) .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| { substs .as_slice(&Interner) @@ -637,7 +638,7 @@ impl<'a> InferenceContext<'a> { }, ) { Some(derefed_ty) => { - canonicalized.decanonicalize_ty(derefed_ty.value) + canonicalized.decanonicalize_ty(&mut self.table, derefed_ty) } None => self.err_ty(), } @@ -740,8 +741,9 @@ impl<'a> InferenceContext<'a> { krate, index_trait, ); - let self_ty = - self_ty.map_or(self.err_ty(), |t| canonicalized.decanonicalize_ty(t.value)); + let self_ty = self_ty.map_or(self.err_ty(), |t| { + canonicalized.decanonicalize_ty(&mut self.table, t) + }); self.resolve_associated_type_with_params( self_ty, self.resolve_ops_index_output(), @@ -987,7 +989,7 @@ impl<'a> InferenceContext<'a> { }); let (receiver_ty, method_ty, substs) = match resolved { 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 substs = self.substs_for_method_call(generics, generic_args, &ty); self.write_method_resolution(tgt_expr, func, substs.clone()); diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 9f1253825ef..4c1e758904e 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -41,8 +41,13 @@ where } impl> Canonicalized { - pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty { - chalk_ir::Substitute::apply(&self.free_vars, ty, &Interner) + /// this method is wrong and shouldn't exist + pub(super) fn decanonicalize_ty(&self, table: &mut InferenceTable, ty: Canonical) -> 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( diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 3921c365517..3533d2010c5 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs @@ -380,7 +380,7 @@ pub(crate) fn lookup_method( traits_in_scope: &FxHashSet, visible_from_module: Option, name: &Name, -) -> Option<(Ty, FunctionId)> { +) -> Option<(Canonical, FunctionId)> { iterate_method_candidates( ty, db, @@ -421,7 +421,7 @@ pub fn iterate_method_candidates( visible_from_module: Option, name: Option<&Name>, mode: LookupMode, - mut callback: impl FnMut(&Ty, AssocItemId) -> Option, + mut callback: impl FnMut(&Canonical, AssocItemId) -> Option, ) -> Option { let mut slot = None; iterate_method_candidates_dyn( @@ -454,7 +454,7 @@ pub fn iterate_method_candidates_dyn( visible_from_module: Option, name: Option<&Name>, mode: LookupMode, - callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, + callback: &mut dyn FnMut(&Canonical, AssocItemId) -> ControlFlow<()>, ) -> ControlFlow<()> { match mode { LookupMode::MethodCall => { @@ -520,7 +520,7 @@ fn iterate_method_candidates_with_autoref( traits_in_scope: &FxHashSet, visible_from_module: Option, name: Option<&Name>, - mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, + mut callback: &mut dyn FnMut(&Canonical, AssocItemId) -> ControlFlow<()>, ) -> ControlFlow<()> { iterate_method_candidates_by_receiver( &deref_chain[0], @@ -580,7 +580,7 @@ fn iterate_method_candidates_by_receiver( traits_in_scope: &FxHashSet, visible_from_module: Option, name: Option<&Name>, - mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, + mut callback: &mut dyn FnMut(&Canonical, AssocItemId) -> ControlFlow<()>, ) -> ControlFlow<()> { // 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 @@ -622,7 +622,7 @@ fn iterate_method_candidates_for_self_ty( traits_in_scope: &FxHashSet, visible_from_module: Option, name: Option<&Name>, - mut callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, + mut callback: &mut dyn FnMut(&Canonical, AssocItemId) -> ControlFlow<()>, ) -> ControlFlow<()> { iterate_inherent_methods( self_ty, @@ -645,7 +645,7 @@ fn iterate_trait_method_candidates( traits_in_scope: &FxHashSet, name: Option<&Name>, receiver_ty: Option<&Canonical>, - callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, + callback: &mut dyn FnMut(&Canonical, AssocItemId) -> ControlFlow<()>, ) -> ControlFlow<()> { 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 @@ -697,7 +697,7 @@ fn iterate_trait_method_candidates( } known_implemented = true; // FIXME: we shouldn't be ignoring the binders here - callback(&self_ty.value, *item)? + callback(&self_ty, *item)? } } ControlFlow::Continue(()) @@ -738,7 +738,7 @@ fn iterate_inherent_methods( receiver_ty: Option<&Canonical>, krate: CrateId, visible_from_module: Option, - callback: &mut dyn FnMut(&Ty, AssocItemId) -> ControlFlow<()>, + callback: &mut dyn FnMut(&Canonical, AssocItemId) -> ControlFlow<()>, ) -> ControlFlow<()> { let def_crates = match def_crates(db, &self_ty.value, krate) { Some(k) => k, @@ -773,7 +773,7 @@ fn iterate_inherent_methods( cov_mark::hit!(impl_self_type_match_without_receiver); 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)?; } } diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 70a1c37dc07..618499fdc19 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs @@ -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 { } + +pub struct BitSlice { } + +impl core::ops::Deref for BitArray { + type Target = BitSlice; +} + +impl BitSlice { + pub fn split_first(&self) -> Option<(T, &Self)> { loop {} } +} + +fn multiexp_inner() { + let exp: &BitArray; + exp.split_first(); +} + "#, + ); +}