mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 17:28:09 +00:00
Fix box pattern inference panic
This commit is contained in:
parent
1ae20d2b89
commit
af50e8d955
3 changed files with 51 additions and 9 deletions
|
@ -513,10 +513,10 @@ impl<'a> InferenceContext<'a> {
|
|||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
||||
if let Some(box_) = self.resolve_boxed_box() {
|
||||
let mut sb =
|
||||
Substitution::builder(generics(self.db.upcast(), box_.into()).len());
|
||||
Substitution::build_for_generics(&generics(self.db.upcast(), box_.into()));
|
||||
sb = sb.push(inner_ty);
|
||||
match self.db.generic_defaults(box_.into()).as_ref() {
|
||||
[_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => {
|
||||
match self.db.generic_defaults(box_.into()).get(1) {
|
||||
Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => {
|
||||
sb = sb.push(alloc_ty.value.clone());
|
||||
}
|
||||
_ => (),
|
||||
|
|
|
@ -13,7 +13,9 @@ use hir_expand::name::Name;
|
|||
|
||||
use super::{BindingMode, Expectation, InferenceContext};
|
||||
use crate::{
|
||||
lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyKind,
|
||||
lower::lower_to_chalk_mutability,
|
||||
utils::{generics, variant_data},
|
||||
Interner, Substitution, Ty, TyKind,
|
||||
};
|
||||
|
||||
impl<'a> InferenceContext<'a> {
|
||||
|
@ -233,13 +235,31 @@ impl<'a> InferenceContext<'a> {
|
|||
Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())),
|
||||
Pat::Box { inner } => match self.resolve_boxed_box() {
|
||||
Some(box_adt) => {
|
||||
let inner_expected = match expected.as_adt() {
|
||||
Some((adt, substs)) if adt == box_adt => substs.as_single().clone(),
|
||||
_ => self.result.standard_types.unknown.clone(),
|
||||
let (inner_ty, alloc_ty) = match expected.as_adt() {
|
||||
Some((adt, subst)) if adt == box_adt => {
|
||||
(subst[0].clone(), subst.get(1).cloned())
|
||||
}
|
||||
_ => (self.result.standard_types.unknown.clone(), None),
|
||||
};
|
||||
|
||||
let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm);
|
||||
Ty::adt_ty(box_adt, Substitution::single(inner_ty))
|
||||
let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm);
|
||||
let mut sb = Substitution::build_for_generics(&generics(
|
||||
self.db.upcast(),
|
||||
box_adt.into(),
|
||||
));
|
||||
sb = sb.push(inner_ty);
|
||||
if sb.remaining() == 1 {
|
||||
sb = sb.push(match alloc_ty {
|
||||
Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty,
|
||||
_ => match self.db.generic_defaults(box_adt.into()).get(1) {
|
||||
Some(alloc_ty) if !alloc_ty.value.is_unknown() => {
|
||||
alloc_ty.value.clone()
|
||||
}
|
||||
_ => self.table.new_type_var(),
|
||||
},
|
||||
});
|
||||
}
|
||||
Ty::adt_ty(box_adt, sb.build())
|
||||
}
|
||||
None => self.err_ty(),
|
||||
},
|
||||
|
|
|
@ -656,6 +656,28 @@ fn slice_tail_pattern() {
|
|||
|
||||
#[test]
|
||||
fn box_pattern() {
|
||||
check_infer(
|
||||
r#"
|
||||
pub struct Global;
|
||||
#[lang = "owned_box"]
|
||||
pub struct Box<T, A = Global>(T);
|
||||
|
||||
fn foo(params: Box<i32>) {
|
||||
match params {
|
||||
box integer => {}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
83..89 'params': Box<i32, Global>
|
||||
101..155 '{ ... } }': ()
|
||||
107..153 'match ... }': ()
|
||||
113..119 'params': Box<i32, Global>
|
||||
130..141 'box integer': Box<i32, Global>
|
||||
134..141 'integer': i32
|
||||
145..147 '{}': ()
|
||||
"#]],
|
||||
);
|
||||
check_infer(
|
||||
r#"
|
||||
#[lang = "owned_box"]
|
||||
|
|
Loading…
Reference in a new issue