aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model.rs85
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};
32use ra_db::{CrateId, CrateName, Edition, FileId}; 32use ra_db::{CrateId, CrateName, Edition, FileId};
33use ra_prof::profile; 33use 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