1212//! to pass a prebuilt Clippy from the outside when running `cargo clippy`, but that would be
1313//! (as usual) a massive undertaking/refactoring.
1414
15+ use build_helper:: exit;
16+
1517use super :: compile:: { run_cargo, rustc_cargo, std_cargo} ;
1618use super :: tool:: { SourceType , prepare_tool_cargo} ;
1719use crate :: builder:: { Builder , ShouldRun } ;
@@ -154,6 +156,15 @@ impl Std {
154156 crates,
155157 }
156158 }
159+
160+ fn from_build_compiler (
161+ build_compiler : Compiler ,
162+ target : TargetSelection ,
163+ config : LintConfig ,
164+ crates : Vec < String > ,
165+ ) -> Self {
166+ Self { build_compiler, target, config, crates }
167+ }
157168}
158169
159170impl Step for Std {
@@ -476,6 +487,7 @@ lint_any!(
476487 TestFloatParse , "src/tools/test-float-parse" , "test-float-parse" , Mode :: ToolStd ;
477488) ;
478489
490+ /// Runs Clippy on in-tree sources of selected projects using in-tree CLippy.
479491#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
480492pub struct CI {
481493 target : TargetSelection ,
@@ -496,7 +508,20 @@ impl Step for CI {
496508 }
497509
498510 fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
511+ if builder. top_stage != 2 {
512+ eprintln ! ( "ERROR: `x clippy ci` should always be executed with --stage 2" ) ;
513+ exit ! ( 1 ) ;
514+ }
515+
516+ // We want to check in-tree source using in-tree clippy. However, if we naively did
517+ // a stage 2 `x clippy ci`, it would *build* a stage 2 rustc, in order to lint stage 2
518+ // std, which is wasteful.
519+ // So we want to lint stage 2 [bootstrap/rustc/...], but only stage 1 std rustc_codegen_gcc.
520+ // We thus construct the compilers in this step manually, to optimize the number of
521+ // steps that get built.
522+
499523 builder. ensure ( Bootstrap {
524+ // This will be the stage 1 compiler
500525 build_compiler : prepare_compiler_for_check ( builder, self . target , Mode :: ToolTarget ) ,
501526 target : self . target ,
502527 config : self . config . merge ( & LintConfig {
@@ -506,6 +531,7 @@ impl Step for CI {
506531 forbid : vec ! [ ] ,
507532 } ) ,
508533 } ) ;
534+
509535 let library_clippy_cfg = LintConfig {
510536 allow : vec ! [ "clippy::all" . into( ) ] ,
511537 warn : vec ! [ ] ,
@@ -523,8 +549,9 @@ impl Step for CI {
523549 ] ,
524550 forbid : vec ! [ ] ,
525551 } ;
526- builder. ensure ( Std :: new (
527- builder,
552+ builder. ensure ( Std :: from_build_compiler (
553+ // This will be the stage 1 compiler, to avoid building rustc stage 2 just to lint std
554+ builder. compiler ( 1 , self . target ) ,
528555 self . target ,
529556 self . config . merge ( & library_clippy_cfg) ,
530557 vec ! [ ] ,
@@ -549,6 +576,7 @@ impl Step for CI {
549576 ] ,
550577 forbid : vec ! [ ] ,
551578 } ;
579+ // This will lint stage 2 rustc using stage 1 Clippy
552580 builder. ensure ( Rustc :: new (
553581 builder,
554582 self . target ,
@@ -562,6 +590,7 @@ impl Step for CI {
562590 deny : vec ! [ "warnings" . into( ) ] ,
563591 forbid : vec ! [ ] ,
564592 } ;
593+ // This will check stage 2 rustc
565594 builder. ensure ( CodegenGcc :: new (
566595 builder,
567596 self . target ,
0 commit comments