Merge from rustc

This commit is contained in:
Ralf Jung 2024-05-12 15:44:24 +02:00
commit 1e7fba9e06
545 changed files with 9070 additions and 5305 deletions

View file

@ -2,3 +2,4 @@ pub mod ci;
pub mod git;
pub mod metrics;
pub mod util;
pub mod stage0_parser;

View file

@ -0,0 +1,76 @@
use std::collections::BTreeMap;
#[derive(Default, Clone)]
pub struct Stage0 {
pub compiler: VersionMetadata,
pub rustfmt: Option<VersionMetadata>,
pub config: Stage0Config,
pub checksums_sha256: BTreeMap<String, String>,
}
#[derive(Default, Clone)]
pub struct VersionMetadata {
pub date: String,
pub version: String,
}
#[derive(Default, Clone)]
pub struct Stage0Config {
pub dist_server: String,
pub artifacts_server: String,
pub artifacts_with_llvm_assertions_server: String,
pub git_merge_commit_email: String,
pub git_repository: String,
pub nightly_branch: String,
}
pub fn parse_stage0_file() -> Stage0 {
let stage0_content = include_str!("../../../stage0");
let mut stage0 = Stage0::default();
for line in stage0_content.lines() {
let line = line.trim();
if line.is_empty() {
continue;
}
// Ignore comments
if line.starts_with('#') {
continue;
}
let (key, value) = line.split_once('=').unwrap();
match key {
"dist_server" => stage0.config.dist_server = value.to_owned(),
"artifacts_server" => stage0.config.artifacts_server = value.to_owned(),
"artifacts_with_llvm_assertions_server" => {
stage0.config.artifacts_with_llvm_assertions_server = value.to_owned()
}
"git_merge_commit_email" => stage0.config.git_merge_commit_email = value.to_owned(),
"git_repository" => stage0.config.git_repository = value.to_owned(),
"nightly_branch" => stage0.config.nightly_branch = value.to_owned(),
"compiler_date" => stage0.compiler.date = value.to_owned(),
"compiler_version" => stage0.compiler.version = value.to_owned(),
"rustfmt_date" => {
stage0.rustfmt.get_or_insert(VersionMetadata::default()).date = value.to_owned();
}
"rustfmt_version" => {
stage0.rustfmt.get_or_insert(VersionMetadata::default()).version = value.to_owned();
}
dist if dist.starts_with("dist") => {
stage0.checksums_sha256.insert(key.to_owned(), value.to_owned());
}
unsupported => {
println!("'{unsupported}' field is not supported.");
}
}
}
stage0
}

View file

@ -7,8 +7,8 @@ edition = "2021"
[dependencies]
anyhow = "1.0.34"
build_helper = { path = "../build_helper" }
curl = "0.4.38"
indexmap = { version = "2.0.0", features = ["serde"] }
serde = { version = "1.0.125", features = ["derive"] }
serde_json = { version = "1.0.59", features = ["preserve_order"] }
toml = "0.5.7"

View file

