11//! Implementation of running clippy on the compiler, standard library and various tools.
2+ //!
3+ //! This serves a double purpose:
4+ //! - The first is to run Clippy itself on in-tree code, in order to test and dogfood it.
5+ //! - The second is to actually lint the in-tree codebase on CI, with a hard-coded set of rules,
6+ //! which is performed by the `x clippy ci` command.
7+ //!
8+ //! In order to prepare a build compiler for running clippy, use the
9+ //! `check::prepare_compiler_for_check` function. That prepares a compiler and a standard library
10+ //! for running Clippy. The second part (actually building Clippy) is performed inside
11+ //! [Builder::cargo_clippy_cmd]. It would be nice if this was more explicit, and we actually had
12+ //! to pass a prebuilt Clippy from the outside when running `cargo clippy`, but that would be
13+ //! (as usual) a massive undertaking/refactoring.
214
315use super :: check;
416use super :: compile:: { run_cargo, rustc_cargo, std_cargo} ;
517use super :: tool:: { RustcPrivateCompilers , SourceType , prepare_tool_cargo} ;
618use crate :: builder:: { Builder , ShouldRun } ;
19+ use crate :: core:: build_steps:: check:: prepare_compiler_for_check;
720use crate :: core:: build_steps:: compile:: std_crates_for_run_make;
821use crate :: core:: builder;
922use crate :: core:: builder:: { Alias , Kind , RunConfig , Step , StepMetadata , crate_description} ;
1023use crate :: utils:: build_stamp:: { self , BuildStamp } ;
11- use crate :: { Mode , Subcommand , TargetSelection } ;
24+ use crate :: { Compiler , Mode , Subcommand , TargetSelection } ;
1225
1326/// Disable the most spammy clippy lints
1427const IGNORED_RULES_FOR_STD_AND_RUSTC : & [ & str ] = & [
@@ -179,14 +192,35 @@ impl Step for Std {
179192 }
180193}
181194
195+ /// Lints the compiler.
196+ ///
197+ /// This will build Clippy with the `build_compiler` and use it to lint
198+ /// in-tree rustc.
182199#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
183200pub struct Rustc {
184- pub target : TargetSelection ,
201+ build_compiler : Compiler ,
202+ target : TargetSelection ,
185203 config : LintConfig ,
186204 /// Whether to lint only a subset of crates.
187205 crates : Vec < String > ,
188206}
189207
208+ impl Rustc {
209+ fn new (
210+ builder : & Builder < ' _ > ,
211+ target : TargetSelection ,
212+ config : LintConfig ,
213+ crates : Vec < String > ,
214+ ) -> Self {
215+ Self {
216+ build_compiler : prepare_compiler_for_check ( builder, target, Mode :: Rustc ) ,
217+ target,
218+ config,
219+ crates,
220+ }
221+ }
222+ }
223+
190224impl Step for Rustc {
191225 type Output = ( ) ;
192226 const ONLY_HOSTS : bool = true ;
@@ -197,43 +231,26 @@ impl Step for Rustc {
197231 }
198232
199233 fn make_run ( run : RunConfig < ' _ > ) {
234+ let builder = run. builder ;
200235 let crates = run. make_run_crates ( Alias :: Compiler ) ;
201236 let config = LintConfig :: new ( run. builder ) ;
202- run. builder . ensure ( Rustc { target : run. target , config, crates } ) ;
237+ run. builder . ensure ( Rustc :: new ( builder , run. target , config, crates) ) ;
203238 }
204239
205- /// Lints the compiler.
206- ///
207- /// This will lint the compiler for a particular stage of the build using
208- /// the `compiler` targeting the `target` architecture.
209240 fn run ( self , builder : & Builder < ' _ > ) {
210- let compiler = builder . compiler ( builder . top_stage , builder . config . host_target ) ;
241+ let build_compiler = self . build_compiler ;
211242 let target = self . target ;
212243
213- if !builder. download_rustc ( ) {
214- if compiler. stage != 0 {
215- // If we're not in stage 0, then we won't have a std from the beta
216- // compiler around. That means we need to make sure there's one in
217- // the sysroot for the compiler to find. Otherwise, we're going to
218- // fail when building crates that need to generate code (e.g., build
219- // scripts and their dependencies).
220- builder. std ( compiler, compiler. host ) ;
221- builder. std ( compiler, target) ;
222- } else {
223- builder. ensure ( check:: Std :: new ( compiler, target) ) ;
224- }
225- }
226-
227244 let mut cargo = builder:: Cargo :: new (
228245 builder,
229- compiler ,
246+ build_compiler ,
230247 Mode :: Rustc ,
231248 SourceType :: InTree ,
232249 target,
233250 Kind :: Clippy ,
234251 ) ;
235252
236- rustc_cargo ( builder, & mut cargo, target, & compiler , & self . crates ) ;
253+ rustc_cargo ( builder, & mut cargo, target, & self . build_compiler , & self . crates ) ;
237254
238255 // Explicitly pass -p for all compiler crates -- this will force cargo
239256 // to also lint the tests/benches/examples for these crates, rather
@@ -249,15 +266,15 @@ impl Step for Rustc {
249266 builder,
250267 cargo,
251268 lint_args ( builder, & self . config , IGNORED_RULES_FOR_STD_AND_RUSTC ) ,
252- & build_stamp:: librustc_stamp ( builder, compiler , target) ,
269+ & build_stamp:: librustc_stamp ( builder, build_compiler , target) ,
253270 vec ! [ ] ,
254271 true ,
255272 false ,
256273 ) ;
257274 }
258275
259276 fn metadata ( & self ) -> Option < StepMetadata > {
260- Some ( StepMetadata :: clippy ( "rustc" , self . target ) )
277+ Some ( StepMetadata :: clippy ( "rustc" , self . target ) . built_by ( self . build_compiler ) )
261278 }
262279}
263280
@@ -515,11 +532,12 @@ impl Step for CI {
515532 ] ,
516533 forbid : vec ! [ ] ,
517534 } ;
518- builder. ensure ( Rustc {
519- target : self . target ,
520- config : self . config . merge ( & compiler_clippy_cfg) ,
521- crates : vec ! [ ] ,
522- } ) ;
535+ builder. ensure ( Rustc :: new (
536+ builder,
537+ self . target ,
538+ self . config . merge ( & compiler_clippy_cfg) ,
539+ vec ! [ ] ,
540+ ) ) ;
523541
524542 let rustc_codegen_gcc = LintConfig {
525543 allow : vec ! [ ] ,
0 commit comments