Fix box pattern inference panic

This commit is contained in:
Lukas Wirth 2021-03-21 18:18:25 +01:00
parent 1ae20d2b89
commit af50e8d955
3 changed files with 51 additions and 9 deletions

View file

@ -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());
}
_ => (),

View file

@ -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(),
},

View file

@ -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"]