mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
try to infer array type from slice pattern
rust-analyzer equivalent of rust-lang/rust#2827aa97
This commit is contained in:
parent
bc10a44798
commit
d092918b55
@ -6,12 +6,13 @@ use hir_def::{
|
|||||||
expr_store::Body,
|
expr_store::Body,
|
||||||
hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, Literal, Pat, PatId},
|
hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, Literal, Pat, PatId},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
HasModule,
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use stdx::TupleExt;
|
use stdx::TupleExt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
consteval::{try_const_usize, usize_const},
|
consteval::{self, try_const_usize, usize_const},
|
||||||
infer::{
|
infer::{
|
||||||
coerce::CoerceNever, expr::ExprIsRead, BindingMode, Expectation, InferenceContext,
|
coerce::CoerceNever, expr::ExprIsRead, BindingMode, Expectation, InferenceContext,
|
||||||
TypeMismatch,
|
TypeMismatch,
|
||||||
@ -479,6 +480,19 @@ impl InferenceContext<'_> {
|
|||||||
suffix: &[PatId],
|
suffix: &[PatId],
|
||||||
default_bm: BindingMode,
|
default_bm: BindingMode,
|
||||||
) -> Ty {
|
) -> Ty {
|
||||||
|
let expected = self.resolve_ty_shallow(expected);
|
||||||
|
|
||||||
|
// If `expected` is an infer ty, we try to equate it to an array if the given pattern
|
||||||
|
// allows it. See issue #16609
|
||||||
|
if expected.is_ty_var() {
|
||||||
|
if let Some(resolved_array_ty) =
|
||||||
|
self.try_resolve_slice_ty_to_array_ty(prefix, suffix, slice)
|
||||||
|
{
|
||||||
|
self.unify(&expected, &resolved_array_ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let expected = self.resolve_ty_shallow(&expected);
|
||||||
let elem_ty = match expected.kind(Interner) {
|
let elem_ty = match expected.kind(Interner) {
|
||||||
TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
|
TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
|
||||||
_ => self.err_ty(),
|
_ => self.err_ty(),
|
||||||
@ -553,6 +567,25 @@ impl InferenceContext<'_> {
|
|||||||
| Pat::Expr(_) => false,
|
| Pat::Expr(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_resolve_slice_ty_to_array_ty(
|
||||||
|
&mut self,
|
||||||
|
before: &[PatId],
|
||||||
|
suffix: &[PatId],
|
||||||
|
slice: &Option<PatId>,
|
||||||
|
) -> Option<Ty> {
|
||||||
|
if !slice.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = before.len() + suffix.len();
|
||||||
|
let size =
|
||||||
|
consteval::usize_const(self.db, Some(len as u128), self.owner.krate(self.db.upcast()));
|
||||||
|
|
||||||
|
let elem_ty = self.table.new_type_var();
|
||||||
|
let array_ty = TyKind::Array(elem_ty.clone(), size).intern(Interner);
|
||||||
|
Some(array_ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn contains_explicit_ref_binding(body: &Body, pat_id: PatId) -> bool {
|
pub(super) fn contains_explicit_ref_binding(body: &Body, pat_id: PatId) -> bool {
|
||||||
|
@ -3814,3 +3814,31 @@ async fn foo(a: (), b: i32) -> u32 {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn irrefutable_slices() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
//- minicore: from
|
||||||
|
struct A;
|
||||||
|
|
||||||
|
impl From<A> for [u8; 2] {
|
||||||
|
fn from(a: A) -> Self {
|
||||||
|
[0; 2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<A> for [u8; 3] {
|
||||||
|
fn from(a: A) -> Self {
|
||||||
|
[0; 3]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = A;
|
||||||
|
let [b, c] = a.into();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user