1 //! AST -> `ItemTree` lowering code.
3 use std
::{collections::hash_map::Entry, sync::Arc}
;
5 use hir_expand
::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}
;
6 use syntax
::ast
::{self, HasModuleItem}
;
9 generics
::{GenericParams, TypeParamData, TypeParamProvenance}
,
10 type_ref
::{LifetimeRef, TraitBoundModifier, TraitRef}
,
15 fn id
<N
: ItemTreeNode
>(index
: Idx
<N
>) -> FileItemTreeId
<N
> {
16 FileItemTreeId { index, _p: PhantomData }
19 pub(super) struct Ctx
<'a
> {
20 db
: &'a
dyn DefDatabase
,
22 source_ast_id_map
: Arc
<AstIdMap
>,
23 body_ctx
: crate::body
::LowerCtx
<'a
>,
27 pub(super) fn new(db
: &'a
dyn DefDatabase
, file
: HirFileId
) -> Self {
30 tree
: ItemTree
::default(),
31 source_ast_id_map
: db
.ast_id_map(file
),
32 body_ctx
: crate::body
::LowerCtx
::new(db
, file
),
36 pub(super) fn hygiene(&self) -> &Hygiene
{
37 self.body_ctx
.hygiene()
40 pub(super) fn lower_module_items(mut self, item_owner
: &dyn HasModuleItem
) -> ItemTree
{
42 item_owner
.items().flat_map(|item
| self.lower_mod_item(&item
)).collect();
46 pub(super) fn lower_macro_stmts(mut self, stmts
: ast
::MacroStmts
) -> ItemTree
{
47 self.tree
.top_level
= stmts
51 ast
::Stmt
::Item(item
) => Some(item
),
52 // Macro calls can be both items and expressions. The syntax library always treats
53 // them as expressions here, so we undo that.
54 ast
::Stmt
::ExprStmt(es
) => match es
.expr()?
{
55 ast
::Expr
::MacroExpr(expr
) => {
56 cov_mark
::hit
!(macro_call_in_macro_stmts_is_added_to_item_tree
);
57 Some(expr
.macro_call()?
.into())
64 .flat_map(|item
| self.lower_mod_item(&item
))
67 if let Some(ast
::Expr
::MacroExpr(tail_macro
)) = stmts
.expr() {
68 if let Some(call
) = tail_macro
.macro_call() {
69 cov_mark
::hit
!(macro_stmt_with_trailing_macro_expr
);
70 if let Some(mod_item
) = self.lower_mod_item(&call
.into()) {
71 self.tree
.top_level
.push(mod_item
);
79 pub(super) fn lower_block(mut self, block
: &ast
::BlockExpr
) -> ItemTree
{
80 self.tree
.top_level
= block
82 .filter_map(|stmt
| match stmt
{
83 ast
::Stmt
::Item(item
) => self.lower_mod_item(&item
),
84 // Macro calls can be both items and expressions. The syntax library always treats
85 // them as expressions here, so we undo that.
86 ast
::Stmt
::ExprStmt(es
) => match es
.expr()?
{
87 ast
::Expr
::MacroExpr(expr
) => self.lower_mod_item(&expr
.macro_call()?
.into()),
97 fn data(&mut self) -> &mut ItemTreeData
{
101 fn lower_mod_item(&mut self, item
: &ast
::Item
) -> Option
<ModItem
> {
102 let attrs
= RawAttrs
::new(self.db
.upcast(), item
, self.hygiene());
103 let item
: ModItem
= match item
{
104 ast
::Item
::Struct(ast
) => self.lower_struct(ast
)?
.into(),
105 ast
::Item
::Union(ast
) => self.lower_union(ast
)?
.into(),
106 ast
::Item
::Enum(ast
) => self.lower_enum(ast
)?
.into(),
107 ast
::Item
::Fn(ast
) => self.lower_function(ast
)?
.into(),
108 ast
::Item
::TypeAlias(ast
) => self.lower_type_alias(ast
)?
.into(),
109 ast
::Item
::Static(ast
) => self.lower_static(ast
)?
.into(),
110 ast
::Item
::Const(ast
) => self.lower_const(ast
).into(),
111 ast
::Item
::Module(ast
) => self.lower_module(ast
)?
.into(),
112 ast
::Item
::Trait(ast
) => self.lower_trait(ast
)?
.into(),
113 ast
::Item
::Impl(ast
) => self.lower_impl(ast
)?
.into(),
114 ast
::Item
::Use(ast
) => self.lower_use(ast
)?
.into(),
115 ast
::Item
::ExternCrate(ast
) => self.lower_extern_crate(ast
)?
.into(),
116 ast
::Item
::MacroCall(ast
) => self.lower_macro_call(ast
)?
.into(),
117 ast
::Item
::MacroRules(ast
) => self.lower_macro_rules(ast
)?
.into(),
118 ast
::Item
::MacroDef(ast
) => self.lower_macro_def(ast
)?
.into(),
119 ast
::Item
::ExternBlock(ast
) => self.lower_extern_block(ast
).into(),
122 self.add_attrs(item
.into(), attrs
);
127 fn add_attrs(&mut self, item
: AttrOwner
, attrs
: RawAttrs
) {
128 match self.tree
.attrs
.entry(item
) {
129 Entry
::Occupied(mut entry
) => {
130 *entry
.get_mut() = entry
.get().merge(attrs
);
132 Entry
::Vacant(entry
) => {
138 fn lower_assoc_item(&mut self, item
: &ast
::AssocItem
) -> Option
<AssocItem
> {
140 ast
::AssocItem
::Fn(ast
) => self.lower_function(ast
).map(Into
::into
),
141 ast
::AssocItem
::TypeAlias(ast
) => self.lower_type_alias(ast
).map(Into
::into
),
142 ast
::AssocItem
::Const(ast
) => Some(self.lower_const(ast
).into()),
143 ast
::AssocItem
::MacroCall(ast
) => self.lower_macro_call(ast
).map(Into
::into
),
147 fn lower_struct(&mut self, strukt
: &ast
::Struct
) -> Option
<FileItemTreeId
<Struct
>> {
148 let visibility
= self.lower_visibility(strukt
);
149 let name
= strukt
.name()?
.as_name();
150 let generic_params
= self.lower_generic_params(GenericsOwner
::Struct
, strukt
);
151 let fields
= self.lower_fields(&strukt
.kind());
152 let ast_id
= self.source_ast_id_map
.ast_id(strukt
);
153 let res
= Struct { name, visibility, generic_params, fields, ast_id }
;
154 Some(id(self.data().structs
.alloc(res
)))
157 fn lower_fields(&mut self, strukt_kind
: &ast
::StructKind
) -> Fields
{
159 ast
::StructKind
::Record(it
) => {
160 let range
= self.lower_record_fields(it
);
161 Fields
::Record(range
)
163 ast
::StructKind
::Tuple(it
) => {
164 let range
= self.lower_tuple_fields(it
);
167 ast
::StructKind
::Unit
=> Fields
::Unit
,
171 fn lower_record_fields(&mut self, fields
: &ast
::RecordFieldList
) -> IdxRange
<Field
> {
172 let start
= self.next_field_idx();
173 for field
in fields
.fields() {
174 if let Some(data
) = self.lower_record_field(&field
) {
175 let idx
= self.data().fields
.alloc(data
);
176 self.add_attrs(idx
.into(), RawAttrs
::new(self.db
.upcast(), &field
, self.hygiene()));
179 let end
= self.next_field_idx();
180 IdxRange
::new(start
..end
)
183 fn lower_record_field(&mut self, field
: &ast
::RecordField
) -> Option
<Field
> {
184 let name
= field
.name()?
.as_name();
185 let visibility
= self.lower_visibility(field
);
186 let type_ref
= self.lower_type_ref_opt(field
.ty());
187 let ast_id
= FieldAstId
::Record(self.source_ast_id_map
.ast_id(field
));
188 let res
= Field { name, type_ref, visibility, ast_id }
;
192 fn lower_tuple_fields(&mut self, fields
: &ast
::TupleFieldList
) -> IdxRange
<Field
> {
193 let start
= self.next_field_idx();
194 for (i
, field
) in fields
.fields().enumerate() {
195 let data
= self.lower_tuple_field(i
, &field
);
196 let idx
= self.data().fields
.alloc(data
);
197 self.add_attrs(idx
.into(), RawAttrs
::new(self.db
.upcast(), &field
, self.hygiene()));
199 let end
= self.next_field_idx();
200 IdxRange
::new(start
..end
)
203 fn lower_tuple_field(&mut self, idx
: usize, field
: &ast
::TupleField
) -> Field
{
204 let name
= Name
::new_tuple_field(idx
);
205 let visibility
= self.lower_visibility(field
);
206 let type_ref
= self.lower_type_ref_opt(field
.ty());
207 let ast_id
= FieldAstId
::Tuple(self.source_ast_id_map
.ast_id(field
));
208 Field { name, type_ref, visibility, ast_id }
211 fn lower_union(&mut self, union: &ast
::Union
) -> Option
<FileItemTreeId
<Union
>> {
212 let visibility
= self.lower_visibility(union);
213 let name
= union.name()?
.as_name();
214 let generic_params
= self.lower_generic_params(GenericsOwner
::Union
, union);
215 let fields
= match union.record_field_list() {
216 Some(record_field_list
) => self.lower_fields(&StructKind
::Record(record_field_list
)),
217 None
=> Fields
::Record(IdxRange
::new(self.next_field_idx()..self.next_field_idx())),
219 let ast_id
= self.source_ast_id_map
.ast_id(union);
220 let res
= Union { name, visibility, generic_params, fields, ast_id }
;
221 Some(id(self.data().unions
.alloc(res
)))
224 fn lower_enum(&mut self, enum_
: &ast
::Enum
) -> Option
<FileItemTreeId
<Enum
>> {
225 let visibility
= self.lower_visibility(enum_
);
226 let name
= enum_
.name()?
.as_name();
227 let generic_params
= self.lower_generic_params(GenericsOwner
::Enum
, enum_
);
228 let variants
= match &enum_
.variant_list() {
229 Some(variant_list
) => self.lower_variants(variant_list
),
230 None
=> IdxRange
::new(self.next_variant_idx()..self.next_variant_idx()),
232 let ast_id
= self.source_ast_id_map
.ast_id(enum_
);
233 let res
= Enum { name, visibility, generic_params, variants, ast_id }
;
234 Some(id(self.data().enums
.alloc(res
)))
237 fn lower_variants(&mut self, variants
: &ast
::VariantList
) -> IdxRange
<Variant
> {
238 let start
= self.next_variant_idx();
239 for variant
in variants
.variants() {
240 if let Some(data
) = self.lower_variant(&variant
) {
241 let idx
= self.data().variants
.alloc(data
);
244 RawAttrs
::new(self.db
.upcast(), &variant
, self.hygiene()),
248 let end
= self.next_variant_idx();
249 IdxRange
::new(start
..end
)
252 fn lower_variant(&mut self, variant
: &ast
::Variant
) -> Option
<Variant
> {
253 let name
= variant
.name()?
.as_name();
254 let fields
= self.lower_fields(&variant
.kind());
255 let ast_id
= self.source_ast_id_map
.ast_id(variant
);
256 let res
= Variant { name, fields, ast_id }
;
260 fn lower_function(&mut self, func
: &ast
::Fn
) -> Option
<FileItemTreeId
<Function
>> {
261 let visibility
= self.lower_visibility(func
);
262 let name
= func
.name()?
.as_name();
264 let mut has_self_param
= false;
265 let start_param
= self.next_param_idx();
266 if let Some(param_list
) = func
.param_list() {
267 if let Some(self_param
) = param_list
.self_param() {
268 let self_type
= match self_param
.ty() {
269 Some(type_ref
) => TypeRef
::from_ast(&self.body_ctx
, type_ref
),
271 let self_type
= TypeRef
::Path(name
![Self].into());
272 match self_param
.kind() {
273 ast
::SelfParamKind
::Owned
=> self_type
,
274 ast
::SelfParamKind
::Ref
=> TypeRef
::Reference(
276 self_param
.lifetime().as_ref().map(LifetimeRef
::new
),
279 ast
::SelfParamKind
::MutRef
=> TypeRef
::Reference(
281 self_param
.lifetime().as_ref().map(LifetimeRef
::new
),
287 let ty
= Interned
::new(self_type
);
288 let idx
= self.data().params
.alloc(Param
::Normal(None
, ty
));
291 RawAttrs
::new(self.db
.upcast(), &self_param
, self.hygiene()),
293 has_self_param
= true;
295 for param
in param_list
.params() {
296 let idx
= match param
.dotdotdot_token() {
297 Some(_
) => self.data().params
.alloc(Param
::Varargs
),
299 let type_ref
= TypeRef
::from_ast_opt(&self.body_ctx
, param
.ty());
300 let ty
= Interned
::new(type_ref
);
301 let mut pat
= param
.pat();
302 // FIXME: This really shouldn't be here, in fact FunctionData/ItemTree's function shouldn't know about
303 // pattern names at all
304 let name
= 'name
: loop {
306 Some(ast
::Pat
::RefPat(ref_pat
)) => pat
= ref_pat
.pat(),
307 Some(ast
::Pat
::IdentPat(ident
)) => {
308 break 'name ident
.name().map(|it
| it
.as_name())
310 _
=> break 'name None
,
313 self.data().params
.alloc(Param
::Normal(name
, ty
))
316 self.add_attrs(idx
.into(), RawAttrs
::new(self.db
.upcast(), ¶m
, self.hygiene()));
319 let end_param
= self.next_param_idx();
320 let params
= IdxRange
::new(start_param
..end_param
);
322 let ret_type
= match func
.ret_type() {
323 Some(rt
) => match rt
.ty() {
324 Some(type_ref
) => TypeRef
::from_ast(&self.body_ctx
, type_ref
),
325 None
if rt
.thin_arrow_token().is_some() => TypeRef
::Error
,
326 None
=> TypeRef
::unit(),
328 None
=> TypeRef
::unit(),
331 let (ret_type
, async_ret_type
) = if func
.async_token().is_some() {
332 let async_ret_type
= ret_type
.clone();
333 let future_impl
= desugar_future_path(ret_type
);
334 let ty_bound
= Interned
::new(TypeBound
::Path(future_impl
, TraitBoundModifier
::None
));
335 (TypeRef
::ImplTrait(vec
![ty_bound
]), Some(async_ret_type
))
340 let abi
= func
.abi().map(lower_abi
);
342 let ast_id
= self.source_ast_id_map
.ast_id(func
);
344 let mut flags
= FnFlags
::default();
345 if func
.body().is_some() {
346 flags
|= FnFlags
::HAS_BODY
;
349 flags
|= FnFlags
::HAS_SELF_PARAM
;
351 if func
.default_token().is_some() {
352 flags
|= FnFlags
::HAS_DEFAULT_KW
;
354 if func
.const_token().is_some() {
355 flags
|= FnFlags
::HAS_CONST_KW
;
357 if func
.async_token().is_some() {
358 flags
|= FnFlags
::HAS_ASYNC_KW
;
360 if func
.unsafe_token().is_some() {
361 flags
|= FnFlags
::HAS_UNSAFE_KW
;
364 let mut res
= Function
{
367 explicit_generic_params
: Interned
::new(GenericParams
::default()),
370 ret_type
: Interned
::new(ret_type
),
371 async_ret_type
: async_ret_type
.map(Interned
::new
),
375 res
.explicit_generic_params
=
376 self.lower_generic_params(GenericsOwner
::Function(&res
), func
);
378 Some(id(self.data().functions
.alloc(res
)))
383 type_alias
: &ast
::TypeAlias
,
384 ) -> Option
<FileItemTreeId
<TypeAlias
>> {
385 let name
= type_alias
.name()?
.as_name();
386 let type_ref
= type_alias
.ty().map(|it
| self.lower_type_ref(&it
));
387 let visibility
= self.lower_visibility(type_alias
);
388 let bounds
= self.lower_type_bounds(type_alias
);
389 let generic_params
= self.lower_generic_params(GenericsOwner
::TypeAlias
, type_alias
);
390 let ast_id
= self.source_ast_id_map
.ast_id(type_alias
);
391 let res
= TypeAlias
{
394 bounds
: bounds
.into_boxed_slice(),
399 Some(id(self.data().type_aliases
.alloc(res
)))
402 fn lower_static(&mut self, static_
: &ast
::Static
) -> Option
<FileItemTreeId
<Static
>> {
403 let name
= static_
.name()?
.as_name();
404 let type_ref
= self.lower_type_ref_opt(static_
.ty());
405 let visibility
= self.lower_visibility(static_
);
406 let mutable
= static_
.mut_token().is_some();
407 let ast_id
= self.source_ast_id_map
.ast_id(static_
);
408 let res
= Static { name, visibility, mutable, type_ref, ast_id }
;
409 Some(id(self.data().statics
.alloc(res
)))
412 fn lower_const(&mut self, konst
: &ast
::Const
) -> FileItemTreeId
<Const
> {
413 let name
= konst
.name().map(|it
| it
.as_name());
414 let type_ref
= self.lower_type_ref_opt(konst
.ty());
415 let visibility
= self.lower_visibility(konst
);
416 let ast_id
= self.source_ast_id_map
.ast_id(konst
);
417 let res
= Const { name, visibility, type_ref, ast_id }
;
418 id(self.data().consts
.alloc(res
))
421 fn lower_module(&mut self, module
: &ast
::Module
) -> Option
<FileItemTreeId
<Mod
>> {
422 let name
= module
.name()?
.as_name();
423 let visibility
= self.lower_visibility(module
);
424 let kind
= if module
.semicolon_token().is_some() {
430 .map(|list
| list
.items().flat_map(|item
| self.lower_mod_item(&item
)).collect())
432 cov_mark
::hit
!(name_res_works_for_broken_modules
);
433 Box
::new([]) as Box
<[_
]>
437 let ast_id
= self.source_ast_id_map
.ast_id(module
);
438 let res
= Mod { name, visibility, kind, ast_id }
;
439 Some(id(self.data().mods
.alloc(res
)))
442 fn lower_trait(&mut self, trait_def
: &ast
::Trait
) -> Option
<FileItemTreeId
<Trait
>> {
443 let name
= trait_def
.name()?
.as_name();
444 let visibility
= self.lower_visibility(trait_def
);
445 let generic_params
= self.lower_generic_params(GenericsOwner
::Trait(trait_def
), trait_def
);
446 let is_auto
= trait_def
.auto_token().is_some();
447 let is_unsafe
= trait_def
.unsafe_token().is_some();
448 let items
= trait_def
.assoc_item_list().map(|list
| {
451 let attrs
= RawAttrs
::new(self.db
.upcast(), &item
, self.hygiene());
452 self.lower_assoc_item(&item
).map(|item
| {
453 self.add_attrs(ModItem
::from(item
).into(), attrs
);
459 let ast_id
= self.source_ast_id_map
.ast_id(trait_def
);
460 let res
= Trait { name, visibility, generic_params, is_auto, is_unsafe, items, ast_id }
;
461 Some(id(self.data().traits
.alloc(res
)))
464 fn lower_impl(&mut self, impl_def
: &ast
::Impl
) -> Option
<FileItemTreeId
<Impl
>> {
465 let generic_params
= self.lower_generic_params(GenericsOwner
::Impl
, impl_def
);
466 // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
467 // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
469 let target_trait
= impl_def
.trait_().and_then(|tr
| self.lower_trait_ref(&tr
));
470 let self_ty
= self.lower_type_ref(&impl_def
.self_ty()?
);
471 let is_negative
= impl_def
.excl_token().is_some();
473 // We cannot use `assoc_items()` here as that does not include macro calls.
477 .flat_map(|it
| it
.assoc_items())
479 let assoc
= self.lower_assoc_item(&item
)?
;
480 let attrs
= RawAttrs
::new(self.db
.upcast(), &item
, self.hygiene());
481 self.add_attrs(ModItem
::from(assoc
).into(), attrs
);
485 let ast_id
= self.source_ast_id_map
.ast_id(impl_def
);
486 let res
= Impl { generic_params, target_trait, self_ty, is_negative, items, ast_id }
;
487 Some(id(self.data().impls
.alloc(res
)))
490 fn lower_use(&mut self, use_item
: &ast
::Use
) -> Option
<FileItemTreeId
<Import
>> {
491 let visibility
= self.lower_visibility(use_item
);
492 let ast_id
= self.source_ast_id_map
.ast_id(use_item
);
493 let (use_tree
, _
) = lower_use_tree(self.db
, self.hygiene(), use_item
.use_tree()?
)?
;
495 let res
= Import { visibility, ast_id, use_tree }
;
496 Some(id(self.data().imports
.alloc(res
)))
499 fn lower_extern_crate(
501 extern_crate
: &ast
::ExternCrate
,
502 ) -> Option
<FileItemTreeId
<ExternCrate
>> {
503 let name
= extern_crate
.name_ref()?
.as_name();
504 let alias
= extern_crate
.rename().map(|a
| {
505 a
.name().map(|it
| it
.as_name()).map_or(ImportAlias
::Underscore
, ImportAlias
::Alias
)
507 let visibility
= self.lower_visibility(extern_crate
);
508 let ast_id
= self.source_ast_id_map
.ast_id(extern_crate
);
510 let res
= ExternCrate { name, alias, visibility, ast_id }
;
511 Some(id(self.data().extern_crates
.alloc(res
)))
514 fn lower_macro_call(&mut self, m
: &ast
::MacroCall
) -> Option
<FileItemTreeId
<MacroCall
>> {
515 let path
= Interned
::new(ModPath
::from_src(self.db
.upcast(), m
.path()?
, self.hygiene())?
);
516 let ast_id
= self.source_ast_id_map
.ast_id(m
);
517 let expand_to
= hir_expand
::ExpandTo
::from_call_site(m
);
518 let res
= MacroCall { path, ast_id, expand_to }
;
519 Some(id(self.data().macro_calls
.alloc(res
)))
522 fn lower_macro_rules(&mut self, m
: &ast
::MacroRules
) -> Option
<FileItemTreeId
<MacroRules
>> {
523 let name
= m
.name().map(|it
| it
.as_name())?
;
524 let ast_id
= self.source_ast_id_map
.ast_id(m
);
526 let res
= MacroRules { name, ast_id }
;
527 Some(id(self.data().macro_rules
.alloc(res
)))
530 fn lower_macro_def(&mut self, m
: &ast
::MacroDef
) -> Option
<FileItemTreeId
<MacroDef
>> {
531 let name
= m
.name().map(|it
| it
.as_name())?
;
533 let ast_id
= self.source_ast_id_map
.ast_id(m
);
534 let visibility
= self.lower_visibility(m
);
536 let res
= MacroDef { name, ast_id, visibility }
;
537 Some(id(self.data().macro_defs
.alloc(res
)))
540 fn lower_extern_block(&mut self, block
: &ast
::ExternBlock
) -> FileItemTreeId
<ExternBlock
> {
541 let ast_id
= self.source_ast_id_map
.ast_id(block
);
542 let abi
= block
.abi().map(lower_abi
);
543 let children
: Box
<[_
]> = block
.extern_item_list().map_or(Box
::new([]), |list
| {
546 // Note: All items in an `extern` block need to be lowered as if they're outside of one
547 // (in other words, the knowledge that they're in an extern block must not be used).
548 // This is because an extern block can contain macros whose ItemTree's top-level items
549 // should be considered to be in an extern block too.
550 let attrs
= RawAttrs
::new(self.db
.upcast(), &item
, self.hygiene());
551 let id
: ModItem
= match item
{
552 ast
::ExternItem
::Fn(ast
) => self.lower_function(&ast
)?
.into(),
553 ast
::ExternItem
::Static(ast
) => self.lower_static(&ast
)?
.into(),
554 ast
::ExternItem
::TypeAlias(ty
) => self.lower_type_alias(&ty
)?
.into(),
555 ast
::ExternItem
::MacroCall(call
) => self.lower_macro_call(&call
)?
.into(),
557 self.add_attrs(id
.into(), attrs
);
563 let res
= ExternBlock { abi, ast_id, children }
;
564 id(self.data().extern_blocks
.alloc(res
))
567 fn lower_generic_params(
569 owner
: GenericsOwner
<'_
>,
570 node
: &dyn ast
::HasGenericParams
,
571 ) -> Interned
<GenericParams
> {
572 let mut generics
= GenericParams
::default();
574 GenericsOwner
::Function(_
)
575 | GenericsOwner
::Struct
576 | GenericsOwner
::Enum
577 | GenericsOwner
::Union
578 | GenericsOwner
::TypeAlias
=> {
579 generics
.fill(&self.body_ctx
, node
);
581 GenericsOwner
::Trait(trait_def
) => {
582 // traits get the Self type as an implicit first type parameter
583 generics
.type_or_consts
.alloc(
585 name
: Some(name
![Self]),
587 provenance
: TypeParamProvenance
::TraitSelf
,
591 // add super traits as bounds on Self
592 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
593 let self_param
= TypeRef
::Path(name
![Self].into());
594 generics
.fill_bounds(&self.body_ctx
, trait_def
, Either
::Left(self_param
));
595 generics
.fill(&self.body_ctx
, node
);
597 GenericsOwner
::Impl
=> {
598 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
599 // type-parameter, but rather is a type-alias for impl's target
600 // type, so this is handled by the resolver.
601 generics
.fill(&self.body_ctx
, node
);
605 generics
.shrink_to_fit();
606 Interned
::new(generics
)
609 fn lower_type_bounds(&mut self, node
: &dyn ast
::HasTypeBounds
) -> Vec
<Interned
<TypeBound
>> {
610 match node
.type_bound_list() {
611 Some(bound_list
) => bound_list
613 .map(|it
| Interned
::new(TypeBound
::from_ast(&self.body_ctx
, it
)))
619 fn lower_visibility(&mut self, item
: &dyn ast
::HasVisibility
) -> RawVisibilityId
{
620 let vis
= RawVisibility
::from_ast_with_hygiene(self.db
, item
.visibility(), self.hygiene());
621 self.data().vis
.alloc(vis
)
624 fn lower_trait_ref(&mut self, trait_ref
: &ast
::Type
) -> Option
<Interned
<TraitRef
>> {
625 let trait_ref
= TraitRef
::from_ast(&self.body_ctx
, trait_ref
.clone())?
;
626 Some(Interned
::new(trait_ref
))
629 fn lower_type_ref(&mut self, type_ref
: &ast
::Type
) -> Interned
<TypeRef
> {
630 let tyref
= TypeRef
::from_ast(&self.body_ctx
, type_ref
.clone());
634 fn lower_type_ref_opt(&mut self, type_ref
: Option
<ast
::Type
>) -> Interned
<TypeRef
> {
635 match type_ref
.map(|ty
| self.lower_type_ref(&ty
)) {
637 None
=> Interned
::new(TypeRef
::Error
),
641 fn next_field_idx(&self) -> Idx
<Field
> {
642 Idx
::from_raw(RawIdx
::from(
643 self.tree
.data
.as_ref().map_or(0, |data
| data
.fields
.len() as u32),
646 fn next_variant_idx(&self) -> Idx
<Variant
> {
647 Idx
::from_raw(RawIdx
::from(
648 self.tree
.data
.as_ref().map_or(0, |data
| data
.variants
.len() as u32),
651 fn next_param_idx(&self) -> Idx
<Param
> {
652 Idx
::from_raw(RawIdx
::from(
653 self.tree
.data
.as_ref().map_or(0, |data
| data
.params
.len() as u32),
658 fn desugar_future_path(orig
: TypeRef
) -> Path
{
659 let path
= path
![core
::future
::Future
];
660 let mut generic_args
: Vec
<_
> =
661 std
::iter
::repeat(None
).take(path
.segments().len() - 1).collect();
662 let binding
= AssociatedTypeBinding
{
665 type_ref
: Some(orig
),
666 bounds
: Box
::default(),
668 generic_args
.push(Some(Interned
::new(GenericArgs
{
669 bindings
: Box
::new([binding
]),
670 ..GenericArgs
::empty()
673 Path
::from_known_path(path
, generic_args
)
676 enum GenericsOwner
<'a
> {
677 /// We need access to the partially-lowered `Function` for lowering `impl Trait` in argument
679 Function(&'a Function
),
683 /// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter.
684 Trait(&'a ast
::Trait
),
689 fn lower_abi(abi
: ast
::Abi
) -> Interned
<str> {
690 // FIXME: Abi::abi() -> Option<SyntaxToken>?
691 match abi
.syntax().last_token() {
692 Some(tok
) if tok
.kind() == SyntaxKind
::STRING
=> {
693 // FIXME: Better way to unescape?
694 Interned
::new_str(tok
.text().trim_matches('
"'))
697 // `extern` default to be `extern "C
"`.
698 Interned::new_str("C
")
703 struct UseTreeLowering<'a> {
704 db: &'a dyn DefDatabase,
705 hygiene: &'a Hygiene,
706 mapping: Arena<ast::UseTree>,
709 impl UseTreeLowering<'_> {
710 fn lower_use_tree(&mut self, tree: ast::UseTree) -> Option<UseTree> {
711 if let Some(use_tree_list) = tree.use_tree_list() {
712 let prefix = match tree.path() {
713 // E.g. use something::{{{inner}}};
715 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
716 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
718 match ModPath::from_src(self.db.upcast(), path, self.hygiene) {
719 Some(it) => Some(it),
720 None => return None, // FIXME: report errors somewhere
726 use_tree_list.use_trees().filter_map(|tree| self.lower_use_tree(tree)).collect();
730 UseTreeKind::Prefixed { prefix: prefix.map(Interned::new), list },
735 let is_glob = tree.star_token().is_some();
736 let path = match tree.path() {
737 Some(path) => Some(ModPath::from_src(self.db.upcast(), path, self.hygiene)?),
740 let alias = tree.rename().map(|a| {
741 a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
743 if alias.is_some() && is_glob {
747 match (path, alias, is_glob) {
748 (path, None, true) => {
750 cov_mark::hit!(glob_enum_group);
752 Some(self.use_tree(UseTreeKind::Glob { path: path.map(Interned::new) }, tree))
754 // Globs can't be renamed
755 (_, Some(_), true) | (None, None, false) => None,
756 // `bla::{ as Name}` is invalid
757 (None, Some(_), false) => None,
758 (Some(path), alias, false) => Some(
759 self.use_tree(UseTreeKind::Single { path: Interned::new(path), alias }, tree),
765 fn use_tree(&mut self, kind: UseTreeKind, ast: ast::UseTree) -> UseTree {
766 let index = self.mapping.alloc(ast);
767 UseTree { index, kind }
771 pub(super) fn lower_use_tree(
772 db: &dyn DefDatabase,
775 ) -> Option<(UseTree, Arena<ast::UseTree>)> {
776 let mut lowering = UseTreeLowering { db, hygiene, mapping: Arena::new() };
777 let tree = lowering.lower_use_tree(tree)?;
778 Some((tree, lowering.mapping))