Skip to content

Commit 3b689a9

Browse files
committed
Rust: crate graph: extract associated types
1 parent 362a09a commit 3b689a9

File tree

1 file changed

+142
-53
lines changed

1 file changed

+142
-53
lines changed

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

+142-53
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ use ra_ap_hir_def::{
2323
use ra_ap_hir_def::{GenericDefId, Lookup};
2424
use ra_ap_hir_def::{HasModule, visibility::VisibilityExplicitness};
2525
use ra_ap_hir_def::{ModuleId, resolver::HasResolver};
26-
use ra_ap_hir_ty::TyExt;
2726
use ra_ap_hir_ty::WhereClause;
2827
use ra_ap_hir_ty::{Binders, FnPointer};
29-
use ra_ap_hir_ty::{GenericArg, Ty};
28+
use ra_ap_hir_ty::{GenericArg, Ty, from_assoc_type_id};
3029
use ra_ap_hir_ty::{Interner, ProjectionTy};
30+
use ra_ap_hir_ty::{ProjectionTyExt, TyExt};
3131
use ra_ap_hir_ty::{TraitRefExt, TyLoweringContext};
3232
use ra_ap_ide_db::RootDatabase;
3333
use ra_ap_vfs::{Vfs, VfsPath};
@@ -274,7 +274,7 @@ fn emit_module_items(
274274
module: &ModuleData,
275275
trap: &mut TrapFile,
276276
) -> Vec<trap::Label<generated::Item>> {
277-
let mut items = Vec::new();
277+
let mut items: Vec<trap::Label<generated::Item>> = Vec::new();
278278
let mut uses = HashMap::new();
279279
let item_scope = &module.scope;
280280
for (name, item) in item_scope.entries() {
@@ -298,7 +298,10 @@ fn emit_module_items(
298298
items.push(emit_function(db, trap, None, function, name).into());
299299
}
300300
ModuleDefId::ConstId(konst) => {
301-
items.extend(emit_const(db, name.as_str(), trap, None, konst, vis));
301+
items.extend(
302+
emit_const(db, trap, None, name.as_str(), konst, vis)
303+
.map(Into::<trap::Label<_>>::into),
304+
);
302305
}
303306
ModuleDefId::StaticId(statik) => {
304307
items.extend(emit_static(db, name.as_str(), trap, statik, vis));
@@ -339,8 +342,12 @@ fn emit_module_items(
339342
ModuleDefId::TraitId(trait_id) => {
340343
items.extend(emit_trait(db, name.as_str(), trap, trait_id, vis));
341344
}
342-
ModuleDefId::TraitAliasId(_) | ModuleDefId::TypeAliasId(_) => (), // TODO
343-
ModuleDefId::BuiltinType(_) => (), // TODO?
345+
ModuleDefId::TypeAliasId(type_alias_id_) => items.extend(
346+
emit_type_alias(db, trap, None, name.as_str(), type_alias_id_, vis)
347+
.map(Into::<trap::Label<_>>::into),
348+
),
349+
ModuleDefId::TraitAliasId(_) => (),
350+
ModuleDefId::BuiltinType(_) => (),
344351
// modules are handled separatedly
345352
ModuleDefId::ModuleId(_) => (),
346353
// Enum variants cannot be declarted, only imported
@@ -459,12 +466,12 @@ fn collect_generic_parameters(
459466

460467
fn emit_const(
461468
db: &dyn HirDatabase,
462-
name: &str,
463469
trap: &mut TrapFile,
464470
container: Option<GenericDefId>,
471+
name: &str,
465472
konst: ra_ap_hir_def::ConstId,
466473
visibility: Visibility,
467-
) -> Option<trap::Label<generated::Item>> {
474+
) -> Option<trap::Label<generated::Const>> {
468475
let type_ = db.value_ty(konst.into());
469476
let parameters = collect_generic_parameters(db, konst.into(), container);
470477
assert_eq!(
@@ -481,19 +488,16 @@ fn emit_const(
481488
}));
482489
let konst = db.const_data(konst);
483490
let visibility = emit_visibility(db, trap, visibility);
484-
Some(
485-
trap.emit(generated::Const {
486-
id: trap::TrapId::Star,
487-
name,
488-
attrs: vec![],
489-
body: None,
490-
is_const: true,
491-
is_default: konst.has_body,
492-
type_repr,
493-
visibility,
494-
})
495-
.into(),
496-
)
491+
Some(trap.emit(generated::Const {
492+
id: trap::TrapId::Star,
493+
name,
494+
attrs: vec![],
495+
body: None,
496+
is_const: true,
497+
is_default: konst.has_body,
498+
type_repr,
499+
visibility,
500+
}))
497501
}
498502

499503
fn emit_static(
@@ -535,6 +539,39 @@ fn emit_static(
535539
)
536540
}
537541

542+
fn emit_type_alias(
543+
db: &dyn HirDatabase,
544+
trap: &mut TrapFile,
545+
container: Option<GenericDefId>,
546+
name: &str,
547+
alias_id: ra_ap_hir_def::TypeAliasId,
548+
visibility: Visibility,
549+
) -> Option<trap::Label<generated::TypeAlias>> {
550+
let (type_, _) = db.type_for_type_alias_with_diagnostics(alias_id);
551+
let parameters = collect_generic_parameters(db, alias_id.into(), container);
552+
assert_eq!(type_.binders.len(Interner), parameters.len());
553+
let ty_vars = &[parameters];
554+
let type_repr = emit_hir_ty(trap, db, ty_vars, type_.skip_binders());
555+
let name = Some(trap.emit(generated::Name {
556+
id: trap::TrapId::Star,
557+
text: Some(name.to_owned()),
558+
}));
559+
let visibility = emit_visibility(db, trap, visibility);
560+
let alias = db.type_alias_data(alias_id);
561+
let generic_param_list = emit_generic_param_list(trap, db, ty_vars, alias_id.into());
562+
Some(trap.emit(generated::TypeAlias {
563+
id: trap::TrapId::Star,
564+
name,
565+
attrs: vec![],
566+
is_default: container.is_some() && alias.type_ref.is_some(),
567+
type_repr,
568+
visibility,
569+
generic_param_list,
570+
type_bound_list: None,
571+
where_clause: None,
572+
}))
573+
}
574+
538575
fn emit_generic_param_list(
539576
trap: &mut TrapFile,
540577
db: &dyn HirDatabase,
@@ -742,12 +779,29 @@ fn emit_trait(
742779
let assoc_items: Vec<trap::Label<generated::AssocItem>> = trait_items
743780
.items
744781
.iter()
745-
.flat_map(|(name, item)| {
746-
if let AssocItemId::FunctionId(function) = item {
747-
Some(emit_function(db, trap, Some(trait_id.into()), *function, name).into())
748-
} else {
749-
None
782+
.flat_map(|(name, item)| match item {
783+
AssocItemId::FunctionId(function_id) => {
784+
Some(emit_function(db, trap, Some(trait_id.into()), *function_id, name).into())
750785
}
786+
787+
AssocItemId::ConstId(const_id) => emit_const(
788+
db,
789+
trap,
790+
Some(trait_id.into()),
791+
name.as_str(),
792+
*const_id,
793+
visibility,
794+
)
795+
.map(Into::into),
796+
AssocItemId::TypeAliasId(type_alias_id) => emit_type_alias(
797+
db,
798+
trap,
799+
Some(trait_id.into()),
800+
name.as_str(),
801+
*type_alias_id,
802+
visibility,
803+
)
804+
.map(Into::into),
751805
})
752806
.collect();
753807
let assoc_item_list = Some(trap.emit(generated::AssocItemList {
@@ -1253,36 +1307,71 @@ fn emit_hir_ty(
12531307

12541308
chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(ProjectionTy {
12551309
associated_ty_id,
1256-
substitution: _,
1310+
substitution,
12571311
}))
1258-
| chalk_ir::TyKind::AssociatedType(associated_ty_id, _) => {
1259-
let assoc_ty_data = db.associated_ty_data(*associated_ty_id);
1312+
| chalk_ir::TyKind::AssociatedType(associated_ty_id, substitution) => {
1313+
let pt = ProjectionTy {
1314+
associated_ty_id: *associated_ty_id,
1315+
substitution: substitution.clone(),
1316+
};
12601317

1261-
let _name = db
1262-
.type_alias_data(assoc_ty_data.name)
1263-
.name
1264-
.as_str()
1265-
.to_owned();
1318+
// <Self as Trait<...>>::Name<...>
12661319

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

0 commit comments

Comments
 (0)