@@ -3232,6 +3232,7 @@ impl<'a> Resolver<'a> {
32323232 -> PathResult < ' a > {
32333233 let mut module = None ;
32343234 let mut allow_super = true ;
3235+ let mut second_binding = None ;
32353236
32363237 for ( i, & ident) in path. iter ( ) . enumerate ( ) {
32373238 debug ! ( "resolve_path ident {} {:?}" , i, ident) ;
@@ -3321,7 +3322,9 @@ impl<'a> Resolver<'a> {
33213322 . map ( MacroBinding :: binding)
33223323 } else {
33233324 match self . resolve_ident_in_lexical_scope ( ident, ns, record_used, path_span) {
3325+ // we found a locally-imported or available item/module
33243326 Some ( LexicalScopeBinding :: Item ( binding) ) => Ok ( binding) ,
3327+ // we found a local variable or type param
33253328 Some ( LexicalScopeBinding :: Def ( def) )
33263329 if opt_ns == Some ( TypeNS ) || opt_ns == Some ( ValueNS ) => {
33273330 return PathResult :: NonModule ( PathResolution :: with_unresolved_segments (
@@ -3334,13 +3337,22 @@ impl<'a> Resolver<'a> {
33343337
33353338 match binding {
33363339 Ok ( binding) => {
3340+ if i == 1 {
3341+ second_binding = Some ( binding) ;
3342+ }
33373343 let def = binding. def ( ) ;
33383344 let maybe_assoc = opt_ns != Some ( MacroNS ) && PathSource :: Type . is_expected ( def) ;
33393345 if let Some ( next_module) = binding. module ( ) {
33403346 module = Some ( next_module) ;
33413347 } else if def == Def :: Err {
33423348 return PathResult :: NonModule ( err_path_resolution ( ) ) ;
33433349 } else if opt_ns. is_some ( ) && ( is_last || maybe_assoc) {
3350+ self . lint_if_path_starts_with_module (
3351+ node_id,
3352+ path,
3353+ path_span,
3354+ second_binding,
3355+ ) ;
33443356 return PathResult :: NonModule ( PathResolution :: with_unresolved_segments (
33453357 def, path. len ( ) - i - 1
33463358 ) ) ;
@@ -3349,33 +3361,6 @@ impl<'a> Resolver<'a> {
33493361 format ! ( "Not a module `{}`" , ident) ,
33503362 is_last) ;
33513363 }
3352-
3353- if let Some ( id) = node_id {
3354- if i == 1 && self . session . features_untracked ( ) . crate_in_paths
3355- && !self . session . rust_2018 ( ) {
3356- let prev_name = path[ 0 ] . name ;
3357- if prev_name == keywords:: Extern . name ( ) ||
3358- prev_name == keywords:: CrateRoot . name ( ) {
3359- let mut is_crate = false ;
3360- if let NameBindingKind :: Import { directive : d, .. } = binding. kind {
3361- if let ImportDirectiveSubclass :: ExternCrate ( ..) = d. subclass {
3362- is_crate = true ;
3363- }
3364- }
3365-
3366- if !is_crate {
3367- let diag = lint:: builtin:: BuiltinLintDiagnostics
3368- :: AbsPathWithModule ( path_span) ;
3369- self . session . buffer_lint_with_diagnostic (
3370- lint:: builtin:: ABSOLUTE_PATH_STARTING_WITH_MODULE ,
3371- id, path_span,
3372- "Absolute paths must start with `self`, `super`, \
3373- `crate`, or an external crate name in the 2018 edition",
3374- diag) ;
3375- }
3376- }
3377- }
3378- }
33793364 }
33803365 Err ( Undetermined ) => return PathResult :: Indeterminate ,
33813366 Err ( Determined ) => {
@@ -3408,9 +3393,67 @@ impl<'a> Resolver<'a> {
34083393 }
34093394 }
34103395
3396+ self . lint_if_path_starts_with_module ( node_id, path, path_span, second_binding) ;
3397+
34113398 PathResult :: Module ( module. unwrap_or ( self . graph_root ) )
34123399 }
34133400
3401+ fn lint_if_path_starts_with_module ( & self ,
3402+ id : Option < NodeId > ,
3403+ path : & [ Ident ] ,
3404+ path_span : Span ,
3405+ second_binding : Option < & NameBinding > ) {
3406+ // In the 2018 edition this lint is a hard error, so nothing to do
3407+ if self . session . rust_2018 ( ) {
3408+ return
3409+ }
3410+ // In the 2015 edition there's no use in emitting lints unless the
3411+ // crate's already enabled the feature that we're going to suggest
3412+ if !self . session . features_untracked ( ) . crate_in_paths {
3413+ return
3414+ }
3415+ let id = match id {
3416+ Some ( id) => id,
3417+ None => return ,
3418+ } ;
3419+ let first_name = match path. get ( 0 ) {
3420+ Some ( ident) => ident. name ,
3421+ None => return ,
3422+ } ;
3423+
3424+ // We're only interested in `use` paths which should start with
3425+ // `{{root}}` or `extern` currently.
3426+ if first_name != keywords:: Extern . name ( ) && first_name != keywords:: CrateRoot . name ( ) {
3427+ return
3428+ }
3429+
3430+ if let Some ( part) = path. get ( 1 ) {
3431+ if part. name == keywords:: Crate . name ( ) {
3432+ return
3433+ }
3434+ }
3435+
3436+ // If the first element of our path was actually resolved to an
3437+ // `ExternCrate` (also used for `crate::...`) then no need to issue a
3438+ // warning, this looks all good!
3439+ if let Some ( binding) = second_binding {
3440+ if let NameBindingKind :: Import { directive : d, .. } = binding. kind {
3441+ if let ImportDirectiveSubclass :: ExternCrate ( ..) = d. subclass {
3442+ return
3443+ }
3444+ }
3445+ }
3446+
3447+ let diag = lint:: builtin:: BuiltinLintDiagnostics
3448+ :: AbsPathWithModule ( path_span) ;
3449+ self . session . buffer_lint_with_diagnostic (
3450+ lint:: builtin:: ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE ,
3451+ id, path_span,
3452+ "Absolute paths must start with `self`, `super`, \
3453+ `crate`, or an external crate name in the 2018 edition",
3454+ diag) ;
3455+ }
3456+
34143457 // Resolve a local definition, potentially adjusting for closures.
34153458 fn adjust_local_def ( & mut self ,
34163459 ns : Namespace ,
0 commit comments