Skip to content

Commit 7bfd5f1

Browse files
committed
Rust: crate graph: extract associated types
1 parent 2f87630 commit 7bfd5f1

File tree

1 file changed

+141
-51
lines changed

1 file changed

+141
-51
lines changed

Diff for: rust/extractor/src/crate_graph.rs

+141-51
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use ra_ap_hir_def::{
2525
use ra_ap_hir_def::{HasModule, visibility::VisibilityExplicitness};
2626
use ra_ap_hir_def::{ModuleId, resolver::HasResolver};
2727
use ra_ap_hir_ty::GenericArg;
28+
use ra_ap_hir_ty::ProjectionTyExt;
2829
use ra_ap_hir_ty::TraitRefExt;
2930
use ra_ap_hir_ty::Ty;
3031
use ra_ap_hir_ty::TyExt;
@@ -279,7 +280,7 @@ fn emit_module_items(
279280
module: &ModuleData,
280281
trap: &mut TrapFile,
281282
) -> Vec<trap::Label<generated::Item>> {
282-
let mut items = Vec::new();
283+
let mut items: Vec<trap::Label<generated::Item>> = Vec::new();
283284
let mut uses = HashMap::new();
284285
let item_scope = &module.scope;
285286
for (name, item) in item_scope.entries() {
@@ -303,7 +304,10 @@ fn emit_module_items(
303304
items.push(emit_function(db, trap, None, function, name).into());
304305
}
305306
ModuleDefId::ConstId(konst) => {
306-
items.extend(emit_const(db, name.as_str(), trap, None, konst, vis));
307+
items.extend(
308+
emit_const(db, trap, None, name.as_str(), konst, vis)
309+
.map(Into::<trap::Label<_>>::into),
310+
);
307311
}
308312
ModuleDefId::StaticId(statik) => {
309313
items.extend(emit_static(db, name.as_str(), trap, statik, vis));
@@ -344,8 +348,12 @@ fn emit_module_items(
344348
ModuleDefId::TraitId(trait_id) => {
345349
items.extend(emit_trait(db, name.as_str(), trap, trait_id, vis));
346350
}
347-
ModuleDefId::TraitAliasId(_) | ModuleDefId::TypeAliasId(_) => (), // TODO
348-
ModuleDefId::BuiltinType(_) => (), // TODO?
351+
ModuleDefId::TypeAliasId(type_alias_id_) => items.extend(
352+
emit_type_alias(db, trap, None, name.as_str(), type_alias_id_, vis)
353+
.map(Into::<trap::Label<_>>::into),
354+
),
355+
ModuleDefId::TraitAliasId(_) => (),
356+
ModuleDefId::BuiltinType(_) => (),
349357
// modules are handled separatedly
350358
ModuleDefId::ModuleId(_) => (),
351359
// Enum variants cannot be declarted, only imported
@@ -464,12 +472,12 @@ fn collect_generic_parameters(
464472

465473
fn emit_const(
466474
db: &dyn HirDatabase,
467-
name: &str,
468475
trap: &mut TrapFile,
469476
container: Option<GenericDefId>,
477+
name: &str,
470478
konst: ra_ap_hir_def::ConstId,
471479
visibility: Visibility,
472-
) -> Option<trap::Label<generated::Item>> {
480+
) -> Option<trap::Label<generated::Const>> {
473481
let type_ = db.value_ty(konst.into());
474482
let parameters = collect_generic_parameters(db, konst.into(), container);
475483
assert_eq!(
@@ -486,19 +494,16 @@ fn emit_const(
486494
}));
487495
let konst = db.const_data(konst);
488496
let visibility = emit_visibility(db, trap, visibility);
489-
Some(
490-
trap.emit(generated::Const {
491-
id: trap::TrapId::Star,
492-
name,
493-
attrs: vec![],
494-
body: None,
495-
is_const: true,
496-
is_default: konst.has_body(),
497-
type_repr,
498-
visibility,
499-
})
500-
.into(),
501-
)
497+
Some(trap.emit(generated::Const {
498+
id: trap::TrapId::Star,
499+
name,
500+
attrs: vec![],
501+
body: None,
502+
is_const: true,
503+
is_default: konst.has_body(),
504+
type_repr,
505+
visibility,
506+
}))
502507
}
503508

504509
fn emit_static(
@@ -540,6 +545,39 @@ fn emit_static(
540545
)
541546
}
542547

548+
fn emit_type_alias(
549+
db: &dyn HirDatabase,
550+
trap: &mut TrapFile,
551+
container: Option<GenericDefId>,
552+
name: &str,
553+
alias_id: ra_ap_hir_def::TypeAliasId,
554+
visibility: Visibility,
555+
) -> Option<trap::Label<generated::TypeAlias>> {
556+
let (type_, _) = db.type_for_type_alias_with_diagnostics(alias_id);
557+
let parameters = collect_generic_parameters(db, alias_id.into(), container);
558+
assert_eq!(type_.binders.len(Interner), parameters.len());
559+
let ty_vars = &[parameters];
560+
let type_repr = emit_hir_ty(trap, db, ty_vars, type_.skip_binders());
561+
let name = Some(trap.emit(generated::Name {
562+
id: trap::TrapId::Star,
563+
text: Some(name.to_owned()),
564+
}));
565+
let visibility = emit_visibility(db, trap, visibility);
566+
let alias = db.type_alias_data(alias_id);
567+
let generic_param_list = emit_generic_param_list(trap, db, ty_vars, alias_id.into());
568+
Some(trap.emit(generated::TypeAlias {
569+
id: trap::TrapId::Star,
570+
name,
571+
attrs: vec![],
572+
is_default: container.is_some() && alias.type_ref.is_some(),
573+
type_repr,
574+
visibility,
575+
generic_param_list,
576+
type_bound_list: None,
577+
where_clause: None,
578+
}))
579+
}
580+
543581
fn emit_generic_param_list(
544582
trap: &mut TrapFile,
545583
db: &dyn HirDatabase,
@@ -747,12 +785,29 @@ fn emit_trait(
747785
let assoc_items: Vec<trap::Label<generated::AssocItem>> = trait_items
748786
.items
749787
.iter()
750-
.flat_map(|(name, item)| {
751-
if let AssocItemId::FunctionId(function) = item {
752-
Some(emit_function(db, trap, Some(trait_id.into()), *function, name).into())
753-
} else {
754-
None
788+
.flat_map(|(name, item)| match item {
789+
AssocItemId::FunctionId(function_id) => {
790+
Some(emit_function(db, trap, Some(trait_id.into()), *function_id, name).into())
755791
}
792+
793+
AssocItemId::ConstId(const_id) => emit_const(
794+
db,
795+
trap,
796+
Some(trait_id.into()),
797+
name.as_str(),
798+
*const_id,
799+
visibility,
800+
)
801+
.map(Into::into),
802+
AssocItemId::TypeAliasId(type_alias_id) => emit_type_alias(
803+
db,
804+
trap,
805+
Some(trait_id.into()),
806+
name.as_str(),
807+
*type_alias_id,
808+
visibility,
809+
)
810+
.map(Into::into),
756811
})
757812
.collect();
758813
let assoc_item_list = Some(trap.emit(generated::AssocItemList {
@@ -1258,36 +1313,71 @@ fn emit_hir_ty(
12581313

12591314
chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(ProjectionTy {
12601315
associated_ty_id,
1261-
substitution: _,
1316+
substitution,
12621317
}))
1263-
| chalk_ir::TyKind::AssociatedType(associated_ty_id, _) => {
1264-
let assoc_ty_data = db.associated_ty_data(from_assoc_type_id(*associated_ty_id));
1318+
| chalk_ir::TyKind::AssociatedType(associated_ty_id, substitution) => {
1319+
let pt = ProjectionTy {
1320+
associated_ty_id: *associated_ty_id,
1321+
substitution: substitution.clone(),
1322+
};
12651323

1266-
let _name = db
1267-
.type_alias_data(assoc_ty_data.name)
1268-
.name
1269-
.as_str()
1270-
.to_owned();
1324+
// <Self as Trait<...>>::Name<...>
12711325

1272-
let trait_ref = ra_ap_hir_ty::TraitRef {
1273-
trait_id: assoc_ty_data.trait_id,
1274-
substitution: assoc_ty_data.binders.identity_substitution(Interner),
1275-
};
1276-
let mut trait_path = make_path(db, trait_ref.hir_trait_id());
1277-
trait_path.push(
1278-
db.trait_data(trait_ref.hir_trait_id())
1279-
.name
1280-
.as_str()
1281-
.to_owned(),
1282-
);
1283-
//TODO
1284-
// trap.emit(generated::AssociatedType {
1285-
// id: trap::TrapId::Star,
1286-
// trait_path,
1287-
// name,
1288-
// })
1289-
// .into()
1290-
None
1326+
let qualifier = trap.emit(generated::PathSegment {
1327+
id: trap::TrapId::Star,
1328+
generic_arg_list: None,
1329+
identifier: None,
1330+
parenthesized_arg_list: None,
1331+
ret_type: None,
1332+
return_type_syntax: None,
1333+
});
1334+
let self_ty = pt.self_type_parameter(db);
1335+
let self_ty = emit_hir_ty(trap, db, ty_vars, &self_ty);
1336+
if let Some(self_ty) = self_ty {
1337+
generated::PathSegment::emit_type_repr(qualifier, self_ty, &mut trap.writer)
1338+
}
1339+
let trait_ref = pt.trait_ref(db);
1340+
let trait_ref = trait_path(db, trap, ty_vars, &trait_ref);
1341+
let trait_ref = trait_ref.map(|path| {
1342+
trap.emit(generated::PathTypeRepr {
1343+
id: trap::TrapId::Star,
1344+
path: Some(path),
1345+
})
1346+
});
1347+
if let Some(trait_ref) = trait_ref {
1348+
generated::PathSegment::emit_trait_type_repr(qualifier, trait_ref, &mut trap.writer)
1349+
}
1350+
let data = db.type_alias_data(from_assoc_type_id(*associated_ty_id));
1351+
1352+
let identifier = Some(trap.emit(generated::NameRef {
1353+
id: trap::TrapId::Star,
1354+
text: Some(data.name.as_str().to_owned()),
1355+
}));
1356+
let segment = trap.emit(generated::PathSegment {
1357+
id: trap::TrapId::Star,
1358+
generic_arg_list: None,
1359+
identifier,
1360+
parenthesized_arg_list: None,
1361+
ret_type: None,
1362+
return_type_syntax: None,
1363+
});
1364+
let qualifier = trap.emit(generated::Path {
1365+
id: trap::TrapId::Star,
1366+
qualifier: None,
1367+
segment: Some(qualifier),
1368+
});
1369+
let path = trap.emit(generated::Path {
1370+
id: trap::TrapId::Star,
1371+
qualifier: Some(qualifier),
1372+
segment: Some(segment),
1373+
});
1374+
Some(
1375+
trap.emit(generated::PathTypeRepr {
1376+
id: trap::TrapId::Star,
1377+
path: Some(path),
1378+
})
1379+
.into(),
1380+
)
12911381
}
12921382
chalk_ir::TyKind::BoundVar(var) => {
12931383
let var_ = ty_vars

0 commit comments

Comments
 (0)