@@ -653,6 +653,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
653
653
let tcx = self . infcx . tcx ;
654
654
value. fold_with ( & mut BottomUpFolder {
655
655
tcx,
656
+ reg_op : |reg| reg,
656
657
fldop : |ty| {
657
658
if let ty:: TyAnon ( def_id, substs) = ty. sty {
658
659
// Check that this is `impl Trait` type is
@@ -690,26 +691,35 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
690
691
// }
691
692
// ```
692
693
if let Some ( anon_node_id) = tcx. hir . as_local_node_id ( def_id) {
693
- let anon_parent_def_id = match tcx. hir . expect_item ( anon_node_id) . node {
694
+ let in_definition_scope = match tcx. hir . expect_item ( anon_node_id) . node {
695
+ // impl trait
694
696
hir:: ItemKind :: Existential ( hir:: ExistTy {
695
697
impl_trait_fn : Some ( parent) ,
696
698
..
697
- } ) => parent,
699
+ } ) => parent == self . parent_def_id ,
700
+ // named existential types
701
+ hir:: ItemKind :: Existential ( hir:: ExistTy {
702
+ impl_trait_fn : None ,
703
+ ..
704
+ } ) => may_define_existential_type (
705
+ tcx,
706
+ self . parent_def_id ,
707
+ anon_node_id,
708
+ ) ,
698
709
_ => {
699
710
let anon_parent_node_id = tcx. hir . get_parent ( anon_node_id) ;
700
- tcx. hir . local_def_id ( anon_parent_node_id)
711
+ self . parent_def_id == tcx. hir . local_def_id ( anon_parent_node_id)
701
712
} ,
702
713
} ;
703
- if self . parent_def_id == anon_parent_def_id {
714
+ if in_definition_scope {
704
715
return self . fold_anon_ty ( ty, def_id, substs) ;
705
716
}
706
717
707
718
debug ! (
708
719
"instantiate_anon_types_in_map: \
709
- encountered anon with wrong parent \
710
- def_id={:?} \
711
- anon_parent_def_id={:?}",
712
- def_id, anon_parent_def_id
720
+ encountered anon outside it's definition scope \
721
+ def_id={:?}",
722
+ def_id,
713
723
) ;
714
724
}
715
725
}
@@ -742,6 +752,10 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
742
752
let ty_var = infcx. next_ty_var ( TypeVariableOrigin :: TypeInference ( span) ) ;
743
753
744
754
let predicates_of = tcx. predicates_of ( def_id) ;
755
+ debug ! (
756
+ "instantiate_anon_types: predicates: {:#?}" ,
757
+ predicates_of,
758
+ ) ;
745
759
let bounds = predicates_of. instantiate ( tcx, substs) ;
746
760
debug ! ( "instantiate_anon_types: bounds={:?}" , bounds) ;
747
761
@@ -751,6 +765,18 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
751
765
required_region_bounds
752
766
) ;
753
767
768
+ // make sure that we are in fact defining the *entire* type
769
+ // e.g. `existential type Foo<T: Bound>: Bar;` needs to be
770
+ // defined by a function like `fn foo<T: Bound>() -> Foo<T>`.
771
+ debug ! (
772
+ "instantiate_anon_types: param_env: {:#?}" ,
773
+ self . param_env,
774
+ ) ;
775
+ debug ! (
776
+ "instantiate_anon_types: generics: {:#?}" ,
777
+ tcx. generics_of( def_id) ,
778
+ ) ;
779
+
754
780
self . anon_types . insert (
755
781
def_id,
756
782
AnonTypeDecl {
@@ -778,3 +804,42 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
778
804
ty_var
779
805
}
780
806
}
807
+
808
+ /// Whether `anon_node_id` is a sibling or a child of a sibling of `def_id`
809
+ ///
810
+ /// ```rust
811
+ /// pub mod foo {
812
+ /// pub mod bar {
813
+ /// pub existential type Baz;
814
+ ///
815
+ /// fn f1() -> Baz { .. }
816
+ /// }
817
+ ///
818
+ /// fn f2() -> bar::Baz { .. }
819
+ /// }
820
+ /// ```
821
+ ///
822
+ /// Here, `def_id` will be the `DefId` of the existential type `Baz`.
823
+ /// `anon_node_id` is the `NodeId` of the reference to Baz -- so either the return type of f1 or f2.
824
+ /// We will return true if the reference is within the same module as the existential type
825
+ /// So true for f1, false for f2.
826
+ pub fn may_define_existential_type (
827
+ tcx : TyCtxt ,
828
+ def_id : DefId ,
829
+ anon_node_id : ast:: NodeId ,
830
+ ) -> bool {
831
+ let mut node_id = tcx
832
+ . hir
833
+ . as_local_node_id ( def_id)
834
+ . unwrap ( ) ;
835
+ // named existential types can be defined by any siblings or
836
+ // children of siblings
837
+ let mod_id = tcx. hir . get_parent ( anon_node_id) ;
838
+ // so we walk up the node tree until we hit the root or the parent
839
+ // of the anon type
840
+ while node_id != mod_id && node_id != ast:: CRATE_NODE_ID {
841
+ node_id = tcx. hir . get_parent ( node_id) ;
842
+ }
843
+ // syntactically we are allowed to define the concrete type
844
+ node_id == mod_id
845
+ }
0 commit comments