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 { pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
use rustc_hir::*; 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 hir_id = tcx.local_def_id_to_hir_id(def_id);
let node = tcx.hir_node(hir_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::query::plumbing::CyclePlaceholder;
use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::util::IntTypeExt; 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::symbol::Ident;
use rustc_span::{Span, DUMMY_SP}; 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 // 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 // side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the
// associated type in the impl. // associated type in the impl.
if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = match tcx.opt_rpitit_info(def_id.to_def_id()) {
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) {
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) { Ok(map) => {
Ok(map) => { let assoc_item = tcx.associated_item(def_id);
let assoc_item = tcx.associated_item(def_id); return map[&assoc_item.trait_item_def_id.unwrap()];
return map[&assoc_item.trait_item_def_id.unwrap()]; }
} Err(_) => {
Err(_) => { return ty::EarlyBinder::bind(Ty::new_error_with_message(
return ty::EarlyBinder::bind(Ty::new_error_with_message( tcx,
tcx, DUMMY_SP,
DUMMY_SP, "Could not collect return position impl trait in trait tys",
"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); 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) => { BuiltinLintDiag::RedundantImport(spans, ident) => {
for (span, is_imported) in spans { for (span, is_imported) in spans {
let introduced = if is_imported { "imported" } else { "defined" }; 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) => { 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 /// creates and returns the associated items that correspond to each impl trait in return position
/// of the implemented trait. /// of the implemented trait.
query associated_types_for_impl_traits_in_associated_fn(fn_def_id: DefId) -> &'tcx [DefId] { 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() } cache_on_disk_if { fn_def_id.is_local() }
separate_provide_extern separate_provide_extern
} }
@ -834,7 +834,7 @@ rustc_queries! {
/// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding /// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
/// associated item. /// associated item.
query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId { 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 } cache_on_disk_if { true }
} }

View File

@ -58,52 +58,61 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.thir[scrutinee].span, this.thir[scrutinee].span,
), ),
ExprKind::If { cond, then, else_opt, if_then_scope } => { ExprKind::If { cond, then, else_opt, if_then_scope } => {
let then_blk;
let then_span = this.thir[then].span; let then_span = this.thir[then].span;
let then_source_info = this.source_info(then_span); let then_source_info = this.source_info(then_span);
let condition_scope = this.local_scope(); let condition_scope = this.local_scope();
let mut else_blk = unpack!( let then_and_else_blocks = this.in_scope(
then_blk = this.in_scope( (if_then_scope, then_source_info),
(if_then_scope, then_source_info), LintLevel::Inherited,
LintLevel::Inherited, |this| {
|this| { // FIXME: Does this need extra logic to handle let-chains?
let source_info = if this.is_let(cond) { let source_info = if this.is_let(cond) {
let variable_scope = let variable_scope =
this.new_source_scope(then_span, LintLevel::Inherited, None); this.new_source_scope(then_span, LintLevel::Inherited, None);
this.source_scope = variable_scope; this.source_scope = variable_scope;
SourceInfo { span: then_span, scope: variable_scope } SourceInfo { span: then_span, scope: variable_scope }
} else { } else {
this.source_info(then_span) 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
));
this.expr_into_dest(destination, then_blk, then) // Lower the condition, and have it branch into `then` and `else` blocks.
}); let (then_block, else_block) =
then_block.and(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 `BlockAnd<BasicBlock>` into `(then_blk, else_blk)`.
unpack!(this.expr_into_dest(destination, else_blk, else_opt)) 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 { } else {
// Body of the `if` expression without an `else` clause must return `()`, thus // There is no `else` arm, so we know both arms have type `()`.
// we implicitly generate an `else {}` if it is not specified. // Generate the implicit `else {}` by assigning unit.
let correct_si = this.source_info(expr_span.shrink_to_hi()); let correct_si = this.source_info(expr_span.shrink_to_hi());
this.cfg.push_assign_unit(else_blk, correct_si, destination, this.tcx); 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(); let join_block = this.cfg.start_new_block();
this.cfg.goto(then_blk, source_info, join_block); this.cfg.goto(then_blk, source_info, join_block);
this.cfg.goto(else_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); 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> { impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
@ -335,6 +410,8 @@ impl Resolver<'_, '_> {
}; };
visit::walk_crate(&mut visitor, krate); visit::walk_crate(&mut visitor, krate);
visitor.report_unused_extern_crate_items(maybe_unused_extern_crates);
for unused in visitor.unused_imports.values() { for unused in visitor.unused_imports.values() {
let mut fixes = Vec::new(); let mut fixes = Vec::new();
let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) { 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 unused_imports = visitor.unused_imports;
let mut check_redundant_imports = FxIndexSet::default(); let mut check_redundant_imports = FxIndexSet::default();
for module in self.arenas.local_modules().iter() { 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 is_redundant = true;
let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None }; let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
self.per_ns(|this, ns| { self.per_ns(|this, ns| {
if is_redundant && let Ok(binding) = source_bindings[ns].get() { if is_redundant && let Ok(binding) = source_bindings[ns].get() {
if binding.res() == Res::Err { if binding.res() == Res::Err {

View File

@ -377,10 +377,12 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability)] = &[
// tidy-alphabetical-start // tidy-alphabetical-start
("d", Unstable(sym::loongarch_target_feature)), ("d", Unstable(sym::loongarch_target_feature)),
("f", Unstable(sym::loongarch_target_feature)), ("f", Unstable(sym::loongarch_target_feature)),
("frecipe", Unstable(sym::loongarch_target_feature)),
("lasx", Unstable(sym::loongarch_target_feature)), ("lasx", Unstable(sym::loongarch_target_feature)),
("lbt", Unstable(sym::loongarch_target_feature)), ("lbt", Unstable(sym::loongarch_target_feature)),
("lsx", Unstable(sym::loongarch_target_feature)), ("lsx", Unstable(sym::loongarch_target_feature)),
("lvz", Unstable(sym::loongarch_target_feature)), ("lvz", Unstable(sym::loongarch_target_feature)),
("relax", Unstable(sym::loongarch_target_feature)),
("ual", Unstable(sym::loongarch_target_feature)), ("ual", Unstable(sym::loongarch_target_feature)),
// tidy-alphabetical-end // 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() if trait_clause.def_id() == goal.predicate.def_id()
&& trait_clause.polarity() == goal.predicate.polarity && trait_clause.polarity() == goal.predicate.polarity
{ {
// FIXME: Constness
ecx.probe_misc_candidate("assumption").enter(|ecx| { ecx.probe_misc_candidate("assumption").enter(|ecx| {
let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
ecx.eq( ecx.eq(

View File

@ -4,7 +4,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::query::Providers; 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; use rustc_span::symbol::kw;
pub(crate) fn provide(providers: &mut Providers) { 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. // Copy defaultness of the containing function.
trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id)); 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); 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. // There are no inferred outlives for the synthesized associated type.
trait_assoc_ty.inferred_outlives_of(&[]); 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)); impl_assoc_ty.defaultness(tcx.defaultness(impl_fn_def_id));
// Copy generics_of the trait's associated item but the impl as the parent. // 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 // FIXME: This may be detrimental to diagnostics, as we resolve the early-bound vars
// generics. // here to paramswhose parent are items in the trait. We could synthesize new params
// here, but it seems overkill.
impl_assoc_ty.generics_of({ impl_assoc_ty.generics_of({
let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id); let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id);
let trait_assoc_parent_count = trait_assoc_generics.parent_count; 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. # This is only useful for verifying that rustc generates reproducible builds.
#full-bootstrap = false #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 # 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" # but also tools such as Cargo. This will also produce "combined installers"
# which are used to install Rust and Cargo together. # 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")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] { impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
#[inline] #[inline]

View File

@ -80,6 +80,7 @@ fn test_named_thread_truncation() {
#[test] #[test]
fn test_get_os_named_thread() { fn test_get_os_named_thread() {
use crate::sys::thread::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 handler = thread::spawn(|| {
let name = c"test me please"; let name = c"test me please";
Thread::set_name(name); Thread::set_name(name);

View File

@ -557,7 +557,9 @@ class RustBuild(object):
shutil.rmtree(bin_root) shutil.rmtree(bin_root)
key = self.stage0_compiler.date 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) rustc_cache = os.path.join(cache_dst, key)
if not os.path.exists(rustc_cache): if not os.path.exists(rustc_cache):
os.makedirs(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). # (others are conditionally saved).
o("manage-submodules", "build.submodules", "let the build manage the git submodules") 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("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") o("extended", "build.extended", "build an extended rust tool set")
v("tools", None, "List of extended tools will be installed") 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 /// 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. /// Returns `None` if all files should be formatted.
fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, String> { 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 vendor: bool,
pub target_config: HashMap<TargetSelection, Target>, pub target_config: HashMap<TargetSelection, Target>,
pub full_bootstrap: bool, pub full_bootstrap: bool,
pub bootstrap_cache_path: Option<PathBuf>,
pub extended: bool, pub extended: bool,
pub tools: Option<HashSet<String>>, pub tools: Option<HashSet<String>>,
pub sanitizers: bool, pub sanitizers: bool,
@ -827,6 +828,7 @@ define_config! {
locked_deps: Option<bool> = "locked-deps", locked_deps: Option<bool> = "locked-deps",
vendor: Option<bool> = "vendor", vendor: Option<bool> = "vendor",
full_bootstrap: Option<bool> = "full-bootstrap", full_bootstrap: Option<bool> = "full-bootstrap",
bootstrap_cache_path: Option<PathBuf> = "bootstrap-cache-path",
extended: Option<bool> = "extended", extended: Option<bool> = "extended",
tools: Option<HashSet<String>> = "tools", tools: Option<HashSet<String>> = "tools",
verbose: Option<usize> = "verbose", verbose: Option<usize> = "verbose",
@ -1389,6 +1391,7 @@ impl Config {
locked_deps, locked_deps,
vendor, vendor,
full_bootstrap, full_bootstrap,
bootstrap_cache_path,
extended, extended,
tools, tools,
verbose, verbose,
@ -1477,6 +1480,7 @@ impl Config {
config.reuse = reuse.map(PathBuf::from); config.reuse = reuse.map(PathBuf::from);
config.submodules = submodules; config.submodules = submodules;
config.android_ndk = android_ndk; config.android_ndk = android_ndk;
config.bootstrap_cache_path = bootstrap_cache_path;
set(&mut config.low_priority, low_priority); set(&mut config.low_priority, low_priority);
set(&mut config.compiler_docs, compiler_docs); set(&mut config.compiler_docs, compiler_docs);
set(&mut config.library_docs_private_items, library_docs_private_items); set(&mut config.library_docs_private_items, library_docs_private_items);

View File

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

View File

@ -136,4 +136,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Info, severity: ChangeSeverity::Info,
summary: "`x install` now skips providing tarball sources (under 'build/dist' path) to speed up the installation process.", 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. /// 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. /// 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. /// If `extensions` is empty, all files will be returned.
pub fn get_git_modified_files( pub fn get_git_modified_files(
config: &GitConfig<'_>, config: &GitConfig<'_>,
@ -125,13 +126,19 @@ pub fn get_git_modified_files(
if let Some(git_dir) = git_dir { if let Some(git_dir) = git_dir {
git.current_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() .lines()
.map(|s| s.trim().to_owned()) .filter_map(|f| {
.filter(|f| { let (status, name) = f.trim().split_once(char::is_whitespace).unwrap();
Path::new(f).extension().map_or(false, |ext| { if status == "D" {
None
} else if Path::new(name).extension().map_or(false, |ext| {
extensions.is_empty() || extensions.contains(&ext.to_str().unwrap()) extensions.is_empty() || extensions.contains(&ext.to_str().unwrap())
}) }) {
Some(name.to_owned())
} else {
None
}
}) })
.collect(); .collect();
Ok(Some(files)) Ok(Some(files))

View File

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

View File

@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra`
LL | cfg!(target_feature = "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 = 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 warning: 27 warnings emitted

View File

@ -154,7 +154,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
LL | target_feature = "_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 = 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` 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