Skip to content

Commit a7ccba9

Browse files
committed
Rust: crate graph: type variables
1 parent 2c31363 commit a7ccba9

File tree

3 files changed

+120
-32
lines changed

3 files changed

+120
-32
lines changed

rust/extractor/src/crate_graph.rs

Lines changed: 98 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use ra_ap_hir_def::{
1818
};
1919
use ra_ap_hir_def::{HasModule, visibility::VisibilityExplicitness};
2020
use ra_ap_hir_def::{ModuleId, resolver::HasResolver};
21+
use ra_ap_hir_ty::GenericArg;
2122
use ra_ap_hir_ty::TraitRefExt;
2223
use ra_ap_hir_ty::Ty;
2324
use ra_ap_hir_ty::TyExt;
@@ -244,7 +245,7 @@ fn emit_reexport(
244245
name,
245246
})
246247
});
247-
let path = make_qualified_path(trap, path_components);
248+
let path = make_qualified_path(trap, path_components, None);
248249
let use_tree = trap.emit(generated::UseTree {
249250
id: trap::TrapId::Star,
250251
is_glob: false,
@@ -638,15 +639,13 @@ fn emit_module_impls(
638639
module.scope.impls().for_each(|imp| {
639640
let self_ty = db.impl_self_ty(imp);
640641
let self_ty = emit_hir_ty(trap, db, self_ty.skip_binders());
641-
let imp_data = db.impl_data(imp);
642-
let trait_ = imp_data
643-
.target_trait
644-
.as_ref()
645-
.and_then(|t| make_qualified_path(trap, emit_hir_path(&imp_data.types_map[t.path])));
646-
let trait_ = trait_.map(|trait_| {
642+
let path = db
643+
.impl_trait(imp)
644+
.map(|trait_ref| trait_path(db, trap, trait_ref.skip_binders()));
645+
let trait_ = path.map(|path| {
647646
trap.emit(generated::PathTypeRepr {
648647
id: trap::TrapId::Star,
649-
path: Some(trait_),
648+
path,
650649
})
651650
.into()
652651
});
@@ -759,7 +758,7 @@ fn emit_visibility(
759758
Visibility::Module(_, VisibilityExplicitness::Implicit) => None,
760759
};
761760
path.map(|path| {
762-
let path = make_qualified_path(trap, path);
761+
let path = make_qualified_path(trap, path, None);
763762
trap.emit(generated::Visibility {
764763
id: trap::TrapId::Star,
765764
path,
@@ -859,14 +858,7 @@ fn emit_hir_type_bound(
859858
) -> Option<trap::Label<generated::TypeBound>> {
860859
match type_bound.skip_binders() {
861860
WhereClause::Implemented(trait_ref) => {
862-
let mut path = make_path(db, trait_ref.hir_trait_id());
863-
path.push(
864-
db.trait_data(trait_ref.hir_trait_id())
865-
.name
866-
.as_str()
867-
.to_owned(),
868-
);
869-
let path = make_qualified_path(trap, path);
861+
let path = trait_path(db, trap, trait_ref);
870862
let type_repr = Some(
871863
trap.emit(generated::PathTypeRepr {
872864
id: trap::TrapId::Star,
@@ -887,11 +879,22 @@ fn emit_hir_type_bound(
887879
}
888880
}
889881

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

897900
fn emit_hir_fn_ptr(
@@ -995,22 +998,25 @@ fn make_path_mod(db: &dyn DefDatabase, module: ModuleId) -> Vec<String> {
995998
path.reverse();
996999
path
9971000
}
1001+
9981002
fn make_qualified_path(
9991003
trap: &mut TrapFile,
10001004
path: Vec<String>,
1005+
generic_arg_list: Option<trap::Label<generated::GenericArgList>>,
10011006
) -> Option<trap::Label<generated::Path>> {
10021007
fn qualified_path(
10031008
trap: &mut TrapFile,
10041009
qualifier: Option<trap::Label<generated::Path>>,
10051010
name: String,
1011+
generic_arg_list: Option<trap::Label<generated::GenericArgList>>,
10061012
) -> trap::Label<generated::Path> {
10071013
let identifier = Some(trap.emit(generated::NameRef {
10081014
id: trap::TrapId::Star,
10091015
text: Some(name),
10101016
}));
10111017
let segment = Some(trap.emit(generated::PathSegment {
10121018
id: trap::TrapId::Star,
1013-
generic_arg_list: None,
1019+
generic_arg_list,
10141020
identifier,
10151021
parenthesized_arg_list: None,
10161022
ret_type: None,
@@ -1022,8 +1028,10 @@ fn make_qualified_path(
10221028
segment,
10231029
})
10241030
}
1031+
let args = std::iter::repeat_n(None, &path.len() - 1).chain(std::iter::once(generic_arg_list));
10251032
path.into_iter()
1026-
.fold(None, |q, p| Some(qualified_path(trap, q, p)))
1033+
.zip(args)
1034+
.fold(None, |q, (p, a)| Some(qualified_path(trap, q, p, a)))
10271035
}
10281036
fn emit_hir_ty(
10291037
trap: &mut TrapFile,
@@ -1109,7 +1117,7 @@ fn emit_hir_ty(
11091117
)
11101118
}
11111119

1112-
chalk_ir::TyKind::Adt(adt_id, _substitution) => {
1120+
chalk_ir::TyKind::Adt(adt_id, substitution) => {
11131121
let mut path = make_path(db, adt_id.0);
11141122
let name = match adt_id.0 {
11151123
ra_ap_hir_def::AdtId::StructId(struct_id) => {
@@ -1123,7 +1131,8 @@ fn emit_hir_ty(
11231131
}
11241132
};
11251133
path.push(name);
1126-
let path = make_qualified_path(trap, path);
1134+
let generic_arg_list = emit_generic_arg_list(trap, db, substitution.as_slice(Interner));
1135+
let path = make_qualified_path(trap, path, generic_arg_list);
11271136
Some(
11281137
trap.emit(generated::PathTypeRepr {
11291138
id: trap::TrapId::Star,
@@ -1133,7 +1142,7 @@ fn emit_hir_ty(
11331142
)
11341143
}
11351144
chalk_ir::TyKind::Scalar(scalar) => {
1136-
let path = make_qualified_path(trap, vec![scalar_to_str(scalar).to_owned()]);
1145+
let path = make_qualified_path(trap, vec![scalar_to_str(scalar).to_owned()], None);
11371146
Some(
11381147
trap.emit(generated::PathTypeRepr {
11391148
id: trap::TrapId::Star,
@@ -1143,7 +1152,7 @@ fn emit_hir_ty(
11431152
)
11441153
}
11451154
chalk_ir::TyKind::Str => {
1146-
let path = make_qualified_path(trap, vec!["str".to_owned()]);
1155+
let path = make_qualified_path(trap, vec!["str".to_owned()], None);
11471156
Some(
11481157
trap.emit(generated::PathTypeRepr {
11491158
id: trap::TrapId::Star,
@@ -1234,7 +1243,7 @@ fn emit_hir_ty(
12341243
}
12351244
chalk_ir::TyKind::BoundVar(var) => {
12361245
let var = format!("T_{}_{}", var.debruijn.depth(), var.index);
1237-
let path = make_qualified_path(trap, vec![var]);
1246+
let path = make_qualified_path(trap, vec![var], None);
12381247
Some(
12391248
trap.emit(generated::PathTypeRepr {
12401249
id: trap::TrapId::Star,
@@ -1255,6 +1264,66 @@ fn emit_hir_ty(
12551264
}
12561265
}
12571266

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