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 }
/// let bar: fn() -> i32 = foo;
/// ```
FnPtr,
FnPtr { num_args: u16 },
/// The never type `!`.
Never,
/// A tuple type. For example, `(i32, bool)`.
Tuple,
Tuple { cardinality: u16 },
}
/// A nominal type with (maybe 0) type parameters. This might be a primitive
@ -299,7 +299,7 @@ impl Ty {
Ty::Apply(ApplicationTy { ctor, parameters })
}
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)) {
@ -352,7 +352,9 @@ impl Ty {
pub fn as_tuple(&self) -> Option<&Substs> {
match self {
Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple, parameters }) => Some(parameters),
Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { .. }, parameters }) => {
Some(parameters)
}
_ => None,
}
}
@ -380,7 +382,7 @@ impl Ty {
fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> {
match self {
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) => {
let sig = db.callable_item_signature(def);
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))?;
}
TypeCtor::Never => write!(f, "!")?,
TypeCtor::Tuple => {
TypeCtor::Tuple { .. } => {
let ts = &self.parameters;
if ts.len() == 1 {
write!(f, "({},)", ts[0].display(f.db))?;
@ -476,7 +478,7 @@ impl HirDisplay for ApplicationTy {
write!(f, ")")?;
}
}
TypeCtor::FnPtr => {
TypeCtor::FnPtr { .. } => {
let sig = FnSig::from_fn_ptr_substs(&self.parameters);
write!(f, "fn(")?;
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 inner_tys = args
let inner_tys: Substs = args
.iter()
.zip(expectations_iter)
.map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm))
.collect::<Vec<_>>()
.into();
Ty::apply(TypeCtor::Tuple, Substs(inner_tys))
Ty::apply(TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, inner_tys)
}
Pat::Ref { pat, mutability } => {
let expectation = match expected.as_reference() {
@ -1073,7 +1073,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
.autoderef(self.db)
.find_map(|derefed_ty| match derefed_ty {
Ty::Apply(a_ty) => match a_ty.ctor {
TypeCtor::Tuple => {
TypeCtor::Tuple { .. } => {
let i = name.to_string().parse::<usize>().ok();
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::apply(TypeCtor::Tuple, Substs(ty_vec.into()))
Ty::apply(
TypeCtor::Tuple { cardinality: ty_vec.len() as u16 },
Substs(ty_vec.into()),
)
}
Expr::Array(array) => {
let elem_ty = match &expected.ty {

View file

@ -29,7 +29,10 @@ impl Ty {
TypeRef::Tuple(inner) => {
let inner_tys =
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::RawPtr(inner, mutability) => {
@ -53,7 +56,7 @@ impl Ty {
let inner_tys =
params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
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,
}

View file

@ -184,6 +184,7 @@ where
debug!("struct_datum {:?}", 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 extract this to a method on Ty
let (num_params, upstream) = match type_ctor {
TypeCtor::Bool
| TypeCtor::Char
@ -192,7 +193,8 @@ where
| TypeCtor::Never
| TypeCtor::Str => (0, 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::Adt(adt) => {
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
TypeCtor::Tuple => {
TypeCtor::Tuple { .. } => {
for (i, ty) in a_ty.parameters.iter().enumerate() {
acc.add_pos_field(ctx, i, ty);
}