@@ -135,6 +135,7 @@ use syntax::util::parser::ExprPrecedence;
135
135
136
136
use rustc_error_codes:: * ;
137
137
138
+ use std:: borrow:: Cow ;
138
139
use std:: cell:: { Cell , Ref , RefCell , RefMut } ;
139
140
use std:: cmp;
140
141
use std:: collections:: hash_map:: Entry ;
@@ -254,6 +255,8 @@ pub struct Inherited<'a, 'tcx> {
254
255
/// not clear.
255
256
implicit_region_bound : Option < ty:: Region < ' tcx > > ,
256
257
258
+ inferred_paths : RefCell < FxHashMap < hir:: HirId , InferredPath < ' tcx > > > ,
259
+
257
260
body_id : Option < hir:: BodyId > ,
258
261
}
259
262
@@ -619,6 +622,13 @@ pub struct FnCtxt<'a, 'tcx> {
619
622
inh : & ' a Inherited < ' a , ' tcx > ,
620
623
}
621
624
625
+ #[ derive( Clone , Debug ) ]
626
+ struct InferredPath < ' tcx > {
627
+ span : Span ,
628
+ ty : Option < Ty < ' tcx > > ,
629
+ args : Option < Cow < ' tcx , [ Ty < ' tcx > ] > > ,
630
+ }
631
+
622
632
impl < ' a , ' tcx > Deref for FnCtxt < ' a , ' tcx > {
623
633
type Target = Inherited < ' a , ' tcx > ;
624
634
fn deref ( & self ) -> & Self :: Target {
@@ -685,6 +695,7 @@ impl Inherited<'a, 'tcx> {
685
695
opaque_types : RefCell :: new ( Default :: default ( ) ) ,
686
696
opaque_types_vars : RefCell :: new ( Default :: default ( ) ) ,
687
697
implicit_region_bound,
698
+ inferred_paths : RefCell :: new ( Default :: default ( ) ) ,
688
699
body_id,
689
700
}
690
701
}
@@ -1053,6 +1064,32 @@ fn typeck_tables_of_with_fallback<'tcx>(
1053
1064
// All type checking constraints were added, try to fallback unsolved variables.
1054
1065
fcx. select_obligations_where_possible ( false , |_| { } ) ;
1055
1066
let mut fallback_has_occurred = false ;
1067
+ let unresolved_paths: FxHashMap < hir:: HirId , InferredPath < ' tcx > > = fcx
1068
+ . inferred_paths
1069
+ . borrow ( )
1070
+ . iter ( )
1071
+ . map ( |( id, path) | ( * id, path. clone ( ) ) )
1072
+ . filter ( |( hir_id, path) | {
1073
+ debug ! (
1074
+ "typeck_tables_of_with_fallback: inspecting path ({:?}, {:?})" ,
1075
+ hir_id, path
1076
+ ) ;
1077
+ let debug_resolved = fcx. infcx . resolve_vars_if_possible ( & path. ty ) ;
1078
+ if fcx. infcx . unresolved_type_vars ( & path. ty ) . is_some ( ) {
1079
+ debug ! (
1080
+ "typeck_tables_of_with_fallback: unresolved vars in ty: {:?}" ,
1081
+ debug_resolved
1082
+ ) ;
1083
+ true
1084
+ } else {
1085
+ debug ! (
1086
+ "typeck_tables_of_with_fallback: all vars resolved in ty: {:?}" ,
1087
+ debug_resolved
1088
+ ) ;
1089
+ false
1090
+ }
1091
+ } )
1092
+ . collect ( ) ;
1056
1093
1057
1094
// We do fallback in two passes, to try to generate
1058
1095
// better error messages.
@@ -1095,6 +1132,42 @@ fn typeck_tables_of_with_fallback<'tcx>(
1095
1132
// See if we can make any more progress.
1096
1133
fcx. select_obligations_where_possible ( fallback_has_occurred, |_| { } ) ;
1097
1134
1135
+ for ( call_id, path) in unresolved_paths {
1136
+ debug ! (
1137
+ "Resolved ty: {:?} at span {:?} : expr={:?} parent={:?} path={:?}" ,
1138
+ path. span,
1139
+ path. ty,
1140
+ tcx. hir( ) . get( call_id) ,
1141
+ tcx. hir( ) . get( tcx. hir( ) . get_parent_node( call_id) ) ,
1142
+ path
1143
+ ) ;
1144
+
1145
+ let ty = fcx. infcx . resolve_vars_if_possible ( & path. ty ) ;
1146
+ debug ! ( "Fully resolved ty: {:?}" , ty) ;
1147
+
1148
+ let ty = ty. unwrap_or_else ( || bug ! ( "Missing ty in path: {:?}" , path) ) ;
1149
+
1150
+ if let ty:: FnDef ( _, substs) = ty. kind {
1151
+ debug ! ( "Got substs: {:?}" , substs) ;
1152
+ let mut inhabited = true ;
1153
+ for arg in & * path. args . unwrap ( ) {
1154
+ let resolved_arg = fcx. infcx . resolve_vars_if_possible ( arg) ;
1155
+
1156
+ if resolved_arg. conservative_is_privately_uninhabited ( tcx) {
1157
+ debug ! ( "Arg is uninhabited: {:?}" , resolved_arg) ;
1158
+ inhabited = false ;
1159
+ break ;
1160
+ } else {
1161
+ debug ! ( "Arg is inhabited: {:?}" , resolved_arg) ;
1162
+ }
1163
+ }
1164
+
1165
+ if inhabited {
1166
+ debug ! ( "All arguments are inhabited!" ) ;
1167
+ }
1168
+ }
1169
+ }
1170
+
1098
1171
// Even though coercion casts provide type hints, we check casts after fallback for
1099
1172
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
1100
1173
fcx. check_casts ( ) ;
@@ -3624,7 +3697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3624
3697
self . check_argument_types (
3625
3698
sp,
3626
3699
expr,
3627
- & err_inputs[ .. ] ,
3700
+ err_inputs,
3628
3701
& [ ] ,
3629
3702
args_no_rcvr,
3630
3703
false ,
@@ -3732,13 +3805,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3732
3805
& self ,
3733
3806
sp : Span ,
3734
3807
expr : & ' tcx hir:: Expr < ' tcx > ,
3735
- fn_inputs : & [ Ty < ' tcx > ] ,
3808
+ fn_inputs : impl Into < Cow < ' tcx , [ Ty < ' tcx > ] > > ,
3736
3809
expected_arg_tys : & [ Ty < ' tcx > ] ,
3737
3810
args : & ' tcx [ hir:: Expr < ' tcx > ] ,
3738
3811
c_variadic : bool ,
3739
3812
tuple_arguments : TupleArgumentsFlag ,
3740
3813
def_span : Option < Span > ,
3741
3814
) {
3815
+ let fn_inputs = fn_inputs. into ( ) ;
3816
+ debug ! ( "check_argument_types: storing arguments for expr {:?}" , expr) ;
3817
+ match self . inferred_paths . borrow_mut ( ) . entry ( expr. hir_id ) {
3818
+ Entry :: Vacant ( e) => {
3819
+ debug ! ( "check_argument_types: making new entry for types {:?}" , fn_inputs) ;
3820
+ e. insert ( InferredPath { span : sp, ty : None , args : Some ( fn_inputs. clone ( ) ) } ) ;
3821
+ }
3822
+ Entry :: Occupied ( mut e) => {
3823
+ debug ! (
3824
+ "check_argument_types: modifiying exsting entry {:?} with types {:?}" ,
3825
+ e. get( ) ,
3826
+ fn_inputs
3827
+ ) ;
3828
+ e. get_mut ( ) . args = Some ( fn_inputs. clone ( ) ) ;
3829
+ }
3830
+ }
3831
+
3742
3832
let tcx = self . tcx ;
3743
3833
// Grab the argument types, supplying fresh type variables
3744
3834
// if the wrong number of arguments were supplied
@@ -5425,6 +5515,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5425
5515
// the referenced item.
5426
5516
let ty_substituted = self . instantiate_type_scheme ( span, & substs, & ty) ;
5427
5517
5518
+ if ty_substituted. has_infer_types ( ) {
5519
+ debug ! (
5520
+ "instantiate_value_path: saving path with infer: ({:?}, {:?})" ,
5521
+ span, ty_substituted
5522
+ ) ;
5523
+ let parent_id = tcx. hir ( ) . get_parent_node ( hir_id) ;
5524
+ let parent = tcx. hir ( ) . get ( parent_id) ;
5525
+ match parent {
5526
+ Node :: Expr ( hir:: Expr { span : p_span, kind : ExprKind :: Call ( ..) , .. } )
5527
+ | Node :: Expr ( hir:: Expr { span : p_span, kind : ExprKind :: MethodCall ( ..) , .. } ) => {
5528
+ match self . inferred_paths . borrow_mut ( ) . entry ( parent_id) {
5529
+ Entry :: Vacant ( e) => {
5530
+ debug ! ( "instantiate_value_path: inserting new path" ) ;
5531
+ e. insert ( InferredPath {
5532
+ span : * p_span,
5533
+ ty : Some ( ty_substituted) ,
5534
+ args : None ,
5535
+ } ) ;
5536
+ }
5537
+ Entry :: Occupied ( mut e) => {
5538
+ debug ! ( "instantiate_value_path: updating existing path {:?}" , e. get( ) ) ;
5539
+ e. get_mut ( ) . ty = Some ( ty_substituted) ;
5540
+ }
5541
+ }
5542
+ }
5543
+ _ => { }
5544
+ }
5545
+ }
5546
+
5428
5547
if let Some ( UserSelfTy { impl_def_id, self_ty } ) = user_self_ty {
5429
5548
// In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
5430
5549
// is inherent, there is no `Self` parameter; instead, the impl needs
0 commit comments