diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 85 |
1 files changed, 50 insertions, 35 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index d0a8199a6..ffd5278ec 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, InEnvironment, Substs, TraitEnvironment, TraitRef, | 29 | method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs, |
30 | Ty, TyDefId, TypeCtor, | 30 | TraitEnvironment, 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; |
@@ -1379,8 +1379,17 @@ impl Type { | |||
1379 | self.ty.value.dyn_trait().map(Into::into) | 1379 | self.ty.value.dyn_trait().map(Into::into) |
1380 | } | 1380 | } |
1381 | 1381 | ||
1382 | pub fn as_impl_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { | 1382 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { |
1383 | self.ty.value.impl_trait_ref(db).map(|it| it.trait_.into()) | 1383 | self.ty.value.impl_trait_bounds(db).map(|it| { |
1384 | it.into_iter() | ||
1385 | .filter_map(|pred| match pred { | ||
1386 | hir_ty::GenericPredicate::Implemented(trait_ref) => { | ||
1387 | Some(Trait::from(trait_ref.trait_)) | ||
1388 | } | ||
1389 | _ => None, | ||
1390 | }) | ||
1391 | .collect() | ||
1392 | }) | ||
1384 | } | 1393 | } |
1385 | 1394 | ||
1386 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { | 1395 | pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { |
@@ -1410,71 +1419,77 @@ impl Type { | |||
1410 | } | 1419 | } |
1411 | 1420 | ||
1412 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { | 1421 | pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { |
1413 | // TypeWalk::walk does not preserve items order! | 1422 | // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself. |
1414 | fn walk_substs(db: &dyn HirDatabase, substs: &Substs, cb: &mut impl FnMut(Type)) { | 1423 | // We need a different order here. |
1424 | |||
1425 | fn walk_substs( | ||
1426 | db: &dyn HirDatabase, | ||
1427 | type_: &Type, | ||
1428 | substs: &Substs, | ||
1429 | cb: &mut impl FnMut(Type), | ||
1430 | ) { | ||
1415 | for ty in substs.iter() { | 1431 | for ty in substs.iter() { |
1416 | walk_ty(db, ty, cb); | 1432 | walk_type(db, &type_.derived(ty.clone()), cb); |
1417 | } | 1433 | } |
1418 | } | 1434 | } |
1419 | 1435 | ||
1420 | fn walk_trait( | 1436 | fn walk_bounds( |
1421 | db: &dyn HirDatabase, | 1437 | db: &dyn HirDatabase, |
1422 | ty: Ty, | 1438 | type_: &Type, |
1423 | trait_ref: &TraitRef, | 1439 | bounds: &[GenericPredicate], |
1424 | cb: &mut impl FnMut(Type), | 1440 | cb: &mut impl FnMut(Type), |
1425 | ) { | 1441 | ) { |
1426 | let def_db: &dyn DefDatabase = db.upcast(); | 1442 | for pred in bounds { |
1427 | let resolver = trait_ref.trait_.resolver(def_db); | 1443 | match pred { |
1428 | let krate = trait_ref.trait_.lookup(def_db).container.module(def_db).krate; | 1444 | GenericPredicate::Implemented(trait_ref) => { |
1429 | cb(Type::new_with_resolver_inner(db, krate, &resolver, ty)); | 1445 | cb(type_.clone()); |
1430 | walk_substs(db, &trait_ref.substs, cb); | 1446 | walk_substs(db, type_, &trait_ref.substs, cb); |
1447 | } | ||
1448 | _ => (), | ||
1449 | } | ||
1450 | } | ||
1431 | } | 1451 | } |
1432 | 1452 | ||
1433 | fn walk_ty(db: &dyn HirDatabase, ty: &Ty, cb: &mut impl FnMut(Type)) { | 1453 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { |
1434 | let def_db: &dyn DefDatabase = db.upcast(); | 1454 | let ty = type_.ty.value.strip_references(); |
1435 | let ty = ty.strip_references(); | ||
1436 | match ty { | 1455 | match ty { |
1437 | Ty::Apply(ApplicationTy { ctor, parameters }) => { | 1456 | Ty::Apply(ApplicationTy { ctor, parameters }) => { |
1438 | match ctor { | 1457 | match ctor { |
1439 | TypeCtor::Adt(adt) => { | 1458 | TypeCtor::Adt(_) => { |
1440 | cb(Type::from_def(db, adt.module(def_db).krate, *adt)); | 1459 | cb(type_.derived(ty.clone())); |
1441 | } | 1460 | } |
1442 | TypeCtor::AssociatedType(_) => { | 1461 | TypeCtor::AssociatedType(_) => { |
1443 | if let Some(trait_id) = ty.associated_type_parent_trait(db) { | 1462 | if let Some(_) = ty.associated_type_parent_trait(db) { |
1444 | let resolver = trait_id.resolver(def_db); | 1463 | cb(type_.derived(ty.clone())); |
1445 | let krate = trait_id.lookup(def_db).container.module(def_db).krate; | ||
1446 | cb(Type::new_with_resolver_inner(db, krate, &resolver, ty.clone())); | ||
1447 | } | 1464 | } |
1448 | } | 1465 | } |
1449 | _ => (), | 1466 | _ => (), |
1450 | } | 1467 | } |
1451 | 1468 | ||
1452 | // adt params, tuples, etc... | 1469 | // adt params, tuples, etc... |
1453 | walk_substs(db, parameters, cb); | 1470 | walk_substs(db, type_, parameters, cb); |
1454 | } | 1471 | } |
1455 | Ty::Opaque(opaque_ty) => { | 1472 | Ty::Opaque(opaque_ty) => { |
1456 | if let Some(trait_ref) = ty.impl_trait_ref(db) { | 1473 | if let Some(bounds) = ty.impl_trait_bounds(db) { |
1457 | walk_trait(db, ty.clone(), &trait_ref, cb); | 1474 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); |
1458 | } | 1475 | } |
1459 | 1476 | ||
1460 | walk_substs(db, &opaque_ty.parameters, cb); | 1477 | walk_substs(db, type_, &opaque_ty.parameters, cb); |
1461 | } | 1478 | } |
1462 | Ty::Placeholder(_) => { | 1479 | Ty::Placeholder(_) => { |
1463 | if let Some(trait_ref) = ty.impl_trait_ref(db) { | 1480 | if let Some(bounds) = ty.impl_trait_bounds(db) { |
1464 | walk_trait(db, ty.clone(), &trait_ref, cb); | 1481 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); |
1465 | } | 1482 | } |
1466 | } | 1483 | } |
1467 | Ty::Dyn(_) => { | 1484 | Ty::Dyn(bounds) => { |
1468 | if let Some(trait_ref) = ty.dyn_trait_ref() { | 1485 | walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); |
1469 | walk_trait(db, ty.clone(), trait_ref, cb); | ||
1470 | } | ||
1471 | } | 1486 | } |
1472 | 1487 | ||
1473 | _ => (), | 1488 | _ => (), |
1474 | } | 1489 | } |
1475 | } | 1490 | } |
1476 | 1491 | ||
1477 | walk_ty(db, &self.ty.value, &mut cb); | 1492 | walk_type(db, self, &mut cb); |
1478 | } | 1493 | } |
1479 | } | 1494 | } |
1480 | 1495 | ||