mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-11 16:15:03 +00:00
Represent FnPtr and Tuple using Substs
This commit is contained in:
parent
51323a852a
commit
bc7752e527
@ -89,13 +89,13 @@ pub enum Ty {
|
||||
/// fn foo() -> i32 { 1 }
|
||||
/// let bar: fn() -> i32 = foo;
|
||||
/// ```
|
||||
FnPtr(FnSig),
|
||||
FnPtr(Substs),
|
||||
|
||||
/// The never type `!`.
|
||||
Never,
|
||||
|
||||
/// A tuple type. For example, `(i32, bool)`.
|
||||
Tuple(Arc<[Ty]>),
|
||||
Tuple(Substs),
|
||||
|
||||
/// A type parameter; for example, `T` in `fn f<T>(x: T) {}
|
||||
Param {
|
||||
@ -127,6 +127,10 @@ impl Substs {
|
||||
Substs(Arc::new([]))
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &Ty> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
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();
|
||||
@ -148,6 +152,11 @@ impl FnSig {
|
||||
params.push(ret);
|
||||
FnSig { params_and_return: params.into() }
|
||||
}
|
||||
|
||||
pub fn from_fn_ptr_substs(substs: &Substs) -> FnSig {
|
||||
FnSig { params_and_return: Arc::clone(&substs.0) }
|
||||
}
|
||||
|
||||
pub fn params(&self) -> &[Ty] {
|
||||
&self.params_and_return[0..self.params_and_return.len() - 1]
|
||||
}
|
||||
@ -168,7 +177,7 @@ impl FnSig {
|
||||
|
||||
impl Ty {
|
||||
pub fn unit() -> Self {
|
||||
Ty::Tuple(Arc::new([]))
|
||||
Ty::Tuple(Substs::empty())
|
||||
}
|
||||
|
||||
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||
@ -182,10 +191,9 @@ impl Ty {
|
||||
}
|
||||
}
|
||||
Ty::FnPtr(sig) => {
|
||||
for input in sig.params() {
|
||||
input.walk(f);
|
||||
for t in sig.iter() {
|
||||
t.walk(f);
|
||||
}
|
||||
sig.ret().walk(f);
|
||||
}
|
||||
Ty::FnDef { substs, .. } => {
|
||||
for t in substs.0.iter() {
|
||||
@ -216,12 +224,7 @@ impl Ty {
|
||||
Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f),
|
||||
Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f),
|
||||
Ty::Tuple(ts) => {
|
||||
// Without an Arc::make_mut_slice, we can't avoid the clone here:
|
||||
let mut v: Vec<_> = ts.iter().cloned().collect();
|
||||
for t in &mut v {
|
||||
t.walk_mut(f);
|
||||
}
|
||||
*ts = v.into();
|
||||
ts.walk_mut(f);
|
||||
}
|
||||
Ty::FnPtr(sig) => {
|
||||
sig.walk_mut(f);
|
||||
@ -324,15 +327,16 @@ impl HirDisplay for Ty {
|
||||
}
|
||||
Ty::Never => write!(f, "!")?,
|
||||
Ty::Tuple(ts) => {
|
||||
if ts.len() == 1 {
|
||||
write!(f, "({},)", ts[0].display(f.db))?;
|
||||
if ts.0.len() == 1 {
|
||||
write!(f, "({},)", ts.0[0].display(f.db))?;
|
||||
} else {
|
||||
write!(f, "(")?;
|
||||
f.write_joined(&**ts, ", ")?;
|
||||
f.write_joined(&*ts.0, ", ")?;
|
||||
write!(f, ")")?;
|
||||
}
|
||||
}
|
||||
Ty::FnPtr(sig) => {
|
||||
let sig = FnSig::from_fn_ptr_substs(sig);
|
||||
write!(f, "fn(")?;
|
||||
f.write_joined(sig.params(), ", ")?;
|
||||
write!(f, ") -> {}", sig.ret().display(f.db))?;
|
||||
|
@ -38,7 +38,7 @@ use crate::{
|
||||
resolve::{Resolver, Resolution},
|
||||
nameres::Namespace
|
||||
};
|
||||
use super::{Ty, TypableDef, Substs, primitive, op};
|
||||
use super::{Ty, TypableDef, Substs, primitive, op, FnSig};
|
||||
|
||||
/// The entry point of type inference.
|
||||
pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> {
|
||||
@ -257,10 +257,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
self.unify_inner(t1, t2, depth + 1)
|
||||
}
|
||||
(Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify_inner(t1, t2, depth + 1),
|
||||
(Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true,
|
||||
(Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => {
|
||||
ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth + 1))
|
||||
}
|
||||
(Ty::FnPtr(sig1), Ty::FnPtr(sig2)) => self.unify_substs(sig1, sig2, depth + 1),
|
||||
(Ty::Tuple(ts1), Ty::Tuple(ts2)) => self.unify_substs(ts1, ts2, depth + 1),
|
||||
(Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
|
||||
| (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
|
||||
| (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => {
|
||||
@ -632,7 +630,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
let ty = match &body[pat] {
|
||||
Pat::Tuple(ref args) => {
|
||||
let expectations = match *expected {
|
||||
Ty::Tuple(ref tuple_args) => &**tuple_args,
|
||||
Ty::Tuple(ref tuple_args) => &*tuple_args.0,
|
||||
_ => &[],
|
||||
};
|
||||
let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown));
|
||||
@ -644,7 +642,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
|
||||
Ty::Tuple(inner_tys)
|
||||
Ty::Tuple(Substs(inner_tys))
|
||||
}
|
||||
Pat::Ref { pat, mutability } => {
|
||||
let expectation = match *expected {
|
||||
@ -789,7 +787,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
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.params().to_vec(), sig.ret().clone()),
|
||||
Ty::FnPtr(sig) => {
|
||||
let sig = FnSig::from_fn_ptr_substs(sig);
|
||||
(sig.params().to_vec(), sig.ret().clone())
|
||||
}
|
||||
Ty::FnDef { substs, def, .. } => {
|
||||
let sig = self.db.callable_item_signature(*def);
|
||||
let ret_ty = sig.ret().clone().subst(&substs);
|
||||
@ -828,6 +829,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
let method_ty = self.insert_type_vars(method_ty);
|
||||
let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
|
||||
Ty::FnPtr(sig) => {
|
||||
let sig = FnSig::from_fn_ptr_substs(sig);
|
||||
if !sig.params().is_empty() {
|
||||
(sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone())
|
||||
} else {
|
||||
@ -923,7 +925,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
.find_map(|derefed_ty| match derefed_ty {
|
||||
Ty::Tuple(fields) => {
|
||||
let i = name.to_string().parse::<usize>().ok();
|
||||
i.and_then(|i| fields.get(i).cloned())
|
||||
i.and_then(|i| fields.0.get(i).cloned())
|
||||
}
|
||||
Ty::Adt { def_id: AdtDef::Struct(s), ref substs, .. } => {
|
||||
s.field(self.db, name).map(|field| {
|
||||
@ -1016,7 +1018,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
ty_vec.push(self.infer_expr(*arg, &Expectation::none()));
|
||||
}
|
||||
|
||||
Ty::Tuple(Arc::from(ty_vec))
|
||||
Ty::Tuple(Substs(ty_vec.into()))
|
||||
}
|
||||
Expr::Array { exprs } => {
|
||||
let elem_ty = match &expected.ty {
|
||||
|
@ -30,7 +30,7 @@ impl Ty {
|
||||
TypeRef::Tuple(inner) => {
|
||||
let inner_tys =
|
||||
inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
|
||||
Ty::Tuple(inner_tys.into())
|
||||
Ty::Tuple(Substs(inner_tys.into()))
|
||||
}
|
||||
TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path),
|
||||
TypeRef::RawPtr(inner, mutability) => {
|
||||
@ -53,7 +53,7 @@ impl Ty {
|
||||
TypeRef::Fn(params) => {
|
||||
let inner_tys =
|
||||
params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
|
||||
let sig = FnSig { params_and_return: inner_tys.into() };
|
||||
let sig = Substs(inner_tys.into());
|
||||
Ty::FnPtr(sig)
|
||||
}
|
||||
TypeRef::Error => Ty::Unknown,
|
||||
|
Loading…
Reference in New Issue
Block a user