mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
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:
parent
061e5d7f71
commit
bf7edd3783
10 changed files with 178 additions and 149 deletions
|
@ -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(
|
||||||
|
|
|
@ -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(<));
|
let lifetime = inner.lifetime().map(|lt| LifetimeRef::new(<));
|
||||||
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([])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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, ", ")?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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] {
|
||||||
|
|
|
@ -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),
|
||||||
})
|
})
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -2420,8 +2420,8 @@ impl SelfParam {
|
||||||
func_data
|
func_data
|
||||||
.params
|
.params
|
||||||
.first()
|
.first()
|
||||||
.map(|¶m| match func_data.types_map[param] {
|
.map(|¶m| 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,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue