mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 05:45:12 +00:00
Fix completion with a partially unknown type
To test whether the receiver type matches for the impl, we unify the given self type (in this case `HashSet<{unknown}>`) with the self type of the impl (`HashSet<?0>`), but if the given self type contains Unknowns, they won't be unified with the variables in those places. So we got a receiver type that was different from the expected one, and concluded the impl doesn't match. The fix is slightly hacky; if after the unification, our variables are still there, we make them fall back to Unknown. This does make some sense though, since we don't want to 'leak' the variables. Fixes #3547.
This commit is contained in:
parent
e5df8c4028
commit
adc7b8ea2d
2 changed files with 56 additions and 3 deletions
|
@ -516,9 +516,31 @@ pub(crate) fn inherent_impl_substs(
|
|||
let self_ty_with_vars =
|
||||
Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars };
|
||||
let substs = super::infer::unify(&self_ty_with_vars, self_ty);
|
||||
// we only want the substs for the vars we added, not the ones from self_ty
|
||||
let result = substs.map(|s| s.suffix(vars.len()));
|
||||
result
|
||||
// We only want the substs for the vars we added, not the ones from self_ty.
|
||||
// Also, if any of the vars we added are still in there, we replace them by
|
||||
// Unknown. I think this can only really happen if self_ty contained
|
||||
// Unknown, and in that case we want the result to contain Unknown in those
|
||||
// places again.
|
||||
substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.num_vars))
|
||||
}
|
||||
|
||||
/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
|
||||
/// num_vars_to_keep) by `Ty::Unknown`.
|
||||
fn fallback_bound_vars(s: Substs, num_vars_to_keep: usize) -> Substs {
|
||||
s.fold_binders(
|
||||
&mut |ty, binders| {
|
||||
if let Ty::Bound(idx) = &ty {
|
||||
if *idx >= binders as u32 {
|
||||
Ty::Unknown
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
},
|
||||
num_vars_to_keep,
|
||||
)
|
||||
}
|
||||
|
||||
fn transform_receiver_ty(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue