+
+/// Whether `anon_node_id` is a sibling or a child of a sibling of `def_id`
+///
+/// ```rust
+/// pub mod foo {
+/// pub mod bar {
+/// pub existential type Baz;
+///
+/// fn f1() -> Baz { .. }
+/// }
+///
+/// fn f2() -> bar::Baz { .. }
+/// }
+/// ```
+///
+/// Here, `def_id` will be the `DefId` of the existential type `Baz`.
+/// `anon_node_id` is the `NodeId` of the reference to Baz -- so either the return type of f1 or f2.
+/// We will return true if the reference is within the same module as the existential type
+/// So true for f1, false for f2.
+pub fn may_define_existential_type(
+ tcx: TyCtxt,
+ def_id: DefId,
+ anon_node_id: ast::NodeId,
+) -> bool {
+ let mut node_id = tcx
+ .hir
+ .as_local_node_id(def_id)
+ .unwrap();
+ // named existential types can be defined by any siblings or
+ // children of siblings
+ let mod_id = tcx.hir.get_parent(anon_node_id);
+ // so we walk up the node tree until we hit the root or the parent
+ // of the anon type
+ while node_id != mod_id && node_id != ast::CRATE_NODE_ID {
+ node_id = tcx.hir.get_parent(node_id);
+ }
+ // syntactically we are allowed to define the concrete type
+ node_id == mod_id
+}