Skip to content

Commit 0a97476

Browse files
committed
Rust: crate graph: type variables
1 parent 88439b4 commit 0a97476

File tree

3 files changed

+120
-34
lines changed

3 files changed

+120
-34
lines changed

rust/extractor/src/crate_graph.rs

Lines changed: 98 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,13 @@ use ra_ap_hir_def::{
1919
use ra_ap_hir_def::{HasModule, visibility::VisibilityExplicitness};
2020
use ra_ap_hir_def::{ModuleId, resolver::HasResolver};
2121
use ra_ap_hir_ty::TraitRefExt;
22-
use ra_ap_hir_ty::Ty;
2322
use ra_ap_hir_ty::TyExt;
2423
use ra_ap_hir_ty::WhereClause;
2524
use ra_ap_hir_ty::{Binders, FnPointer};
25+
use ra_ap_hir_ty::{GenericArg, Ty};
2626
use ra_ap_hir_ty::{Interner, ProjectionTy};
2727
use ra_ap_ide_db::RootDatabase;
2828
use ra_ap_vfs::{Vfs, VfsPath};
29-
3029
use std::hash::Hasher;
3130
use std::{cmp::Ordering, collections::HashMap, path::PathBuf};
3231
use std::{hash::Hash, vec};
@@ -242,7 +241,7 @@ fn emit_reexport(
242241
name,
243242
})
244243
});
245-
let path = make_qualified_path(trap, path_components);
244+
let path = make_qualified_path(trap, path_components, None);
246245
let use_tree = trap.emit(generated::UseTree {
247246
id: trap::TrapId::Star,
248247
is_glob: false,
@@ -636,15 +635,13 @@ fn emit_module_impls(
636635
module.scope.impls().for_each(|imp| {
637636
let self_ty = db.impl_self_ty(imp);
638637
let self_ty = emit_hir_ty(trap, db, self_ty.skip_binders());
639-
let imp_data = db.impl_data(imp);
640-
let trait_ = imp_data
641-
.target_trait
642-
.as_ref()
643-
.and_then(|t| make_qualified_path(trap, emit_hir_path(&imp_data.types_map[t.path])));
644-
let trait_ = trait_.map(|trait_| {
638+
let path = db
639+
.impl_trait(imp)
640+
.map(|trait_ref| trait_path(db, trap, trait_ref.skip_binders()));
641+
let trait_ = path.map(|path| {
645642
trap.emit(generated::PathTypeRepr {
646643
id: trap::TrapId::Star,
647-
path: Some(trait_),
644+
path,
648645
})
649646
.into()
650647
});
@@ -757,7 +754,7 @@ fn emit_visibility(
757754
Visibility::Module(_, VisibilityExplicitness::Implicit) => None,
758755
};
759756
path.map(|path| {
760-
let path = make_qualified_path(trap, path);
757+
let path = make_qualified_path(trap, path, None);
761758
trap.emit(generated::Visibility {
762759
id: trap::TrapId::Star,
763760
path,
@@ -855,14 +852,7 @@ fn emit_hir_type_bound(
855852
) -> Option<trap::Label<generated::TypeBound>> {
856853
match type_bound.skip_binders() {
857854
WhereClause::Implemented(trait_ref) => {
858-
let mut path = make_path(db, trait_ref.hir_trait_id());
859-
path.push(
860-
db.trait_data(trait_ref.hir_trait_id())
861-
.name
862-
.as_str()
863-
.to_owned(),
864-
);
865-
let path = make_qualified_path(trap, path);
855+
let path = trait_path(db, trap, trait_ref);
866856
let type_repr = Some(
867857
trap.emit(generated::PathTypeRepr {
868858
id: trap::TrapId::Star,
@@ -883,11 +873,22 @@ fn emit_hir_type_bound(
883873
}
884874
}
885875

886-
fn emit_hir_path(path: &ra_ap_hir_def::path::Path) -> Vec<String> {
887-
path.segments()
888-
.iter()
889-
.map(|x| x.name.as_str().to_owned())
890-
.collect()
876+
fn trait_path(
877+
db: &dyn HirDatabase,
878+
trap: &mut TrapFile,
879+
trait_ref: &chalk_ir::TraitRef<Interner>,
880+
) -> Option<trap::Label<generated::Path>> {
881+
let mut path = make_path(db, trait_ref.hir_trait_id());
882+
path.push(
883+
db.trait_data(trait_ref.hir_trait_id())
884+
.name
885+
.as_str()
886+
.to_owned(),
887+
);
888+
let generic_arg_list =
889+
emit_generic_arg_list(trap, db, &trait_ref.substitution.as_slice(Interner)[1..]);
890+
let path = make_qualified_path(trap, path, generic_arg_list);
891+
path
891892
}
892893

893894
fn emit_hir_fn_ptr(
@@ -991,22 +992,25 @@ fn make_path_mod(db: &dyn DefDatabase, module: ModuleId) -> Vec<String> {
991992
path.reverse();
992993
path
993994
}
995+
994996
fn make_qualified_path(
995997
trap: &mut TrapFile,
996998
path: Vec<String>,
999+
generic_arg_list: Option<trap::Label<generated::GenericArgList>>,
9971000
) -> Option<trap::Label<generated::Path>> {
9981001
fn qualified_path(
9991002
trap: &mut TrapFile,
10001003
qualifier: Option<trap::Label<generated::Path>>,
10011004
name: String,
1005+
generic_arg_list: Option<trap::Label<generated::GenericArgList>>,
10021006
) -> trap::Label<generated::Path> {
10031007
let identifier = Some(trap.emit(generated::NameRef {
10041008
id: trap::TrapId::Star,
10051009
text: Some(name),
10061010
}));
10071011
let segment = Some(trap.emit(generated::PathSegment {
10081012
id: trap::TrapId::Star,
1009-
generic_arg_list: None,
1013+
generic_arg_list,
10101014
identifier,
10111015
parenthesized_arg_list: None,
10121016
ret_type: None,
@@ -1018,8 +1022,10 @@ fn make_qualified_path(
10181022
segment,
10191023
})
10201024
}
1025+
let args = std::iter::repeat_n(None, &path.len() - 1).chain(std::iter::once(generic_arg_list));
10211026
path.into_iter()
1022-
.fold(None, |q, p| Some(qualified_path(trap, q, p)))
1027+
.zip(args)
1028+
.fold(None, |q, (p, a)| Some(qualified_path(trap, q, p, a)))
10231029
}
10241030
fn emit_hir_ty(
10251031
trap: &mut TrapFile,
@@ -1105,7 +1111,7 @@ fn emit_hir_ty(
11051111
)
11061112
}
11071113

1108-
chalk_ir::TyKind::Adt(adt_id, _substitution) => {
1114+
chalk_ir::TyKind::Adt(adt_id, substitution) => {
11091115
let mut path = make_path(db, adt_id.0);
11101116
let name = match adt_id.0 {
11111117
ra_ap_hir_def::AdtId::StructId(struct_id) => {
@@ -1119,7 +1125,8 @@ fn emit_hir_ty(
11191125
}
11201126
};
11211127
path.push(name);
1122-
let path = make_qualified_path(trap, path);
1128+
let generic_arg_list = emit_generic_arg_list(trap, db, substitution.as_slice(Interner));
1129+
let path = make_qualified_path(trap, path, generic_arg_list);
11231130
Some(
11241131
trap.emit(generated::PathTypeRepr {
11251132
id: trap::TrapId::Star,
@@ -1129,7 +1136,7 @@ fn emit_hir_ty(
11291136
)
11301137
}
11311138
chalk_ir::TyKind::Scalar(scalar) => {
1132-
let path = make_qualified_path(trap, vec![scalar_to_str(scalar).to_owned()]);
1139+
let path = make_qualified_path(trap, vec![scalar_to_str(scalar).to_owned()], None);
11331140
Some(
11341141
trap.emit(generated::PathTypeRepr {
11351142
id: trap::TrapId::Star,
@@ -1139,7 +1146,7 @@ fn emit_hir_ty(
11391146
)
11401147
}
11411148
chalk_ir::TyKind::Str => {
1142-
let path = make_qualified_path(trap, vec!["str".to_owned()]);
1149+
let path = make_qualified_path(trap, vec!["str".to_owned()], None);
11431150
Some(
11441151
trap.emit(generated::PathTypeRepr {
11451152
id: trap::TrapId::Star,
@@ -1230,7 +1237,7 @@ fn emit_hir_ty(
12301237
}
12311238
chalk_ir::TyKind::BoundVar(var) => {
12321239
let var = format!("T_{}_{}", var.debruijn.depth(), var.index);
1233-
let path = make_qualified_path(trap, vec![var]);
1240+
let path = make_qualified_path(trap, vec![var], None);
12341241
Some(
12351242
trap.emit(generated::PathTypeRepr {
12361243
id: trap::TrapId::Star,
@@ -1251,6 +1258,66 @@ fn emit_hir_ty(
12511258
}
12521259
}
12531260

1261+
fn emit_generic_arg_list(
1262+
trap: &mut TrapFile,
1263+
db: &dyn HirDatabase,
1264+
args: &[GenericArg],
1265+
) -> Option<trap::Label<generated::GenericArgList>> {
1266+
if args.is_empty() {
1267+
return None;
1268+
}
1269+
let generic_args = args
1270+
.iter()
1271+
.flat_map(|arg| {
1272+
if let Some(ty) = arg.ty(Interner) {
1273+
let type_repr = emit_hir_ty(trap, db, ty);
1274+
Some(
1275+
trap.emit(generated::TypeArg {
1276+
id: trap::TrapId::Star,
1277+
type_repr,
1278+
})
1279+
.into(),
1280+
)
1281+
} else if let Some(l) = arg.lifetime(Interner) {
1282+
let text = match l.data(Interner) {
1283+
chalk_ir::LifetimeData::BoundVar(var) => {
1284+
format!("'T_{}_{}", var.debruijn.depth(), var.index).into()
1285+
}
1286+
chalk_ir::LifetimeData::Static => "'static'".to_owned().into(),
1287+
_ => None,
1288+
};
1289+
let lifetime = trap.emit(generated::Lifetime {
1290+
id: trap::TrapId::Star,
1291+
text,
1292+
});
1293+
Some(
1294+
trap.emit(generated::LifetimeArg {
1295+
id: trap::TrapId::Star,
1296+
lifetime: Some(lifetime),
1297+
})
1298+
.into(),
1299+
)
1300+
} else if let Some(_) = arg.constant(Interner) {
1301+
Some(
1302+
trap.emit(generated::ConstArg {
1303+
id: trap::TrapId::Star,
1304+
expr: None,
1305+
})
1306+
.into(),
1307+
)
1308+
} else {
1309+
None
1310+
}
1311+
})
1312+
.collect();
1313+
1314+
trap.emit(generated::GenericArgList {
1315+
id: trap::TrapId::Star,
1316+
generic_args,
1317+
})
1318+
.into()
1319+
}
1320+
12541321
enum Variant {
12551322
Unit,
12561323
Record(trap::Label<generated::StructFieldList>),

rust/ql/test/extractor-tests/crate_graph/module.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,13 @@ pub static X_B: X = X::B;
4343

4444
pub use std::fs::create_dir as mkdir;
4545
pub use std::{fs::*, path::PathBuf};
46+
47+
pub struct LocalKey<T: 'static> {
48+
inner: fn(Option<&mut Option<T>>) -> *const T,
49+
}
50+
51+
impl From<usize> for X {
52+
fn from(x: usize) -> Self {
53+
X::A
54+
}
55+
}

rust/ql/test/extractor-tests/crate_graph/modules.expected

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,18 @@
1010

1111
#-----| fn fmt
1212

13+
#-----| fn from
14+
1315
#-----| fn length
1416

17+
#-----| impl ...::AsString for ...::X { ... }
18+
#-----| -> fn as_string
19+
1520
#-----| impl ...::Display for ...::X { ... }
1621
#-----| -> fn fmt
1722

18-
#-----| impl AsString for ...::X { ... }
19-
#-----| -> fn as_string
23+
#-----| impl ...::From::<...> for ...::X { ... }
24+
#-----| -> fn from
2025

2126
lib.rs:
2227
# 0| mod crate
@@ -27,8 +32,10 @@ lib.rs:
2732
#-----| -> Static
2833
#-----| -> enum X
2934
#-----| -> fn length
35+
#-----| -> impl ...::AsString for ...::X { ... }
3036
#-----| -> impl ...::Display for ...::X { ... }
31-
#-----| -> impl AsString for ...::X { ... }
37+
#-----| -> impl ...::From::<...> for ...::X { ... }
38+
#-----| -> struct LocalKey
3239
#-----| -> struct X_List
3340
#-----| -> trait AsString
3441
#-----| -> use ...::DirBuilder
@@ -62,6 +69,8 @@ lib.rs:
6269
#-----| -> use ...::symlink_metadata
6370
#-----| -> use ...::write
6471

72+
#-----| struct LocalKey
73+
6574
#-----| struct X_List
6675

6776
#-----| trait AsString

0 commit comments

Comments
 (0)