Differentiate Tuple / FnPtr type constructors by cardinality

This is necessary because Chalk (reasonably) expects each 'struct' to know how
many type parameters it takes.
This commit is contained in:
Florian Diebold 2019-05-04 19:07:25 +02:00
parent 19fbd91998
commit a4eb1a546c
5 changed files with 25 additions and 15 deletions

View File

@ -82,13 +82,13 @@ pub enum TypeCtor {
/// fn foo() -> i32 { 1 } /// fn foo() -> i32 { 1 }
/// let bar: fn() -> i32 = foo; /// let bar: fn() -> i32 = foo;
/// ``` /// ```
FnPtr, FnPtr { num_args: u16 },
/// The never type `!`. /// The never type `!`.
Never, Never,
/// A tuple type. For example, `(i32, bool)`. /// A tuple type. For example, `(i32, bool)`.
Tuple, Tuple { cardinality: u16 },
} }
/// A nominal type with (maybe 0) type parameters. This might be a primitive /// A nominal type with (maybe 0) type parameters. This might be a primitive
@ -299,7 +299,7 @@ impl Ty {
Ty::Apply(ApplicationTy { ctor, parameters }) Ty::Apply(ApplicationTy { ctor, parameters })
} }
pub fn unit() -> Self { pub fn unit() -> Self {
Ty::apply(TypeCtor::Tuple, Substs::empty()) Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty())
} }
pub fn walk(&self, f: &mut impl FnMut(&Ty)) { pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
@ -352,7 +352,9 @@ impl Ty {
pub fn as_tuple(&self) -> Option<&Substs> { pub fn as_tuple(&self) -> Option<&Substs> {
match self { match self {
Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple, parameters }) => Some(parameters), Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { .. }, parameters }) => {
Some(parameters)
}
_ => None, _ => None,
} }
} }
@ -380,7 +382,7 @@ impl Ty {
fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> { fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> {
match self { match self {
Ty::Apply(a_ty) => match a_ty.ctor { Ty::Apply(a_ty) => match a_ty.ctor {
TypeCtor::FnPtr => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)), TypeCtor::FnPtr { .. } => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)),
TypeCtor::FnDef(def) => { TypeCtor::FnDef(def) => {
let sig = db.callable_item_signature(def); let sig = db.callable_item_signature(def);
Some(sig.subst(&a_ty.parameters)) Some(sig.subst(&a_ty.parameters))
@ -466,7 +468,7 @@ impl HirDisplay for ApplicationTy {
write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?; write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?;
} }
TypeCtor::Never => write!(f, "!")?, TypeCtor::Never => write!(f, "!")?,
TypeCtor::Tuple => { TypeCtor::Tuple { .. } => {
let ts = &self.parameters; let ts = &self.parameters;
if ts.len() == 1 { if ts.len() == 1 {
write!(f, "({},)", ts[0].display(f.db))?; write!(f, "({},)", ts[0].display(f.db))?;
@ -476,7 +478,7 @@ impl HirDisplay for ApplicationTy {
write!(f, ")")?; write!(f, ")")?;
} }
} }
TypeCtor::FnPtr => { TypeCtor::FnPtr { .. } => {
let sig = FnSig::from_fn_ptr_substs(&self.parameters); let sig = FnSig::from_fn_ptr_substs(&self.parameters);
write!(f, "fn(")?; write!(f, "fn(")?;
f.write_joined(sig.params(), ", ")?; f.write_joined(sig.params(), ", ")?;

View File

@ -739,14 +739,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
}; };
let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown));
let inner_tys = args let inner_tys: Substs = args
.iter() .iter()
.zip(expectations_iter) .zip(expectations_iter)
.map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm)) .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into(); .into();
Ty::apply(TypeCtor::Tuple, Substs(inner_tys)) Ty::apply(TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, inner_tys)
} }
Pat::Ref { pat, mutability } => { Pat::Ref { pat, mutability } => {
let expectation = match expected.as_reference() { let expectation = match expected.as_reference() {
@ -1073,7 +1073,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
.autoderef(self.db) .autoderef(self.db)
.find_map(|derefed_ty| match derefed_ty { .find_map(|derefed_ty| match derefed_ty {
Ty::Apply(a_ty) => match a_ty.ctor { Ty::Apply(a_ty) => match a_ty.ctor {
TypeCtor::Tuple => { TypeCtor::Tuple { .. } => {
let i = name.to_string().parse::<usize>().ok(); let i = name.to_string().parse::<usize>().ok();
i.and_then(|i| a_ty.parameters.0.get(i).cloned()) i.and_then(|i| a_ty.parameters.0.get(i).cloned())
} }
@ -1184,7 +1184,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
ty_vec.push(self.infer_expr(*arg, &Expectation::none())); ty_vec.push(self.infer_expr(*arg, &Expectation::none()));
} }
Ty::apply(TypeCtor::Tuple, Substs(ty_vec.into())) Ty::apply(
TypeCtor::Tuple { cardinality: ty_vec.len() as u16 },
Substs(ty_vec.into()),
)
} }
Expr::Array(array) => { Expr::Array(array) => {
let elem_ty = match &expected.ty { let elem_ty = match &expected.ty {

View File

@ -29,7 +29,10 @@ impl Ty {
TypeRef::Tuple(inner) => { TypeRef::Tuple(inner) => {
let inner_tys = let inner_tys =
inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
Ty::apply(TypeCtor::Tuple, Substs(inner_tys.into())) Ty::apply(
TypeCtor::Tuple { cardinality: inner_tys.len() as u16 },
Substs(inner_tys.into()),
)
} }
TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path),
TypeRef::RawPtr(inner, mutability) => { TypeRef::RawPtr(inner, mutability) => {
@ -53,7 +56,7 @@ impl Ty {
let inner_tys = let inner_tys =
params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
let sig = Substs(inner_tys.into()); let sig = Substs(inner_tys.into());
Ty::apply(TypeCtor::FnPtr, sig) Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig)
} }
TypeRef::Error => Ty::Unknown, TypeRef::Error => Ty::Unknown,
} }

View File

@ -184,6 +184,7 @@ where
debug!("struct_datum {:?}", struct_id); debug!("struct_datum {:?}", struct_id);
let type_ctor = from_chalk(self.db, struct_id); let type_ctor = from_chalk(self.db, struct_id);
// FIXME might be nicer if we can create a fake GenericParams for the TypeCtor // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor
// FIXME extract this to a method on Ty
let (num_params, upstream) = match type_ctor { let (num_params, upstream) = match type_ctor {
TypeCtor::Bool TypeCtor::Bool
| TypeCtor::Char | TypeCtor::Char
@ -192,7 +193,8 @@ where
| TypeCtor::Never | TypeCtor::Never
| TypeCtor::Str => (0, true), | TypeCtor::Str => (0, true),
TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => (1, true), TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => (1, true),
TypeCtor::FnPtr | TypeCtor::Tuple => unimplemented!(), // FIXME tuples and FnPtr are currently variadic... we need to make the parameter number explicit TypeCtor::FnPtr { num_args } => (num_args as usize + 1, true),
TypeCtor::Tuple { cardinality } => (cardinality as usize, true),
TypeCtor::FnDef(_) => unimplemented!(), TypeCtor::FnDef(_) => unimplemented!(),
TypeCtor::Adt(adt) => { TypeCtor::Adt(adt) => {
let generic_params = adt.generic_params(self.db); let generic_params = adt.generic_params(self.db);

View File

@ -24,7 +24,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
} }
} }
// FIXME unions // FIXME unions
TypeCtor::Tuple => { TypeCtor::Tuple { .. } => {
for (i, ty) in a_ty.parameters.iter().enumerate() { for (i, ty) in a_ty.parameters.iter().enumerate() {
acc.add_pos_field(ctx, i, ty); acc.add_pos_field(ctx, i, ty);
} }