Auto merge of #122113 - matthiaskrgr:rollup-5d1jnwi, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #121958 (Fix redundant import errors for preload extern crate)
 - #121976 (Add an option to have an external download/bootstrap cache)
 - #122022 (loongarch: add frecipe and relax target feature)
 - #122026 (Do not try to format removed files)
 - #122027 (Uplift some feeding out of `associated_type_for_impl_trait_in_impl` and into queries)
 - #122063 (Make the lowering of `thir::ExprKind::If` easier to follow)
 - #122074 (Add missing PartialOrd trait implementation doc for array)
 - #122082 (remove outdated fixme comment)
 - #122091 (Note why we're using a new thread in `test_get_os_named_thread`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-03-07 02:30:40 +00:00
commit aa029ce4d8
31 changed files with 402 additions and 180 deletions

View file

@ -14,6 +14,43 @@ use rustc_span::Span;
pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
use rustc_hir::*;
// For an RPITIT, synthesize generics which are equal to the opaque's generics
// and parent fn's generics compressed into one list.
if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) =
tcx.opt_rpitit_info(def_id.to_def_id())
{
let trait_def_id = tcx.parent(fn_def_id);
let opaque_ty_generics = tcx.generics_of(opaque_def_id);
let opaque_ty_parent_count = opaque_ty_generics.parent_count;
let mut params = opaque_ty_generics.params.clone();
let parent_generics = tcx.generics_of(trait_def_id);
let parent_count = parent_generics.parent_count + parent_generics.params.len();
let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
for param in &mut params {
param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
- opaque_ty_parent_count as u32;
}
trait_fn_params.extend(params);
params = trait_fn_params;
let param_def_id_to_index =
params.iter().map(|param| (param.def_id, param.index)).collect();
return ty::Generics {
parent: Some(trait_def_id),
parent_count,
params,
param_def_id_to_index,
has_self: opaque_ty_generics.has_self,
has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
host_effect_index: parent_generics.host_effect_index,
};
}
let hir_id = tcx.local_def_id_to_hir_id(def_id);
let node = tcx.hir_node(hir_id);

View file

@ -5,7 +5,7 @@ use rustc_hir::HirId;
use rustc_middle::query::plumbing::CyclePlaceholder;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};
@ -350,22 +350,31 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
// If we are computing `type_of` the synthesized associated type for an RPITIT in the impl
// side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the
// associated type in the impl.
if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) =
tcx.opt_rpitit_info(def_id.to_def_id())
{
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
Ok(map) => {
let assoc_item = tcx.associated_item(def_id);
return map[&assoc_item.trait_item_def_id.unwrap()];
}
Err(_) => {
return ty::EarlyBinder::bind(Ty::new_error_with_message(
tcx,
DUMMY_SP,
"Could not collect return position impl trait in trait tys",
));
match tcx.opt_rpitit_info(def_id.to_def_id()) {
Some(ty::ImplTraitInTraitData::Impl { fn_def_id }) => {
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
Ok(map) => {
let assoc_item = tcx.associated_item(def_id);
return map[&assoc_item.trait_item_def_id.unwrap()];
}
Err(_) => {
return ty::EarlyBinder::bind(Ty::new_error_with_message(
tcx,
DUMMY_SP,
"Could not collect return position impl trait in trait tys",
));
}
}
}
// For an RPITIT in a trait, just return the corresponding opaque.
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
return ty::EarlyBinder::bind(Ty::new_opaque(
tcx,
opaque_def_id,
ty::GenericArgs::identity_for_item(tcx, opaque_def_id),
));
}
None => {}
}
let hir_id = tcx.local_def_id_to_hir_id(def_id);

View file

