|
1 | 1 | use super::OverlapError; |
2 | 2 |
|
3 | | -use crate::ich::{self, StableHashingContext}; |
4 | 3 | use crate::traits; |
5 | | -use crate::ty::fast_reject::{self, SimplifiedType}; |
6 | | -use crate::ty::{self, TyCtxt, TypeFoldable}; |
7 | | -use rustc_data_structures::fx::FxHashMap; |
8 | | -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
9 | | -use rustc_hir::def_id::{DefId, DefIdMap}; |
10 | | -use syntax::ast::Ident; |
11 | | - |
12 | | -/// A per-trait graph of impls in specialization order. At the moment, this |
13 | | -/// graph forms a tree rooted with the trait itself, with all other nodes |
14 | | -/// representing impls, and parent-child relationships representing |
15 | | -/// specializations. |
16 | | -/// |
17 | | -/// The graph provides two key services: |
18 | | -/// |
19 | | -/// - Construction. This implicitly checks for overlapping impls (i.e., impls |
20 | | -/// that overlap but where neither specializes the other -- an artifact of the |
21 | | -/// simple "chain" rule. |
22 | | -/// |
23 | | -/// - Parent extraction. In particular, the graph can give you the *immediate* |
24 | | -/// parents of a given specializing impl, which is needed for extracting |
25 | | -/// default items amongst other things. In the simple "chain" rule, every impl |
26 | | -/// has at most one parent. |
27 | | -#[derive(RustcEncodable, RustcDecodable, HashStable)] |
28 | | -pub struct Graph { |
29 | | - // All impls have a parent; the "root" impls have as their parent the `def_id` |
30 | | - // of the trait. |
31 | | - parent: DefIdMap<DefId>, |
32 | | - |
33 | | - // The "root" impls are found by looking up the trait's def_id. |
34 | | - children: DefIdMap<Children>, |
35 | | -} |
| 4 | +use rustc::ty::fast_reject::{self, SimplifiedType}; |
| 5 | +use rustc::ty::{self, TyCtxt, TypeFoldable}; |
| 6 | +use rustc_hir::def_id::DefId; |
36 | 7 |
|
37 | | -/// Children of a given impl, grouped into blanket/non-blanket varieties as is |
38 | | -/// done in `TraitDef`. |
39 | | -#[derive(Default, RustcEncodable, RustcDecodable)] |
40 | | -struct Children { |
41 | | - // Impls of a trait (or specializations of a given impl). To allow for |
42 | | - // quicker lookup, the impls are indexed by a simplified version of their |
43 | | - // `Self` type: impls with a simplifiable `Self` are stored in |
44 | | - // `nonblanket_impls` keyed by it, while all other impls are stored in |
45 | | - // `blanket_impls`. |
46 | | - // |
47 | | - // A similar division is used within `TraitDef`, but the lists there collect |
48 | | - // together *all* the impls for a trait, and are populated prior to building |
49 | | - // the specialization graph. |
50 | | - /// Impls of the trait. |
51 | | - nonblanket_impls: FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>, |
52 | | - |
53 | | - /// Blanket impls associated with the trait. |
54 | | - blanket_impls: Vec<DefId>, |
55 | | -} |
| 8 | +pub use rustc::traits::types::specialization_graph::*; |
56 | 9 |
|
57 | 10 | #[derive(Copy, Clone, Debug)] |
58 | 11 | pub enum FutureCompatOverlapErrorKind { |
@@ -269,10 +222,6 @@ where |
269 | 222 | } |
270 | 223 |
|
271 | 224 | impl<'tcx> Graph { |
272 | | - pub fn new() -> Graph { |
273 | | - Graph { parent: Default::default(), children: Default::default() } |
274 | | - } |
275 | | - |
276 | 225 | /// Insert a local impl into the specialization graph. If an existing impl |
277 | 226 | /// conflicts with it (has overlap, but neither specializes the other), |
278 | 227 | /// information about the area of overlap is returned in the `Err`. |
@@ -383,145 +332,4 @@ impl<'tcx> Graph { |
383 | 332 |
|
384 | 333 | self.children.entry(parent).or_default().insert_blindly(tcx, child); |
385 | 334 | } |
386 | | - |
387 | | - /// The parent of a given impl, which is the `DefId` of the trait when the |
388 | | - /// impl is a "specialization root". |
389 | | - pub fn parent(&self, child: DefId) -> DefId { |
390 | | - *self.parent.get(&child).unwrap_or_else(|| panic!("Failed to get parent for {:?}", child)) |
391 | | - } |
392 | | -} |
393 | | - |
394 | | -/// A node in the specialization graph is either an impl or a trait |
395 | | -/// definition; either can serve as a source of item definitions. |
396 | | -/// There is always exactly one trait definition node: the root. |
397 | | -#[derive(Debug, Copy, Clone)] |
398 | | -pub enum Node { |
399 | | - Impl(DefId), |
400 | | - Trait(DefId), |
401 | | -} |
402 | | - |
403 | | -impl<'tcx> Node { |
404 | | - pub fn is_from_trait(&self) -> bool { |
405 | | - match *self { |
406 | | - Node::Trait(..) => true, |
407 | | - _ => false, |
408 | | - } |
409 | | - } |
410 | | - |
411 | | - /// Iterate over the items defined directly by the given (impl or trait) node. |
412 | | - pub fn items(&self, tcx: TyCtxt<'tcx>) -> ty::AssocItemsIterator<'tcx> { |
413 | | - tcx.associated_items(self.def_id()) |
414 | | - } |
415 | | - |
416 | | - /// Finds an associated item defined in this node. |
417 | | - /// |
418 | | - /// If this returns `None`, the item can potentially still be found in |
419 | | - /// parents of this node. |
420 | | - pub fn item( |
421 | | - &self, |
422 | | - tcx: TyCtxt<'tcx>, |
423 | | - trait_item_name: Ident, |
424 | | - trait_item_kind: ty::AssocKind, |
425 | | - trait_def_id: DefId, |
426 | | - ) -> Option<ty::AssocItem> { |
427 | | - use crate::ty::AssocKind::*; |
428 | | - |
429 | | - tcx.associated_items(self.def_id()).find(move |impl_item| { |
430 | | - match (trait_item_kind, impl_item.kind) { |
431 | | - | (Const, Const) |
432 | | - | (Method, Method) |
433 | | - | (Type, Type) |
434 | | - | (Type, OpaqueTy) // assoc. types can be made opaque in impls |
435 | | - => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id), |
436 | | - |
437 | | - | (Const, _) |
438 | | - | (Method, _) |
439 | | - | (Type, _) |
440 | | - | (OpaqueTy, _) |
441 | | - => false, |
442 | | - } |
443 | | - }) |
444 | | - } |
445 | | - |
446 | | - pub fn def_id(&self) -> DefId { |
447 | | - match *self { |
448 | | - Node::Impl(did) => did, |
449 | | - Node::Trait(did) => did, |
450 | | - } |
451 | | - } |
452 | | -} |
453 | | - |
454 | | -#[derive(Copy, Clone)] |
455 | | -pub struct Ancestors<'tcx> { |
456 | | - trait_def_id: DefId, |
457 | | - specialization_graph: &'tcx Graph, |
458 | | - current_source: Option<Node>, |
459 | | -} |
460 | | - |
461 | | -impl Iterator for Ancestors<'_> { |
462 | | - type Item = Node; |
463 | | - fn next(&mut self) -> Option<Node> { |
464 | | - let cur = self.current_source.take(); |
465 | | - if let Some(Node::Impl(cur_impl)) = cur { |
466 | | - let parent = self.specialization_graph.parent(cur_impl); |
467 | | - |
468 | | - self.current_source = if parent == self.trait_def_id { |
469 | | - Some(Node::Trait(parent)) |
470 | | - } else { |
471 | | - Some(Node::Impl(parent)) |
472 | | - }; |
473 | | - } |
474 | | - cur |
475 | | - } |
476 | | -} |
477 | | - |
478 | | -pub struct NodeItem<T> { |
479 | | - pub node: Node, |
480 | | - pub item: T, |
481 | | -} |
482 | | - |
483 | | -impl<T> NodeItem<T> { |
484 | | - pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> NodeItem<U> { |
485 | | - NodeItem { node: self.node, item: f(self.item) } |
486 | | - } |
487 | | -} |
488 | | - |
489 | | -impl<'tcx> Ancestors<'tcx> { |
490 | | - /// Finds the bottom-most (ie. most specialized) definition of an associated |
491 | | - /// item. |
492 | | - pub fn leaf_def( |
493 | | - mut self, |
494 | | - tcx: TyCtxt<'tcx>, |
495 | | - trait_item_name: Ident, |
496 | | - trait_item_kind: ty::AssocKind, |
497 | | - ) -> Option<NodeItem<ty::AssocItem>> { |
498 | | - let trait_def_id = self.trait_def_id; |
499 | | - self.find_map(|node| { |
500 | | - node.item(tcx, trait_item_name, trait_item_kind, trait_def_id) |
501 | | - .map(|item| NodeItem { node, item }) |
502 | | - }) |
503 | | - } |
504 | | -} |
505 | | - |
506 | | -/// Walk up the specialization ancestors of a given impl, starting with that |
507 | | -/// impl itself. |
508 | | -pub fn ancestors( |
509 | | - tcx: TyCtxt<'tcx>, |
510 | | - trait_def_id: DefId, |
511 | | - start_from_impl: DefId, |
512 | | -) -> Ancestors<'tcx> { |
513 | | - let specialization_graph = tcx.specialization_graph_of(trait_def_id); |
514 | | - Ancestors { |
515 | | - trait_def_id, |
516 | | - specialization_graph, |
517 | | - current_source: Some(Node::Impl(start_from_impl)), |
518 | | - } |
519 | | -} |
520 | | - |
521 | | -impl<'a> HashStable<StableHashingContext<'a>> for Children { |
522 | | - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { |
523 | | - let Children { ref nonblanket_impls, ref blanket_impls } = *self; |
524 | | - |
525 | | - ich::hash_stable_trait_impls(hcx, hasher, blanket_impls, nonblanket_impls); |
526 | | - } |
527 | 335 | } |
0 commit comments