Skip to content

Commit c7cba3d

Browse files
committed
Auto merge of #52024 - oli-obk:existential_parse, r=nikomatsakis
Implement existential types (not for associated types yet) r? @nikomatsakis cc @Centril @varkor @alexreg
2 parents 11864c4 + 9017f79 commit c7cba3d

File tree

216 files changed

+2028
-146
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

216 files changed

+2028
-146
lines changed

src/librustc/hir/def.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@ pub enum Def {
3737
Enum(DefId),
3838
Variant(DefId),
3939
Trait(DefId),
40+
/// `existential type Foo: Bar;`
4041
Existential(DefId),
42+
/// `type Foo = Bar;`
4143
TyAlias(DefId),
4244
TyForeign(DefId),
4345
TraitAlias(DefId),
4446
AssociatedTy(DefId),
47+
/// `existential type Foo: Bar;`
48+
AssociatedExistential(DefId),
4549
PrimTy(hir::PrimTy),
4650
TyParam(DefId),
4751
SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
@@ -245,7 +249,7 @@ impl Def {
245249
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
246250
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
247251
Def::AssociatedConst(id) | Def::Macro(id, ..) |
248-
Def::Existential(id) |
252+
Def::Existential(id) | Def::AssociatedExistential(id) |
249253
Def::GlobalAsm(id) | Def::TyForeign(id) => {
250254
id
251255
}
@@ -276,6 +280,7 @@ impl Def {
276280
Def::TyAlias(..) => "type alias",
277281
Def::TraitAlias(..) => "trait alias",
278282
Def::AssociatedTy(..) => "associated type",
283+
Def::AssociatedExistential(..) => "associated existential type",
279284
Def::Struct(..) => "struct",
280285
Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
281286
Def::StructCtor(.., CtorKind::Const) => "unit struct",

src/librustc/hir/intravisit.rs

+4
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
907907
visitor.visit_id(impl_item.id);
908908
visitor.visit_ty(ty);
909909
}
910+
ImplItemKind::Existential(ref bounds) => {
911+
visitor.visit_id(impl_item.id);
912+
walk_list!(visitor, visit_param_bound, bounds);
913+
}
910914
}
911915
}
912916

