Shrink TypeRef from 16 from 32 bytes

Only references and arrays need to be boxed, and they comprise only 9.4% of the types (according to counting on r-a's code).

This saves 17mb.
This commit is contained in:
Chayim Refael Friedman 2024-10-20 01:56:51 +03:00
parent 061e5d7f71
commit bf7edd3783
10 changed files with 178 additions and 149 deletions

View file

@ -11,7 +11,10 @@ use hir_expand::{
ExpandResult, ExpandResult,
}; };
use la_arena::{Arena, RawIdx}; use la_arena::{Arena, RawIdx};
use stdx::impl_from; use stdx::{
impl_from,
thin_vec::{EmptyOptimizedThinVec, ThinVec},
};
use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds}; use syntax::ast::{self, HasGenericParams, HasName, HasTypeBounds};
use triomphe::Arc; use triomphe::Arc;
@ -22,7 +25,10 @@ use crate::{
lower::LowerCtx, lower::LowerCtx,
nameres::{DefMap, MacroSubNs}, nameres::{DefMap, MacroSubNs},
path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path}, path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef, TypeRefId, TypesMap, TypesSourceMap}, type_ref::{
ArrayType, ConstRef, FnType, LifetimeRef, RefType, TypeBound, TypeRef, TypeRefId, TypesMap,
TypesSourceMap,
},
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId, AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
}; };
@ -590,7 +596,7 @@ impl GenericParamsCollector {
self.where_predicates.push(predicate); self.where_predicates.push(predicate);
} }
fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<Vec<TypeBound>>) { fn fill_impl_trait_bounds(&mut self, impl_bounds: Vec<ThinVec<TypeBound>>) {
for bounds in impl_bounds { for bounds in impl_bounds {
let param = TypeParamData { let param = TypeParamData {
name: None, name: None,
@ -598,10 +604,10 @@ impl GenericParamsCollector {
provenance: TypeParamProvenance::ArgumentImplTrait, provenance: TypeParamProvenance::ArgumentImplTrait,
}; };
let param_id = self.type_or_consts.alloc(param.into()); let param_id = self.type_or_consts.alloc(param.into());
for bound in bounds { for bound in &bounds {
self.where_predicates.push(WherePredicate::TypeBound { self.where_predicates.push(WherePredicate::TypeBound {
target: WherePredicateTypeTarget::TypeOrConstParam(param_id), target: WherePredicateTypeTarget::TypeOrConstParam(param_id),
bound, bound: bound.clone(),
}); });
} }
} }
@ -725,46 +731,45 @@ fn copy_type_ref(
to_source_map: &mut TypesSourceMap, to_source_map: &mut TypesSourceMap,
) -> TypeRefId { ) -> TypeRefId {
let result = match &from[type_ref] { let result = match &from[type_ref] {
&TypeRef::Fn { ref params, is_varargs, is_unsafe, ref abi } => { TypeRef::Fn(fn_) => {
let params = params let params = fn_.params().iter().map(|(name, param_type)| {
.iter() (name.clone(), copy_type_ref(*param_type, from, from_source_map, to, to_source_map))
.map(|(name, param_type)| { });
( TypeRef::Fn(FnType::new(fn_.is_varargs(), fn_.is_unsafe(), fn_.abi().clone(), params))
name.clone(),
copy_type_ref(*param_type, from, from_source_map, to, to_source_map),
)
})
.collect();
TypeRef::Fn { params, is_varargs, is_unsafe, abi: abi.clone() }
} }
TypeRef::Tuple(types) => TypeRef::Tuple( TypeRef::Tuple(types) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter(
types types.iter().map(|&t| copy_type_ref(t, from, from_source_map, to, to_source_map)),
.iter() )),
.map(|&t| copy_type_ref(t, from, from_source_map, to, to_source_map))
.collect(),
),
&TypeRef::RawPtr(type_ref, mutbl) => TypeRef::RawPtr( &TypeRef::RawPtr(type_ref, mutbl) => TypeRef::RawPtr(
copy_type_ref(type_ref, from, from_source_map, to, to_source_map), copy_type_ref(type_ref, from, from_source_map, to, to_source_map),
mutbl, mutbl,
), ),
TypeRef::Reference(type_ref, lifetime, mutbl) => TypeRef::Reference( TypeRef::Reference(ref_) => TypeRef::Reference(Box::new(RefType {
copy_type_ref(*type_ref, from, from_source_map, to, to_source_map), ty: copy_type_ref(ref_.ty, from, from_source_map, to, to_source_map),
lifetime.clone(), lifetime: ref_.lifetime.clone(),
*mutbl, mutability: ref_.mutability,
), })),
TypeRef::Array(type_ref, len) => TypeRef::Array( TypeRef::Array(array) => TypeRef::Array(Box::new(ArrayType {
copy_type_ref(*type_ref, from, from_source_map, to, to_source_map), ty: copy_type_ref(array.ty, from, from_source_map, to, to_source_map),
len.clone(), len: array.len.clone(),
), })),
&TypeRef::Slice(type_ref) => { &TypeRef::Slice(type_ref) => {
TypeRef::Slice(copy_type_ref(type_ref, from, from_source_map, to, to_source_map)) TypeRef::Slice(copy_type_ref(type_ref, from, from_source_map, to, to_source_map))
} }
TypeRef::ImplTrait(bounds) => TypeRef::ImplTrait( TypeRef::ImplTrait(bounds) => TypeRef::ImplTrait(ThinVec::from_iter(copy_type_bounds(
copy_type_bounds(bounds, from, from_source_map, to, to_source_map).into(), bounds,
), from,
TypeRef::DynTrait(bounds) => TypeRef::DynTrait( from_source_map,
copy_type_bounds(bounds, from, from_source_map, to, to_source_map).into(), to,
), to_source_map,
))),
TypeRef::DynTrait(bounds) => TypeRef::DynTrait(ThinVec::from_iter(copy_type_bounds(
bounds,
from,
from_source_map,
to,
to_source_map,
))),
TypeRef::Path(path) => { TypeRef::Path(path) => {
TypeRef::Path(copy_path(path, from, from_source_map, to, to_source_map)) TypeRef::Path(copy_path(path, from, from_source_map, to, to_source_map))
} }
@ -833,7 +838,8 @@ fn copy_generic_args(
copy_type_ref(type_ref, from, from_source_map, to, to_source_map) copy_type_ref(type_ref, from, from_source_map, to, to_source_map)
}); });
let bounds = let bounds =
copy_type_bounds(&binding.bounds, from, from_source_map, to, to_source_map); copy_type_bounds(&binding.bounds, from, from_source_map, to, to_source_map)
.collect();
AssociatedTypeBinding { name, args, type_ref, bounds } AssociatedTypeBinding { name, args, type_ref, bounds }
}) })
.collect(); .collect();
@ -846,17 +852,14 @@ fn copy_generic_args(
}) })
} }
fn copy_type_bounds( fn copy_type_bounds<'a>(
bounds: &[TypeBound], bounds: &'a [TypeBound],
from: &TypesMap, from: &'a TypesMap,
from_source_map: &TypesSourceMap, from_source_map: &'a TypesSourceMap,
to: &mut TypesMap, to: &'a mut TypesMap,
to_source_map: &mut TypesSourceMap, to_source_map: &'a mut TypesSourceMap,
) -> Box<[TypeBound]> { ) -> impl stdx::thin_vec::TrustedLen<Item = TypeBound> + 'a {
bounds bounds.iter().map(|bound| copy_type_bound(bound, from, from_source_map, to, to_source_map))
.iter()
.map(|bound| copy_type_bound(bound, from, from_source_map, to, to_source_map))
.collect()
} }
fn copy_type_bound( fn copy_type_bound(

View file

@ -12,6 +12,7 @@ use hir_expand::{
use intern::{sym, Symbol}; use intern::{sym, Symbol};
use la_arena::{Arena, ArenaMap, Idx}; use la_arena::{Arena, ArenaMap, Idx};
use span::Edition; use span::Edition;
use stdx::thin_vec::{thin_vec_with_header_struct, EmptyOptimizedThinVec, ThinVec};
use syntax::{ use syntax::{
ast::{self, HasGenericArgs, HasName, IsString}, ast::{self, HasGenericArgs, HasName, IsString},
AstPtr, AstPtr,
@ -108,31 +109,51 @@ impl TraitRef {
} }
} }
thin_vec_with_header_struct! {
pub new(pub(crate)) struct FnType, FnTypeHeader {
pub params: [(Option<Name>, TypeRefId)],
pub is_varargs: bool,
pub is_unsafe: bool,
pub abi: Option<Symbol>; ref,
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct ArrayType {
pub ty: TypeRefId,
// FIXME: This should be Ast<ConstArg>
pub len: ConstRef,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct RefType {
pub ty: TypeRefId,
pub lifetime: Option<LifetimeRef>,
pub mutability: Mutability,
}
/// Compare ty::Ty /// Compare ty::Ty
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum TypeRef { pub enum TypeRef {
Never, Never,
Placeholder, Placeholder,
Tuple(Vec<TypeRefId>), Tuple(EmptyOptimizedThinVec<TypeRefId>),
Path(Path), Path(Path),
RawPtr(TypeRefId, Mutability), RawPtr(TypeRefId, Mutability),
Reference(TypeRefId, Option<LifetimeRef>, Mutability), Reference(Box<RefType>),
// FIXME: This should be Array(TypeRefId, Ast<ConstArg>), Array(Box<ArrayType>),
Array(TypeRefId, ConstRef),
Slice(TypeRefId), Slice(TypeRefId),
/// A fn pointer. Last element of the vector is the return type. /// A fn pointer. Last element of the vector is the return type.
Fn { Fn(FnType),
params: Box<[(Option<Name>, TypeRefId)]>, ImplTrait(ThinVec<TypeBound>),
is_varargs: bool, DynTrait(ThinVec<TypeBound>),
is_unsafe: bool,
abi: Option<Symbol>,
},
ImplTrait(Vec<TypeBound>),
DynTrait(Vec<TypeBound>),
Macro(AstId<ast::MacroCall>), Macro(AstId<ast::MacroCall>),
Error, Error,
} }
#[cfg(target_arch = "x86_64")]
const _: () = assert!(size_of::<TypeRef>() == 16);
pub type TypeRefId = Idx<TypeRef>; pub type TypeRefId = Idx<TypeRef>;
#[derive(Default, Clone, PartialEq, Eq, Debug, Hash)] #[derive(Default, Clone, PartialEq, Eq, Debug, Hash)]
@ -222,9 +243,9 @@ impl TypeRef {
pub fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> TypeRefId { pub fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> TypeRefId {
let ty = match &node { let ty = match &node {
ast::Type::ParenType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()), ast::Type::ParenType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()),
ast::Type::TupleType(inner) => { ast::Type::TupleType(inner) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter(
TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect()) Vec::from_iter(inner.fields().map(|it| TypeRef::from_ast(ctx, it))),
} )),
ast::Type::NeverType(..) => TypeRef::Never, ast::Type::NeverType(..) => TypeRef::Never,
ast::Type::PathType(inner) => { ast::Type::PathType(inner) => {
// FIXME: Use `Path::from_src` // FIXME: Use `Path::from_src`
@ -241,14 +262,17 @@ impl TypeRef {
} }
ast::Type::ArrayType(inner) => { ast::Type::ArrayType(inner) => {
let len = ConstRef::from_const_arg(ctx, inner.const_arg()); let len = ConstRef::from_const_arg(ctx, inner.const_arg());
TypeRef::Array(TypeRef::from_ast_opt(ctx, inner.ty()), len) TypeRef::Array(Box::new(ArrayType {
ty: TypeRef::from_ast_opt(ctx, inner.ty()),
len,
}))
} }
ast::Type::SliceType(inner) => TypeRef::Slice(TypeRef::from_ast_opt(ctx, inner.ty())), ast::Type::SliceType(inner) => TypeRef::Slice(TypeRef::from_ast_opt(ctx, inner.ty())),
ast::Type::RefType(inner) => { ast::Type::RefType(inner) => {
let inner_ty = TypeRef::from_ast_opt(ctx, inner.ty()); let inner_ty = TypeRef::from_ast_opt(ctx, inner.ty());
let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(&lt)); let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(&lt));
let mutability = Mutability::from_mutable(inner.mut_token().is_some()); let mutability = Mutability::from_mutable(inner.mut_token().is_some());
TypeRef::Reference(inner_ty, lifetime, mutability) TypeRef::Reference(Box::new(RefType { ty: inner_ty, lifetime, mutability }))
} }
ast::Type::InferType(_inner) => TypeRef::Placeholder, ast::Type::InferType(_inner) => TypeRef::Placeholder,
ast::Type::FnPtrType(inner) => { ast::Type::FnPtrType(inner) => {
@ -256,7 +280,7 @@ impl TypeRef {
.ret_type() .ret_type()
.and_then(|rt| rt.ty()) .and_then(|rt| rt.ty())
.map(|it| TypeRef::from_ast(ctx, it)) .map(|it| TypeRef::from_ast(ctx, it))
.unwrap_or_else(|| ctx.alloc_type_ref_desugared(TypeRef::Tuple(Vec::new()))); .unwrap_or_else(|| ctx.alloc_type_ref_desugared(TypeRef::unit()));
let mut is_varargs = false; let mut is_varargs = false;
let mut params = if let Some(pl) = inner.param_list() { let mut params = if let Some(pl) = inner.param_list() {
if let Some(param) = pl.params().last() { if let Some(param) = pl.params().last() {
@ -288,12 +312,7 @@ impl TypeRef {
let abi = inner.abi().map(lower_abi); let abi = inner.abi().map(lower_abi);
params.push((None, ret_ty)); params.push((None, ret_ty));
TypeRef::Fn { TypeRef::Fn(FnType::new(is_varargs, inner.unsafe_token().is_some(), abi, params))
params: params.into(),
is_varargs,
is_unsafe: inner.unsafe_token().is_some(),
abi,
}
} }
// for types are close enough for our purposes to the inner type for now... // for types are close enough for our purposes to the inner type for now...
ast::Type::ForType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()), ast::Type::ForType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()),
@ -325,7 +344,7 @@ impl TypeRef {
} }
pub(crate) fn unit() -> TypeRef { pub(crate) fn unit() -> TypeRef {
TypeRef::Tuple(Vec::new()) TypeRef::Tuple(EmptyOptimizedThinVec::empty())
} }
pub fn walk(this: TypeRefId, map: &TypesMap, f: &mut impl FnMut(&TypeRef)) { pub fn walk(this: TypeRefId, map: &TypesMap, f: &mut impl FnMut(&TypeRef)) {
@ -335,14 +354,13 @@ impl TypeRef {
let type_ref = &map[type_ref]; let type_ref = &map[type_ref];
f(type_ref); f(type_ref);
match type_ref { match type_ref {
TypeRef::Fn { params, is_varargs: _, is_unsafe: _, abi: _ } => { TypeRef::Fn(fn_) => {
params.iter().for_each(|&(_, param_type)| go(param_type, f, map)) fn_.params().iter().for_each(|&(_, param_type)| go(param_type, f, map))
} }
TypeRef::Tuple(types) => types.iter().for_each(|&t| go(t, f, map)), TypeRef::Tuple(types) => types.iter().for_each(|&t| go(t, f, map)),
TypeRef::RawPtr(type_ref, _) TypeRef::RawPtr(type_ref, _) | TypeRef::Slice(type_ref) => go(*type_ref, f, map),
| TypeRef::Reference(type_ref, ..) TypeRef::Reference(it) => go(it.ty, f, map),
| TypeRef::Array(type_ref, _) TypeRef::Array(it) => go(it.ty, f, map),
| TypeRef::Slice(type_ref) => go(*type_ref, f, map),
TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => { TypeRef::ImplTrait(bounds) | TypeRef::DynTrait(bounds) => {
for bound in bounds { for bound in bounds {
match bound { match bound {
@ -394,11 +412,13 @@ impl TypeRef {
pub(crate) fn type_bounds_from_ast( pub(crate) fn type_bounds_from_ast(
lower_ctx: &LowerCtx<'_>, lower_ctx: &LowerCtx<'_>,
type_bounds_opt: Option<ast::TypeBoundList>, type_bounds_opt: Option<ast::TypeBoundList>,
) -> Vec<TypeBound> { ) -> ThinVec<TypeBound> {
if let Some(type_bounds) = type_bounds_opt { if let Some(type_bounds) = type_bounds_opt {
type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect() ThinVec::from_iter(Vec::from_iter(
type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)),
))
} else { } else {
vec![] ThinVec::from_iter([])
} }
} }

View file

@ -12,6 +12,7 @@ use intern::{sym, Symbol};
use la_arena::Arena; use la_arena::Arena;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use span::{AstIdMap, SyntaxContextId}; use span::{AstIdMap, SyntaxContextId};
use stdx::thin_vec::ThinVec;
use syntax::{ use syntax::{
ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString}, ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString},
AstNode, AstNode,
@ -33,8 +34,8 @@ use crate::{
lower::LowerCtx, lower::LowerCtx,
path::AssociatedTypeBinding, path::AssociatedTypeBinding,
type_ref::{ type_ref::{
LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId, TypesMap, LifetimeRef, RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId,
TypesSourceMap, TypesMap, TypesSourceMap,
}, },
visibility::RawVisibility, visibility::RawVisibility,
LocalLifetimeParamId, LocalTypeOrConstParamId, LocalLifetimeParamId, LocalTypeOrConstParamId,
@ -463,20 +464,20 @@ impl<'a> Ctx<'a> {
)); ));
match self_param.kind() { match self_param.kind() {
ast::SelfParamKind::Owned => self_type, ast::SelfParamKind::Owned => self_type,
ast::SelfParamKind::Ref => { ast::SelfParamKind::Ref => body_ctx.alloc_type_ref_desugared(
body_ctx.alloc_type_ref_desugared(TypeRef::Reference( TypeRef::Reference(Box::new(RefType {
self_type, ty: self_type,
self_param.lifetime().as_ref().map(LifetimeRef::new), lifetime: self_param.lifetime().as_ref().map(LifetimeRef::new),
Mutability::Shared, mutability: Mutability::Shared,
)) })),
} ),
ast::SelfParamKind::MutRef => { ast::SelfParamKind::MutRef => body_ctx.alloc_type_ref_desugared(
body_ctx.alloc_type_ref_desugared(TypeRef::Reference( TypeRef::Reference(Box::new(RefType {
self_type, ty: self_type,
self_param.lifetime().as_ref().map(LifetimeRef::new), lifetime: self_param.lifetime().as_ref().map(LifetimeRef::new),
Mutability::Mut, mutability: Mutability::Mut,
)) })),
} ),
} }
} }
}; };
@ -511,7 +512,7 @@ impl<'a> Ctx<'a> {
let ret_type = if func.async_token().is_some() { let ret_type = if func.async_token().is_some() {
let future_impl = desugar_future_path(ret_type); let future_impl = desugar_future_path(ret_type);
let ty_bound = TypeBound::Path(future_impl, TraitBoundModifier::None); let ty_bound = TypeBound::Path(future_impl, TraitBoundModifier::None);
body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(vec![ty_bound])) body_ctx.alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound])))
} else { } else {
ret_type ret_type
}; };

View file

@ -6,6 +6,7 @@ use hir_expand::{
AstId, HirFileId, InFile, AstId, HirFileId, InFile,
}; };
use span::{AstIdMap, AstIdNode}; use span::{AstIdMap, AstIdNode};
use stdx::thin_vec::ThinVec;
use syntax::ast; use syntax::ast;
use triomphe::Arc; use triomphe::Arc;
@ -20,7 +21,7 @@ pub struct LowerCtx<'a> {
file_id: HirFileId, file_id: HirFileId,
span_map: OnceCell<SpanMap>, span_map: OnceCell<SpanMap>,
ast_id_map: OnceCell<Arc<AstIdMap>>, ast_id_map: OnceCell<Arc<AstIdMap>>,
impl_trait_bounds: RefCell<Vec<Vec<TypeBound>>>, impl_trait_bounds: RefCell<Vec<ThinVec<TypeBound>>>,
// Prevent nested impl traits like `impl Foo<impl Bar>`. // Prevent nested impl traits like `impl Foo<impl Bar>`.
outer_impl_trait: RefCell<bool>, outer_impl_trait: RefCell<bool>,
types_map: RefCell<(&'a mut TypesMap, &'a mut TypesSourceMap)>, types_map: RefCell<(&'a mut TypesMap, &'a mut TypesSourceMap)>,
@ -95,11 +96,11 @@ impl<'a> LowerCtx<'a> {
) )
} }
pub fn update_impl_traits_bounds(&self, bounds: Vec<TypeBound>) { pub fn update_impl_traits_bounds(&self, bounds: ThinVec<TypeBound>) {
self.impl_trait_bounds.borrow_mut().push(bounds); self.impl_trait_bounds.borrow_mut().push(bounds);
} }
pub fn take_impl_traits_bounds(&self) -> Vec<Vec<TypeBound>> { pub fn take_impl_traits_bounds(&self) -> Vec<ThinVec<TypeBound>> {
self.impl_trait_bounds.take() self.impl_trait_bounds.take()
} }

View file

@ -9,6 +9,7 @@ use hir_expand::{
name::{AsName, Name}, name::{AsName, Name},
}; };
use intern::{sym, Interned}; use intern::{sym, Interned};
use stdx::thin_vec::EmptyOptimizedThinVec;
use syntax::ast::{self, AstNode, HasGenericArgs, HasTypeBounds}; use syntax::ast::{self, AstNode, HasGenericArgs, HasTypeBounds};
use crate::{ use crate::{
@ -267,8 +268,9 @@ fn lower_generic_args_from_fn_path(
let type_ref = TypeRef::from_ast_opt(ctx, param.ty()); let type_ref = TypeRef::from_ast_opt(ctx, param.ty());
param_types.push(type_ref); param_types.push(type_ref);
} }
let args = let args = Box::new([GenericArg::Type(
Box::new([GenericArg::Type(ctx.alloc_type_ref_desugared(TypeRef::Tuple(param_types)))]); ctx.alloc_type_ref_desugared(TypeRef::Tuple(EmptyOptimizedThinVec::from_iter(param_types))),
)]);
let bindings = if let Some(ret_type) = ret_type { let bindings = if let Some(ret_type) = ret_type {
let type_ref = TypeRef::from_ast_opt(ctx, ret_type.ty()); let type_ref = TypeRef::from_ast_opt(ctx, ret_type.ty());
Box::new([AssociatedTypeBinding { Box::new([AssociatedTypeBinding {
@ -279,7 +281,7 @@ fn lower_generic_args_from_fn_path(
}]) }])
} else { } else {
// -> () // -> ()
let type_ref = ctx.alloc_type_ref_desugared(TypeRef::Tuple(Vec::new())); let type_ref = ctx.alloc_type_ref_desugared(TypeRef::unit());
Box::new([AssociatedTypeBinding { Box::new([AssociatedTypeBinding {
name: Name::new_symbol_root(sym::Output.clone()), name: Name::new_symbol_root(sym::Output.clone()),
args: None, args: None,

View file

@ -187,35 +187,35 @@ pub(crate) fn print_type_ref(
write!(buf, "{mtbl} ")?; write!(buf, "{mtbl} ")?;
print_type_ref(db, *pointee, map, buf, edition)?; print_type_ref(db, *pointee, map, buf, edition)?;
} }
TypeRef::Reference(pointee, lt, mtbl) => { TypeRef::Reference(ref_) => {
let mtbl = match mtbl { let mtbl = match ref_.mutability {
Mutability::Shared => "", Mutability::Shared => "",
Mutability::Mut => "mut ", Mutability::Mut => "mut ",
}; };
write!(buf, "&")?; write!(buf, "&")?;
if let Some(lt) = lt { if let Some(lt) = &ref_.lifetime {
write!(buf, "{} ", lt.name.display(db.upcast(), edition))?; write!(buf, "{} ", lt.name.display(db.upcast(), edition))?;
} }
write!(buf, "{mtbl}")?; write!(buf, "{mtbl}")?;
print_type_ref(db, *pointee, map, buf, edition)?; print_type_ref(db, ref_.ty, map, buf, edition)?;
} }
TypeRef::Array(elem, len) => { TypeRef::Array(array) => {
write!(buf, "[")?; write!(buf, "[")?;
print_type_ref(db, *elem, map, buf, edition)?; print_type_ref(db, array.ty, map, buf, edition)?;
write!(buf, "; {}]", len.display(db.upcast(), edition))?; write!(buf, "; {}]", array.len.display(db.upcast(), edition))?;
} }
TypeRef::Slice(elem) => { TypeRef::Slice(elem) => {
write!(buf, "[")?; write!(buf, "[")?;
print_type_ref(db, *elem, map, buf, edition)?; print_type_ref(db, *elem, map, buf, edition)?;
write!(buf, "]")?; write!(buf, "]")?;
} }
TypeRef::Fn { params: args_and_ret, is_varargs: varargs, is_unsafe, abi } => { TypeRef::Fn(fn_) => {
let ((_, return_type), args) = let ((_, return_type), args) =
args_and_ret.split_last().expect("TypeRef::Fn is missing return type"); fn_.params().split_last().expect("TypeRef::Fn is missing return type");
if *is_unsafe { if fn_.is_unsafe() {
write!(buf, "unsafe ")?; write!(buf, "unsafe ")?;
} }
if let Some(abi) = abi { if let Some(abi) = fn_.abi() {
buf.write_str("extern ")?; buf.write_str("extern ")?;
buf.write_str(abi.as_str())?; buf.write_str(abi.as_str())?;
buf.write_char(' ')?; buf.write_char(' ')?;
@ -227,7 +227,7 @@ pub(crate) fn print_type_ref(
} }
print_type_ref(db, *typeref, map, buf, edition)?; print_type_ref(db, *typeref, map, buf, edition)?;
} }
if *varargs { if fn_.is_varargs() {
if !args.is_empty() { if !args.is_empty() {
write!(buf, ", ")?; write!(buf, ", ")?;
} }

View file

@ -1964,39 +1964,39 @@ impl HirDisplayWithTypesMap for TypeRefId {
write!(f, "{mutability}")?; write!(f, "{mutability}")?;
inner.hir_fmt(f, types_map)?; inner.hir_fmt(f, types_map)?;
} }
TypeRef::Reference(inner, lifetime, mutability) => { TypeRef::Reference(ref_) => {
let mutability = match mutability { let mutability = match ref_.mutability {
hir_def::type_ref::Mutability::Shared => "", hir_def::type_ref::Mutability::Shared => "",
hir_def::type_ref::Mutability::Mut => "mut ", hir_def::type_ref::Mutability::Mut => "mut ",
}; };
write!(f, "&")?; write!(f, "&")?;
if let Some(lifetime) = lifetime { if let Some(lifetime) = &ref_.lifetime {
write!(f, "{} ", lifetime.name.display(f.db.upcast(), f.edition()))?; write!(f, "{} ", lifetime.name.display(f.db.upcast(), f.edition()))?;
} }
write!(f, "{mutability}")?; write!(f, "{mutability}")?;
inner.hir_fmt(f, types_map)?; ref_.ty.hir_fmt(f, types_map)?;
} }
TypeRef::Array(inner, len) => { TypeRef::Array(array) => {
write!(f, "[")?; write!(f, "[")?;
inner.hir_fmt(f, types_map)?; array.ty.hir_fmt(f, types_map)?;
write!(f, "; {}]", len.display(f.db.upcast(), f.edition()))?; write!(f, "; {}]", array.len.display(f.db.upcast(), f.edition()))?;
} }
TypeRef::Slice(inner) => { TypeRef::Slice(inner) => {
write!(f, "[")?; write!(f, "[")?;
inner.hir_fmt(f, types_map)?; inner.hir_fmt(f, types_map)?;
write!(f, "]")?; write!(f, "]")?;
} }
&TypeRef::Fn { params: ref parameters, is_varargs, is_unsafe, ref abi } => { TypeRef::Fn(fn_) => {
if is_unsafe { if fn_.is_unsafe() {
write!(f, "unsafe ")?; write!(f, "unsafe ")?;
} }
if let Some(abi) = abi { if let Some(abi) = fn_.abi() {
f.write_str("extern \"")?; f.write_str("extern \"")?;
f.write_str(abi.as_str())?; f.write_str(abi.as_str())?;
f.write_str("\" ")?; f.write_str("\" ")?;
} }
write!(f, "fn(")?; write!(f, "fn(")?;
if let Some(((_, return_type), function_parameters)) = parameters.split_last() { if let Some(((_, return_type), function_parameters)) = fn_.params().split_last() {
for index in 0..function_parameters.len() { for index in 0..function_parameters.len() {
let (param_name, param_type) = &function_parameters[index]; let (param_name, param_type) = &function_parameters[index];
if let Some(name) = param_name { if let Some(name) = param_name {
@ -2009,8 +2009,8 @@ impl HirDisplayWithTypesMap for TypeRefId {
write!(f, ", ")?; write!(f, ", ")?;
} }
} }
if is_varargs { if fn_.is_varargs() {
write!(f, "{}...", if parameters.len() == 1 { "" } else { ", " })?; write!(f, "{}...", if fn_.params().len() == 1 { "" } else { ", " })?;
} }
write!(f, ")")?; write!(f, ")")?;
match &types_map[*return_type] { match &types_map[*return_type] {

View file

@ -297,37 +297,39 @@ impl<'a> TyLoweringContext<'a> {
let inner_ty = self.lower_ty(inner); let inner_ty = self.lower_ty(inner);
TyKind::Raw(lower_to_chalk_mutability(mutability), inner_ty).intern(Interner) TyKind::Raw(lower_to_chalk_mutability(mutability), inner_ty).intern(Interner)
} }
TypeRef::Array(inner, len) => { TypeRef::Array(array) => {
let inner_ty = self.lower_ty(*inner); let inner_ty = self.lower_ty(array.ty);
let const_len = self.lower_const(len, TyBuilder::usize()); let const_len = self.lower_const(&array.len, TyBuilder::usize());
TyKind::Array(inner_ty, const_len).intern(Interner) TyKind::Array(inner_ty, const_len).intern(Interner)
} }
&TypeRef::Slice(inner) => { &TypeRef::Slice(inner) => {
let inner_ty = self.lower_ty(inner); let inner_ty = self.lower_ty(inner);
TyKind::Slice(inner_ty).intern(Interner) TyKind::Slice(inner_ty).intern(Interner)
} }
TypeRef::Reference(inner, lifetime, mutability) => { TypeRef::Reference(ref_) => {
let inner_ty = self.lower_ty(*inner); let inner_ty = self.lower_ty(ref_.ty);
// FIXME: It should infer the eldided lifetimes instead of stubbing with static // FIXME: It should infer the eldided lifetimes instead of stubbing with static
let lifetime = let lifetime = ref_
lifetime.as_ref().map_or_else(error_lifetime, |lr| self.lower_lifetime(lr)); .lifetime
TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty) .as_ref()
.map_or_else(error_lifetime, |lr| self.lower_lifetime(lr));
TyKind::Ref(lower_to_chalk_mutability(ref_.mutability), lifetime, inner_ty)
.intern(Interner) .intern(Interner)
} }
TypeRef::Placeholder => TyKind::Error.intern(Interner), TypeRef::Placeholder => TyKind::Error.intern(Interner),
&TypeRef::Fn { ref params, is_varargs: variadic, is_unsafe, ref abi } => { TypeRef::Fn(fn_) => {
let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
Substitution::from_iter( Substitution::from_iter(
Interner, Interner,
params.iter().map(|&(_, tr)| ctx.lower_ty(tr)), fn_.params().iter().map(|&(_, tr)| ctx.lower_ty(tr)),
) )
}); });
TyKind::Function(FnPointer { TyKind::Function(FnPointer {
num_binders: 0, // FIXME lower `for<'a> fn()` correctly num_binders: 0, // FIXME lower `for<'a> fn()` correctly
sig: FnSig { sig: FnSig {
abi: abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol), abi: fn_.abi().as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe }, safety: if fn_.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
variadic, variadic: fn_.is_varargs(),
}, },
substitution: FnSubst(substs), substitution: FnSubst(substs),
}) })

View file

@ -196,13 +196,13 @@ impl HirDisplay for SelfParam {
let param = *data.params.first().unwrap(); let param = *data.params.first().unwrap();
match &data.types_map[param] { match &data.types_map[param] {
TypeRef::Path(p) if p.is_self_type() => f.write_str("self"), TypeRef::Path(p) if p.is_self_type() => f.write_str("self"),
TypeRef::Reference(inner, lifetime, mut_) if matches!(&data.types_map[*inner], TypeRef::Path(p) if p.is_self_type()) => TypeRef::Reference(ref_) if matches!(&data.types_map[ref_.ty], TypeRef::Path(p) if p.is_self_type()) =>
{ {
f.write_char('&')?; f.write_char('&')?;
if let Some(lifetime) = lifetime { if let Some(lifetime) = &ref_.lifetime {
write!(f, "{} ", lifetime.name.display(f.db.upcast(), f.edition()))?; write!(f, "{} ", lifetime.name.display(f.db.upcast(), f.edition()))?;
} }
if let hir_def::type_ref::Mutability::Mut = mut_ { if let hir_def::type_ref::Mutability::Mut = ref_.mutability {
f.write_str("mut ")?; f.write_str("mut ")?;
} }
f.write_str("self") f.write_str("self")

View file

@ -2420,8 +2420,8 @@ impl SelfParam {
func_data func_data
.params .params
.first() .first()
.map(|&param| match func_data.types_map[param] { .map(|&param| match &func_data.types_map[param] {
TypeRef::Reference(.., mutability) => match mutability { TypeRef::Reference(ref_) => match ref_.mutability {
hir_def::type_ref::Mutability::Shared => Access::Shared, hir_def::type_ref::Mutability::Shared => Access::Shared,
hir_def::type_ref::Mutability::Mut => Access::Exclusive, hir_def::type_ref::Mutability::Mut => Access::Exclusive,
}, },