/// The definition of the function / constructor.
def: CallableDef,
/// Parameters and return type
- sig: Arc<FnSig>,
+ sig: FnSig,
/// Substitutions for the generic parameters of the type
substs: Substs,
},
/// fn foo() -> i32 { 1 }
/// let bar: fn() -> i32 = foo;
/// ```
- FnPtr(Arc<FnSig>),
+ FnPtr(FnSig),
/// The never type `!`.
Never,
pub fn empty() -> Substs {
Substs(Arc::new([]))
}
+
+ pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
+ // Without an Arc::make_mut_slice, we can't avoid the clone here:
+ let mut v: Vec<_> = self.0.iter().cloned().collect();
+ for t in &mut v {
+ t.walk_mut(f);
+ }
+ self.0 = v.into();
+ }
}
/// A function signature.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct FnSig {
- input: Vec<Ty>,
- output: Ty,
+ params_and_return: Arc<[Ty]>,
+}
+
+impl FnSig {
+ pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig {
+ params.push(ret);
+ FnSig { params_and_return: params.into() }
+ }
+ pub fn params(&self) -> &[Ty] {
+ &self.params_and_return[0..self.params_and_return.len() - 1]
+ }
+
+ pub fn ret(&self) -> &Ty {
+ &self.params_and_return[self.params_and_return.len() - 1]
+ }
+
+ pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
+ // Without an Arc::make_mut_slice, we can't avoid the clone here:
+ let mut v: Vec<_> = self.params_and_return.iter().cloned().collect();
+ for t in &mut v {
+ t.walk_mut(f);
+ }
+ self.params_and_return = v.into();
+ }
}
impl Ty {
}
}
Ty::FnPtr(sig) => {
- for input in &sig.input {
+ for input in sig.params() {
input.walk(f);
}
- sig.output.walk(f);
+ sig.ret().walk(f);
}
Ty::FnDef { substs, sig, .. } => {
- for input in &sig.input {
+ for input in sig.params() {
input.walk(f);
}
- sig.output.walk(f);
+ sig.ret().walk(f);
for t in substs.0.iter() {
t.walk(f);
}
*ts = v.into();
}
Ty::FnPtr(sig) => {
- let sig_mut = Arc::make_mut(sig);
- for input in &mut sig_mut.input {
- input.walk_mut(f);
- }
- sig_mut.output.walk_mut(f);
+ sig.walk_mut(f);
}
Ty::FnDef { substs, sig, .. } => {
- let sig_mut = Arc::make_mut(sig);
- for input in &mut sig_mut.input {
- input.walk_mut(f);
- }
- sig_mut.output.walk_mut(f);
- // Without an Arc::make_mut_slice, we can't avoid the clone here:
- let mut v: Vec<_> = substs.0.iter().cloned().collect();
- for t in &mut v {
- t.walk_mut(f);
- }
- substs.0 = v.into();
+ sig.walk_mut(f);
+ substs.walk_mut(f);
}
Ty::Adt { substs, .. } => {
- // Without an Arc::make_mut_slice, we can't avoid the clone here:
- let mut v: Vec<_> = substs.0.iter().cloned().collect();
- for t in &mut v {
- t.walk_mut(f);
- }
- substs.0 = v.into();
+ substs.walk_mut(f);
}
Ty::Bool
| Ty::Char
}
Ty::FnPtr(sig) => {
write!(f, "fn(")?;
- f.write_joined(&sig.input, ", ")?;
- write!(f, ") -> {}", sig.output.display(f.db))?;
+ f.write_joined(sig.params(), ", ")?;
+ write!(f, ") -> {}", sig.ret().display(f.db))?;
}
Ty::FnDef { def, substs, sig, .. } => {
let name = match def {
write!(f, ">")?;
}
write!(f, "(")?;
- f.write_joined(&sig.input, ", ")?;
- write!(f, ") -> {}", sig.output.display(f.db))?;
+ f.write_joined(sig.params(), ", ")?;
+ write!(f, ") -> {}", sig.ret().display(f.db))?;
}
Ty::Adt { def_id, substs, .. } => {
let name = match def_id {
Expr::Call { callee, args } => {
let callee_ty = self.infer_expr(*callee, &Expectation::none());
let (param_tys, ret_ty) = match &callee_ty {
- Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()),
+ Ty::FnPtr(sig) => (sig.params().to_vec(), sig.ret().clone()),
Ty::FnDef { substs, sig, .. } => {
- let ret_ty = sig.output.clone().subst(&substs);
+ let ret_ty = sig.ret().clone().subst(&substs);
let param_tys =
- sig.input.iter().map(|ty| ty.clone().subst(&substs)).collect();
+ sig.params().iter().map(|ty| ty.clone().subst(&substs)).collect();
(param_tys, ret_ty)
}
_ => {
let method_ty = self.insert_type_vars(method_ty);
let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
Ty::FnPtr(sig) => {
- if !sig.input.is_empty() {
- (sig.input[0].clone(), sig.input[1..].to_vec(), sig.output.clone())
+ if !sig.params().is_empty() {
+ (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone())
} else {
- (Ty::Unknown, Vec::new(), sig.output.clone())
+ (Ty::Unknown, Vec::new(), sig.ret().clone())
}
}
Ty::FnDef { substs, sig, .. } => {
- let ret_ty = sig.output.clone().subst(&substs);
+ let ret_ty = sig.ret().clone().subst(&substs);
- if !sig.input.is_empty() {
- let mut arg_iter = sig.input.iter().map(|ty| ty.clone().subst(&substs));
- let receiver_ty = arg_iter.next().unwrap();
- (receiver_ty, arg_iter.collect(), ret_ty)
+ if !sig.params().is_empty() {
+ let mut params_iter =
+ sig.params().iter().map(|ty| ty.clone().subst(&substs));
+ let receiver_ty = params_iter.next().unwrap();
+ (receiver_ty, params_iter.collect(), ret_ty)
} else {
(Ty::Unknown, Vec::new(), ret_ty)
}
}
TypeRef::Placeholder => Ty::Unknown,
TypeRef::Fn(params) => {
- let mut inner_tys =
+ let inner_tys =
params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
- let return_ty =
- inner_tys.pop().expect("TypeRef::Fn should always have at least return type");
- let sig = FnSig { input: inner_tys, output: return_ty };
- Ty::FnPtr(Arc::new(sig))
+ let sig = FnSig { params_and_return: inner_tys.into() };
+ Ty::FnPtr(sig)
}
TypeRef::Error => Ty::Unknown,
}
Ty::from_hir(db, &resolver, type_ref)
}
+fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
+ let signature = def.signature(db);
+ let resolver = def.resolver(db);
+ let params =
+ signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
+ let ret = Ty::from_hir(db, &resolver, signature.ret_type());
+ FnSig::from_params_and_return(params, ret)
+}
+
/// Build the declared type of a function. This should not need to look at the
/// function body.
fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
- let signature = def.signature(db);
- let resolver = def.resolver(db);
+ let sig = fn_sig_for_fn(db, def);
let generics = def.generic_params(db);
- let input =
- signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
- let output = Ty::from_hir(db, &resolver, signature.ret_type());
- let sig = Arc::new(FnSig { input, output });
let substs = make_substs(&generics);
Ty::FnDef { def: def.into(), sig, substs }
}
Ty::from_hir(db, &resolver, signature.type_ref())
}
-/// Build the type of a tuple struct constructor.
-fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
+fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
let var_data = def.variant_data(db);
let fields = match var_data.fields() {
Some(fields) => fields,
- None => return type_for_struct(db, def), // Unit struct
+ None => panic!("fn_sig_for_struct_constructor called on unit struct"),
};
let resolver = def.resolver(db);
- let generics = def.generic_params(db);
- let input = fields
+ let params = fields
.iter()
.map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
.collect::<Vec<_>>();
- let output = type_for_struct(db, def);
- let sig = Arc::new(FnSig { input, output });
+ let ret = type_for_struct(db, def);
+ FnSig::from_params_and_return(params, ret)
+}
+
+/// Build the type of a tuple struct constructor.
+fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
+ let var_data = def.variant_data(db);
+ if var_data.fields().is_none() {
+ return type_for_struct(db, def); // Unit struct
+ }
+ let sig = fn_sig_for_struct_constructor(db, def);
+ let generics = def.generic_params(db);
let substs = make_substs(&generics);
Ty::FnDef { def: def.into(), sig, substs }
}
-/// Build the type of a tuple enum variant constructor.
-fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
+fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig {
let var_data = def.variant_data(db);
let fields = match var_data.fields() {
Some(fields) => fields,
- None => return type_for_enum(db, def.parent_enum(db)), // Unit variant
+ None => panic!("fn_sig_for_enum_variant_constructor called for unit variant"),
};
let resolver = def.parent_enum(db).resolver(db);
- let generics = def.parent_enum(db).generic_params(db);
- let input = fields
+ let params = fields
.iter()
.map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
.collect::<Vec<_>>();
+ let generics = def.parent_enum(db).generic_params(db);
+ let substs = make_substs(&generics);
+ let ret = type_for_enum(db, def.parent_enum(db)).subst(&substs);
+ FnSig::from_params_and_return(params, ret)
+}
+
+/// Build the type of a tuple enum variant constructor.
+fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
+ let var_data = def.variant_data(db);
+ if var_data.fields().is_none() {
+ return type_for_enum(db, def.parent_enum(db)); // Unit variant
+ }
+ let sig = fn_sig_for_enum_variant_constructor(db, def);
+ let generics = def.parent_enum(db).generic_params(db);
let substs = make_substs(&generics);
- let output = type_for_enum(db, def.parent_enum(db)).subst(&substs);
- let sig = Arc::new(FnSig { input, output });
Ty::FnDef { def: def.into(), sig, substs }
}