@@ -12,10 +12,10 @@ use tracing::debug;
1212use { rustc_ast as ast, rustc_hir as hir} ;
1313
1414use crate :: lints:: {
15- BadOptAccessDiag , DefaultHashTypesDiag , DiagOutOfImpl , LintPassByHand ,
16- NonGlobImportTypeIrInherent , QueryInstability , QueryUntracked , SpanUseEqCtxtDiag ,
17- SymbolInternStringLiteralDiag , TyQualified , TykindDiag , TykindKind , TypeIrDirectUse ,
18- TypeIrInherentUsage , TypeIrTraitUsage , UntranslatableDiag ,
15+ BadOptAccessDiag , DefaultHashTypesDiag , DiagOutOfImpl , ImplicitSysrootCrateImportDiag ,
16+ LintPassByHand , NonGlobImportTypeIrInherent , QueryInstability , QueryUntracked ,
17+ SpanUseEqCtxtDiag , SymbolInternStringLiteralDiag , TyQualified , TykindDiag , TykindKind ,
18+ TypeIrDirectUse , TypeIrInherentUsage , TypeIrTraitUsage , UntranslatableDiag ,
1919} ;
2020use crate :: { EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext } ;
2121
@@ -745,3 +745,40 @@ impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
745745 }
746746 }
747747}
748+
749+ declare_tool_lint ! {
750+ /// The `implicit_sysroot_crate_import` detects use of `extern crate` to import non-sysroot crates
751+ /// (e.g. crates.io deps) from the sysroot, which is dangerous because these crates are not guaranteed
752+ /// to exist exactly once, and so may be missing entirely or appear multiple times resulting in ambiguity.
753+ pub rustc:: IMPLICIT_SYSROOT_CRATE_IMPORT ,
754+ Allow ,
755+ "Forbid uses of non-sysroot crates in `extern crate`" ,
756+ report_in_external_macro: true
757+ }
758+
759+ declare_lint_pass ! ( ImplicitSysrootCrateImport => [ IMPLICIT_SYSROOT_CRATE_IMPORT ] ) ;
760+
761+ impl EarlyLintPass for ImplicitSysrootCrateImport {
762+ fn check_item ( & mut self , cx : & EarlyContext < ' _ > , item : & ast:: Item ) {
763+ fn is_whitelisted ( crate_name : & str ) -> bool {
764+ // Whitelist of allowed crates.
765+ crate_name. starts_with ( "rustc_" )
766+ || matches ! (
767+ crate_name,
768+ "test" | "self" | "core" | "alloc" | "std" | "proc_macro" | "tikv_jemalloc_sys"
769+ )
770+ }
771+
772+ if let ast:: ItemKind :: ExternCrate ( original_name, imported_name) = & item. kind {
773+ let name = original_name. as_ref ( ) . unwrap_or ( & imported_name. name ) . as_str ( ) ;
774+ let externs = & cx. builder . sess ( ) . opts . externs ;
775+ if externs. get ( name) . is_none ( ) && !is_whitelisted ( name) {
776+ cx. emit_span_lint (
777+ IMPLICIT_SYSROOT_CRATE_IMPORT ,
778+ item. span ,
779+ ImplicitSysrootCrateImportDiag { name } ,
780+ ) ;
781+ }
782+ }
783+ }
784+ }
0 commit comments