@ -1,15 +1,17 @@
#![deny(unused_variables)]
use anyhow::{Context, Error};
use build_helper::stage0_parser::{parse_stage0_file, Stage0Config, VersionMetadata};
use curl::easy::Easy;
use indexmap::IndexMap;
use std::collections::HashMap;
const PATH: &str = "src/stage0.json";
const PATH: &str = "src/stage0";
const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo", "clippy-preview"];
const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview", "rustc"];
struct Tool {
config: Config,
comments: Vec<String>,
config: Stage0Config,
channel: Channel,
date: Option<String>,
@ -35,37 +37,64 @@ impl Tool {
.try_into()
.map_err(|_| anyhow::anyhow!("failed to parse version"))?;
let existing: Stage0 = serde_json::from_slice(&std::fs::read(PATH)?)?;
let existing = parse_stage0_file();
Ok(Self {
channel,
version,
date,
config: existing.config,
comments: existing.comments,
checksums: IndexMap::new(),
})
Ok(Self { channel, version, date, config: existing.config, checksums: IndexMap::new() })
}
fn update_json(mut self) -> Result<(), Error> {
std::fs::write(
PATH,
format!(
"{}\n",
serde_json::to_string_pretty(&Stage0 {
compiler: self.detect_compiler()?,
rustfmt: self.detect_rustfmt()?,
checksums_sha256: {
// Keys are sorted here instead of beforehand because values in this map
// are added while filling the other struct fields just above this block.
self.checksums.sort_keys();
self.checksums
},
config: self.config,
comments: self.comments,
})?
),
)?;
fn update_stage0_file(mut self) -> Result<(), Error> {
const COMMENTS: &str = r#"# The configuration above this comment is editable, and can be changed
# by forks of the repository if they have alternate values.
#
# The section below is generated by `./x.py run src/tools/bump-stage0`,
# run that command again to update the bootstrap compiler.
#
# All changes below this comment will be overridden the next time the
# tool is executed.
"#;
let mut file_content = String::new();
// Destructure `Stage0Config` here to ensure the stage0 file is synced with any new
// fields when they are added.
let Stage0Config {
dist_server,
artifacts_server,
artifacts_with_llvm_assertions_server,
git_merge_commit_email,
git_repository,
nightly_branch,
} = &self.config;
file_content.push_str(&format!("dist_server={}", dist_server));
file_content.push_str(&format!("\nartifacts_server={}", artifacts_server));
file_content.push_str(&format!(
"\nartifacts_with_llvm_assertions_server={}",
artifacts_with_llvm_assertions_server
));
file_content.push_str(&format!("\ngit_merge_commit_email={}", git_merge_commit_email));
file_content.push_str(&format!("\ngit_repository={}", git_repository));
file_content.push_str(&format!("\nnightly_branch={}", nightly_branch));
file_content.push_str("\n\n");
file_content.push_str(COMMENTS);
let compiler = self.detect_compiler()?;
file_content.push_str(&format!("\ncompiler_date={}", compiler.date));
file_content.push_str(&format!("\ncompiler_version={}", compiler.version));
if let Some(rustfmt) = self.detect_rustfmt()? {
file_content.push_str(&format!("\nrustfmt_date={}", rustfmt.date));
file_content.push_str(&format!("\nrustfmt_version={}", rustfmt.version));
}
file_content.push_str("\n");
for (key, value) in self.checksums {
file_content.push_str(&format!("\n{}={}", key, value));
}
std::fs::write(PATH, file_content)?;
Ok(())
}
@ -76,7 +105,7 @@ impl Tool {
// On the master branch the compiler version is configured to `beta` whereas if you're looking
// at the beta or stable channel you'll likely see `1.x.0` as the version, with the previous
// release's version number.
fn detect_compiler(&mut self) -> Result<Stage0Toolchain, Error> {
fn detect_compiler(&mut self) -> Result<VersionMetadata, Error> {
let channel = match self.channel {
Channel::Stable | Channel::Beta => {
// The 1.XX manifest points to the latest point release of that minor release.
@ -87,7 +116,7 @@ impl Tool {
let manifest = fetch_manifest(&self.config, &channel, self.date.as_deref())?;
self.collect_checksums(&manifest, COMPILER_COMPONENTS)?;
Ok(Stage0Toolchain {
Ok(VersionMetadata {
date: manifest.date,
version: if self.channel == Channel::Nightly {
"beta".to_string()
@ -106,14 +135,14 @@ impl Tool {
/// We use a nightly rustfmt to format the source because it solves some bootstrapping issues
/// with use of new syntax in this repo. For the beta/stable channels rustfmt is not provided,
/// as we don't want to depend on rustfmt from nightly there.
fn detect_rustfmt(&mut self) -> Result<Option<Stage0Toolchain>, Error> {
fn detect_rustfmt(&mut self) -> Result<Option<VersionMetadata>, Error> {
if self.channel != Channel::Nightly {
return Ok(None);
}
let manifest = fetch_manifest(&self.config, "nightly", self.date.as_deref())?;
self.collect_checksums(&manifest, RUSTFMT_COMPONENTS)?;
Ok(Some(Stage0Toolchain { date: manifest.date, version: "nightly".into() }))
Ok(Some(VersionMetadata { date: manifest.date, version: "nightly".into() }))
}
fn collect_checksums(&mut self, manifest: &Manifest, components: &[&str]) -> Result<(), Error> {
@ -143,11 +172,15 @@ impl Tool {
fn main() -> Result<(), Error> {
let tool = Tool::new(std::env::args().nth(1))?;
tool.update_json()?;
tool.update_stage0_file()?;
Ok(())
}
fn fetch_manifest(config: &Config, channel: &str, date: Option<&str>) -> Result<Manifest, Error> {
fn fetch_manifest(
config: &Stage0Config,
channel: &str,
date: Option<&str>,
) -> Result<Manifest, Error> {
let url = if let Some(date) = date {
format!("{}/dist/{}/channel-rust-{}.toml", config.dist_server, date, channel)
} else {
@ -180,42 +213,6 @@ enum Channel {
Nightly,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Stage0 {
config: Config,
// Comments are explicitly below the config, do not move them above.
//
// Downstream forks of the compiler codebase can change the configuration values defined above,
// but doing so would risk merge conflicts whenever they import new changes that include a
// bootstrap compiler bump.
//
// To lessen the pain, a big block of comments is placed between the configuration and the
// auto-generated parts of the file, preventing git diffs of the config to include parts of the
// auto-generated content and vice versa. This should prevent merge conflicts.
#[serde(rename = "__comments")]
comments: Vec<String>,
compiler: Stage0Toolchain,
rustfmt: Option<Stage0Toolchain>,
checksums_sha256: IndexMap<String, String>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Config {
dist_server: String,
// There are other fields in the configuration, which will be read by src/bootstrap or other
// tools consuming stage0.json. To avoid the need to update bump-stage0 every time a new field
// is added, we collect all the fields in an untyped Value and serialize them back with the
// same order and structure they were deserialized in.
#[serde(flatten)]
other: serde_json::Value,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Stage0Toolchain {
date: String,
version: String,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Manifest {
date: String,

View file

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_hir;
use rustc_hir::{intravisit, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::layout::LayoutOf;
@ -105,8 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
too_large_for_stack: self.too_large_for_stack,
};
let infcx = cx.tcx.infer_ctxt().build();
ExprUseVisitor::new(&mut v, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
ExprUseVisitor::for_clippy(cx, fn_def_id, &mut v).consume_body(body).into_ok();
for node in v.set {
span_lint_hir(

View file

@ -8,6 +8,7 @@
#![feature(never_type)]
#![feature(rustc_private)]
#![feature(stmt_expr_attributes)]
#![feature(unwrap_infallible)]
#![recursion_limit = "512"]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![allow(

View file

@ -4,7 +4,6 @@ use clippy_utils::{get_enclosing_block, higher, path_to_local};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Node, PatKind};
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty;
@ -61,15 +60,12 @@ fn check_for_mutation(
span_low: None,
span_high: None,
};
let infcx = cx.tcx.infer_ctxt().build();
ExprUseVisitor::new(
&mut delegate,
&infcx,
ExprUseVisitor::for_clippy(
cx,
body.hir_id.owner.def_id,
cx.param_env,
cx.typeck_results(),
&mut delegate,
)
.walk_expr(body);
.walk_expr(body).into_ok();
delegate.mutation_span()
}

View file

@ -9,7 +9,6 @@ use rustc_lint::LateContext;
use rustc_middle::mir::{FakeReadCause, Mutability};
use rustc_middle::ty::{self, BorrowKind};
use rustc_span::sym;
use rustc_trait_selection::infer::TyCtxtInferExt;
use super::ITER_OVEREAGER_CLONED;
use crate::redundant_clone::REDUNDANT_CLONE;
@ -69,16 +68,13 @@ pub(super) fn check<'tcx>(
let mut delegate = MoveDelegate {
used_move: HirIdSet::default(),
};
let infcx = cx.tcx.infer_ctxt().build();
ExprUseVisitor::new(
ExprUseVisitor::for_clippy(
cx,
closure.def_id,
&mut delegate,
&infcx,
closure.body.hir_id.owner.def_id,
cx.param_env,
cx.typeck_results(),
)
.consume_body(body);
.consume_body(body).into_ok();
let mut to_be_discarded = false;

View file

@ -417,7 +417,7 @@ fn get_input_traits_and_projections<'tcx>(
}
},
ClauseKind::Projection(projection_predicate) => {
if projection_predicate.projection_ty.self_ty() == input {
if projection_predicate.projection_term.self_ty() == input {
projection_predicates.push(projection_predicate);
}
},

View file

@ -320,11 +320,11 @@ fn is_mixed_projection_predicate<'tcx>(
&& (term_param_ty.index as usize) < generics.parent_count
{
// The inner-most self type is a type parameter from the current function.
let mut projection_ty = projection_predicate.projection_ty;
let mut projection_term = projection_predicate.projection_term;
loop {
match projection_ty.self_ty().kind() {
match *projection_term.self_ty().kind() {
ty::Alias(ty::Projection, inner_projection_ty) => {
projection_ty = *inner_projection_ty;
projection_term = inner_projection_ty.into();
},
ty::Param(param_ty) => {
return (param_ty.index as usize) >= generics.parent_count;
@ -404,14 +404,11 @@ fn replace_types<'tcx>(
// The `replaced.insert(...)` check provides some protection against infinite loops.
if replaced.insert(param_ty.index) {
for projection_predicate in projection_predicates {
if projection_predicate.projection_ty.self_ty() == param_ty.to_ty(cx.tcx)
if projection_predicate.projection_term.self_ty() == param_ty.to_ty(cx.tcx)
&& let Some(term_ty) = projection_predicate.term.ty()
&& let ty::Param(term_param_ty) = term_ty.kind()
{
let projection = cx.tcx.mk_ty_from_kind(ty::Alias(
ty::Projection,
projection_predicate.projection_ty.with_self_ty(cx.tcx, new_ty),
));
let projection = projection_predicate.projection_term.with_self_ty(cx.tcx, new_ty).expect_ty(cx.tcx).to_ty(cx.tcx);
if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
&& args[term_param_ty.index as usize] != GenericArg::from(projected_ty)

View file

@ -11,7 +11,6 @@ use rustc_hir::{
PatKind,
};
use rustc_hir_typeck::expr_use_visitor as euv;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{self, Ty, TyCtxt, UpvarId, UpvarPath};
@ -102,7 +101,6 @@ fn should_skip<'tcx>(
fn check_closures<'tcx>(
ctx: &mut MutablyUsedVariablesCtxt<'tcx>,
cx: &LateContext<'tcx>,
infcx: &InferCtxt<'tcx>,
checked_closures: &mut FxHashSet<LocalDefId>,
closures: FxHashSet<LocalDefId>,
) {
@ -119,7 +117,7 @@ fn check_closures<'tcx>(
.associated_body()
.map(|(_, body_id)| hir.body(body_id))
{
euv::ExprUseVisitor::new(ctx, infcx, closure, cx.param_env, cx.typeck_results()).consume_body(body);
euv::ExprUseVisitor::for_clippy(cx, closure, &mut *ctx).consume_body(body).into_ok();
}
}
}
@ -196,8 +194,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
async_closures: FxHashSet::default(),
tcx: cx.tcx,
};
let infcx = cx.tcx.infer_ctxt().build();
euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx).consume_body(body).into_ok();
let mut checked_closures = FxHashSet::default();
@ -210,13 +207,13 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
}
ControlFlow::<()>::Continue(())
});
check_closures(&mut ctx, cx, &infcx, &mut checked_closures, closures);
check_closures(&mut ctx, cx, &mut checked_closures, closures);
if is_async {
while !ctx.async_closures.is_empty() {
let async_closures = ctx.async_closures.clone();
ctx.async_closures.clear();
check_closures(&mut ctx, cx, &infcx, &mut checked_closures, async_closures);
check_closures(&mut ctx, cx, &mut checked_closures, async_closures);
}
}
ctx.generate_mutably_used_ids_from_aliases()

View file

@ -13,7 +13,6 @@ use rustc_hir::{
TyKind,
};
use rustc_hir_typeck::expr_use_visitor as euv;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
@ -134,8 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
// function body.
let MovedVariablesCtxt { moved_vars } = {
let mut ctx = MovedVariablesCtxt::default();
let infcx = cx.tcx.infer_ctxt().build();
euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx).consume_body(body).into_ok();
ctx
};

View file

@ -11,7 +11,6 @@ use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, Pl
use rustc_lint::LateContext;
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::BorrowKind;
use rustc_trait_selection::infer::TyCtxtInferExt;
use super::ASSIGN_OP_PATTERN;
@ -119,15 +118,8 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
}
let mut s = S(HirIdSet::default());
let infcx = cx.tcx.infer_ctxt().build();
let mut v = ExprUseVisitor::new(
&mut s,
&infcx,
cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
cx.param_env,
cx.typeck_results(),
);
v.consume_expr(e);
let v = ExprUseVisitor::for_clippy(cx, e.hir_id.owner.def_id, &mut s);
v.consume_expr(e).into_ok();
s.0
}
@ -151,14 +143,7 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
}
let mut s = S(HirIdSet::default());
let infcx = cx.tcx.infer_ctxt().build();
let mut v = ExprUseVisitor::new(
&mut s,
&infcx,
cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
cx.param_env,
cx.typeck_results(),
);
v.consume_expr(e);
let v = ExprUseVisitor::for_clippy(cx, e.hir_id.owner.def_id, &mut s);
v.consume_expr(e).into_ok();
s.0
}

View file

@ -66,7 +66,7 @@ fn get_projection_pred<'tcx>(
let projection_pred = cx
.tcx
.instantiate_bound_regions_with_erased(proj_pred.kind().rebind(pred));
if projection_pred.projection_ty.args == trait_pred.trait_ref.args {
if projection_pred.projection_term.args == trait_pred.trait_ref.args {
return Some(projection_pred);
}
}

View file

@ -6,7 +6,6 @@ use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Node, PathSegment, UnOp};
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_middle::lint::in_external_macro;
@ -252,16 +251,13 @@ impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
local_id: unwrap_info.local_id,
};
let infcx = self.cx.tcx.infer_ctxt().build();
let mut vis = ExprUseVisitor::new(
&mut delegate,
&infcx,
let vis = ExprUseVisitor::for_clippy(
self.cx,
cond.hir_id.owner.def_id,
self.cx.param_env,
self.cx.typeck_results(),
&mut delegate,
);
vis.walk_expr(cond);
vis.walk_expr(branch);
vis.walk_expr(cond).into_ok();
vis.walk_expr(branch).into_ok();
if delegate.is_mutated {
// if the variable is mutated, we don't know whether it can be unwrapped.

View file

@ -7,6 +7,7 @@
#![feature(never_type)]
#![feature(rustc_private)]
#![feature(assert_matches)]
#![feature(unwrap_infallible)]
#![recursion_limit = "512"]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![allow(

View file

@ -11,7 +11,6 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{EarlyContext, LateContext, LintContext};
use rustc_middle::hir::place::ProjectionKind;
use rustc_middle::mir::{FakeReadCause, Mutability};
@ -831,8 +830,9 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti
applicability: Applicability::MachineApplicable,
};
let infcx = cx.tcx.infer_ctxt().build();
ExprUseVisitor::new(&mut visitor, &infcx, def_id, cx.param_env, cx.typeck_results()).consume_body(closure_body);
ExprUseVisitor::for_clippy(cx, def_id, &mut visitor)
.consume_body(closure_body)
.into_ok();
if !visitor.suggestion_start.is_empty() {
return Some(DerefClosure {

View file

@ -795,7 +795,7 @@ fn sig_from_bounds<'tcx>(
inputs = Some(i);
},
ty::ClauseKind::Projection(p)
if Some(p.projection_ty.def_id) == lang_items.fn_once_output() && p.projection_ty.self_ty() == ty =>
if Some(p.projection_term.def_id) == lang_items.fn_once_output() && p.projection_term.self_ty() == ty =>
{
if output.is_some() {
// Multiple different fn trait impls. Is this even allowed?
@ -834,7 +834,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
}
inputs = Some(i);
},
ty::ClauseKind::Projection(p) if Some(p.projection_ty.def_id) == lang_items.fn_once_output() => {
ty::ClauseKind::Projection(p) if Some(p.projection_term.def_id) == lang_items.fn_once_output() => {
if output.is_some() {
// Multiple different fn trait impls. Is this even allowed?
return None;

View file

@ -5,7 +5,6 @@ use hir::def::Res;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, Expr, ExprKind, HirId, HirIdSet};
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, Place, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
use rustc_middle::mir::FakeReadCause;
@ -17,15 +16,13 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) ->
used_mutably: HirIdSet::default(),
skip: false,
};
let infcx = cx.tcx.infer_ctxt().build();
ExprUseVisitor::new(
&mut delegate,
&infcx,
ExprUseVisitor::for_clippy(
cx,
expr.hir_id.owner.def_id,
cx.param_env,
cx.typeck_results(),
&mut delegate,
)
.walk_expr(expr);
.walk_expr(expr)
.into_ok();
if delegate.skip {
return None;

View file

@ -54,6 +54,15 @@ pub fn static_lib(name: &str) -> PathBuf {
tmp_dir().join(static_lib_name(name))
}
pub fn python_command() -> Command {
let python_path = std::env::var("PYTHON").expect("PYTHON environment variable does not exist");
Command::new(python_path)
}
pub fn source_path() -> PathBuf {
std::env::var("S").expect("S variable does not exist").into()
}
/// Construct the static library name based on the platform.
pub fn static_lib_name(name: &str) -> String {
// See tools.mk (irrelevant lines omitted):

View file

@ -1,5 +1,5 @@
use std::env;
use std::ffi::OsString;
use std::ffi::{OsStr, OsString};
use std::io::Write;
use std::path::Path;
use std::process::{Command, Output, Stdio};
@ -176,6 +176,13 @@ impl Rustc {
self
}
/// Specify the crate name.
pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
self.cmd.arg("--crate-name");
self.cmd.arg(name.as_ref());
self
}
/// Get the [`Output`][::std::process::Output] of the finished process.
#[track_caller]
pub fn command_output(&mut self) -> ::std::process::Output {

View file

@ -1,4 +1,5 @@
use std::env;
use std::ffi::OsStr;
use std::io::Write;
use std::path::Path;
use std::process::{Command, Output, Stdio};
@ -45,6 +46,21 @@ impl Rustdoc {
Self { cmd, stdin: None }
}
/// Specify where an external library is located.
pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
assert!(
!crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
"crate name cannot contain whitespace or path separators"
);
let path = path.as_ref().to_string_lossy();
self.cmd.arg("--extern");
self.cmd.arg(format!("{crate_name}={path}"));
self
}
/// Specify path to the input file.
pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self.cmd.arg(path.as_ref());
@ -107,6 +123,34 @@ impl Rustdoc {
self
}
/// Specify the target triple, or a path to a custom target json spec file.
pub fn target(&mut self, target: &str) -> &mut Self {
self.cmd.arg(format!("--target={target}"));
self
}
/// Specify the crate type.
pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
self.cmd.arg("--crate-type");
self.cmd.arg(crate_type);
self
}
/// Specify the crate name.
pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
self.cmd.arg("--crate-name");
self.cmd.arg(name.as_ref());
self
}
/// Add a directory to the library search path. It corresponds to the `-L`
/// rustdoc option.
pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self.cmd.arg("-L");
self.cmd.arg(path.as_ref());
self
}
#[track_caller]
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
let caller_location = std::panic::Location::caller();

View file

@ -1,6 +1,3 @@
run-make/alloc-no-oom-handling/Makefile
run-make/alloc-no-rc/Makefile
run-make/alloc-no-sync/Makefile
run-make/allocator-shim-circular-deps/Makefile
run-make/allow-non-lint-warnings-cmdline/Makefile
run-make/allow-warnings-cmdline-stability/Makefile
@ -12,7 +9,6 @@ run-make/c-dynamic-dylib/Makefile
run-make/c-dynamic-rlib/Makefile
run-make/c-link-to-rust-dylib/Makefile
run-make/c-link-to-rust-staticlib/Makefile
run-make/c-link-to-rust-va-list-fn/Makefile
run-make/c-static-dylib/Makefile
run-make/c-static-rlib/Makefile
run-make/c-unwind-abi-catch-lib-panic/Makefile
@ -248,12 +244,9 @@ run-make/rustdoc-io-error/Makefile
run-make/rustdoc-scrape-examples-invalid-expr/Makefile
run-make/rustdoc-scrape-examples-macros/Makefile
run-make/rustdoc-scrape-examples-multiple/Makefile
run-make/rustdoc-scrape-examples-ordering/Makefile
run-make/rustdoc-scrape-examples-remap/Makefile
run-make/rustdoc-scrape-examples-test/Makefile
run-make/rustdoc-scrape-examples-whitespace/Makefile
run-make/rustdoc-shared-flags/Makefile
run-make/rustdoc-target-spec-json-path/Makefile
run-make/rustdoc-themes/Makefile
run-make/rustdoc-verify-output-files/Makefile
run-make/rustdoc-with-out-dir-option/Makefile

View file

@ -395,6 +395,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",