@ -143,7 +143,11 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
BuiltinLintDiag::RedundantImport(spans, ident) => {
for (span, is_imported) in spans {
let introduced = if is_imported { "imported" } else { "defined" };
diag.span_label(span, format!("the item `{ident}` is already {introduced} here"));
let span_msg = if span.is_dummy() { "by prelude" } else { "here" };
diag.span_label(
span,
format!("the item `{ident}` is already {introduced} {span_msg}"),
);
}
}
BuiltinLintDiag::DeprecatedMacro(suggestion, span) => {

View file

@ -826,7 +826,7 @@ rustc_queries! {
/// creates and returns the associated items that correspond to each impl trait in return position
/// of the implemented trait.
query associated_types_for_impl_traits_in_associated_fn(fn_def_id: DefId) -> &'tcx [DefId] {
desc { |tcx| "creating associated items for impl trait in trait returned by `{}`", tcx.def_path_str(fn_def_id) }
desc { |tcx| "creating associated items for opaque types returned by `{}`", tcx.def_path_str(fn_def_id) }
cache_on_disk_if { fn_def_id.is_local() }
separate_provide_extern
}
@ -834,7 +834,7 @@ rustc_queries! {
/// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
/// associated item.
query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
desc { |tcx| "creates the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) }
desc { |tcx| "creating the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) }
cache_on_disk_if { true }
}

View file

@ -58,52 +58,61 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.thir[scrutinee].span,
),
ExprKind::If { cond, then, else_opt, if_then_scope } => {
let then_blk;
let then_span = this.thir[then].span;
let then_source_info = this.source_info(then_span);
let condition_scope = this.local_scope();
let mut else_blk = unpack!(
then_blk = this.in_scope(
(if_then_scope, then_source_info),
LintLevel::Inherited,
|this| {
let source_info = if this.is_let(cond) {
let variable_scope =
this.new_source_scope(then_span, LintLevel::Inherited, None);
this.source_scope = variable_scope;
SourceInfo { span: then_span, scope: variable_scope }
} else {
this.source_info(then_span)
};
let (then_block, else_block) =
this.in_if_then_scope(condition_scope, then_span, |this| {
let then_blk = unpack!(this.then_else_break(
block,
cond,
Some(condition_scope), // Temp scope
condition_scope,
source_info,
true, // Declare `let` bindings normally
));
let then_and_else_blocks = this.in_scope(
(if_then_scope, then_source_info),
LintLevel::Inherited,
|this| {
// FIXME: Does this need extra logic to handle let-chains?
let source_info = if this.is_let(cond) {
let variable_scope =
this.new_source_scope(then_span, LintLevel::Inherited, None);
this.source_scope = variable_scope;
SourceInfo { span: then_span, scope: variable_scope }
} else {
this.source_info(then_span)
};
this.expr_into_dest(destination, then_blk, then)
});
then_block.and(else_block)
},
)
// Lower the condition, and have it branch into `then` and `else` blocks.
let (then_block, else_block) =
this.in_if_then_scope(condition_scope, then_span, |this| {
let then_blk = unpack!(this.then_else_break(
block,
cond,
Some(condition_scope), // Temp scope
condition_scope,
source_info,
true, // Declare `let` bindings normally
));
// Lower the `then` arm into its block.
this.expr_into_dest(destination, then_blk, then)
});
// Pack `(then_block, else_block)` into `BlockAnd<BasicBlock>`.
then_block.and(else_block)
},
);
else_blk = if let Some(else_opt) = else_opt {
unpack!(this.expr_into_dest(destination, else_blk, else_opt))
// Unpack `BlockAnd<BasicBlock>` into `(then_blk, else_blk)`.
let (then_blk, mut else_blk);
else_blk = unpack!(then_blk = then_and_else_blocks);
// If there is an `else` arm, lower it into `else_blk`.
if let Some(else_expr) = else_opt {
unpack!(else_blk = this.expr_into_dest(destination, else_blk, else_expr));
} else {
// Body of the `if` expression without an `else` clause must return `()`, thus
// we implicitly generate an `else {}` if it is not specified.
// There is no `else` arm, so we know both arms have type `()`.
// Generate the implicit `else {}` by assigning unit.
let correct_si = this.source_info(expr_span.shrink_to_hi());
this.cfg.push_assign_unit(else_blk, correct_si, destination, this.tcx);
else_blk
};
}
// The `then` and `else` arms have been lowered into their respective
// blocks, so make both of them meet up in a new block.
let join_block = this.cfg.start_new_block();
this.cfg.goto(then_blk, source_info, join_block);
this.cfg.goto(else_blk, source_info, join_block);

View file

@ -137,6 +137,81 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
self.check_import_as_underscore(item, *id);
}
}
fn report_unused_extern_crate_items(
&mut self,
maybe_unused_extern_crates: FxHashMap<ast::NodeId, Span>,
) {
let tcx = self.r.tcx();
for extern_crate in &self.extern_crate_items {
let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_');
// If the crate is fully unused, we suggest removing it altogether.
// We do this in any edition.
if warn_if_unused {
if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) {
self.r.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_EXTERN_CRATES,
extern_crate.id,
span,
"unused extern crate",
BuiltinLintDiag::UnusedExternCrate {
removal_span: extern_crate.span_with_attributes,
},
);
continue;
}
}
// If we are not in Rust 2018 edition, then we don't make any further
// suggestions.
if !tcx.sess.at_least_rust_2018() {
continue;
}
// If the extern crate has any attributes, they may have funky
// semantics we can't faithfully represent using `use` (most
// notably `#[macro_use]`). Ignore it.
if extern_crate.has_attrs {
continue;
}
// If the extern crate is renamed, then we cannot suggest replacing it with a use as this
// would not insert the new name into the prelude, where other imports in the crate may be
// expecting it.
if extern_crate.renames {
continue;
}
// If the extern crate isn't in the extern prelude,
// there is no way it can be written as a `use`.
if !self
.r
.extern_prelude
.get(&extern_crate.ident)
.is_some_and(|entry| !entry.introduced_by_item)
{
continue;
}
let vis_span = extern_crate
.vis_span
.find_ancestor_inside(extern_crate.span)
.unwrap_or(extern_crate.vis_span);
let ident_span = extern_crate
.ident
.span
.find_ancestor_inside(extern_crate.span)
.unwrap_or(extern_crate.ident.span);
self.r.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_EXTERN_CRATES,
extern_crate.id,
extern_crate.span,
"`extern crate` is not idiomatic in the new edition",
BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span },
);
}
}
}
impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
@ -335,6 +410,8 @@ impl Resolver<'_, '_> {
};
visit::walk_crate(&mut visitor, krate);
visitor.report_unused_extern_crate_items(maybe_unused_extern_crates);
for unused in visitor.unused_imports.values() {
let mut fixes = Vec::new();
let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) {
@ -416,75 +493,6 @@ impl Resolver<'_, '_> {
);
}
for extern_crate in visitor.extern_crate_items {
let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_');
// If the crate is fully unused, we suggest removing it altogether.
// We do this in any edition.
if warn_if_unused {
if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) {
visitor.r.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_EXTERN_CRATES,
extern_crate.id,
span,
"unused extern crate",
BuiltinLintDiag::UnusedExternCrate {
removal_span: extern_crate.span_with_attributes,
},
);
continue;
}
}
// If we are not in Rust 2018 edition, then we don't make any further
// suggestions.
if !tcx.sess.at_least_rust_2018() {
continue;
}
// If the extern crate has any attributes, they may have funky
// semantics we can't faithfully represent using `use` (most
// notably `#[macro_use]`). Ignore it.
if extern_crate.has_attrs {
continue;
}
// If the extern crate is renamed, then we cannot suggest replacing it with a use as this
// would not insert the new name into the prelude, where other imports in the crate may be
// expecting it.
if extern_crate.renames {
continue;
}
// If the extern crate isn't in the extern prelude,
// there is no way it can be written as a `use`.
if !visitor
.r
.extern_prelude
.get(&extern_crate.ident)
.is_some_and(|entry| !entry.introduced_by_item)
{
continue;
}
let vis_span = extern_crate
.vis_span
.find_ancestor_inside(extern_crate.span)
.unwrap_or(extern_crate.vis_span);
let ident_span = extern_crate
.ident
.span
.find_ancestor_inside(extern_crate.span)
.unwrap_or(extern_crate.ident.span);
visitor.r.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_EXTERN_CRATES,
extern_crate.id,
extern_crate.span,
"`extern crate` is not idiomatic in the new edition",
BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span },
);
}
let unused_imports = visitor.unused_imports;
let mut check_redundant_imports = FxIndexSet::default();
for module in self.arenas.local_modules().iter() {

View file

@ -1336,9 +1336,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
let mut is_redundant = true;
let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
self.per_ns(|this, ns| {
if is_redundant && let Ok(binding) = source_bindings[ns].get() {
if binding.res() == Res::Err {

View file

@ -377,10 +377,12 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability)] = &[
// tidy-alphabetical-start
("d", Unstable(sym::loongarch_target_feature)),
("f", Unstable(sym::loongarch_target_feature)),
("frecipe", Unstable(sym::loongarch_target_feature)),
("lasx", Unstable(sym::loongarch_target_feature)),
("lbt", Unstable(sym::loongarch_target_feature)),
("lsx", Unstable(sym::loongarch_target_feature)),
("lvz", Unstable(sym::loongarch_target_feature)),
("relax", Unstable(sym::loongarch_target_feature)),
("ual", Unstable(sym::loongarch_target_feature)),
// tidy-alphabetical-end
];

View file

@ -102,7 +102,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
if trait_clause.def_id() == goal.predicate.def_id()
&& trait_clause.polarity() == goal.predicate.polarity
{
// FIXME: Constness
ecx.probe_misc_candidate("assumption").enter(|ecx| {
let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
ecx.eq(

View file

@ -4,7 +4,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, GenericArgs, ImplTraitInTraitData, Ty, TyCtxt};
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
use rustc_span::symbol::kw;
pub(crate) fn provide(providers: &mut Providers) {
@ -284,48 +284,8 @@ fn associated_type_for_impl_trait_in_trait(
// Copy defaultness of the containing function.
trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id));
// Copy type_of of the opaque.
trait_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_opaque(
tcx,
opaque_ty_def_id.to_def_id(),
GenericArgs::identity_for_item(tcx, opaque_ty_def_id),
)));
trait_assoc_ty.is_type_alias_impl_trait(false);
// Copy generics_of of the opaque type item but the trait is the parent.
trait_assoc_ty.generics_of({
let opaque_ty_generics = tcx.generics_of(opaque_ty_def_id);
let opaque_ty_parent_count = opaque_ty_generics.parent_count;
let mut params = opaque_ty_generics.params.clone();
let parent_generics = tcx.generics_of(trait_def_id);
let parent_count = parent_generics.parent_count + parent_generics.params.len();
let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
for param in &mut params {
param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
- opaque_ty_parent_count as u32;
}
trait_fn_params.extend(params);
params = trait_fn_params;
let param_def_id_to_index =
params.iter().map(|param| (param.def_id, param.index)).collect();
ty::Generics {
parent: Some(trait_def_id.to_def_id()),
parent_count,
params,
param_def_id_to_index,
has_self: opaque_ty_generics.has_self,
has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
host_effect_index: parent_generics.host_effect_index,
}
});
// There are no inferred outlives for the synthesized associated type.
trait_assoc_ty.inferred_outlives_of(&[]);
@ -382,8 +342,9 @@ fn associated_type_for_impl_trait_in_impl(
impl_assoc_ty.defaultness(tcx.defaultness(impl_fn_def_id));
// Copy generics_of the trait's associated item but the impl as the parent.
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) resolves to the trait instead of the impl
// generics.
// FIXME: This may be detrimental to diagnostics, as we resolve the early-bound vars
// here to paramswhose parent are items in the trait. We could synthesize new params
// here, but it seems overkill.
impl_assoc_ty.generics_of({
let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id);
let trait_assoc_parent_count = trait_assoc_generics.parent_count;

View file

@ -300,6 +300,10 @@
# This is only useful for verifying that rustc generates reproducible builds.
#full-bootstrap = false
# Set the bootstrap/download cache path. It is useful when building rust
# repeatedly in a CI invironment.
# bootstrap-cache-path = /shared/cache
# Enable a build of the extended Rust tool set which is not only the compiler
# but also tools such as Cargo. This will also produce "combined installers"
# which are used to install Rust and Cargo together.

View file

@ -360,6 +360,7 @@ where
}
}
/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
#[inline]

View file

@ -80,6 +80,7 @@ fn test_named_thread_truncation() {
#[test]
fn test_get_os_named_thread() {
use crate::sys::thread::Thread;
// Spawn a new thread to avoid interfering with other tests running on this thread.
let handler = thread::spawn(|| {
let name = c"test me please";
Thread::set_name(name);

View file

@ -557,7 +557,9 @@ class RustBuild(object):
shutil.rmtree(bin_root)
key = self.stage0_compiler.date
cache_dst = os.path.join(self.build_dir, "cache")
cache_dst = (self.get_toml('bootstrap-cache-path', 'build') or
os.path.join(self.build_dir, "cache"))
rustc_cache = os.path.join(cache_dst, key)
if not os.path.exists(rustc_cache):
os.makedirs(rustc_cache)

View file

@ -149,6 +149,7 @@ v("default-linker", "rust.default-linker", "the default linker")
# (others are conditionally saved).
o("manage-submodules", "build.submodules", "let the build manage the git submodules")
o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two (not recommended except for testing reproducible builds)")
o("bootstrap-cache-path", "build.bootstrap-cache-path", "use provided path for the bootstrap cache")
o("extended", "build.extended", "build an extended rust tool set")
v("tools", None, "List of extended tools will be installed")

View file

@ -81,7 +81,7 @@ fn update_rustfmt_version(build: &Builder<'_>) {
}
/// Returns the Rust files modified between the `merge-base` of HEAD and
/// rust-lang/master and what is now on the disk.
/// rust-lang/master and what is now on the disk. Does not include removed files.
///
/// Returns `None` if all files should be formatted.
fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, String> {

View file

@ -161,6 +161,7 @@ pub struct Config {
pub vendor: bool,
pub target_config: HashMap<TargetSelection, Target>,
pub full_bootstrap: bool,
pub bootstrap_cache_path: Option<PathBuf>,
pub extended: bool,
pub tools: Option<HashSet<String>>,
pub sanitizers: bool,
@ -827,6 +828,7 @@ define_config! {
locked_deps: Option<bool> = "locked-deps",
vendor: Option<bool> = "vendor",
full_bootstrap: Option<bool> = "full-bootstrap",
bootstrap_cache_path: Option<PathBuf> = "bootstrap-cache-path",
extended: Option<bool> = "extended",
tools: Option<HashSet<String>> = "tools",
verbose: Option<usize> = "verbose",
@ -1389,6 +1391,7 @@ impl Config {
locked_deps,
vendor,
full_bootstrap,
bootstrap_cache_path,
extended,
tools,
verbose,
@ -1477,6 +1480,7 @@ impl Config {
config.reuse = reuse.map(PathBuf::from);
config.submodules = submodules;
config.android_ndk = android_ndk;
config.bootstrap_cache_path = bootstrap_cache_path;
set(&mut config.low_priority, low_priority);
set(&mut config.compiler_docs, compiler_docs);
set(&mut config.library_docs_private_items, library_docs_private_items);

View file

@ -578,7 +578,9 @@ impl Config {
return;
}
let cache_dst = self.out.join("cache");
let cache_dst =
self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache"));
let cache_dir = cache_dst.join(key);
if !cache_dir.exists() {
t!(fs::create_dir_all(&cache_dir));
@ -705,7 +707,9 @@ download-rustc = false
let llvm_assertions = self.llvm_assertions;
let cache_prefix = format!("llvm-{llvm_sha}-{llvm_assertions}");
let cache_dst = self.out.join("cache");
let cache_dst =
self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache"));
let rustc_cache = cache_dst.join(cache_prefix);
if !rustc_cache.exists() {
t!(fs::create_dir_all(&rustc_cache));

View file

@ -136,4 +136,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Info,
summary: "`x install` now skips providing tarball sources (under 'build/dist' path) to speed up the installation process.",
},
ChangeInfo {
change_id: 121976,
severity: ChangeSeverity::Info,
summary: "A new `boostrap-cache-path` option has been introduced which can be utilized to modify the cache path for bootstrap.",
},
];

View file

@ -113,6 +113,7 @@ pub fn get_git_merge_base(
/// Returns the files that have been modified in the current branch compared to the master branch.
/// The `extensions` parameter can be used to filter the files by their extension.
/// Does not include removed files.
/// If `extensions` is empty, all files will be returned.
pub fn get_git_modified_files(
config: &GitConfig<'_>,
@ -125,13 +126,19 @@ pub fn get_git_modified_files(
if let Some(git_dir) = git_dir {
git.current_dir(git_dir);
}
let files = output_result(git.args(["diff-index", "--name-only", merge_base.trim()]))?
let files = output_result(git.args(["diff-index", "--name-status", merge_base.trim()]))?
.lines()
.map(|s| s.trim().to_owned())
.filter(|f| {
Path::new(f).extension().map_or(false, |ext| {
.filter_map(|f| {
let (status, name) = f.trim().split_once(char::is_whitespace).unwrap();
if status == "D" {
None
} else if Path::new(name).extension().map_or(false, |ext| {
extensions.is_empty() || extensions.contains(&ext.to_str().unwrap())
})
}) {
Some(name.to_owned())
} else {
None
}
})
.collect();
Ok(Some(files))

View file

@ -39,7 +39,7 @@
//@ revisions: loongarch64
//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
//@[loongarch64] needs-llvm-components: loongarch
//@[loongarch64] min-llvm-version: 17
//@[loongarch64] min-llvm-version: 18
//@ revisions: wasm
//@[wasm] compile-flags: --target wasm32-unknown-unknown
//@[wasm] needs-llvm-components: webassembly

View file

@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra`
LL | cfg!(target_feature = "zebra");
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2` and 186 more
= note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2` and 187 more
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
warning: 27 warnings emitted

View file

@ -154,7 +154,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
LL | target_feature = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt`
= note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt`
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`

View file

@ -0,0 +1,18 @@
//@ check-pass
// Check that we don't hit a query cycle when:
// 1. Computing generics_of, which requires...
// 2. Calling resolve_bound_vars, which requires...
// 3. Calling associated_items, which requires...
// 4. Calling associated_type_for_impl_trait_in_trait, which requires...
// 5. Computing generics_of, which cycles.
pub trait Foo<'a> {
type Assoc;
fn demo<T>(other: T) -> impl Foo<'a, Assoc = Self::Assoc>
where
T: Foo<'a, Assoc = ()>;
}
fn main() {}

View file

@ -0,0 +1 @@
pub fn item() {}

View file

@ -0,0 +1,11 @@
//@ compile-flags: --extern aux_issue_121915 --edition 2015
//@ aux-build: aux-issue-121915.rs
extern crate aux_issue_121915;
#[deny(unused_imports)]
fn main() {
use aux_issue_121915;
//~^ ERROR the item `aux_issue_121915` is imported redundantly
aux_issue_121915::item();
}

View file

@ -0,0 +1,17 @@
error: the item `aux_issue_121915` is imported redundantly
--> $DIR/redundant-import-issue-121915-2015.rs:8:9
|
LL | extern crate aux_issue_121915;
| ------------------------------ the item `aux_issue_121915` is already imported here
...
LL | use aux_issue_121915;
| ^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/redundant-import-issue-121915-2015.rs:6:8
|
LL | #[deny(unused_imports)]
| ^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -0,0 +1,9 @@
//@ compile-flags: --extern aux_issue_121915 --edition 2018
//@ aux-build: aux-issue-121915.rs
#[deny(unused_imports)]
fn main() {
use aux_issue_121915;
//~^ ERROR the item `aux_issue_121915` is imported redundantly
aux_issue_121915::item();
}

View file

@ -0,0 +1,14 @@
error: the item `aux_issue_121915` is imported redundantly
--> $DIR/redundant-import-issue-121915.rs:6:9
|
LL | use aux_issue_121915;
| ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by prelude
|
note: the lint level is defined here
--> $DIR/redundant-import-issue-121915.rs:4:8
|
LL | #[deny(unused_imports)]
| ^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -0,0 +1,40 @@
//@ compile-flags: --edition 2021
#![deny(unused_imports)]
#![allow(dead_code)]
fn test0() {
// Test remove FlatUnused
use std::convert::TryFrom;
//~^ ERROR the item `TryFrom` is imported redundantly
let _ = u32::try_from(5i32);
}
fn test1() {
// FIXME(yukang) Test remove NestedFullUnused
use std::convert::{TryFrom, TryInto};
//~^ ERROR the item `TryFrom` is imported redundantly
//~| ERROR the item `TryInto` is imported redundantly
let _ = u32::try_from(5i32);
let _a: i32 = u32::try_into(5u32).unwrap();
}
fn test2() {
// FIXME(yukang): Test remove both redundant and unused
use std::convert::{AsMut, Into};
//~^ ERROR unused import: `AsMut`
//~| ERROR the item `Into` is imported redundantly
let _a: u32 = (5u8).into();
}
fn test3() {
// Test remove NestedPartialUnused
use std::convert::{From, Infallible};
//~^ ERROR unused import: `From`
trait MyTrait {}
impl MyTrait for fn() -> Infallible {}
}
fn main() {}

View file

@ -0,0 +1,56 @@
error: the item `TryFrom` is imported redundantly
--> $DIR/suggest-remove-issue-121315.rs:7:9
|
LL | use std::convert::TryFrom;
| ^^^^^^^^^^^^^^^^^^^^^
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `TryFrom` is already defined here
|
note: the lint level is defined here
--> $DIR/suggest-remove-issue-121315.rs:2:9
|
LL | #![deny(unused_imports)]
| ^^^^^^^^^^^^^^
error: the item `TryFrom` is imported redundantly
--> $DIR/suggest-remove-issue-121315.rs:14:24
|
LL | use std::convert::{TryFrom, TryInto};
| ^^^^^^^
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `TryFrom` is already defined here
error: the item `TryInto` is imported redundantly
--> $DIR/suggest-remove-issue-121315.rs:14:33
|
LL | use std::convert::{TryFrom, TryInto};
| ^^^^^^^
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `TryInto` is already defined here
error: unused import: `AsMut`
--> $DIR/suggest-remove-issue-121315.rs:24:24
|
LL | use std::convert::{AsMut, Into};
| ^^^^^
error: the item `Into` is imported redundantly
--> $DIR/suggest-remove-issue-121315.rs:24:31
|
LL | use std::convert::{AsMut, Into};
| ^^^^
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
|
= note: the item `Into` is already defined here
error: unused import: `From`
--> $DIR/suggest-remove-issue-121315.rs:33:24
|
LL | use std::convert::{From, Infallible};
| ^^^^
error: aborting due to 6 previous errors