diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 9cc6c16c12639..c86788db988eb 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -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); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 417f0fceaa81f..2217e5280a736 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -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 { - 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); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 085e90260515b..61f0ab14e8c1c 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -686,6 +686,11 @@ pub fn create_global_ctxt<'tcx>( /// Runs the type-checking, region checking and other miscellaneous analysis /// passes on the crate. fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { + if tcx.sess.opts.unstable_opts.hir_stats { + rustc_passes::hir_stats::print_hir_stats(tcx); + } + + #[cfg(debug_assertions)] rustc_passes::hir_id_validator::check_crate(tcx); let sess = tcx.sess; diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index a58a37bf3ac08..a0be1c09c9a3d 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -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) => { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b0431ae05d395..ebfdf8aa197fb 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -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 } } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 9a6d44983520b..69f3d3101fa21 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -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 - )); - - this.expr_into_dest(destination, then_blk, then) - }); - then_block.and(else_block) - }, - ) + 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) + }; + + // 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`. + 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` 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); diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 02f56ecb10b57..dd6c116695784 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,38 +1,26 @@ use rustc_data_structures::sync::Lock; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_hir::intravisit; -use rustc_hir::{HirId, ItemLocalId}; +use rustc_hir::{intravisit, HirId, ItemLocalId}; use rustc_index::bit_set::GrowableBitSet; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; pub fn check_crate(tcx: TyCtxt<'_>) { - if tcx.sess.opts.unstable_opts.hir_stats { - crate::hir_stats::print_hir_stats(tcx); - } - - #[cfg(debug_assertions)] - { - let errors = Lock::new(Vec::new()); + let errors = Lock::new(Vec::new()); - tcx.hir().par_for_each_module(|module_id| { - let mut v = HirIdValidator { - tcx, - owner: None, - hir_ids_seen: Default::default(), - errors: &errors, - }; + tcx.hir().par_for_each_module(|module_id| { + let mut v = + HirIdValidator { tcx, owner: None, hir_ids_seen: Default::default(), errors: &errors }; - tcx.hir().visit_item_likes_in_module(module_id, &mut v); - }); + tcx.hir().visit_item_likes_in_module(module_id, &mut v); + }); - let errors = errors.into_inner(); + let errors = errors.into_inner(); - if !errors.is_empty() { - let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); - tcx.dcx().delayed_bug(message); - } + if !errors.is_empty() { + let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); + tcx.dcx().delayed_bug(message); } } @@ -90,7 +78,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.error(|| { format!( "ItemLocalIds not assigned densely in {pretty_owner}. \ - Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}" + Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}" ) }); } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 7227b185f4d3b..e03052bcfede8 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -28,6 +28,7 @@ mod debugger_visualizer; mod diagnostic_items; pub mod entry; mod errors; +#[cfg(debug_assertions)] pub mod hir_id_validator; pub mod hir_stats; mod lang_items; diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 13fec70e0a7f3..bf1ea2e270932 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -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, + ) { + 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() { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 6647a9a279285..80ec69ab318af 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -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 { diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 2b7ac68c21dfb..b5cee4f34f5ee 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -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 ]; diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 80198ba39f9be..16febf05b60e9 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -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( diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index db37bec4b827c..26d3370469a5d 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -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; diff --git a/config.example.toml b/config.example.toml index d12ed052fe4a8..c1939933850c4 100644 --- a/config.example.toml +++ b/config.example.toml @@ -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. diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 42663ff2b53f0..8b5b48c59c29b 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -360,6 +360,7 @@ where } } +/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for [T; N] { #[inline] diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 813ede0641530..b5195f9093f62 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -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); diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 0d604c0d3e5e0..6e49bcc974469 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -557,7 +557,9 @@ def download_toolchain(self): 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) diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 8b65e8ff9c3e1..4257c0f7991a6 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -149,6 +149,7 @@ def v(*args): # (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") diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 700c3ee4fdacf..fc9f9789bd683 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -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>, String> { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 875a4efae02fc..326f8f57173a1 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -161,6 +161,7 @@ pub struct Config { pub vendor: bool, pub target_config: HashMap, pub full_bootstrap: bool, + pub bootstrap_cache_path: Option, pub extended: bool, pub tools: Option>, pub sanitizers: bool, @@ -827,6 +828,7 @@ define_config! { locked_deps: Option = "locked-deps", vendor: Option = "vendor", full_bootstrap: Option = "full-bootstrap", + bootstrap_cache_path: Option = "bootstrap-cache-path", extended: Option = "extended", tools: Option> = "tools", verbose: Option = "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); diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 185089a646bfa..27829eab9379d 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -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)); diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 9a50ad4437e73..d166b84e51fc5 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -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.", + }, ]; diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index b91dc38e9248f..a3c857b0268c9 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -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)) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index a4f60ea268464..3ee4542810c65 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -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 diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 93333e5ef2a5b..007f9de033147 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -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 for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 86df829fe726c..49674daac2627 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -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 for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs b/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs new file mode 100644 index 0000000000000..882497d1015d3 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/rpitit-cycle-in-generics-of.rs @@ -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(other: T) -> impl Foo<'a, Assoc = Self::Assoc> + where + T: Foo<'a, Assoc = ()>; +} + +fn main() {} diff --git a/tests/ui/imports/auxiliary/aux-issue-121915.rs b/tests/ui/imports/auxiliary/aux-issue-121915.rs new file mode 100644 index 0000000000000..7f9f5bda79ffd --- /dev/null +++ b/tests/ui/imports/auxiliary/aux-issue-121915.rs @@ -0,0 +1 @@ +pub fn item() {} diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.rs b/tests/ui/imports/redundant-import-issue-121915-2015.rs new file mode 100644 index 0000000000000..d41d190bb58c4 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915-2015.rs @@ -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(); +} diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.stderr b/tests/ui/imports/redundant-import-issue-121915-2015.stderr new file mode 100644 index 0000000000000..174ed4fb96b11 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915-2015.stderr @@ -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 + diff --git a/tests/ui/imports/redundant-import-issue-121915.rs b/tests/ui/imports/redundant-import-issue-121915.rs new file mode 100644 index 0000000000000..237acc4af2565 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915.rs @@ -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(); +} diff --git a/tests/ui/imports/redundant-import-issue-121915.stderr b/tests/ui/imports/redundant-import-issue-121915.stderr new file mode 100644 index 0000000000000..0047d7c34207c --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915.stderr @@ -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 + diff --git a/tests/ui/imports/suggest-remove-issue-121315.rs b/tests/ui/imports/suggest-remove-issue-121315.rs new file mode 100644 index 0000000000000..63533480ec127 --- /dev/null +++ b/tests/ui/imports/suggest-remove-issue-121315.rs @@ -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() {} diff --git a/tests/ui/imports/suggest-remove-issue-121315.stderr b/tests/ui/imports/suggest-remove-issue-121315.stderr new file mode 100644 index 0000000000000..dbd742f6c781f --- /dev/null +++ b/tests/ui/imports/suggest-remove-issue-121315.stderr @@ -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 +