@@ -2864,13 +2864,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2864
2864
( expr_t, "" )
2865
2865
} ;
2866
2866
for ( found_fields, args) in
2867
- self . get_field_candidates_considering_privacy ( span, ty, mod_id, id)
2867
+ self . get_field_candidates_considering_privacy_for_diag ( span, ty, mod_id, id)
2868
2868
{
2869
2869
let field_names = found_fields. iter ( ) . map ( |field| field. name ) . collect :: < Vec < _ > > ( ) ;
2870
2870
let mut candidate_fields: Vec < _ > = found_fields
2871
2871
. into_iter ( )
2872
2872
. filter_map ( |candidate_field| {
2873
- self . check_for_nested_field_satisfying (
2873
+ self . check_for_nested_field_satisfying_condition_for_diag (
2874
2874
span,
2875
2875
& |candidate_field, _| candidate_field. ident ( self . tcx ( ) ) == field,
2876
2876
candidate_field,
@@ -2933,7 +2933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2933
2933
. with_span_label ( field. span , "private field" )
2934
2934
}
2935
2935
2936
- pub ( crate ) fn get_field_candidates_considering_privacy (
2936
+ pub ( crate ) fn get_field_candidates_considering_privacy_for_diag (
2937
2937
& self ,
2938
2938
span : Span ,
2939
2939
base_ty : Ty < ' tcx > ,
@@ -2942,7 +2942,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2942
2942
) -> Vec < ( Vec < & ' tcx ty:: FieldDef > , GenericArgsRef < ' tcx > ) > {
2943
2943
debug ! ( "get_field_candidates(span: {:?}, base_t: {:?}" , span, base_ty) ;
2944
2944
2945
- self . autoderef ( span, base_ty)
2945
+ let mut autoderef = self . autoderef ( span, base_ty) . silence_errors ( ) ;
2946
+ let deref_chain: Vec < _ > = autoderef. by_ref ( ) . collect ( ) ;
2947
+
2948
+ // Don't probe if we hit the recursion limit, since it may result in
2949
+ // quadratic blowup if we then try to further deref the results of this
2950
+ // function. This is a best-effort method, after all.
2951
+ if autoderef. reached_recursion_limit ( ) {
2952
+ return vec ! [ ] ;
2953
+ }
2954
+
2955
+ deref_chain
2956
+ . into_iter ( )
2946
2957
. filter_map ( move |( base_t, _) | {
2947
2958
match base_t. kind ( ) {
2948
2959
ty:: Adt ( base_def, args) if !base_def. is_enum ( ) => {
@@ -2975,7 +2986,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2975
2986
2976
2987
/// This method is called after we have encountered a missing field error to recursively
2977
2988
/// search for the field
2978
- pub ( crate ) fn check_for_nested_field_satisfying (
2989
+ pub ( crate ) fn check_for_nested_field_satisfying_condition_for_diag (
2979
2990
& self ,
2980
2991
span : Span ,
2981
2992
matches : & impl Fn ( & ty:: FieldDef , Ty < ' tcx > ) -> bool ,
@@ -3000,20 +3011,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3000
3011
if matches ( candidate_field, field_ty) {
3001
3012
return Some ( field_path) ;
3002
3013
} else {
3003
- for ( nested_fields, subst) in
3004
- self . get_field_candidates_considering_privacy ( span, field_ty, mod_id, hir_id)
3014
+ for ( nested_fields, subst) in self
3015
+ . get_field_candidates_considering_privacy_for_diag (
3016
+ span, field_ty, mod_id, hir_id,
3017
+ )
3005
3018
{
3006
3019
// recursively search fields of `candidate_field` if it's a ty::Adt
3007
3020
for field in nested_fields {
3008
- if let Some ( field_path) = self . check_for_nested_field_satisfying (
3009
- span,
3010
- matches,
3011
- field,
3012
- subst,
3013
- field_path. clone ( ) ,
3014
- mod_id,
3015
- hir_id,
3016
- ) {
3021
+ if let Some ( field_path) = self
3022
+ . check_for_nested_field_satisfying_condition_for_diag (
3023
+ span,
3024
+ matches,
3025
+ field,
3026
+ subst,
3027
+ field_path. clone ( ) ,
3028
+ mod_id,
3029
+ hir_id,
3030
+ )
3031
+ {
3017
3032
return Some ( field_path) ;
3018
3033
}
3019
3034
}
0 commit comments