@@ -113,7 +113,7 @@ use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, NodeMap};
113
113
114
114
use std:: cell:: { Cell , RefCell , Ref , RefMut } ;
115
115
use rustc_data_structures:: sync:: Lrc ;
116
- use std:: collections:: hash_map:: Entry ;
116
+ use std:: collections:: { hash_map:: Entry , HashSet } ;
117
117
use std:: cmp;
118
118
use std:: fmt:: Display ;
119
119
use std:: iter;
@@ -505,6 +505,9 @@ impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> {
505
505
}
506
506
}
507
507
508
+ #[ derive( Debug ) ]
509
+ struct PathSeg ( DefId , usize ) ;
510
+
508
511
pub struct FnCtxt < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
509
512
body_id : ast:: NodeId ,
510
513
@@ -4770,20 +4773,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4770
4773
err. span_suggestion ( span_semi, "consider removing this semicolon" , "" . to_string ( ) ) ;
4771
4774
}
4772
4775
4773
- // Instantiates the given path, which must refer to an item with the given
4774
- // number of type parameters and type.
4775
- pub fn instantiate_value_path ( & self ,
4776
- segments : & [ hir:: PathSegment ] ,
4777
- opt_self_ty : Option < Ty < ' tcx > > ,
4778
- def : Def ,
4779
- span : Span ,
4780
- node_id : ast:: NodeId )
4781
- -> Ty < ' tcx > {
4782
- debug ! ( "instantiate_value_path(path={:?}, def={:?}, node_id={})" ,
4783
- segments,
4784
- def,
4785
- node_id) ;
4786
-
4776
+ fn def_ids_for_path_segments ( & self ,
4777
+ segments : & [ hir:: PathSegment ] ,
4778
+ def : Def )
4779
+ -> Vec < PathSeg > {
4787
4780
// We need to extract the type parameters supplied by the user in
4788
4781
// the path `path`. Due to the current setup, this is a bit of a
4789
4782
// tricky-process; the problem is that resolve only tells us the
@@ -4829,33 +4822,69 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4829
4822
// The first step then is to categorize the segments appropriately.
4830
4823
4831
4824
assert ! ( !segments. is_empty( ) ) ;
4825
+ let last = segments. len ( ) - 1 ;
4826
+
4827
+ let mut path_segs = vec ! [ ] ;
4832
4828
4833
- let mut ufcs_associated = None ;
4834
- let mut type_segment = None ;
4835
- let mut fn_segment = None ;
4836
4829
match def {
4837
4830
// Case 1. Reference to a struct/variant constructor.
4838
4831
Def :: StructCtor ( def_id, ..) |
4839
4832
Def :: VariantCtor ( def_id, ..) => {
4840
4833
// Everything but the final segment should have no
4841
4834
// parameters at all.
4842
4835
let mut generics = self . tcx . generics_of ( def_id) ;
4843
- if let Some ( def_id) = generics. parent {
4844
- // Variant and struct constructors use the
4845
- // generics of their parent type definition.
4846
- generics = self . tcx . generics_of ( def_id) ;
4847
- }
4848
- type_segment = Some ( ( segments. last ( ) . unwrap ( ) , generics) ) ;
4836
+ // Variant and struct constructors use the
4837
+ // generics of their parent type definition.
4838
+ let generics_def_id = generics. parent . unwrap_or ( def_id) ;
4839
+ path_segs. push ( PathSeg ( generics_def_id, last) ) ;
4849
4840
}
4850
4841
4851
4842
// Case 2. Reference to a top-level value.
4852
4843
Def :: Fn ( def_id) |
4853
4844
Def :: Const ( def_id) |
4854
4845
Def :: Static ( def_id, _) => {
4855
- fn_segment = Some ( ( segments . last ( ) . unwrap ( ) , self . tcx . generics_of ( def_id ) ) ) ;
4846
+ path_segs . push ( PathSeg ( def_id , last ) ) ;
4856
4847
}
4857
4848
4858
4849
// Case 3. Reference to a method or associated const.
4850
+ Def :: Method ( def_id) |
4851
+ Def :: AssociatedConst ( def_id) => {
4852
+ if segments. len ( ) >= 2 {
4853
+ let generics = self . tcx . generics_of ( def_id) ;
4854
+ path_segs. push ( PathSeg ( generics. parent . unwrap ( ) , last - 1 ) ) ;
4855
+ }
4856
+ path_segs. push ( PathSeg ( def_id, last) ) ;
4857
+ }
4858
+
4859
+ // Case 4. Local variable, no generics.
4860
+ Def :: Local ( ..) | Def :: Upvar ( ..) => { }
4861
+
4862
+ _ => bug ! ( "unexpected definition: {:?}" , def) ,
4863
+ }
4864
+
4865
+ debug ! ( "path_segs = {:?}" , path_segs) ;
4866
+
4867
+ path_segs
4868
+ }
4869
+
4870
+ // Instantiates the given path, which must refer to an item with the given
4871
+ // number of type parameters and type.
4872
+ pub fn instantiate_value_path ( & self ,
4873
+ segments : & [ hir:: PathSegment ] ,
4874
+ opt_self_ty : Option < Ty < ' tcx > > ,
4875
+ def : Def ,
4876
+ span : Span ,
4877
+ node_id : ast:: NodeId )
4878
+ -> Ty < ' tcx > {
4879
+ debug ! ( "instantiate_value_path(path={:?}, def={:?}, node_id={})" ,
4880
+ segments,
4881
+ def,
4882
+ node_id) ;
4883
+
4884
+ let path_segs = self . def_ids_for_path_segments ( segments, def) ;
4885
+
4886
+ let mut ufcs_associated = None ;
4887
+ match def {
4859
4888
Def :: Method ( def_id) |
4860
4889
Def :: AssociatedConst ( def_id) => {
4861
4890
let container = self . tcx . associated_item ( def_id) . container ;
@@ -4865,34 +4894,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4865
4894
}
4866
4895
ty:: ImplContainer ( _) => { }
4867
4896
}
4868
-
4869
- let generics = self . tcx . generics_of ( def_id) ;
4870
- if segments. len ( ) >= 2 {
4871
- let parent_generics = self . tcx . generics_of ( generics. parent . unwrap ( ) ) ;
4872
- type_segment = Some ( ( & segments[ segments. len ( ) - 2 ] , parent_generics) ) ;
4873
- } else {
4897
+ if segments. len ( ) == 1 {
4874
4898
// `<T>::assoc` will end up here, and so can `T::assoc`.
4875
4899
let self_ty = opt_self_ty. expect ( "UFCS sugared assoc missing Self" ) ;
4876
4900
ufcs_associated = Some ( ( container, self_ty) ) ;
4877
4901
}
4878
- fn_segment = Some ( ( segments. last ( ) . unwrap ( ) , generics) ) ;
4879
4902
}
4880
-
4881
- // Case 4. Local variable, no generics.
4882
- Def :: Local ( ..) | Def :: Upvar ( ..) => { }
4883
-
4884
- _ => bug ! ( "unexpected definition: {:?}" , def) ,
4903
+ _ => { }
4885
4904
}
4886
4905
4887
- debug ! ( "type_segment={:?} fn_segment={:?}" , type_segment, fn_segment) ;
4888
-
4889
4906
// Now that we have categorized what space the parameters for each
4890
4907
// segment belong to, let's sort out the parameters that the user
4891
4908
// provided (if any) into their appropriate spaces. We'll also report
4892
4909
// errors if type parameters are provided in an inappropriate place.
4893
- let poly_segments = type_segment. is_some ( ) as usize +
4894
- fn_segment. is_some ( ) as usize ;
4895
- AstConv :: prohibit_generics ( self , & segments[ ..segments. len ( ) - poly_segments] ) ;
4910
+ let mut generic_segs = HashSet :: new ( ) ;
4911
+ for PathSeg ( _, index) in & path_segs {
4912
+ generic_segs. insert ( index) ;
4913
+ }
4914
+ let segs: Vec < _ > = segments
4915
+ . iter ( )
4916
+ . enumerate ( )
4917
+ . filter_map ( |( index, seg) | {
4918
+ if !generic_segs. contains ( & index) {
4919
+ Some ( seg)
4920
+ } else {
4921
+ None
4922
+ }
4923
+ } )
4924
+ . cloned ( )
4925
+ . collect ( ) ;
4926
+ AstConv :: prohibit_generics ( self , & segs) ;
4896
4927
4897
4928
match def {
4898
4929
Def :: Local ( nid) | Def :: Upvar ( nid, ..) => {
@@ -4904,24 +4935,66 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4904
4935
_ => { }
4905
4936
}
4906
4937
4938
+ let mut type_segment = None ;
4939
+ let mut fn_segment = None ;
4940
+ match def {
4941
+ // Case 1. Reference to a struct/variant constructor.
4942
+ Def :: StructCtor ( def_id, ..) |
4943
+ Def :: VariantCtor ( def_id, ..) => {
4944
+ // Everything but the final segment should have no
4945
+ // parameters at all.
4946
+ let mut generics = self . tcx . generics_of ( def_id) ;
4947
+ if let Some ( def_id) = generics. parent {
4948
+ // Variant and struct constructors use the
4949
+ // generics of their parent type definition.
4950
+ generics = self . tcx . generics_of ( def_id) ;
4951
+ }
4952
+ type_segment = Some ( ( segments. last ( ) . unwrap ( ) , generics) ) ;
4953
+ }
4954
+
4955
+ // Case 2. Reference to a top-level value.
4956
+ Def :: Fn ( def_id) |
4957
+ Def :: Const ( def_id) |
4958
+ Def :: Static ( def_id, _) => {
4959
+ fn_segment = Some ( ( segments. last ( ) . unwrap ( ) , self . tcx . generics_of ( def_id) ) ) ;
4960
+ }
4961
+
4962
+ // Case 3. Reference to a method or associated const.
4963
+ Def :: Method ( def_id) |
4964
+ Def :: AssociatedConst ( def_id) => {
4965
+ let generics = self . tcx . generics_of ( def_id) ;
4966
+ if segments. len ( ) >= 2 {
4967
+ let parent_generics = self . tcx . generics_of ( generics. parent . unwrap ( ) ) ;
4968
+ type_segment = Some ( ( & segments[ segments. len ( ) - 2 ] , parent_generics) ) ;
4969
+ }
4970
+ fn_segment = Some ( ( segments. last ( ) . unwrap ( ) , generics) ) ;
4971
+ }
4972
+
4973
+ _ => { }
4974
+ }
4975
+
4976
+ debug ! ( "type_segment={:?} fn_segment={:?}" , type_segment, fn_segment) ;
4977
+
4907
4978
// Now we have to compare the types that the user *actually*
4908
4979
// provided against the types that were *expected*. If the user
4909
4980
// did not provide any types, then we want to substitute inference
4910
4981
// variables. If the user provided some types, we may still need
4911
4982
// to add defaults. If the user provided *too many* types, that's
4912
4983
// a problem.
4913
4984
let supress_mismatch = self . check_impl_trait ( span, fn_segment) ;
4914
- self . check_generic_arg_count ( span, & mut type_segment, false , supress_mismatch) ;
4915
- self . check_generic_arg_count ( span, & mut fn_segment, false , supress_mismatch) ;
4985
+ for & PathSeg ( def_id, index) in & path_segs {
4986
+ let generics = self . tcx . generics_of ( def_id) ;
4987
+ self . check_generic_arg_count ( span, & segments[ index] , & generics, false , supress_mismatch) ;
4988
+ }
4916
4989
4917
- let ( fn_start , has_self) = match ( type_segment , fn_segment ) {
4918
- ( _ , Some ( ( _ , generics ) ) ) => {
4919
- ( generics . parent_count , generics . has_self )
4920
- }
4921
- ( Some ( ( _ , generics ) ) , None ) => {
4922
- ( generics . params . len ( ) , generics. has_self )
4923
- }
4924
- ( None , None ) => ( 0 , false )
4990
+ let has_self = path_segs . last ( ) . map ( | PathSeg ( def_id , _ ) | {
4991
+ self . tcx . generics_of ( * def_id ) . has_self
4992
+ } ) . unwrap_or ( false ) ;
4993
+
4994
+ let fn_start = match ( type_segment , fn_segment ) {
4995
+ ( _ , Some ( ( _ , generics) ) ) => generics . parent_count ,
4996
+ ( Some ( ( _ , generics ) ) , None ) => generics . params . len ( ) ,
4997
+ ( None , None ) => 0 ,
4925
4998
} ;
4926
4999
// FIXME(varkor): Separating out the parameters is messy.
4927
5000
let mut lifetimes_type_seg = vec ! [ ] ;
@@ -5091,64 +5164,55 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5091
5164
/// Report errors if the provided parameters are too few or too many.
5092
5165
fn check_generic_arg_count ( & self ,
5093
5166
span : Span ,
5094
- segment : & mut Option < ( & hir:: PathSegment , & ty:: Generics ) > ,
5167
+ segment : & hir:: PathSegment ,
5168
+ generics : & ty:: Generics ,
5095
5169
is_method_call : bool ,
5096
5170
supress_mismatch_error : bool ) {
5097
- let ( lifetimes, types, infer_types, bindings) = segment. map_or (
5098
- ( vec ! [ ] , vec ! [ ] , true , & [ ] [ ..] ) ,
5099
- |( s, _) | {
5100
- s. args . as_ref ( ) . map_or (
5101
- ( vec ! [ ] , vec ! [ ] , s. infer_types , & [ ] [ ..] ) ,
5102
- |data| {
5103
- let ( mut lifetimes, mut types) = ( vec ! [ ] , vec ! [ ] ) ;
5104
- data. args . iter ( ) . for_each ( |arg| match arg {
5105
- GenericArg :: Lifetime ( lt) => lifetimes. push ( lt) ,
5106
- GenericArg :: Type ( ty) => types. push ( ty) ,
5107
- } ) ;
5108
- ( lifetimes, types, s. infer_types , & data. bindings [ ..] )
5109
- }
5110
- )
5171
+ let ( mut lifetimes, mut types) = ( vec ! [ ] , vec ! [ ] ) ;
5172
+ let infer_types = segment. infer_types ;
5173
+ let mut bindings = vec ! [ ] ;
5174
+ if let Some ( ref data) = segment. args {
5175
+ data. args . iter ( ) . for_each ( |arg| match arg {
5176
+ GenericArg :: Lifetime ( lt) => lifetimes. push ( lt. clone ( ) ) ,
5177
+ GenericArg :: Type ( ty) => types. push ( ty. clone ( ) ) ,
5111
5178
} ) ;
5179
+ bindings = data. bindings . clone ( ) . to_vec ( ) ;
5180
+ }
5112
5181
5113
- // Check provided parameters.
5114
- let ( ( ty_required, ty_accepted) , lt_accepted) =
5115
- segment. map_or ( ( ( 0 , 0 ) , 0 ) , |( _, generics) | {
5116
- struct ParamRange {
5117
- required : usize ,
5118
- accepted : usize
5119
- } ;
5182
+ struct ParamRange {
5183
+ required : usize ,
5184
+ accepted : usize
5185
+ } ;
5120
5186
5121
- let mut lt_accepted = 0 ;
5122
- let mut ty_params = ParamRange { required : 0 , accepted : 0 } ;
5123
- for param in & generics. params {
5124
- match param. kind {
5125
- GenericParamDefKind :: Lifetime => lt_accepted += 1 ,
5126
- GenericParamDefKind :: Type { has_default, .. } => {
5127
- ty_params. accepted += 1 ;
5128
- if !has_default {
5129
- ty_params. required += 1 ;
5130
- }
5131
- }
5132
- } ;
5133
- }
5134
- if generics. parent . is_none ( ) && generics. has_self {
5135
- ty_params. required -= 1 ;
5136
- ty_params. accepted -= 1 ;
5187
+ let mut lt_accepted = 0 ;
5188
+ let mut ty_params = ParamRange { required : 0 , accepted : 0 } ;
5189
+ for param in & generics. params {
5190
+ match param. kind {
5191
+ GenericParamDefKind :: Lifetime => lt_accepted += 1 ,
5192
+ GenericParamDefKind :: Type { has_default, .. } => {
5193
+ ty_params. accepted += 1 ;
5194
+ if !has_default {
5195
+ ty_params. required += 1 ;
5196
+ }
5137
5197
}
5198
+ } ;
5199
+ }
5200
+ if generics. parent . is_none ( ) && generics. has_self {
5201
+ ty_params. required -= 1 ;
5202
+ ty_params. accepted -= 1 ;
5203
+ }
5204
+ let ty_accepted = ty_params. accepted ;
5205
+ let ty_required = ty_params. required ;
5138
5206
5139
- ( ( ty_params. required , ty_params. accepted ) , lt_accepted)
5140
- } ) ;
5141
-
5142
- let count_type_params = |n| {
5143
- format ! ( "{} type parameter{}" , n, if n == 1 { "" } else { "s" } )
5144
- } ;
5207
+ let count_type_params = |n| format ! ( "{} type parameter{}" , n, if n == 1 { "" } else { "s" } ) ;
5145
5208
let expected_text = count_type_params ( ty_accepted) ;
5146
5209
let actual_text = count_type_params ( types. len ( ) ) ;
5147
5210
if let Some ( ( mut err, span) ) = if types. len ( ) > ty_accepted {
5148
5211
// To prevent derived errors to accumulate due to extra
5149
5212
// type parameters, we force instantiate_value_path to
5150
5213
// use inference variables instead of the provided types.
5151
- * segment = None ;
5214
+ // FIXME(varkor)
5215
+ // *segment = None;
5152
5216
let span = types[ ty_accepted] . span ;
5153
5217
Some ( ( struct_span_err ! ( self . tcx. sess, span, E0087 ,
5154
5218
"too many type parameters provided: \
@@ -5172,8 +5236,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5172
5236
5173
5237
let infer_lifetimes = lifetimes. len ( ) == 0 ;
5174
5238
// Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
5175
- let has_late_bound_lifetime_defs =
5176
- segment. map_or ( None , |( _, generics) | generics. has_late_bound_regions ) ;
5239
+ let has_late_bound_lifetime_defs = generics. has_late_bound_regions ;
5177
5240
if let ( Some ( span_late) , false ) = ( has_late_bound_lifetime_defs, lifetimes. is_empty ( ) ) {
5178
5241
// Report this as a lint only if no error was reported previously.
5179
5242
let primary_msg = "cannot specify lifetime arguments explicitly \
@@ -5184,7 +5247,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5184
5247
let mut err = self . tcx . sess . struct_span_err ( lifetimes[ 0 ] . span , primary_msg) ;
5185
5248
err. span_note ( span_late, note_msg) ;
5186
5249
err. emit ( ) ;
5187
- * segment = None ;
5250
+ // FIXME(varkor)
5251
+ // *segment = None;
5188
5252
} else {
5189
5253
let mut multispan = MultiSpan :: from_span ( lifetimes[ 0 ] . span ) ;
5190
5254
multispan. push_span_label ( span_late, note_msg. to_string ( ) ) ;
0 commit comments