@@ -4909,6 +4909,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4909
4909
// segment belong to, let's sort out the parameters that the user
4910
4910
// provided (if any) into their appropriate spaces. We'll also report
4911
4911
// errors if type parameters are provided in an inappropriate place.
4912
+
4912
4913
let mut generic_segs = HashSet :: new ( ) ;
4913
4914
for PathSeg ( _, index) in & path_segs {
4914
4915
generic_segs. insert ( index) ;
@@ -4937,104 +4938,115 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4937
4938
// variables. If the user provided some types, we may still need
4938
4939
// to add defaults. If the user provided *too many* types, that's
4939
4940
// a problem.
4940
- let mut infer_lifetimes = FxHashMap ( ) ;
4941
+
4941
4942
let mut supress_errors = FxHashMap ( ) ;
4942
4943
for & PathSeg ( def_id, index) in & path_segs {
4943
4944
let seg = & segments[ index] ;
4944
4945
let generics = self . tcx . generics_of ( def_id) ;
4946
+ // `impl Trait` is treated as a normal generic parameter internally,
4947
+ // but we don't allow users to specify the parameter's value
4948
+ // explicitly, so we have to do some error-checking here.
4945
4949
let supress_mismatch = self . check_impl_trait ( span, seg, & generics) ;
4946
4950
supress_errors. insert ( index,
4947
4951
self . check_generic_arg_count ( span, seg, & generics, false , supress_mismatch) ) ;
4948
- let inferred_lifetimes = if if let Some ( ref data) = seg. args {
4949
- !data. args . iter ( ) . any ( |arg| match arg {
4950
- GenericArg :: Lifetime ( _) => true ,
4951
- _ => false ,
4952
- } )
4953
- } else {
4954
- true
4955
- } {
4956
- generics. own_counts ( ) . lifetimes
4957
- } else {
4958
- 0
4959
- } ;
4960
- infer_lifetimes. insert ( index, inferred_lifetimes) ;
4961
4952
}
4962
4953
4963
4954
let has_self = path_segs. last ( ) . map ( |PathSeg ( def_id, _) | {
4964
4955
self . tcx . generics_of ( * def_id) . has_self
4965
4956
} ) . unwrap_or ( false ) ;
4966
4957
4958
+ // Collect the segments of the path: we need to substitute arguments
4959
+ // for parameters throughout the entire path (wherever there are
4960
+ // generic parameters).
4967
4961
let def_id = def. def_id ( ) ;
4968
4962
let mut parent_defs = self . tcx . generics_of ( def_id) ;
4969
4963
let count = parent_defs. count ( ) ;
4970
- let mut substs: AccumulateVec < [ Kind < ' tcx > ; 8 ] > = if count <= 8 {
4971
- AccumulateVec :: Array ( ArrayVec :: new ( ) )
4972
- } else {
4973
- AccumulateVec :: Heap ( Vec :: with_capacity ( count) )
4974
- } ;
4975
4964
let mut stack = vec ! [ ( def_id, parent_defs) ] ;
4976
4965
while let Some ( def_id) = parent_defs. parent {
4977
4966
parent_defs = self . tcx . generics_of ( def_id) ;
4978
4967
stack. push ( ( def_id, parent_defs) ) ;
4979
4968
}
4980
- macro_rules! push_to_substs {
4981
- ( $kind : expr ) => {
4982
- let k = $kind ;
4983
- match substs {
4984
- AccumulateVec :: Array ( ref mut arr ) => arr . push ( k ) ,
4985
- AccumulateVec :: Heap ( ref mut vec ) => vec . push ( k ) ,
4986
- }
4987
- }
4969
+
4970
+ // We manually build up the substitution, rather than using convenience
4971
+ // methods in subst.rs so that we can iterate over the arguments and
4972
+ // parameters in lock-step linearly, rather than trying to match each pair.
4973
+ let mut substs : AccumulateVec < [ Kind < ' tcx > ; 8 ] > = if count <= 8 {
4974
+ AccumulateVec :: Array ( ArrayVec :: new ( ) )
4975
+ } else {
4976
+ AccumulateVec :: Heap ( Vec :: with_capacity ( count ) )
4988
4977
} ;
4978
+ fn push_kind < ' tcx > ( substs : & mut AccumulateVec < [ Kind < ' tcx > ; 8 ] > , kind : Kind < ' tcx > ) {
4979
+ match substs {
4980
+ AccumulateVec :: Array ( ref mut arr) => arr. push ( kind) ,
4981
+ AccumulateVec :: Heap ( ref mut vec) => vec. push ( kind) ,
4982
+ }
4983
+ }
4984
+
4985
+ // Iterate over each segment of the path.
4989
4986
while let Some ( ( def_id, defs) ) = stack. pop ( ) {
4990
4987
let mut params = defs. params . iter ( ) ;
4991
4988
let mut next_param = params. next ( ) ;
4989
+
4990
+ // `Self` is handled first.
4992
4991
if has_self {
4993
4992
if let Some ( param) = next_param {
4994
4993
if param. index == 0 {
4995
4994
if let GenericParamDefKind :: Type { .. } = param. kind {
4996
- // Handle `Self` first, so we can adjust the index to match the AST.
4997
- push_to_substs ! ( opt_self_ty. map( |ty| ty. into( ) ) . unwrap_or_else( || {
4998
- self . var_for_def( span, param)
4999
- } ) ) ;
4995
+ push_kind ( & mut substs, opt_self_ty. map ( |ty| ty. into ( ) )
4996
+ . unwrap_or_else ( || self . var_for_def ( span, param) ) ) ;
5000
4997
next_param = params. next ( ) ;
5001
4998
}
5002
4999
}
5003
5000
}
5004
5001
}
5005
5002
5006
5003
let mut infer_types = true ;
5004
+ // Check whether this segment takes generic arguments.
5007
5005
if let Some ( & PathSeg ( _, index) ) = path_segs
5008
5006
. iter ( )
5009
5007
. find ( |& PathSeg ( did, _) | * did == def_id) {
5008
+ // If we've encountered an `impl Trait`-related error, we're just
5009
+ // going to infer the arguments for better error messages.
5010
5010
if !supress_errors[ & index] {
5011
5011
infer_types = segments[ index] . infer_types ;
5012
+ // Check whether the user has provided generic arguments.
5012
5013
if let Some ( ref data) = segments[ index] . args {
5013
5014
let args = & data. args ;
5015
+ // We're going to iterate through the generic arguments that the user
5016
+ // provided, matching them with the generic parameters we expect.
5017
+ // Mismatches can occur as a result of elided lifetimes, or for malformed
5018
+ // input. We try to handle both sensibly.
5014
5019
' args: for arg in args {
5015
5020
while let Some ( param) = next_param {
5016
5021
match param. kind {
5017
5022
GenericParamDefKind :: Lifetime => match arg {
5018
5023
GenericArg :: Lifetime ( lt) => {
5019
- push_to_substs ! ( AstConv :: ast_region_to_region( self ,
5020
- lt, Some ( param) ) . into( ) ) ;
5024
+ push_kind ( & mut substs,
5025
+ AstConv :: ast_region_to_region ( self , lt, Some ( param) )
5026
+ . into ( ) ) ;
5021
5027
next_param = params. next ( ) ;
5022
5028
continue ' args;
5023
5029
}
5024
5030
GenericArg :: Type ( _) => {
5025
- // We're inferring a lifetime.
5026
- push_to_substs ! (
5031
+ // We expected a lifetime argument, but got a type
5032
+ // argument. That means we're inferring the lifetimes.
5033
+ push_kind ( & mut substs,
5027
5034
self . re_infer ( span, Some ( param) ) . unwrap ( ) . into ( ) ) ;
5028
5035
next_param = params. next ( ) ;
5029
5036
}
5030
5037
}
5031
5038
GenericParamDefKind :: Type { .. } => match arg {
5032
5039
GenericArg :: Type ( ty) => {
5033
- push_to_substs ! ( self . to_ty( ty) . into( ) ) ;
5040
+ push_kind ( & mut substs , self . to_ty ( ty) . into ( ) ) ;
5034
5041
next_param = params. next ( ) ;
5035
5042
continue ' args;
5036
5043
}
5037
5044
GenericArg :: Lifetime ( _) => {
5045
+ // We expected a type argument, but got a lifetime
5046
+ // argument. This is an error, but we need to handle it
5047
+ // gracefully so we can report sensible errors. In this
5048
+ // case, we're simply going to infer the remaining
5049
+ // arguments.
5038
5050
self . tcx . sess . delay_span_bug ( span,
5039
5051
"found a GenericArg::Lifetime where a \
5040
5052
GenericArg::Type was expected") ;
@@ -5043,34 +5055,40 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5043
5055
}
5044
5056
}
5045
5057
}
5046
- // If we get to this point, we have a GenericArg that is not matched
5047
- // by a GenericParamDef: i.e. the user supplied too many generic args.
5058
+ // We should never be able to reach this point with well-formed input.
5059
+ // Getting to this point means the user supplied more arguments than
5060
+ // there are parameters.
5048
5061
self . tcx . sess . delay_span_bug ( span,
5049
5062
"GenericArg did not have matching GenericParamDef" ) ;
5050
5063
}
5051
5064
}
5052
5065
}
5053
5066
}
5054
5067
5068
+ // If there are fewer arguments than parameters, it means
5069
+ // we're inferring the remaining arguments.
5055
5070
while let Some ( param) = next_param {
5056
5071
match param. kind {
5057
5072
GenericParamDefKind :: Lifetime => {
5058
- push_to_substs ! ( self . re_infer( span, Some ( param) ) . unwrap( ) . into( ) ) ;
5073
+ push_kind ( & mut substs , self . re_infer ( span, Some ( param) ) . unwrap ( ) . into ( ) ) ;
5059
5074
}
5060
5075
GenericParamDefKind :: Type { has_default, .. } => {
5061
5076
if !infer_types && has_default {
5062
- // No type parameter provided, but a default exists.
5077
+ // If we have a default, then we it doesn't matter that we're not
5078
+ // inferring the type arguments: we provide the default where any
5079
+ // is missing.
5063
5080
let default = self . tcx . type_of ( param. def_id ) ;
5064
- push_to_substs ! ( self . normalize_ty(
5081
+ let kind = self . normalize_ty (
5065
5082
span,
5066
5083
default. subst_spanned ( self . tcx , & substs, Some ( span) )
5067
- ) . into( ) ) ;
5084
+ ) . into ( ) ;
5085
+ push_kind ( & mut substs, kind) ;
5068
5086
} else {
5069
- // No type parameters were provided, we can infer all .
5070
- // This can also be reached in some error cases:
5071
- // We prefer to use inference variables instead of
5072
- // TyError to let type inference recover somewhat .
5073
- push_to_substs ! ( self . var_for_def( span, param) ) ;
5087
+ // If no type arguments were provided, we have to infer them .
5088
+ // This case also occurs as a result of some malformed input, e.g.
5089
+ // a lifetime argument being given instead of a type paramter.
5090
+ // Using inference instead of `TyError` gives better error messages .
5091
+ push_kind ( & mut substs , self . var_for_def ( span, param) ) ;
5074
5092
}
5075
5093
}
5076
5094
}
0 commit comments