diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 130 |
1 files changed, 59 insertions, 71 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 5137a16e6..d0a8199a6 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -26,8 +26,8 @@ use hir_ty::{ | |||
26 | autoderef, | 26 | autoderef, |
27 | display::{HirDisplayError, HirFormatter}, | 27 | display::{HirDisplayError, HirFormatter}, |
28 | expr::ExprValidator, | 28 | expr::ExprValidator, |
29 | method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, OpaqueTyId, | 29 | method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, TraitRef, |
30 | Substs, TraitEnvironment, Ty, TyDefId, TypeCtor, | 30 | Ty, TyDefId, TypeCtor, |
31 | }; | 31 | }; |
32 | use ra_db::{CrateId, CrateName, Edition, FileId}; | 32 | use ra_db::{CrateId, CrateName, Edition, FileId}; |
33 | use ra_prof::profile; | 33 | use ra_prof::profile; |
@@ -1375,6 +1375,18 @@ impl Type { | |||
1375 | Some(adt.into()) | 1375 | Some(adt.into()) |
1376 | } | 1376 | } |
1377 | 1377 | ||
1378 | pub fn as_dyn_trait(&self) -> Option<Trait> { | ||
1379 | self.ty.value.dyn_trait().map(Into::into) | ||
1380 | } | ||
1381 | |||
1382 | pub fn as_impl_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { | ||
1383 | self.ty.value.impl_trait_ref(db).map(|it| it.trait_.into()) | ||
1384 | } | ||
1385 | |||
1386 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { | ||
1387 | self.ty.value.associated_type_parent_trait(db).map(Into::into) | ||
1388 | } | ||
1389 | |||
1378 | // FIXME: provide required accessors such that it becomes implementable from outside. | 1390 | // FIXME: provide required accessors such that it becomes implementable from outside. |
1379 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { | 1391 | pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { |
1380 | match (&self.ty.value, &other.ty.value) { | 1392 | match (&self.ty.value, &other.ty.value) { |
@@ -1397,96 +1409,72 @@ impl Type { | |||
1397 | } | 1409 | } |
1398 | } | 1410 | } |
1399 | 1411 | ||
1400 | /// Returns a flattened list of all ADTs and Traits mentioned in the type | 1412 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { |
1401 | pub fn flattened_type_items(&self, db: &dyn HirDatabase) -> Vec<ModuleDef> { | 1413 | // TypeWalk::walk does not preserve items order! |
1402 | fn push_new_item(item: ModuleDef, acc: &mut Vec<ModuleDef>) { | 1414 | fn walk_substs(db: &dyn HirDatabase, substs: &Substs, cb: &mut impl FnMut(Type)) { |
1403 | if !acc.contains(&item) { | 1415 | for ty in substs.iter() { |
1404 | acc.push(item); | 1416 | walk_ty(db, ty, cb); |
1405 | } | 1417 | } |
1406 | } | 1418 | } |
1407 | 1419 | ||
1408 | fn push_bounds( | 1420 | fn walk_trait( |
1409 | db: &dyn HirDatabase, | 1421 | db: &dyn HirDatabase, |
1410 | predicates: &[GenericPredicate], | 1422 | ty: Ty, |
1411 | acc: &mut Vec<ModuleDef>, | 1423 | trait_ref: &TraitRef, |
1424 | cb: &mut impl FnMut(Type), | ||
1412 | ) { | 1425 | ) { |
1413 | for p in predicates.iter() { | 1426 | let def_db: &dyn DefDatabase = db.upcast(); |
1414 | match p { | 1427 | let resolver = trait_ref.trait_.resolver(def_db); |
1415 | GenericPredicate::Implemented(trait_ref) => { | 1428 | let krate = trait_ref.trait_.lookup(def_db).container.module(def_db).krate; |
1416 | push_new_item(Trait::from(trait_ref.trait_).into(), acc); | 1429 | cb(Type::new_with_resolver_inner(db, krate, &resolver, ty)); |
1417 | walk_substs(db, &trait_ref.substs, acc); | 1430 | walk_substs(db, &trait_ref.substs, cb); |
1418 | } | ||
1419 | GenericPredicate::Projection(_) => {} | ||
1420 | GenericPredicate::Error => (), | ||
1421 | } | ||
1422 | } | ||
1423 | } | 1431 | } |
1424 | 1432 | ||
1425 | // TypeWalk::walk does not preserve items order! | 1433 | fn walk_ty(db: &dyn HirDatabase, ty: &Ty, cb: &mut impl FnMut(Type)) { |
1426 | fn walk_substs(db: &dyn HirDatabase, substs: &Substs, acc: &mut Vec<ModuleDef>) { | 1434 | let def_db: &dyn DefDatabase = db.upcast(); |
1427 | for ty in substs.iter() { | 1435 | let ty = ty.strip_references(); |
1428 | walk_type(db, ty, acc); | 1436 | match ty { |
1429 | } | 1437 | Ty::Apply(ApplicationTy { ctor, parameters }) => { |
1430 | } | ||
1431 | |||
1432 | fn walk_type(db: &dyn HirDatabase, ty: &Ty, acc: &mut Vec<ModuleDef>) { | ||
1433 | match ty.strip_references() { | ||
1434 | Ty::Apply(ApplicationTy { ctor, parameters, .. }) => { | ||
1435 | match ctor { | 1438 | match ctor { |
1436 | TypeCtor::Adt(adt_id) => push_new_item(Adt::from(*adt_id).into(), acc), | 1439 | TypeCtor::Adt(adt) => { |
1437 | TypeCtor::AssociatedType(type_alias_id) => { | 1440 | cb(Type::from_def(db, adt.module(def_db).krate, *adt)); |
1438 | let trait_id = match type_alias_id.lookup(db.upcast()).container { | 1441 | } |
1439 | AssocContainerId::TraitId(it) => it, | 1442 | TypeCtor::AssociatedType(_) => { |
1440 | _ => panic!("not an associated type"), | 1443 | if let Some(trait_id) = ty.associated_type_parent_trait(db) { |
1441 | }; | 1444 | let resolver = trait_id.resolver(def_db); |
1442 | 1445 | let krate = trait_id.lookup(def_db).container.module(def_db).krate; | |
1443 | push_new_item(Trait::from(trait_id).into(), acc); | 1446 | cb(Type::new_with_resolver_inner(db, krate, &resolver, ty.clone())); |
1447 | } | ||
1444 | } | 1448 | } |
1445 | _ => (), | 1449 | _ => (), |
1446 | } | 1450 | } |
1451 | |||
1447 | // adt params, tuples, etc... | 1452 | // adt params, tuples, etc... |
1448 | walk_substs(db, parameters, acc); | 1453 | walk_substs(db, parameters, cb); |
1449 | } | 1454 | } |
1450 | Ty::Dyn(predicates) => { | 1455 | Ty::Opaque(opaque_ty) => { |
1451 | push_bounds(db, predicates, acc); | 1456 | if let Some(trait_ref) = ty.impl_trait_ref(db) { |
1457 | walk_trait(db, ty.clone(), &trait_ref, cb); | ||
1458 | } | ||
1459 | |||
1460 | walk_substs(db, &opaque_ty.parameters, cb); | ||
1452 | } | 1461 | } |
1453 | Ty::Placeholder(id) => { | 1462 | Ty::Placeholder(_) => { |
1454 | let generic_params = db.generic_params(id.parent); | 1463 | if let Some(trait_ref) = ty.impl_trait_ref(db) { |
1455 | let param_data = &generic_params.types[id.local_id]; | 1464 | walk_trait(db, ty.clone(), &trait_ref, cb); |
1456 | match param_data.provenance { | ||
1457 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { | ||
1458 | let predicates: Vec<_> = db | ||
1459 | .generic_predicates_for_param(*id) | ||
1460 | .into_iter() | ||
1461 | .map(|pred| pred.value.clone()) | ||
1462 | .collect(); | ||
1463 | push_bounds(db, &predicates, acc); | ||
1464 | } | ||
1465 | _ => (), | ||
1466 | } | 1465 | } |
1467 | } | 1466 | } |
1468 | Ty::Opaque(opaque_ty) => { | 1467 | Ty::Dyn(_) => { |
1469 | let bounds = match opaque_ty.opaque_ty_id { | 1468 | if let Some(trait_ref) = ty.dyn_trait_ref() { |
1470 | OpaqueTyId::ReturnTypeImplTrait(func, idx) => { | 1469 | walk_trait(db, ty.clone(), trait_ref, cb); |
1471 | let datas = db | 1470 | } |
1472 | .return_type_impl_traits(func) | ||
1473 | .expect("impl trait id without data"); | ||
1474 | let data = (*datas) | ||
1475 | .as_ref() | ||
1476 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | ||
1477 | data.clone().subst(&opaque_ty.parameters) | ||
1478 | } | ||
1479 | }; | ||
1480 | push_bounds(db, &bounds.value, acc); | ||
1481 | walk_substs(db, &opaque_ty.parameters, acc); | ||
1482 | } | 1471 | } |
1472 | |||
1483 | _ => (), | 1473 | _ => (), |
1484 | } | 1474 | } |
1485 | } | 1475 | } |
1486 | 1476 | ||
1487 | let mut res: Vec<ModuleDef> = Vec::new(); // not a Set to preserve the order | 1477 | walk_ty(db, &self.ty.value, &mut cb); |
1488 | walk_type(db, &self.ty.value, &mut res); | ||
1489 | res | ||
1490 | } | 1478 | } |
1491 | } | 1479 | } |
1492 | 1480 | ||