@@ -101,14 +101,14 @@ use rustc::infer::opaque_types::OpaqueTypeDecl;
101
101
use rustc:: infer:: type_variable:: { TypeVariableOrigin } ;
102
102
use rustc:: middle:: region;
103
103
use rustc:: mir:: interpret:: { ConstValue , GlobalId } ;
104
- use rustc:: ty:: subst:: { CanonicalUserSubsts , UnpackedKind , Subst , Substs ,
105
- UserSelfTy , UserSubsts } ;
106
104
use rustc:: traits:: { self , ObligationCause , ObligationCauseCode , TraitEngine } ;
107
105
use rustc:: ty:: { self , AdtKind , Ty , TyCtxt , GenericParamDefKind , RegionKind , Visibility ,
108
106
ToPolyTraitRef , ToPredicate } ;
109
107
use rustc:: ty:: adjustment:: { Adjust , Adjustment , AllowTwoPhase , AutoBorrow , AutoBorrowMutability } ;
110
108
use rustc:: ty:: fold:: TypeFoldable ;
111
109
use rustc:: ty:: query:: Providers ;
110
+ use rustc:: ty:: subst:: { CanonicalUserSubsts , UnpackedKind , Subst , Substs ,
111
+ UserSelfTy , UserSubsts } ;
112
112
use rustc:: ty:: util:: { Representability , IntTypeExt , Discr } ;
113
113
use rustc:: ty:: layout:: VariantIdx ;
114
114
use syntax_pos:: { self , BytePos , Span , MultiSpan } ;
@@ -4539,7 +4539,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4539
4539
Def :: Err
4540
4540
} ;
4541
4541
let ( ty, def) = AstConv :: associated_path_def_to_ty ( self , node_id, path_span,
4542
- ty, def, segment) ;
4542
+ ty, qself , def, segment) ;
4543
4543
4544
4544
// Write back the new resolution.
4545
4545
let hir_id = self . tcx . hir ( ) . node_to_hir_id ( node_id) ;
@@ -4558,14 +4558,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4558
4558
span : Span )
4559
4559
-> ( Def , Option < Ty < ' tcx > > , & ' b [ hir:: PathSegment ] )
4560
4560
{
4561
- let ( ty, item_segment) = match * qpath {
4561
+ let ( ty, ty_hir , item_segment) = match * qpath {
4562
4562
hir:: QPath :: Resolved ( ref opt_qself, ref path) => {
4563
4563
return ( path. def ,
4564
4564
opt_qself. as_ref ( ) . map ( |qself| self . to_ty ( qself) ) ,
4565
4565
& path. segments [ ..] ) ;
4566
4566
}
4567
4567
hir:: QPath :: TypeRelative ( ref qself, ref segment) => {
4568
- ( self . to_ty ( qself) , segment)
4568
+ ( self . to_ty ( qself) , qself , segment)
4569
4569
}
4570
4570
} ;
4571
4571
let hir_id = self . tcx . hir ( ) . node_to_hir_id ( node_id) ;
@@ -4575,7 +4575,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4575
4575
return ( * cached_def, Some ( ty) , slice:: from_ref ( & * * item_segment) )
4576
4576
}
4577
4577
let item_name = item_segment. ident ;
4578
- let def = match self . resolve_ufcs ( span, item_name, ty, node_id) {
4578
+ let def = match self . resolve_ufcs ( span, item_name, ty, ty_hir , node_id) {
4579
4579
Ok ( def) => def,
4580
4580
Err ( error) => {
4581
4581
let def = match error {
@@ -5042,6 +5042,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5042
5042
5043
5043
fn def_ids_for_path_segments ( & self ,
5044
5044
segments : & [ hir:: PathSegment ] ,
5045
+ self_ty : Option < Ty < ' tcx > > ,
5045
5046
def : Def )
5046
5047
-> Vec < PathSeg > {
5047
5048
// We need to extract the type parameters supplied by the user in
@@ -5053,15 +5054,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5053
5054
//
5054
5055
// There are basically four cases to consider:
5055
5056
//
5056
- // 1. Reference to a constructor of enum variant or struct:
5057
+ // 1. Reference to a constructor of a struct:
5057
5058
//
5058
5059
// struct Foo<T>(...)
5060
+ //
5061
+ // In this case, the parameters are declared in the type space.
5062
+ //
5063
+ // 2. Reference to a constructor of an enum variant:
5064
+ //
5059
5065
// enum E<T> { Foo(...) }
5060
5066
//
5061
- // In these cases , the parameters are declared in the type
5062
- // space .
5067
+ // In this case , the parameters are defined in the type space,
5068
+ // but may be specified either on the type or the variant .
5063
5069
//
5064
- // 2 . Reference to a fn item or a free constant:
5070
+ // 3 . Reference to a fn item or a free constant:
5065
5071
//
5066
5072
// fn foo<T>() { }
5067
5073
//
@@ -5070,7 +5076,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5070
5076
// type parameters. However, in this case, those parameters are
5071
5077
// declared on a value, and hence are in the `FnSpace`.
5072
5078
//
5073
- // 3 . Reference to a method or an associated constant:
5079
+ // 4 . Reference to a method or an associated constant:
5074
5080
//
5075
5081
// impl<A> SomeStruct<A> {
5076
5082
// fn foo<B>(...)
@@ -5082,7 +5088,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5082
5088
// `SomeStruct::<A>`, contains parameters in TypeSpace, and the
5083
5089
// final segment, `foo::<B>` contains parameters in fn space.
5084
5090
//
5085
- // 4 . Reference to a local variable
5091
+ // 5 . Reference to a local variable
5086
5092
//
5087
5093
// Local variables can't have any type parameters.
5088
5094
//
@@ -5094,9 +5100,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5094
5100
let mut path_segs = vec ! [ ] ;
5095
5101
5096
5102
match def {
5097
- // Case 1. Reference to a struct/variant constructor.
5103
+ // Case 1. Reference to a struct constructor.
5098
5104
Def :: StructCtor ( def_id, ..) |
5099
- Def :: VariantCtor ( def_id, ..) |
5100
5105
Def :: SelfCtor ( .., def_id) => {
5101
5106
// Everything but the final segment should have no
5102
5107
// parameters at all.
@@ -5107,14 +5112,49 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5107
5112
path_segs. push ( PathSeg ( generics_def_id, last) ) ;
5108
5113
}
5109
5114
5110
- // Case 2. Reference to a top-level value.
5115
+ // Case 2. Reference to a variant constructor.
5116
+ Def :: VariantCtor ( def_id, ..) => {
5117
+ if tcx. features ( ) . type_alias_enum_variants {
5118
+ let adt_def = self_ty. and_then ( |t| t. ty_adt_def ( ) ) ;
5119
+ let ( generics_def_id, index) = if let Some ( adt_def) = adt_def {
5120
+ debug_assert ! ( adt_def. is_enum( ) ) ;
5121
+ ( adt_def. did , last)
5122
+ } else if last >= 1 && segments[ last - 1 ] . args . is_some ( ) {
5123
+ // Everything but the penultimate segment should have no
5124
+ // parameters at all.
5125
+ let enum_def_id = self . tcx . parent_def_id ( def_id) . unwrap ( ) ;
5126
+ ( enum_def_id, last - 1 )
5127
+ } else {
5128
+ // FIXME: lint here suggesting `Enum::<...>::Variant` form
5129
+ // instead of `Enum::Variant::<...>` form.
5130
+
5131
+ // Everything but the final segment should have no
5132
+ // parameters at all.
5133
+ let generics = self . tcx . generics_of ( def_id) ;
5134
+ // Variant and struct constructors use the
5135
+ // generics of their parent type definition.
5136
+ ( generics. parent . unwrap_or ( def_id) , last)
5137
+ } ;
5138
+ path_segs. push ( PathSeg ( generics_def_id, index) ) ;
5139
+ } else {
5140
+ // Everything but the final segment should have no
5141
+ // parameters at all.
5142
+ let generics = self . tcx . generics_of ( def_id) ;
5143
+ // Variant and struct constructors use the
5144
+ // generics of their parent type definition.
5145
+ let generics_def_id = generics. parent . unwrap_or ( def_id) ;
5146
+ path_segs. push ( PathSeg ( generics_def_id, last) ) ;
5147
+ }
5148
+ }
5149
+
5150
+ // Case 3. Reference to a top-level value.
5111
5151
Def :: Fn ( def_id) |
5112
5152
Def :: Const ( def_id) |
5113
5153
Def :: Static ( def_id, _) => {
5114
5154
path_segs. push ( PathSeg ( def_id, last) ) ;
5115
5155
}
5116
5156
5117
- // Case 3 . Reference to a method or associated const.
5157
+ // Case 4 . Reference to a method or associated const.
5118
5158
Def :: Method ( def_id) |
5119
5159
Def :: AssociatedConst ( def_id) => {
5120
5160
if segments. len ( ) >= 2 {
@@ -5124,7 +5164,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5124
5164
path_segs. push ( PathSeg ( def_id, last) ) ;
5125
5165
}
5126
5166
5127
- // Case 4 . Local variable, no generics.
5167
+ // Case 5 . Local variable, no generics.
5128
5168
Def :: Local ( ..) | Def :: Upvar ( ..) => { }
5129
5169
5130
5170
_ => bug ! ( "unexpected definition: {:?}" , def) ,
@@ -5152,7 +5192,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5152
5192
node_id,
5153
5193
) ;
5154
5194
5155
- let path_segs = self . def_ids_for_path_segments ( segments, def) ;
5195
+ let path_segs = self . def_ids_for_path_segments ( segments, self_ty , def) ;
5156
5196
5157
5197
let mut user_self_ty = None ;
5158
5198
match def {
@@ -5187,10 +5227,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5187
5227
// provided (if any) into their appropriate spaces. We'll also report
5188
5228
// errors if type parameters are provided in an inappropriate place.
5189
5229
5190
- let generic_segs = path_segs. iter ( ) . map ( |PathSeg ( _, index) | index)
5191
- . collect :: < FxHashSet < _ > > ( ) ;
5230
+ let is_alias_variant_ctor = if tcx. features ( ) . type_alias_enum_variants {
5231
+ match def {
5232
+ Def :: VariantCtor ( _, _) if self_ty. is_some ( ) => true ,
5233
+ _ => false ,
5234
+ } ;
5235
+ } else {
5236
+ false
5237
+ } ;
5238
+
5239
+ let generic_segs: FxHashSet < _ > = path_segs. iter ( ) . map ( |PathSeg ( _, index) | index) . collect ( ) ;
5192
5240
AstConv :: prohibit_generics ( self , segments. iter ( ) . enumerate ( ) . filter_map ( |( index, seg) | {
5193
- if !generic_segs. contains ( & index) {
5241
+ if !generic_segs. contains ( & index) || is_alias_variant_ctor {
5194
5242
Some ( seg)
5195
5243
} else {
5196
5244
None
@@ -5274,6 +5322,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5274
5322
}
5275
5323
}
5276
5324
}
5325
+ Def :: VariantCtor ( _, _) if self_ty. is_some ( ) => {
5326
+ let def_id = def. def_id ( ) ;
5327
+
5328
+ let ty = self . tcx . type_of ( def_id) ;
5329
+ if tcx. features ( ) . type_alias_enum_variants {
5330
+ if let Some ( self_ty) = self_ty {
5331
+ match ty. ty_adt_def ( ) {
5332
+ Some ( adt_def) if adt_def. is_enum ( ) => {
5333
+ return ( self_ty, def) ;
5334
+ }
5335
+ _ => { }
5336
+ }
5337
+ }
5338
+ }
5339
+ ( def_id, ty)
5340
+ }
5277
5341
_ => {
5278
5342
let def_id = def. def_id ( ) ;
5279
5343
0 commit comments