Change:
Mentioning the existential types tracking issue Mentioning and
O_o I don't think I considered closures at all. Should closures be defining uses? Or just uses (and thus only be able to return that type by calling a function that defines the existential)?
As a motivating use case, existential types defined by a closure are required if we want to extend to support referring to local variables.
Yeah, any in-scope use (including in a binding) can be a defining use.
A binding like this? It looks like this is not currently picked up. It is why I had to write rather than simply in my previous comment.
Yeah, the RFC specifies that that should work.
I chose a simpler logic: any in scope use must be a defining use.
We've moved from segmentation faults to an ICE:

Discussion:
opaque_hir_id: hir::HirId, ) -> bool { let mut hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); <del> trace!( "may_define_existential_type(def={:?}, opaque_node={:?})", tcx.hir().get(hir_id), tcx.hir().get(opaque_hir_id) ); </del> // Named existential types can be defined by any siblings or children of siblings. let scope = tcx.hir().get_defining_scope(opaque_hir_id).expect("could not get defining scope");

hir_id = tcx.hir().get_parent_item(hir_id); } // Syntactically, we are allowed to define the concrete type if: <del> hir_id == scope </del> <ins> let res = hir_id == scope; trace!( "may_define_existential_type(def={:?}, opaque_node={:?}) = {}", tcx.hir().get(hir_id), tcx.hir().get(opaque_hir_id), res ); res </ins> }

intravisit::NestedVisitorMap::All(&self.tcx.hir()) } fn visit_item(&mut self, it: &'tcx Item) { <ins> debug!("find_existential_constraints: visiting {:?}", it); </ins> let def_id = self.tcx.hir().local_def_id(it.hir_id); // The existential type itself or its children are not within its reveal scope. if def_id != self.def_id {

} } fn visit_impl_item(&mut self, it: &'tcx ImplItem) { <ins> debug!("find_existential_constraints: visiting {:?}", it); </ins> let def_id = self.tcx.hir().local_def_id(it.hir_id); // The existential type itself or its children are not within its reveal scope. if def_id != self.def_id {

} } fn visit_trait_item(&mut self, it: &'tcx TraitItem) { <ins> debug!("find_existential_constraints: visiting {:?}", it); </ins> let def_id = self.tcx.hir().local_def_id(it.hir_id); self.check(def_id); intravisit::walk_trait_item(self, it);

} else { debug!("find_existential_constraints: scope={:?}", tcx.hir().get(scope)); match tcx.hir().get(scope) { <del> Node::Item(ref it) => intravisit::walk_item(&mut locator, it), Node::ImplItem(ref it) => intravisit::walk_impl_item(&mut locator, it), Node::TraitItem(ref it) => intravisit::walk_trait_item(&mut locator, it), </del> <ins> // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods // This allows our visitor to process the defining item itself, causing // it to pick up any 'sibling' defining uses. // // For example, this code: // ``` // fn foo() { //     existential type Blah: Debug; //     let my_closure = || -> Blah { true }; // } // ``` // // requires us to explicitly process `foo()` in order // to notice the defining usage of `Blah`. Node::Item(ref it) => locator.visit_item(it), Node::ImplItem(ref it) => locator.visit_impl_item(it), Node::TraitItem(ref it) => locator.visit_trait_item(it), </ins> other => bug!( "{:?} is not a valid scope for an existential type item", other

<ins> // Checks to ensure that we properly detect when a closure constrains an existential type #![feature(existential_type)] use std::fmt::Debug; fn main() { existential type Existential: Debug; fn _unused() -> Existential { String::new() } //~^ ERROR: concrete type differs from previous defining existential type use let null = || -> Existential { 0 }; println!("{:?}", null()); } </ins>

<ins> error: concrete type differs from previous defining existential type use --> $DIR/issue-52843-closure-constrain.rs:8:5 | LL |     fn _unused() -> Existential { String::new() } |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `std::string::String` | note: previous use here --> $DIR/issue-52843-closure-constrain.rs:6:1 | LL | / fn main() { LL | |     existential type Existential: Debug; LL | |     fn _unused() -> Existential { String::new() } LL | | LL | |     let null = || -> Existential { 0 }; LL | |     println!("{:?}", null()); LL | | } | |_^ error: aborting due to previous error </ins>