@@ -3124,6 +3124,193 @@ impl<'a> Resolver<'a> {
3124
3124
)
3125
3125
}
3126
3126
3127
+ /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment`
3128
+ /// function.
3129
+ /// Returns `true` if able to provide context-dependent help.
3130
+ fn smart_resolve_context_dep_help (
3131
+ & mut self ,
3132
+ err : & mut DiagnosticBuilder < ' a > ,
3133
+ span : Span ,
3134
+ source : PathSource ,
3135
+ def : Def ,
3136
+ path_str : & str ,
3137
+ fallback_label : & str ,
3138
+ ) -> bool {
3139
+ let ns = source. namespace ( ) ;
3140
+ let is_expected = & |def| source. is_expected ( def) ;
3141
+
3142
+ match ( def, source) {
3143
+ ( Def :: Macro ( ..) , _) => {
3144
+ err. span_suggestion (
3145
+ span,
3146
+ "use `!` to invoke the macro" ,
3147
+ format ! ( "{}!" , path_str) ,
3148
+ Applicability :: MaybeIncorrect ,
3149
+ ) ;
3150
+ }
3151
+ ( Def :: TyAlias ( ..) , PathSource :: Trait ( _) ) => {
3152
+ err. span_label ( span, "type aliases cannot be used as traits" ) ;
3153
+ if nightly_options:: is_nightly_build ( ) {
3154
+ err. note ( "did you mean to use a trait alias?" ) ;
3155
+ }
3156
+ }
3157
+ ( Def :: Mod ( ..) , PathSource :: Expr ( Some ( parent) ) ) => match parent. node {
3158
+ ExprKind :: Field ( _, ident) => {
3159
+ err. span_suggestion (
3160
+ parent. span ,
3161
+ "use the path separator to refer to an item" ,
3162
+ format ! ( "{}::{}" , path_str, ident) ,
3163
+ Applicability :: MaybeIncorrect ,
3164
+ ) ;
3165
+ }
3166
+ ExprKind :: MethodCall ( ref segment, ..) => {
3167
+ let span = parent. span . with_hi ( segment. ident . span . hi ( ) ) ;
3168
+ err. span_suggestion (
3169
+ span,
3170
+ "use the path separator to refer to an item" ,
3171
+ format ! ( "{}::{}" , path_str, segment. ident) ,
3172
+ Applicability :: MaybeIncorrect ,
3173
+ ) ;
3174
+ }
3175
+ _ => return false ,
3176
+ } ,
3177
+ ( Def :: Enum ( ..) , PathSource :: TupleStruct )
3178
+ | ( Def :: Enum ( ..) , PathSource :: Expr ( ..) ) => {
3179
+ if let Some ( variants) = self . collect_enum_variants ( def) {
3180
+ err. note ( & format ! ( "did you mean to use one \
3181
+ of the following variants?\n {}",
3182
+ variants. iter( )
3183
+ . map( |suggestion| path_names_to_string( suggestion) )
3184
+ . map( |suggestion| format!( "- `{}`" , suggestion) )
3185
+ . collect:: <Vec <_>>( )
3186
+ . join( "\n " ) ) ) ;
3187
+ } else {
3188
+ err. note ( "did you mean to use one of the enum's variants?" ) ;
3189
+ }
3190
+ } ,
3191
+ ( Def :: Struct ( def_id) , _) if ns == ValueNS => {
3192
+ if let Some ( ( ctor_def, ctor_vis) )
3193
+ = self . struct_constructors . get ( & def_id) . cloned ( ) {
3194
+ let accessible_ctor = self . is_accessible ( ctor_vis) ;
3195
+ if is_expected ( ctor_def) && !accessible_ctor {
3196
+ err. span_label ( span, format ! ( "constructor is not visible \
3197
+ here due to private fields") ) ;
3198
+ }
3199
+ } else {
3200
+ // HACK(estebank): find a better way to figure out that this was a
3201
+ // parser issue where a struct literal is being used on an expression
3202
+ // where a brace being opened means a block is being started. Look
3203
+ // ahead for the next text to see if `span` is followed by a `{`.
3204
+ let sm = self . session . source_map ( ) ;
3205
+ let mut sp = span;
3206
+ loop {
3207
+ sp = sm. next_point ( sp) ;
3208
+ match sm. span_to_snippet ( sp) {
3209
+ Ok ( ref snippet) => {
3210
+ if snippet. chars ( ) . any ( |c| { !c. is_whitespace ( ) } ) {
3211
+ break ;
3212
+ }
3213
+ }
3214
+ _ => break ,
3215
+ }
3216
+ }
3217
+ let followed_by_brace = match sm. span_to_snippet ( sp) {
3218
+ Ok ( ref snippet) if snippet == "{" => true ,
3219
+ _ => false ,
3220
+ } ;
3221
+ // In case this could be a struct literal that needs to be surrounded
3222
+ // by parenthesis, find the appropriate span.
3223
+ let mut i = 0 ;
3224
+ let mut closing_brace = None ;
3225
+ loop {
3226
+ sp = sm. next_point ( sp) ;
3227
+ match sm. span_to_snippet ( sp) {
3228
+ Ok ( ref snippet) => {
3229
+ if snippet == "}" {
3230
+ let sp = span. to ( sp) ;
3231
+ if let Ok ( snippet) = sm. span_to_snippet ( sp) {
3232
+ closing_brace = Some ( ( sp, snippet) ) ;
3233
+ }
3234
+ break ;
3235
+ }
3236
+ }
3237
+ _ => break ,
3238
+ }
3239
+ i += 1 ;
3240
+ // The bigger the span, the more likely we're incorrect --
3241
+ // bound it to 100 chars long.
3242
+ if i > 100 {
3243
+ break ;
3244
+ }
3245
+ }
3246
+ match source {
3247
+ PathSource :: Expr ( Some ( parent) ) => {
3248
+ match parent. node {
3249
+ ExprKind :: MethodCall ( ref path_assignment, _) => {
3250
+ err. span_suggestion (
3251
+ sm. start_point ( parent. span )
3252
+ . to ( path_assignment. ident . span ) ,
3253
+ "use `::` to access an associated function" ,
3254
+ format ! ( "{}::{}" ,
3255
+ path_str,
3256
+ path_assignment. ident) ,
3257
+ Applicability :: MaybeIncorrect
3258
+ ) ;
3259
+ } ,
3260
+ _ => {
3261
+ err. span_label (
3262
+ span,
3263
+ format ! ( "did you mean `{} {{ /* fields */ }}`?" ,
3264
+ path_str) ,
3265
+ ) ;
3266
+ } ,
3267
+ }
3268
+ } ,
3269
+ PathSource :: Expr ( None ) if followed_by_brace == true => {
3270
+ if let Some ( ( sp, snippet) ) = closing_brace {
3271
+ err. span_suggestion (
3272
+ sp,
3273
+ "surround the struct literal with parenthesis" ,
3274
+ format ! ( "({})" , snippet) ,
3275
+ Applicability :: MaybeIncorrect ,
3276
+ ) ;
3277
+ } else {
3278
+ err. span_label (
3279
+ span,
3280
+ format ! ( "did you mean `({} {{ /* fields */ }})`?" ,
3281
+ path_str) ,
3282
+ ) ;
3283
+ }
3284
+ } ,
3285
+ _ => {
3286
+ err. span_label (
3287
+ span,
3288
+ format ! ( "did you mean `{} {{ /* fields */ }}`?" ,
3289
+ path_str) ,
3290
+ ) ;
3291
+ } ,
3292
+ }
3293
+ }
3294
+ }
3295
+ ( Def :: Union ( ..) , _) |
3296
+ ( Def :: Variant ( ..) , _) |
3297
+ ( Def :: VariantCtor ( _, CtorKind :: Fictive ) , _) if ns == ValueNS => {
3298
+ err. span_label ( span, format ! ( "did you mean `{} {{ /* fields */ }}`?" ,
3299
+ path_str) ) ;
3300
+ }
3301
+ ( Def :: SelfTy ( ..) , _) if ns == ValueNS => {
3302
+ err. span_label ( span, fallback_label) ;
3303
+ err. note ( "can't use `Self` as a constructor, you must use the \
3304
+ implemented struct") ;
3305
+ }
3306
+ ( Def :: TyAlias ( _) , _) | ( Def :: AssociatedTy ( ..) , _) if ns == ValueNS => {
3307
+ err. note ( "can't use a type alias as a constructor" ) ;
3308
+ }
3309
+ _ => return false ,
3310
+ }
3311
+ true
3312
+ }
3313
+
3127
3314
/// Handles error reporting for `smart_resolve_path_fragment` function.
3128
3315
/// Creates base error and amends it with one short label and possibly some longer helps/notes.
3129
3316
fn smart_resolve_report_errors (
@@ -3137,7 +3324,7 @@ impl<'a> Resolver<'a> {
3137
3324
let ns = source. namespace ( ) ;
3138
3325
let is_expected = & |def| source. is_expected ( def) ;
3139
3326
let is_enum_variant = & |def| if let Def :: Variant ( ..) = def { true } else { false } ;
3140
-
3327
+
3141
3328
// Make the base error.
3142
3329
let expected = source. descr_expected ( ) ;
3143
3330
let path_str = Segment :: names_to_string ( path) ;
@@ -3317,188 +3504,13 @@ impl<'a> Resolver<'a> {
3317
3504
3318
3505
// Try context-dependent help if relaxed lookup didn't work.
3319
3506
if let Some ( def) = def {
3320
- match ( def, source) {
3321
- ( Def :: Macro ( ..) , _) => {
3322
- err. span_suggestion (
3323
- span,
3324
- "use `!` to invoke the macro" ,
3325
- format ! ( "{}!" , path_str) ,
3326
- Applicability :: MaybeIncorrect ,
3327
- ) ;
3328
- return ( err, candidates) ;
3329
- }
3330
- ( Def :: TyAlias ( ..) , PathSource :: Trait ( _) ) => {
3331
- err. span_label ( span, "type aliases cannot be used as traits" ) ;
3332
- if nightly_options:: is_nightly_build ( ) {
3333
- err. note ( "did you mean to use a trait alias?" ) ;
3334
- }
3335
- return ( err, candidates) ;
3336
- }
3337
- ( Def :: Mod ( ..) , PathSource :: Expr ( Some ( parent) ) ) => match parent. node {
3338
- ExprKind :: Field ( _, ident) => {
3339
- err. span_suggestion (
3340
- parent. span ,
3341
- "use the path separator to refer to an item" ,
3342
- format ! ( "{}::{}" , path_str, ident) ,
3343
- Applicability :: MaybeIncorrect ,
3344
- ) ;
3345
- return ( err, candidates) ;
3346
- }
3347
- ExprKind :: MethodCall ( ref segment, ..) => {
3348
- let span = parent. span . with_hi ( segment. ident . span . hi ( ) ) ;
3349
- err. span_suggestion (
3350
- span,
3351
- "use the path separator to refer to an item" ,
3352
- format ! ( "{}::{}" , path_str, segment. ident) ,
3353
- Applicability :: MaybeIncorrect ,
3354
- ) ;
3355
- return ( err, candidates) ;
3356
- }
3357
- _ => { }
3358
- } ,
3359
- ( Def :: Enum ( ..) , PathSource :: TupleStruct )
3360
- | ( Def :: Enum ( ..) , PathSource :: Expr ( ..) ) => {
3361
- if let Some ( variants) = self . collect_enum_variants ( def) {
3362
- err. note ( & format ! ( "did you mean to use one \
3363
- of the following variants?\n {}",
3364
- variants. iter( )
3365
- . map( |suggestion| path_names_to_string( suggestion) )
3366
- . map( |suggestion| format!( "- `{}`" , suggestion) )
3367
- . collect:: <Vec <_>>( )
3368
- . join( "\n " ) ) ) ;
3369
-
3370
- } else {
3371
- err. note ( "did you mean to use one of the enum's variants?" ) ;
3372
- }
3373
- return ( err, candidates) ;
3374
- } ,
3375
- ( Def :: Struct ( def_id) , _) if ns == ValueNS => {
3376
- if let Some ( ( ctor_def, ctor_vis) )
3377
- = self . struct_constructors . get ( & def_id) . cloned ( ) {
3378
- let accessible_ctor = self . is_accessible ( ctor_vis) ;
3379
- if is_expected ( ctor_def) && !accessible_ctor {
3380
- err. span_label ( span, format ! ( "constructor is not visible \
3381
- here due to private fields") ) ;
3382
- }
3383
- } else {
3384
- // HACK(estebank): find a better way to figure out that this was a
3385
- // parser issue where a struct literal is being used on an expression
3386
- // where a brace being opened means a block is being started. Look
3387
- // ahead for the next text to see if `span` is followed by a `{`.
3388
- let sm = self . session . source_map ( ) ;
3389
- let mut sp = span;
3390
- loop {
3391
- sp = sm. next_point ( sp) ;
3392
- match sm. span_to_snippet ( sp) {
3393
- Ok ( ref snippet) => {
3394
- if snippet. chars ( ) . any ( |c| { !c. is_whitespace ( ) } ) {
3395
- break ;
3396
- }
3397
- }
3398
- _ => break ,
3399
- }
3400
- }
3401
- let followed_by_brace = match sm. span_to_snippet ( sp) {
3402
- Ok ( ref snippet) if snippet == "{" => true ,
3403
- _ => false ,
3404
- } ;
3405
- // In case this could be a struct literal that needs to be surrounded
3406
- // by parenthesis, find the appropriate span.
3407
- let mut i = 0 ;
3408
- let mut closing_brace = None ;
3409
- loop {
3410
- sp = sm. next_point ( sp) ;
3411
- match sm. span_to_snippet ( sp) {
3412
- Ok ( ref snippet) => {
3413
- if snippet == "}" {
3414
- let sp = span. to ( sp) ;
3415
- if let Ok ( snippet) = sm. span_to_snippet ( sp) {
3416
- closing_brace = Some ( ( sp, snippet) ) ;
3417
- }
3418
- break ;
3419
- }
3420
- }
3421
- _ => break ,
3422
- }
3423
- i += 1 ;
3424
- // The bigger the span, the more likely we're
3425
- // incorrect. Bound it to 100 chars long.
3426
- if i > 100 {
3427
- break ;
3428
- }
3429
- }
3430
- match source {
3431
- PathSource :: Expr ( Some ( parent) ) => {
3432
- match parent. node {
3433
- ExprKind :: MethodCall ( ref path_assignment, _) => {
3434
- err. span_suggestion (
3435
- sm. start_point ( parent. span )
3436
- . to ( path_assignment. ident . span ) ,
3437
- "use `::` to access an associated function" ,
3438
- format ! ( "{}::{}" ,
3439
- path_str,
3440
- path_assignment. ident) ,
3441
- Applicability :: MaybeIncorrect
3442
- ) ;
3443
- return ( err, candidates) ;
3444
- } ,
3445
- _ => {
3446
- err. span_label (
3447
- span,
3448
- format ! ( "did you mean `{} {{ /* fields */ }}`?" ,
3449
- path_str) ,
3450
- ) ;
3451
- return ( err, candidates) ;
3452
- } ,
3453
- }
3454
- } ,
3455
- PathSource :: Expr ( None ) if followed_by_brace == true => {
3456
- if let Some ( ( sp, snippet) ) = closing_brace {
3457
- err. span_suggestion (
3458
- sp,
3459
- "surround the struct literal with parenthesis" ,
3460
- format ! ( "({})" , snippet) ,
3461
- Applicability :: MaybeIncorrect ,
3462
- ) ;
3463
- } else {
3464
- err. span_label (
3465
- span,
3466
- format ! ( "did you mean `({} {{ /* fields */ }})`?" ,
3467
- path_str) ,
3468
- ) ;
3469
- }
3470
- return ( err, candidates) ;
3471
- } ,
3472
- _ => {
3473
- err. span_label (
3474
- span,
3475
- format ! ( "did you mean `{} {{ /* fields */ }}`?" ,
3476
- path_str) ,
3477
- ) ;
3478
- return ( err, candidates) ;
3479
- } ,
3480
- }
3481
- }
3482
- return ( err, candidates) ;
3483
- }
3484
- ( Def :: Union ( ..) , _) |
3485
- ( Def :: Variant ( ..) , _) |
3486
- ( Def :: VariantCtor ( _, CtorKind :: Fictive ) , _) if ns == ValueNS => {
3487
- err. span_label ( span, format ! ( "did you mean `{} {{ /* fields */ }}`?" ,
3488
- path_str) ) ;
3489
- return ( err, candidates) ;
3490
- }
3491
- ( Def :: SelfTy ( ..) , _) if ns == ValueNS => {
3492
- err. span_label ( span, fallback_label) ;
3493
- err. note ( "can't use `Self` as a constructor, you must use the \
3494
- implemented struct") ;
3495
- return ( err, candidates) ;
3496
- }
3497
- ( Def :: TyAlias ( _) , _) | ( Def :: AssociatedTy ( ..) , _) if ns == ValueNS => {
3498
- err. note ( "can't use a type alias as a constructor" ) ;
3499
- return ( err, candidates) ;
3500
- }
3501
- _ => { }
3507
+ if self . smart_resolve_context_dep_help ( & mut err,
3508
+ span,
3509
+ source,
3510
+ def,
3511
+ & path_str,
3512
+ & fallback_label) {
3513
+ return ( err, candidates) ;
3502
3514
}
3503
3515
}
3504
3516
0 commit comments