@@ -3124,6 +3124,193 @@ impl<'a> Resolver<'a> {
31243124 )
31253125 }
31263126
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+
31273314 /// Handles error reporting for `smart_resolve_path_fragment` function.
31283315 /// Creates base error and amends it with one short label and possibly some longer helps/notes.
31293316 fn smart_resolve_report_errors (
@@ -3137,7 +3324,7 @@ impl<'a> Resolver<'a> {
31373324 let ns = source. namespace ( ) ;
31383325 let is_expected = & |def| source. is_expected ( def) ;
31393326 let is_enum_variant = & |def| if let Def :: Variant ( ..) = def { true } else { false } ;
3140-
3327+
31413328 // Make the base error.
31423329 let expected = source. descr_expected ( ) ;
31433330 let path_str = Segment :: names_to_string ( path) ;
@@ -3317,188 +3504,13 @@ impl<'a> Resolver<'a> {
33173504
33183505 // Try context-dependent help if relaxed lookup didn't work.
33193506 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) ;
35023514 }
35033515 }
35043516
0 commit comments