src/librustc/hir/lowering.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ impl<'a> LoweringContext<'a> {
323323
| ItemKind::Union(_, ref generics)
324324
| ItemKind::Enum(_, ref generics)
325325
| ItemKind::Ty(_, ref generics)
326+
| ItemKind::Existential(_, ref generics)
326327
| ItemKind::Trait(_, _, ref generics, ..) => {
327328
let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
328329
let count = generics
@@ -2632,6 +2633,11 @@ impl<'a> LoweringContext<'a> {
26322633
self.lower_ty(t, ImplTraitContext::Disallowed),
26332634
self.lower_generics(generics, ImplTraitContext::Disallowed),
26342635
),
2636+
ItemKind::Existential(ref b, ref generics) => hir::ItemKind::Existential(hir::ExistTy {
2637+
generics: self.lower_generics(generics, ImplTraitContext::Disallowed),
2638+
bounds: self.lower_param_bounds(b, ImplTraitContext::Disallowed),
2639+
impl_trait_fn: None,
2640+
}),
26352641
ItemKind::Enum(ref enum_definition, ref generics) => hir::ItemKind::Enum(
26362642
hir::EnumDef {
26372643
variants: enum_definition
@@ -3037,6 +3043,12 @@ impl<'a> LoweringContext<'a> {
30373043
self.lower_generics(&i.generics, ImplTraitContext::Disallowed),
30383044
hir::ImplItemKind::Type(self.lower_ty(ty, ImplTraitContext::Disallowed)),
30393045
),
3046+
ImplItemKind::Existential(ref bounds) => (
3047+
self.lower_generics(&i.generics, ImplTraitContext::Disallowed),
3048+
hir::ImplItemKind::Existential(
3049+
self.lower_param_bounds(bounds, ImplTraitContext::Disallowed),
3050+
),
3051+
),
30403052
ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
30413053
};
30423054

@@ -3065,6 +3077,7 @@ impl<'a> LoweringContext<'a> {
30653077
kind: match i.node {
30663078
ImplItemKind::Const(..) => hir::AssociatedItemKind::Const,
30673079
ImplItemKind::Type(..) => hir::AssociatedItemKind::Type,
3080+
ImplItemKind::Existential(..) => hir::AssociatedItemKind::Existential,
30683081
ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method {
30693082
has_self: sig.decl.has_self(),
30703083
},
@@ -4335,7 +4348,7 @@ impl<'a> LoweringContext<'a> {
43354348
respan(v.span, node)
43364349
}
43374350

4338-
fn lower_defaultness(&mut self, d: Defaultness, has_value: bool) -> hir::Defaultness {
4351+
fn lower_defaultness(&self, d: Defaultness, has_value: bool) -> hir::Defaultness {
43394352
match d {
43404353
Defaultness::Default => hir::Defaultness::Default {
43414354
has_value: has_value,

src/librustc/hir/map/def_collector.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
116116
ItemKind::Impl(..) => DefPathData::Impl,
117117
ItemKind::Trait(..) => DefPathData::Trait(i.ident.as_interned_str()),
118118
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
119-
ItemKind::TraitAlias(..) |
119+
ItemKind::TraitAlias(..) | ItemKind::Existential(..) |
120120
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
121121
DefPathData::TypeNs(i.ident.as_interned_str()),
122122
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
@@ -250,6 +250,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
250250
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
251251
DefPathData::ValueNs(ii.ident.as_interned_str()),
252252
ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.as_interned_str()),
253+
ImplItemKind::Existential(..) => {
254+
DefPathData::AssocExistentialInImpl(ii.ident.as_interned_str())
255+
},
253256
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
254257
};
255258

src/librustc/hir/map/definitions.rs

+4
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ pub enum DefPathData {
330330
AssocTypeInTrait(InternedString),
331331
/// An associated type **value** (i.e., in an impl)
332332
AssocTypeInImpl(InternedString),
333+
/// An existential associated type **value** (i.e., in an impl)
334+
AssocExistentialInImpl(InternedString),
333335
/// Something in the type NS
334336
TypeNs(InternedString),
335337
/// Something in the value NS
@@ -605,6 +607,7 @@ impl DefPathData {
605607
Trait(name) |
606608
AssocTypeInTrait(name) |
607609
AssocTypeInImpl(name) |
610+
AssocExistentialInImpl(name) |
608611
ValueNs(name) |
609612
Module(name) |
610613
MacroDef(name) |
@@ -631,6 +634,7 @@ impl DefPathData {
631634
Trait(name) |
632635
AssocTypeInTrait(name) |
633636
AssocTypeInImpl(name) |
637+
AssocExistentialInImpl(name) |
634638
ValueNs(name) |
635639
Module(name) |
636640
MacroDef(name) |

src/librustc/hir/map/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ impl<'hir> Map<'hir> {
470470
ImplItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
471471
ImplItemKind::Method(..) => Some(Def::Method(def_id)),
472472
ImplItemKind::Type(..) => Some(Def::AssociatedTy(def_id)),
473+
ImplItemKind::Existential(..) => Some(Def::AssociatedExistential(def_id)),
473474
}
474475
}
475476
NodeVariant(variant) => {
@@ -1323,7 +1324,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
13231324
ItemKind::ForeignMod(..) => "foreign mod",
13241325
ItemKind::GlobalAsm(..) => "global asm",
13251326
ItemKind::Ty(..) => "ty",
1326-
ItemKind::Existential(..) => "existential",
1327+
ItemKind::Existential(..) => "existential type",
13271328
ItemKind::Enum(..) => "enum",
13281329
ItemKind::Struct(..) => "struct",
13291330
ItemKind::Union(..) => "union",
@@ -1347,6 +1348,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
13471348
ImplItemKind::Type(_) => {
13481349
format!("assoc type {} in {}{}", ii.ident, path_str(), id_str)
13491350
}
1351+
ImplItemKind::Existential(_) => {
1352+
format!("assoc existential type {} in {}{}", ii.ident, path_str(), id_str)
1353+
}
13501354
}
13511355
}
13521356
Some(NodeTraitItem(ti)) => {

src/librustc/hir/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,8 @@ pub enum ImplItemKind {
16201620
Method(MethodSig, BodyId),
16211621
/// An associated type
16221622
Type(P<Ty>),
1623+
/// An associated existential type
1624+
Existential(GenericBounds),
16231625
}
16241626

16251627
// Bind a type to an associated type: `A=Foo`.
@@ -2080,7 +2082,7 @@ pub enum ItemKind {
20802082
GlobalAsm(P<GlobalAsm>),
20812083
/// A type alias, e.g. `type Foo = Bar<u8>`
20822084
Ty(P<Ty>, Generics),
2083-
/// A type alias, e.g. `type Foo = Bar<u8>`
2085+
/// An existential type definition, e.g. `existential type Foo: Bar;`
20842086
Existential(ExistTy),
20852087
/// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
20862088
Enum(EnumDef, Generics),
@@ -2138,6 +2140,7 @@ impl ItemKind {
21382140
Some(match *self {
21392141
ItemKind::Fn(_, _, ref generics, _) |
21402142
ItemKind::Ty(_, ref generics) |
2143+
ItemKind::Existential(ExistTy { ref generics, impl_trait_fn: None, .. }) |
21412144
ItemKind::Enum(_, ref generics) |
21422145
ItemKind::Struct(_, ref generics) |
21432146
ItemKind::Union(_, ref generics) |
@@ -2184,6 +2187,7 @@ pub enum AssociatedItemKind {
21842187
Const,
21852188
Method { has_self: bool },
21862189
Type,
2190+
Existential,
21872191
}
21882192

21892193
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]

src/librustc/hir/print.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -627,9 +627,7 @@ impl<'a> State<'a> {
627627
self.end()?
628628
}
629629
hir::ItemKind::Ty(ref ty, ref generics) => {
630-
self.ibox(indent_unit)?;
631-
self.ibox(0)?;
632-
self.word_nbsp(&visibility_qualified(&item.vis, "type"))?;
630+
self.head(&visibility_qualified(&item.vis, "type"))?;
633631
self.print_name(item.name)?;
634632
self.print_generic_params(&generics.params)?;
635633
self.end()?; // end the inner ibox
@@ -642,9 +640,7 @@ impl<'a> State<'a> {
642640
self.end()?; // end the outer ibox
643641
}
644642
hir::ItemKind::Existential(ref exist) => {
645-
self.ibox(indent_unit)?;
646-
self.ibox(0)?;
647-
self.word_nbsp(&visibility_qualified(&item.vis, "existential type"))?;
643+
self.head(&visibility_qualified(&item.vis, "existential type"))?;
648644
self.print_name(item.name)?;
649645
self.print_generic_params(&exist.generics.params)?;
650646
self.end()?; // end the inner ibox
@@ -994,6 +990,10 @@ impl<'a> State<'a> {
994990
hir::ImplItemKind::Type(ref ty) => {
995991
self.print_associated_type(ii.ident, None, Some(ty))?;
996992
}
993+
hir::ImplItemKind::Existential(ref bounds) => {
994+
self.word_space("existential")?;
995+
self.print_associated_type(ii.ident, Some(bounds), None)?;
996+
}
997997
}
998998
self.ann.post(self, NodeSubItem(ii.id))
999999
}

src/librustc/ich/impls_hir.rs

+3
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem {
701701
impl_stable_hash_for!(enum hir::ImplItemKind {
702702
Const(t, body),
703703
Method(sig, body),
704+
Existential(bounds),
704705
Type(t)
705706
});
706707

@@ -890,6 +891,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::AssociatedItemKind {
890891
mem::discriminant(self).hash_stable(hcx, hasher);
891892
match *self {
892893
hir::AssociatedItemKind::Const |
894+
hir::AssociatedItemKind::Existential |
893895
hir::AssociatedItemKind::Type => {
894896
// No fields to hash.
895897
}
@@ -997,6 +999,7 @@ impl_stable_hash_for!(enum hir::def::Def {
997999
TyAlias(def_id),
9981000
TraitAlias(def_id),
9991001
AssociatedTy(def_id),
1002+
AssociatedExistential(def_id),
10001003
PrimTy(prim_ty),
10011004
TyParam(def_id),
10021005
SelfTy(trait_def_id, impl_def_id),

src/librustc/ich/impls_ty.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,7 @@ impl_stable_hash_for!(struct ty::AssociatedItem {
10551055
impl_stable_hash_for!(enum ty::AssociatedKind {
10561056
Const,
10571057
Method,
1058+
Existential,
10581059
Type
10591060
});
10601061

src/librustc/infer/anon_types/mod.rs

+73-8
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
653653
let tcx = self.infcx.tcx;
654654
value.fold_with(&mut BottomUpFolder {
655655
tcx,
656+
reg_op: |reg| reg,
656657
fldop: |ty| {
657658
if let ty::TyAnon(def_id, substs) = ty.sty {
658659
// Check that this is `impl Trait` type is
@@ -690,26 +691,35 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
690691
// }
691692
// ```
692693
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
694696
hir::ItemKind::Existential(hir::ExistTy {
695697
impl_trait_fn: Some(parent),
696698
..
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+
),
698709
_ => {
699710
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)
701712
},
702713
};
703-
if self.parent_def_id == anon_parent_def_id {
714+
if in_definition_scope {
704715
return self.fold_anon_ty(ty, def_id, substs);
705716
}
706717

707718
debug!(
708719
"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,
713723
);
714724
}
715725
}
@@ -742,6 +752,10 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
742752
let ty_var = infcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
743753

744754
let predicates_of = tcx.predicates_of(def_id);
755+
debug!(
756+
"instantiate_anon_types: predicates: {:#?}",
757+
predicates_of,
758+
);
745759
let bounds = predicates_of.instantiate(tcx, substs);
746760
debug!("instantiate_anon_types: bounds={:?}", bounds);
747761

@@ -751,6 +765,18 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
751765
required_region_bounds
752766
);
753767

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+
754780
self.anon_types.insert(
755781
def_id,
756782
AnonTypeDecl {
@@ -778,3 +804,42 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
778804
ty_var
779805
}
780806
}
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+
}

src/librustc/infer/error_reporting/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
279279
fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str {
280280
match item.node {
281281
hir::ImplItemKind::Method(..) => "method body",
282-
hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) => "associated item",
282+
hir::ImplItemKind::Const(..) |
283+
hir::ImplItemKind::Existential(..) |
284+
hir::ImplItemKind::Type(..) => "associated item",
283285
}
284286
}
285287

0 commit comments

Comments
 (0)