diff --git a/Cargo.lock b/Cargo.lock index 5feb21a65b774..635146492b042 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3970,6 +3970,7 @@ version = "0.0.0" dependencies = [ "itertools 0.11.0", "rustc_ast", + "rustc_ast_ir", "rustc_attr", "rustc_data_structures", "rustc_errors", @@ -4038,6 +4039,7 @@ dependencies = [ name = "rustc_infer" version = "0.0.0" dependencies = [ + "rustc_ast_ir", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4632,6 +4634,7 @@ dependencies = [ "bitflags 2.4.2", "itertools 0.11.0", "rustc_ast", + "rustc_ast_ir", "rustc_attr", "rustc_data_structures", "rustc_errors", @@ -4670,6 +4673,7 @@ name = "rustc_transmute" version = "0.0.0" dependencies = [ "itertools 0.11.0", + "rustc_ast_ir", "rustc_data_structures", "rustc_hir", "rustc_infer", @@ -4685,6 +4689,7 @@ name = "rustc_ty_utils" version = "0.0.0" dependencies = [ "itertools 0.11.0", + "rustc_ast_ir", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index f29022386a9d3..9efb87e53cde9 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -15,11 +15,12 @@ use crate::ast::*; -use core::ops::ControlFlow; - use rustc_span::symbol::Ident; use rustc_span::Span; +pub use rustc_ast_ir::visit::VisitorResult; +pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list}; + #[derive(Copy, Clone, Debug, PartialEq)] pub enum AssocCtxt { Trait, @@ -101,51 +102,6 @@ pub enum LifetimeCtxt { GenericArg, } -/// Similar to the `Try` trait, but also implemented for `()`. -pub trait VisitorResult { - type Residual; - fn output() -> Self; - fn from_residual(residual: Self::Residual) -> Self; - fn branch(self) -> ControlFlow; -} - -impl VisitorResult for () { - type Residual = !; - - fn output() -> Self {} - fn from_residual(_: !) -> Self {} - fn branch(self) -> ControlFlow { - ControlFlow::Continue(()) - } -} - -impl VisitorResult for ControlFlow { - type Residual = T; - - fn output() -> Self { - ControlFlow::Continue(()) - } - fn from_residual(residual: Self::Residual) -> Self { - ControlFlow::Break(residual) - } - fn branch(self) -> ControlFlow { - self - } -} - -#[macro_export] -macro_rules! try_visit { - ($e:expr) => { - match $crate::visit::VisitorResult::branch($e) { - core::ops::ControlFlow::Continue(()) => (), - #[allow(unreachable_code)] - core::ops::ControlFlow::Break(r) => { - return $crate::visit::VisitorResult::from_residual(r); - } - } - }; -} - /// Each method of the `Visitor` trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; @@ -316,24 +272,6 @@ pub trait Visitor<'ast>: Sized { } } -#[macro_export] -macro_rules! walk_list { - ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => { - for elem in $list { - $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?)); - } - } -} - -#[macro_export] -macro_rules! visit_opt { - ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => { - if let Some(x) = $opt { - $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?)); - } - } -} - pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result { walk_list!(visitor, visit_item, &krate.items); walk_list!(visitor, visit_attribute, &krate.attrs); diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index 9fe1370921345..ff7a155204716 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(feature = "nightly", feature(never_type))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![cfg_attr(feature = "nightly", allow(internal_features))] @@ -5,6 +6,8 @@ #[macro_use] extern crate rustc_macros; +pub mod visit; + /// The movability of a coroutine / closure literal: /// whether a coroutine contains self-references, causing it to be `!Unpin`. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] diff --git a/compiler/rustc_ast_ir/src/visit.rs b/compiler/rustc_ast_ir/src/visit.rs new file mode 100644 index 0000000000000..dec9f7a47d09d --- /dev/null +++ b/compiler/rustc_ast_ir/src/visit.rs @@ -0,0 +1,82 @@ +use core::ops::ControlFlow; + +/// Similar to the `Try` trait, but also implemented for `()`. +pub trait VisitorResult { + type Residual; + fn output() -> Self; + fn from_residual(residual: Self::Residual) -> Self; + fn from_branch(b: ControlFlow) -> Self; + fn branch(self) -> ControlFlow; +} + +impl VisitorResult for () { + #[cfg(feature = "nightly")] + type Residual = !; + + #[cfg(not(feature = "nightly"))] + type Residual = core::ops::Infallible; + + fn output() -> Self {} + fn from_residual(_: Self::Residual) -> Self {} + fn from_branch(_: ControlFlow) -> Self {} + fn branch(self) -> ControlFlow { + ControlFlow::Continue(()) + } +} + +impl VisitorResult for ControlFlow { + type Residual = T; + + fn output() -> Self { + ControlFlow::Continue(()) + } + fn from_residual(residual: Self::Residual) -> Self { + ControlFlow::Break(residual) + } + fn from_branch(b: Self) -> Self { + b + } + fn branch(self) -> Self { + self + } +} + +#[macro_export] +macro_rules! try_visit { + ($e:expr) => { + match $crate::visit::VisitorResult::branch($e) { + core::ops::ControlFlow::Continue(()) => (), + #[allow(unreachable_code)] + core::ops::ControlFlow::Break(r) => { + return $crate::visit::VisitorResult::from_residual(r); + } + } + }; +} + +#[macro_export] +macro_rules! visit_opt { + ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => { + if let Some(x) = $opt { + $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?)); + } + } +} + +#[macro_export] +macro_rules! walk_list { + ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => { + for elem in $list { + $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?)); + } + } +} + +#[macro_export] +macro_rules! walk_visitable_list { + ($visitor: expr, $list: expr $(, $($extra_args: expr),* )?) => { + for elem in $list { + $crate::try_visit!(elem.visit_with($visitor $(, $($extra_args,)* )?)); + } + } +} diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b56d695c6716a..ba283c75f3fff 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -8,8 +8,7 @@ use itertools::{Either, Itertools}; use rustc_ast::ptr::P; -use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; -use rustc_ast::walk_list; +use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 386d4a54b655b..fae0e1d380c0c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -2,7 +2,8 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::errors; use rustc_ast as ast; -use rustc_ast::{attr, walk_list, EnumDef, VariantData}; +use rustc_ast::visit::walk_list; +use rustc_ast::{attr, EnumDef, VariantData}; use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; use rustc_span::symbol::Ident; use rustc_span::symbol::{kw, sym}; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 2a13671a82978..3427368421f8e 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -30,9 +30,9 @@ where } impl<'tcx> TypeVisitor> for UsedParamsNeedInstantiationVisitor<'tcx> { - type BreakTy = FoundParam; + type Result = ControlFlow; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if !ty.has_param() { return ControlFlow::Continue(()); } @@ -64,7 +64,7 @@ where } } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { match c.kind() { ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam), _ => c.super_visit_with(self), diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index c98dc4deb7579..0b41b4f96820b 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -17,7 +17,7 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt}; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor}; use std::mem; -use std::ops::{ControlFlow, Deref}; +use std::ops::Deref; use super::ops::{self, NonConstOp, Status}; use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; @@ -164,9 +164,9 @@ struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> { } impl<'ck, 'mir, 'tcx> TypeVisitor> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { - ty::FnPtr(_) => ControlFlow::Continue(()), + ty::FnPtr(_) => {} ty::Ref(_, _, hir::Mutability::Mut) => { self.checker.check_op(ops::ty::MutRef(self.kind)); t.super_visit_with(self) diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs index 50a614a1b0279..07a361ba26088 100644 --- a/compiler/rustc_data_structures/src/sync/worker_local.rs +++ b/compiler/rustc_data_structures/src/sync/worker_local.rs @@ -42,7 +42,7 @@ pub struct Registry(Arc); thread_local! { /// The registry associated with the thread. /// This allows the `WorkerLocal` type to clone the registry in its constructor. - static REGISTRY: OnceCell = OnceCell::new(); + static REGISTRY: OnceCell = const { OnceCell::new() }; } struct ThreadData { diff --git a/compiler/rustc_errors/src/markdown/term.rs b/compiler/rustc_errors/src/markdown/term.rs index 88c3c8b9ff2c4..06c1333d93dd0 100644 --- a/compiler/rustc_errors/src/markdown/term.rs +++ b/compiler/rustc_errors/src/markdown/term.rs @@ -9,9 +9,9 @@ const DEFAULT_COLUMN_WIDTH: usize = 140; thread_local! { /// Track the position of viewable characters in our buffer - static CURSOR: Cell = Cell::new(0); + static CURSOR: Cell = const { Cell::new(0) }; /// Width of the terminal - static WIDTH: Cell = Cell::new(DEFAULT_COLUMN_WIDTH); + static WIDTH: Cell = const { Cell::new(DEFAULT_COLUMN_WIDTH) }; } /// Print to terminal output to a buffer diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 9bc7b4bdd1e13..72d4d3c17eb1c 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -14,8 +14,7 @@ use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult}; -use rustc_ast::{try_visit, walk_list}; +use rustc_ast::visit::{self, try_visit, walk_list, AssocCtxt, Visitor, VisitorResult}; use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind}; use rustc_ast::{ForeignItemKind, HasAttrs, HasNodeId}; use rustc_ast::{Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind}; diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 1c38a45d3a32f..88e0238b5235e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -65,8 +65,7 @@ //! example coroutine inference, and possibly also HIR borrowck. use crate::hir::*; -use rustc_ast::visit::VisitorResult; -use rustc_ast::{try_visit, visit_opt, walk_list}; +use rustc_ast::visit::{try_visit, visit_opt, walk_list, VisitorResult}; use rustc_ast::{Attribute, Label}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{Ident, Symbol}; diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 96bebda582815..8bf207f634adb 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1474,15 +1474,14 @@ fn opaque_type_cycle_error( closures: Vec, } impl<'tcx> ty::visit::TypeVisitor> for OpaqueTypeCollector { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match *t.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { self.opaques.push(def); - ControlFlow::Continue(()) } ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => { self.closures.push(def_id); - t.super_visit_with(self) + t.super_visit_with(self); } _ => t.super_visit_with(self), } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 29dc434ab4532..8c4c4fc774ec8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -12,7 +12,6 @@ use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{ elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt, }; -use std::ops::ControlFlow; /// Check that an implementation does not refine an RPITIT from a trait method signature. pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( @@ -211,9 +210,7 @@ struct ImplTraitInTraitCollector<'tcx> { } impl<'tcx> TypeVisitor> for ImplTraitInTraitCollector<'tcx> { - type BreakTy = !; - - fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { if let ty::Alias(ty::Projection, proj) = *ty.kind() && self.tcx.is_impl_trait_in_trait(proj.def_id) { @@ -223,12 +220,11 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitCollector<'tcx> { .explicit_item_bounds(proj.def_id) .iter_instantiated_copied(self.tcx, proj.args) { - pred.visit_with(self)?; + pred.visit_with(self); } } - ControlFlow::Continue(()) } else { - ty.super_visit_with(self) + ty.super_visit_with(self); } } } diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 0f5fd7e99b776..2a4dd6b0e0ef3 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -6,7 +6,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html -use rustc_ast::walk_list; +use rustc_ast::visit::walk_list; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f03d0f8a88529..bec7b7bd9742d 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -809,9 +809,7 @@ impl<'tcx> GATArgsCollector<'tcx> { } impl<'tcx> TypeVisitor> for GATArgsCollector<'tcx> { - type BreakTy = !; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Alias(ty::Projection, p) if p.def_id == self.gat => { for (idx, arg) in p.args.iter().enumerate() { @@ -1456,20 +1454,19 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id params: FxHashSet, } impl<'tcx> ty::visit::TypeVisitor> for CountParams { - type BreakTy = (); - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + type Result = ControlFlow<()>; + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if let ty::Param(param) = t.kind() { self.params.insert(param.index); } t.super_visit_with(self) } - fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, _: ty::Region<'tcx>) -> Self::Result { ControlFlow::Break(()) } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { if let ty::ConstKind::Param(param) = c.kind() { self.params.insert(param.index); } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index ae01bf845751a..ad8ec1036efee 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -6,7 +6,7 @@ //! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file //! is also responsible for assigning their semantics to implicit lifetimes in trait objects. -use rustc_ast::walk_list; +use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; @@ -1964,31 +1964,26 @@ fn is_late_bound_map( arg_is_constrained: Box<[bool]>, } - use std::ops::ControlFlow; use ty::Ty; impl<'tcx> TypeVisitor> for ConstrainedCollectorPostAstConv { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Param(param_ty) => { self.arg_is_constrained[param_ty.index as usize] = true; } - ty::Alias(ty::Projection | ty::Inherent, _) => return ControlFlow::Continue(()), + ty::Alias(ty::Projection | ty::Inherent, _) => return, _ => (), } t.super_visit_with(self) } - fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow { - ControlFlow::Continue(()) - } + fn visit_const(&mut self, _: ty::Const<'tcx>) {} - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { debug!("r={:?}", r.kind()); if let ty::RegionKind::ReEarlyParam(region) = r.kind() { self.arg_is_constrained[region.index as usize] = true; } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index b8de2e46934dd..3b8bb0731fbd8 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -1,9 +1,8 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; use rustc_type_ir::fold::TypeFoldable; -use std::ops::ControlFlow; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct Parameter(pub u32); @@ -61,13 +60,13 @@ struct ParameterCollector { } impl<'tcx> TypeVisitor> for ParameterCollector { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match *t.kind() { // Projections are not injective in general. ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) if !self.include_nonconstraining => { - return ControlFlow::Continue(()); + return; } // All weak alias types should've been expanded beforehand. ty::Alias(ty::Weak, _) if !self.include_nonconstraining => { @@ -80,18 +79,17 @@ impl<'tcx> TypeVisitor> for ParameterCollector { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::ReEarlyParam(data) = *r { self.parameters.push(Parameter::from(data)); } - ControlFlow::Continue(()) } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { match c.kind() { ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => { // Constant expressions are not injective in general. - return c.ty().visit_with(self); + return; } ty::ConstKind::Param(data) => { self.parameters.push(Parameter::from(data)); diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 4d5dcbadc4a24..9618c6d8011ff 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -10,7 +10,6 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable}; -use std::ops::ControlFlow; /// Defines the `TermsContext` basically houses an arena where we can /// allocate terms. @@ -89,15 +88,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> { #[instrument(level = "trace", skip(self), ret)] - fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow { + fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) { if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) { let child_variances = self.tcx.variances_of(def_id); for (a, v) in args.iter().zip_eq(child_variances) { if *v != ty::Bivariant { - a.visit_with(self)?; + a.visit_with(self); } } - ControlFlow::Continue(()) } else { args.visit_with(self) } @@ -106,20 +104,19 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc impl<'tcx> ty::TypeVisitor> for OpaqueTypeLifetimeCollector<'tcx> { #[instrument(level = "trace", skip(self), ret)] - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() { self.variances[ebr.index as usize] = ty::Invariant; } - ControlFlow::Continue(()) } #[instrument(level = "trace", skip(self), ret)] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Alias(_, ty::AliasTy { def_id, args, .. }) if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) => { - self.visit_opaque(*def_id, args) + self.visit_opaque(*def_id, args); } _ => t.super_visit_with(self), } diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 975f93756427e..0a5fa37ed04fa 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" # tidy-alphabetical-start itertools = "0.11" rustc_ast = { path = "../rustc_ast" } +rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 5bdd9412d0e51..b8078413611f5 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -396,9 +396,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty: Ty<'tcx>, } impl<'tcx> TypeVisitor> for MentionsTy<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if t == self.expected_ty { ControlFlow::Break(()) } else { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index f0631dd4b5fb8..a9a5a89a41363 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -337,8 +337,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option> { struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId); impl<'tcx> TypeVisitor> for FindAmbiguousParameter<'_, 'tcx> { - type BreakTy = ty::GenericArg<'tcx>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + type Result = ControlFlow>; + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if let Some(origin) = self.0.type_var_origin(ty) && let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind && let generics = self.0.tcx.generics_of(self.1) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 440d0ad1140c4..893b3f9534de9 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -166,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } - match ty.kind() { + match ty.peel_refs().kind() { ty::Param(param) => { let generics = self.tcx.generics_of(self.body_id); let generic_param = generics.type_param(¶m, self.tcx); @@ -184,7 +184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - ty::Alias(ty::AliasKind::Opaque, _) => { + ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::AliasKind::Opaque, _) => { for unsatisfied in unsatisfied_predicates.iter() { if is_iterator_predicate(unsatisfied.0, self.tcx) { return true; diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 73a02a431dfc0..c1565a7d40fd5 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -8,6 +8,7 @@ doctest = false [dependencies] # tidy-alphabetical-start +rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 342f18a18dcc2..362ca3b4833ea 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -79,7 +79,7 @@ use rustc_middle::ty::{ use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; use std::borrow::Cow; -use std::ops::{ControlFlow, Deref}; +use std::ops::Deref; use std::path::PathBuf; use std::{cmp, fmt, iter}; @@ -1623,7 +1623,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } impl<'tcx> ty::visit::TypeVisitor> for OpaqueTypesVisitor<'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) { let span = self.tcx.def_span(def_id); // Avoid cluttering the output when the "found" and error span overlap: diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 33538309b042a..adde45f081afe 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -23,7 +23,6 @@ use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_span::def_id::LocalDefId; -use std::ops::ControlFlow; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static `impl Trait`, @@ -545,13 +544,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { pub struct TraitObjectVisitor(pub FxIndexSet); impl<'tcx> TypeVisitor> for TraitObjectVisitor { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Dynamic(preds, re, _) if re.is_static() => { if let Some(def_id) = preds.principal_def_id() { self.0.insert(def_id); } - ControlFlow::Continue(()) } _ => t.super_visit_with(self), } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index ded628fe13663..b4cf727bf8f1a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -16,8 +16,6 @@ use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; use rustc_span::Span; -use std::ops::ControlFlow; - impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option { @@ -76,12 +74,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } impl<'tcx> ty::visit::TypeVisitor> for HighlightBuilder<'tcx> { - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if !r.has_name() && self.counter <= 3 { self.highlight.highlighting_region(r, self.counter); self.counter += 1; } - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 7a789a1b41bca..9f11b3ddb61d7 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::{ TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_span::Span; -use std::ops::ControlFlow; mod table; @@ -415,29 +414,22 @@ impl<'tcx, OP> TypeVisitor> for ConstrainOpaqueTypeRegionVisitor<'t where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { t.super_visit_with(self); - ControlFlow::Continue(()) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { match *r { // ignore bound regions, keep visiting - ty::ReBound(_, _) => ControlFlow::Continue(()), - _ => { - (self.op)(r); - ControlFlow::Continue(()) - } + ty::ReBound(_, _) => {} + _ => (self.op)(r), } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { // We're only interested in types involving regions if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) { - return ControlFlow::Continue(()); + return; } match ty.kind() { @@ -488,8 +480,6 @@ where ty.super_visit_with(self); } } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index 42e3d6cad5a97..488f435994d4d 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -2,8 +2,6 @@ use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use std::ops::ControlFlow; - use crate::infer::outlives::test_type_match; use crate::infer::region_constraints::VerifyIfEq; @@ -26,29 +24,22 @@ impl<'tcx, OP> TypeVisitor> for FreeRegionsVisitor<'tcx, OP> where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { t.super_visit_with(self); - ControlFlow::Continue(()) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { match *r { // ignore bound regions, keep visiting - ty::ReBound(_, _) => ControlFlow::Continue(()), - _ => { - (self.op)(r); - ControlFlow::Continue(()) - } + ty::ReBound(_, _) => {} + _ => (self.op)(r), } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { // We're only interested in types involving regions if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) { - return ControlFlow::Continue(()); + return; } // FIXME: Don't consider alias bounds on types that have escaping bound @@ -102,7 +93,7 @@ where && outlives_bounds[1..].iter().all(|other_r| other_r == r) { assert!(r.type_flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS)); - r.visit_with(self)?; + r.visit_with(self); } else { // Skip lifetime parameters that are not captures. let variances = match kind { @@ -114,17 +105,13 @@ where if variances.map(|variances| variances[idx]) != Some(ty::Variance::Bivariant) { - s.visit_with(self)?; + s.visit_with(self); } } } } - _ => { - ty.super_visit_with(self)?; - } + _ => ty.super_visit_with(self), } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index bf4f88530d04e..064e09b875068 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -1,11 +1,11 @@ use crate::traits; use crate::traits::project::Normalized; +use rustc_ast_ir::try_visit; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable}; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor}; use rustc_middle::ty::{self, TyCtxt}; use std::fmt; -use std::ops::ControlFlow; // Structural impls for the structs in `traits`. @@ -84,8 +84,8 @@ impl<'tcx, O: TypeFoldable>> TypeFoldable> impl<'tcx, O: TypeVisitable>> TypeVisitable> for traits::Obligation<'tcx, O> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.predicate.visit_with(visitor)?; + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.predicate.visit_with(visitor)); self.param_env.visit_with(visitor) } } diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 728996f07417c..2692344337973 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -114,6 +114,9 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: diag.span_label(span, format!("the item `{ident}` is already {introduced} here")); } } + BuiltinLintDiagnostics::RedundantImportRemove(span) => { + diag.span_suggestion(span, "remove this import", "", Applicability::MachineApplicable); + } BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => { stability::deprecation_suggestion(diag, "macro", suggestion, span) } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 0862204d88e2d..d78ec8c0dd348 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -17,8 +17,8 @@ use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; use rustc_ast::ptr::P; -use rustc_ast::visit::{self as ast_visit, Visitor}; -use rustc_ast::{self as ast, walk_list, HasAttrs}; +use rustc_ast::visit::{self as ast_visit, walk_list, Visitor}; +use rustc_ast::{self as ast, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_feature::Features; use rustc_middle::ty::RegisteredTools; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index a87e2410b3d8e..df2b763c77540 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1474,9 +1474,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { struct ProhibitOpaqueTypes; impl<'tcx> ty::visit::TypeVisitor> for ProhibitOpaqueTypes { - type BreakTy = Ty<'tcx>; + type Result = ControlFlow>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if !ty.has_opaque_types() { return ControlFlow::Continue(()); } @@ -1620,9 +1620,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } impl<'vis, 'a, 'tcx> ty::visit::TypeVisitor> for FnPtrFinder<'vis, 'a, 'tcx> { - type BreakTy = Ty<'tcx>; + type Result = ControlFlow>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if let ty::FnPtr(sig) = ty.kind() && !self.visitor.is_internal_abi(sig.abi()) { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 198008d4d0db6..06f312f6030aa 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -578,6 +578,7 @@ pub enum BuiltinLintDiagnostics { UnknownCrateTypes(Span, String, String), UnusedImports(String, Vec<(Span, String)>, Option), RedundantImport(Vec<(Span, bool)>, Ident), + RedundantImportRemove(Span), DeprecatedMacro(Option, Span), MissingAbi(Span, Abi), UnusedDocComment(Span), diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs index c8430380345b4..94e86e0e246fe 100644 --- a/compiler/rustc_macros/src/type_visitable.rs +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -34,7 +34,14 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: s.add_bounds(synstructure::AddBounds::Generics); let body_visit = s.each(|bind| { quote! { - ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?; + match ::rustc_ast_ir::visit::VisitorResult::branch( + ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor) + ) { + ::core::ops::ControlFlow::Continue(()) => {}, + ::core::ops::ControlFlow::Break(r) => { + return ::rustc_ast_ir::visit::VisitorResult::from_residual(r); + }, + } } }); s.bind_with(|_| synstructure::BindStyle::Move); @@ -45,9 +52,9 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>( &self, __visitor: &mut __V - ) -> ::std::ops::ControlFlow<__V::BreakTy> { + ) -> __V::Result { match *self { #body_visit } - ::std::ops::ControlFlow::Continue(()) + <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output() } }, ) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index f65fe1a29c7cc..564c35f881d60 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1132,7 +1132,13 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result { // Only try to recover from this specific error. if !matches!(err, libloading::Error::LoadLibraryExW { .. }) { - return Err(err.to_string()); + let err = format_dlopen_err(&err); + // We include the path of the dylib in the error ourselves, so + // if it's in the error, we strip it. + if let Some(err) = err.strip_prefix(&format!(": {}", path.display())) { + return Err(err.to_string()); + } + return Err(err); } last_error = Some(err); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index db27e2bd6301b..4960369a0a7a9 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -3,8 +3,7 @@ use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; use rustc_ast as ast; -use rustc_ast::visit::VisitorResult; -use rustc_ast::walk_list; +use rustc_ast::visit::{walk_list, VisitorResult}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index 26ca90db018e6..0ee97a6bed037 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -85,9 +85,9 @@ macro_rules! TrivialTypeTraversalImpls { fn visit_with>>( &self, _: &mut F) - -> ::std::ops::ControlFlow + -> F::Result { - ::std::ops::ControlFlow::Continue(()) + ::output() } } )+ diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 0dc6512601121..95139b50cb89e 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -1,6 +1,6 @@ -use std::ops::ControlFlow; - +use rustc_ast_ir::try_visit; use rustc_data_structures::intern::Interned; +use rustc_span::def_id::DefId; use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; use crate::traits::query::NoSolution; @@ -9,7 +9,6 @@ use crate::ty::{ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, }; -use rustc_span::def_id::DefId; use super::BuiltinImplSource; @@ -196,13 +195,9 @@ impl<'tcx> TypeFoldable> for ExternalConstraints<'tcx> { } impl<'tcx> TypeVisitable> for ExternalConstraints<'tcx> { - fn visit_with>>( - &self, - visitor: &mut V, - ) -> std::ops::ControlFlow { - self.region_constraints.visit_with(visitor)?; - self.opaque_types.visit_with(visitor)?; - ControlFlow::Continue(()) + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.region_constraints.visit_with(visitor)); + self.opaque_types.visit_with(visitor) } } @@ -235,10 +230,7 @@ impl<'tcx> TypeFoldable> for PredefinedOpaques<'tcx> { } impl<'tcx> TypeVisitable> for PredefinedOpaques<'tcx> { - fn visit_with>>( - &self, - visitor: &mut V, - ) -> std::ops::ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { self.opaque_types.visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 712fbf2444053..2506456f1fb11 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -482,9 +482,9 @@ pub struct IsSuggestableVisitor<'tcx> { } impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { match *t.kind() { Infer(InferTy::TyVar(_)) if self.infer_suggestable => {} @@ -536,7 +536,7 @@ impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { t.super_visit_with(self) } - fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result { match c.kind() { ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {} diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index c87ef870a084e..8079ad121ad9e 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -6,6 +6,8 @@ use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineCon use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; +use rustc_ast_ir::visit::VisitorResult; +use rustc_ast_ir::walk_visitable_list; use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagnosticArg}; use rustc_hir::def_id::DefId; @@ -19,7 +21,7 @@ use std::cmp::Ordering; use std::marker::PhantomData; use std::mem; use std::num::NonZero; -use std::ops::{ControlFlow, Deref}; +use std::ops::Deref; use std::ptr::NonNull; /// An entity in the Rust type system, which can be one of @@ -240,7 +242,7 @@ impl<'tcx> TypeFoldable> for GenericArg<'tcx> { } impl<'tcx> TypeVisitable> for GenericArg<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { match self.unpack() { GenericArgKind::Lifetime(lt) => lt.visit_with(visitor), GenericArgKind::Type(ty) => ty.visit_with(visitor), @@ -554,8 +556,9 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List> { impl<'tcx, T: TypeVisitable>> TypeVisitable> for &'tcx ty::List { #[inline] - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f005a24050442..d966d6f0ac179 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -32,7 +32,7 @@ pub use generic_args::*; pub use generics::*; use rustc_ast as ast; use rustc_ast::node_id::NodeMap; -pub use rustc_ast_ir::{Movability, Mutability}; +pub use rustc_ast_ir::{try_visit, Movability, Mutability}; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; @@ -63,7 +63,6 @@ use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::mem; use std::num::NonZero; -use std::ops::ControlFlow; use std::ptr::NonNull; use std::{fmt, str}; @@ -597,7 +596,7 @@ impl<'tcx> TypeFoldable> for Term<'tcx> { } impl<'tcx> TypeVisitable> for Term<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { self.unpack().visit_with(visitor) } } @@ -1041,8 +1040,8 @@ impl<'tcx> TypeFoldable> for ParamEnv<'tcx> { } impl<'tcx> TypeVisitable> for ParamEnv<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.caller_bounds().visit_with(visitor)?; + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.caller_bounds().visit_with(visitor)); self.reveal().visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 540803d953016..c8c9afa7f4d05 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -27,7 +27,7 @@ use std::cell::Cell; use std::collections::BTreeMap; use std::fmt::{self, Write as _}; use std::iter; -use std::ops::{ControlFlow, Deref, DerefMut}; +use std::ops::{Deref, DerefMut}; // `pretty` is a separate module only for organization. use super::*; @@ -2667,9 +2667,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } impl<'tcx> ty::visit::TypeVisitor> for RegionNameCollector<'tcx> { - type BreakTy = (); - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { trace!("address: {:p}", r.0.0); // Collect all named lifetimes. These allow us to prevent duplication @@ -2678,18 +2676,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(name) = r.get_name() { self.used_region_names.insert(name); } - - ControlFlow::Continue(()) } // We collect types in order to prevent really large types from compiling for // a really long time. See issue #83150 for why this is necessary. - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { let not_previously_inserted = self.type_collector.insert(ty); if not_previously_inserted { ty.super_visit_with(self) - } else { - ControlFlow::Continue(()) } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index c6805ba932357..c8fb11673cf89 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -8,13 +8,14 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use rustc_hir::def::Namespace; use rustc_span::source_map::Spanned; use rustc_target::abi::TyAndLayout; use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx}; use std::fmt::{self, Debug}; -use std::ops::ControlFlow; use super::print::PrettyPrinter; use super::{GenericArg, GenericArgKind, Region}; @@ -482,11 +483,8 @@ impl<'a, 'tcx> Lift<'tcx> for Term<'a> { // Traversal implementations. impl<'tcx> TypeVisitable> for ty::AdtDef<'tcx> { - fn visit_with>>( - &self, - _visitor: &mut V, - ) -> ControlFlow { - ControlFlow::Continue(()) + fn visit_with>>(&self, _visitor: &mut V) -> V::Result { + V::Result::output() } } @@ -500,7 +498,7 @@ impl<'tcx, T: TypeFoldable>> TypeFoldable> for ty::Bin } impl<'tcx, T: TypeVisitable>> TypeVisitable> for ty::Binder<'tcx, T> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_binder(self) } } @@ -517,10 +515,7 @@ impl<'tcx, T: TypeFoldable>> TypeSuperFoldable> for ty impl<'tcx, T: TypeVisitable>> TypeSuperVisitable> for ty::Binder<'tcx, T> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { self.as_ref().skip_binder().visit_with(visitor) } } @@ -553,7 +548,7 @@ impl<'tcx> TypeFoldable> for Ty<'tcx> { } impl<'tcx> TypeVisitable> for Ty<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_ty(*self) } } @@ -609,27 +604,24 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { } impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { match self.kind() { ty::RawPtr(ref tm) => tm.visit_with(visitor), ty::Array(typ, sz) => { - typ.visit_with(visitor)?; + try_visit!(typ.visit_with(visitor)); sz.visit_with(visitor) } ty::Slice(typ) => typ.visit_with(visitor), ty::Adt(_, args) => args.visit_with(visitor), ty::Dynamic(ref trait_ty, ref reg, _) => { - trait_ty.visit_with(visitor)?; + try_visit!(trait_ty.visit_with(visitor)); reg.visit_with(visitor) } ty::Tuple(ts) => ts.visit_with(visitor), ty::FnDef(_, args) => args.visit_with(visitor), ty::FnPtr(ref f) => f.visit_with(visitor), ty::Ref(r, ty, _) => { - r.visit_with(visitor)?; + try_visit!(r.visit_with(visitor)); ty.visit_with(visitor) } ty::Coroutine(_did, ref args) => args.visit_with(visitor), @@ -650,7 +642,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { | ty::Placeholder(..) | ty::Param(..) | ty::Never - | ty::Foreign(..) => ControlFlow::Continue(()), + | ty::Foreign(..) => V::Result::output(), } } } @@ -665,7 +657,7 @@ impl<'tcx> TypeFoldable> for ty::Region<'tcx> { } impl<'tcx> TypeVisitable> for ty::Region<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_region(*self) } } @@ -690,13 +682,13 @@ impl<'tcx> TypeFoldable> for ty::Clause<'tcx> { } impl<'tcx> TypeVisitable> for ty::Predicate<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_predicate(*self) } } impl<'tcx> TypeVisitable> for ty::Clause<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_predicate(self.as_predicate()) } } @@ -712,10 +704,7 @@ impl<'tcx> TypeSuperFoldable> for ty::Predicate<'tcx> { } impl<'tcx> TypeSuperVisitable> for ty::Predicate<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { self.kind().visit_with(visitor) } } @@ -739,7 +728,7 @@ impl<'tcx> TypeFoldable> for ty::Const<'tcx> { } impl<'tcx> TypeVisitable> for ty::Const<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_const(*self) } } @@ -771,16 +760,13 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { } impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { - self.ty().visit_with(visitor)?; + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.ty().visit_with(visitor)); match self.kind() { ConstKind::Param(p) => p.visit_with(visitor), ConstKind::Infer(i) => i.visit_with(visitor), ConstKind::Bound(d, b) => { - d.visit_with(visitor)?; + try_visit!(d.visit_with(visitor)); b.visit_with(visitor) } ConstKind::Placeholder(p) => p.visit_with(visitor), @@ -802,25 +788,19 @@ impl<'tcx> TypeFoldable> for InferConst { } impl<'tcx> TypeVisitable> for InferConst { - fn visit_with>>( - &self, - _visitor: &mut V, - ) -> ControlFlow { - ControlFlow::Continue(()) + fn visit_with>>(&self, _visitor: &mut V) -> V::Result { + V::Result::output() } } impl<'tcx> TypeSuperVisitable> for ty::UnevaluatedConst<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { self.args.visit_with(visitor) } } impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_ty(self.ty) } } @@ -828,10 +808,9 @@ impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { impl<'tcx, T: TypeVisitable> + Debug + Clone> TypeVisitable> for Spanned { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.node.visit_with(visitor)?; - self.span.visit_with(visitor)?; - ControlFlow::Continue(()) + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.node.visit_with(visitor)); + self.span.visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 53690cc58111f..e57303b8f8305 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2108,9 +2108,9 @@ impl<'tcx> Ty<'tcx> { struct ContainsTyVisitor<'tcx>(Ty<'tcx>); impl<'tcx> TypeVisitor> for ContainsTyVisitor<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) } } } @@ -2126,9 +2126,9 @@ impl<'tcx> Ty<'tcx> { struct ContainsClosureVisitor; impl<'tcx> TypeVisitor> for ContainsClosureVisitor { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if let ty::Closure(..) = t.kind() { ControlFlow::Break(()) } else { diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 59d09c3dc7821..218567bbd59e8 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -64,19 +64,19 @@ impl<'tcx> TyCtxt<'tcx> { where F: FnMut(ty::Region<'tcx>) -> bool, { - type BreakTy = (); + type Result = ControlFlow<()>; fn visit_binder>>( &mut self, t: &Binder<'tcx, T>, - ) -> ControlFlow { + ) -> Self::Result { self.outer_index.shift_in(1); let result = t.super_visit_with(self); self.outer_index.shift_out(1); result } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { match *r { ty::ReBound(debruijn, _) if debruijn < self.outer_index => { ControlFlow::Continue(()) @@ -91,7 +91,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { // We're only interested in types involving regions if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) { ty.super_visit_with(self) @@ -140,8 +140,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut collector = LateBoundRegionsCollector::new(just_constrained); let value = value.skip_binder(); let value = if just_constrained { self.expand_weak_alias_tys(value) } else { value }; - let result = value.visit_with(&mut collector); - assert!(result.is_continue()); // should never have stopped early + value.visit_with(&mut collector); collector.regions } } @@ -165,19 +164,19 @@ impl<'tcx> ValidateBoundVars<'tcx> { } impl<'tcx> TypeVisitor> for ValidateBoundVars<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; fn visit_binder>>( &mut self, t: &Binder<'tcx, T>, - ) -> ControlFlow { + ) -> Self::Result { self.binder_index.shift_in(1); let result = t.super_visit_with(self); self.binder_index.shift_out(1); result } - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if t.outer_exclusive_binder() < self.binder_index || !self.visited.insert((self.binder_index, t)) { @@ -211,7 +210,7 @@ impl<'tcx> TypeVisitor> for ValidateBoundVars<'tcx> { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { match *r { ty::ReBound(index, br) if index == self.binder_index => { if self.bound_vars.len() <= br.var.as_usize() { @@ -266,23 +265,19 @@ impl LateBoundRegionsCollector { } impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { - fn visit_binder>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) { self.current_index.shift_in(1); - let result = t.super_visit_with(self); + t.super_visit_with(self); self.current_index.shift_out(1); - result } - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { if self.just_constrained { match t.kind() { // If we are only looking for "constrained" regions, we have to ignore the // inputs to a projection as they may not appear in the normalized form. ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) => { - return ControlFlow::Continue(()); + return; } // All weak alias types should've been expanded beforehand. ty::Alias(ty::Weak, _) => bug!("unexpected weak alias type"), @@ -293,26 +288,25 @@ impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { t.super_visit_with(self) } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { // if we are only looking for "constrained" region, we have to // ignore the inputs of an unevaluated const, as they may not appear // in the normalized form if self.just_constrained { if let ty::ConstKind::Unevaluated(..) = c.kind() { - return ControlFlow::Continue(()); + return; } } c.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::ReBound(debruijn, br) = *r { if debruijn == self.current_index { self.regions.insert(br.kind); } } - ControlFlow::Continue(()) } } @@ -332,7 +326,7 @@ impl MaxUniverse { } impl<'tcx> TypeVisitor> for MaxUniverse { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { if let ty::Placeholder(placeholder) = t.kind() { self.max_universe = ty::UniverseIndex::from_u32( self.max_universe.as_u32().max(placeholder.universe.as_u32()), @@ -342,7 +336,7 @@ impl<'tcx> TypeVisitor> for MaxUniverse { t.super_visit_with(self) } - fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::consts::Const<'tcx>) { if let ty::ConstKind::Placeholder(placeholder) = c.kind() { self.max_universe = ty::UniverseIndex::from_u32( self.max_universe.as_u32().max(placeholder.universe.as_u32()), @@ -352,13 +346,11 @@ impl<'tcx> TypeVisitor> for MaxUniverse { c.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::RePlaceholder(placeholder) = *r { self.max_universe = ty::UniverseIndex::from_u32( self.max_universe.as_u32().max(placeholder.universe.as_u32()), ); } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index f2cf6fe613c33..9a6d44983520b 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -81,10 +81,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let then_blk = unpack!(this.then_else_break( block, cond, - Some(condition_scope), + Some(condition_scope), // Temp scope condition_scope, source_info, - true, + true, // Declare `let` bindings normally )); this.expr_into_dest(destination, then_blk, then) @@ -146,9 +146,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.then_else_break( block, lhs, - Some(condition_scope), + Some(condition_scope), // Temp scope condition_scope, source_info, + // This flag controls how inner `let` expressions are lowered, + // but either way there shouldn't be any of those in here. true, ) }); diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index a6273b92e5d69..29ee07f5d79b7 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -30,21 +30,55 @@ mod util; use std::borrow::Borrow; use std::mem; +/// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded +/// to recursive invocations. +#[derive(Clone, Copy)] +struct ThenElseArgs { + /// Used as the temp scope for lowering `expr`. If absent (for match guards), + /// `self.local_scope()` is used. + temp_scope_override: Option, + /// Scope to pass to [`Builder::break_for_else`]. Must match the scope used + /// by the enclosing call to [`Builder::in_if_then_scope`]. + break_scope: region::Scope, + variable_source_info: SourceInfo, + /// Forwarded to [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`]. + /// When false (for match guards), `let` bindings won't be declared. + declare_let_bindings: bool, +} + impl<'a, 'tcx> Builder<'a, 'tcx> { /// Lowers a condition in a way that ensures that variables bound in any let /// expressions are definitely initialized in the if body. /// - /// If `declare_bindings` is false then variables created in `let` + /// If `declare_let_bindings` is false then variables created in `let` /// expressions will not be declared. This is for if let guards on arms with /// an or pattern, where the guard is lowered multiple times. pub(crate) fn then_else_break( &mut self, - mut block: BasicBlock, + block: BasicBlock, expr_id: ExprId, temp_scope_override: Option, break_scope: region::Scope, variable_source_info: SourceInfo, - declare_bindings: bool, + declare_let_bindings: bool, + ) -> BlockAnd<()> { + self.then_else_break_inner( + block, + expr_id, + ThenElseArgs { + temp_scope_override, + break_scope, + variable_source_info, + declare_let_bindings, + }, + ) + } + + fn then_else_break_inner( + &mut self, + block: BasicBlock, // Block that the condition and branch will be lowered into + expr_id: ExprId, // Condition expression to lower + args: ThenElseArgs, ) -> BlockAnd<()> { let this = self; let expr = &this.thir[expr_id]; @@ -52,54 +86,36 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match expr.kind { ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => { - let lhs_then_block = unpack!(this.then_else_break( - block, - lhs, - temp_scope_override, - break_scope, - variable_source_info, - declare_bindings, - )); - - let rhs_then_block = unpack!(this.then_else_break( - lhs_then_block, - rhs, - temp_scope_override, - break_scope, - variable_source_info, - declare_bindings, - )); - + let lhs_then_block = unpack!(this.then_else_break_inner(block, lhs, args)); + let rhs_then_block = unpack!(this.then_else_break_inner(lhs_then_block, rhs, args)); rhs_then_block.unit() } ExprKind::LogicalOp { op: LogicalOp::Or, lhs, rhs } => { let local_scope = this.local_scope(); let (lhs_success_block, failure_block) = this.in_if_then_scope(local_scope, expr_span, |this| { - this.then_else_break( + this.then_else_break_inner( block, lhs, - temp_scope_override, - local_scope, - variable_source_info, - true, + ThenElseArgs { + break_scope: local_scope, + declare_let_bindings: true, + ..args + }, ) }); - let rhs_success_block = unpack!(this.then_else_break( + let rhs_success_block = unpack!(this.then_else_break_inner( failure_block, rhs, - temp_scope_override, - break_scope, - variable_source_info, - true, + ThenElseArgs { declare_let_bindings: true, ..args }, )); // Make the LHS and RHS success arms converge to a common block. // (We can't just make LHS goto RHS, because `rhs_success_block` // might contain statements that we don't want on the LHS path.) let success_block = this.cfg.start_new_block(); - this.cfg.goto(lhs_success_block, variable_source_info, success_block); - this.cfg.goto(rhs_success_block, variable_source_info, success_block); + this.cfg.goto(lhs_success_block, args.variable_source_info, success_block); + this.cfg.goto(rhs_success_block, args.variable_source_info, success_block); success_block.unit() } ExprKind::Unary { op: UnOp::Not, arg } => { @@ -111,50 +127,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if this.tcx.sess.instrument_coverage() { this.cfg.push_coverage_span_marker(block, this.source_info(expr_span)); } - this.then_else_break( + this.then_else_break_inner( block, arg, - temp_scope_override, - local_scope, - variable_source_info, - true, + ThenElseArgs { + break_scope: local_scope, + declare_let_bindings: true, + ..args + }, ) }); - this.break_for_else(success_block, break_scope, variable_source_info); + this.break_for_else(success_block, args.break_scope, args.variable_source_info); failure_block.unit() } ExprKind::Scope { region_scope, lint_level, value } => { let region_scope = (region_scope, this.source_info(expr_span)); this.in_scope(region_scope, lint_level, |this| { - this.then_else_break( - block, - value, - temp_scope_override, - break_scope, - variable_source_info, - declare_bindings, - ) + this.then_else_break_inner(block, value, args) }) } - ExprKind::Use { source } => this.then_else_break( - block, - source, - temp_scope_override, - break_scope, - variable_source_info, - declare_bindings, - ), + ExprKind::Use { source } => this.then_else_break_inner(block, source, args), ExprKind::Let { expr, ref pat } => this.lower_let_expr( block, expr, pat, - break_scope, - Some(variable_source_info.scope), - variable_source_info.span, - declare_bindings, + args.break_scope, + Some(args.variable_source_info.scope), + args.variable_source_info.span, + args.declare_let_bindings, ), _ => { - let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope()); + let mut block = block; + let temp_scope = args.temp_scope_override.unwrap_or_else(|| this.local_scope()); let mutability = Mutability::Mut; let place = unpack!(block = this.as_temp(block, Some(temp_scope), expr_id, mutability)); @@ -166,7 +170,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = this.source_info(expr_span); this.cfg.terminate(block, source_info, term); - this.break_for_else(else_block, break_scope, source_info); + this.break_for_else(else_block, args.break_scope, source_info); then_block.unit() } @@ -2105,10 +2109,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.then_else_break( block, guard, - None, + None, // Use `self.local_scope()` as the temp scope match_scope, this.source_info(arm.span), - false, + false, // For guards, `let` bindings are declared separately ) }); diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index fb42532e247af..1070d1a1380d8 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -18,7 +18,6 @@ use rustc_middle::ty::{ GenericArgsRef, Ty, TyCtxt, UnusedGenericParams, }; use rustc_span::symbol::sym; -use std::ops::ControlFlow; use crate::errors::UnusedGenericParamsHint; @@ -291,31 +290,29 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor> for MarkUsedGenericParams<'a, 'tcx> { #[instrument(level = "debug", skip(self))] - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { if !c.has_non_region_param() { - return ControlFlow::Continue(()); + return; } match c.kind() { ty::ConstKind::Param(param) => { debug!(?param); self.unused_parameters.mark_used(param.index); - ControlFlow::Continue(()) } ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) if matches!(self.tcx.def_kind(def), DefKind::AnonConst) => { self.visit_child_body(def, args); - ControlFlow::Continue(()) } _ => c.super_visit_with(self), } } #[instrument(level = "debug", skip(self))] - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { if !ty.has_non_region_param() { - return ControlFlow::Continue(()); + return; } match *ty.kind() { @@ -323,18 +320,16 @@ impl<'a, 'tcx> TypeVisitor> for MarkUsedGenericParams<'a, 'tcx> { debug!(?def_id); // Avoid cycle errors with coroutines. if def_id == self.def_id { - return ControlFlow::Continue(()); + return; } // Consider any generic parameters used by any closures/coroutines as used in the // parent. self.visit_child_body(def_id, args); - ControlFlow::Continue(()) } ty::Param(param) => { debug!(?param); self.unused_parameters.mark_used(param.index); - ControlFlow::Continue(()) } _ => ty.super_visit_with(self), } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9d8a9f5fce3e4..fe3598616817b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -11,6 +11,7 @@ extern crate tracing; mod errors; +use rustc_ast::visit::{try_visit, VisitorResult}; use rustc_ast::MacroDef; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; @@ -67,17 +68,13 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> { /// manually. Second, it doesn't visit some type components like signatures of fn types, or traits /// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`. trait DefIdVisitor<'tcx> { - type BreakTy = (); + type Result: VisitorResult = (); const SHALLOW: bool = false; const SKIP_ASSOC_TYS: bool = false; fn tcx(&self) -> TyCtxt<'tcx>; - fn visit_def_id( - &mut self, - def_id: DefId, - kind: &str, - descr: &dyn fmt::Display, - ) -> ControlFlow; + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) + -> Self::Result; /// Not overridden, but used to actually visit types and traits. fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> { @@ -87,25 +84,16 @@ trait DefIdVisitor<'tcx> { dummy: Default::default(), } } - fn visit( - &mut self, - ty_fragment: impl TypeVisitable>, - ) -> ControlFlow { + fn visit(&mut self, ty_fragment: impl TypeVisitable>) -> Self::Result { ty_fragment.visit_with(&mut self.skeleton()) } - fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow { + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> Self::Result { self.skeleton().visit_trait(trait_ref) } - fn visit_predicates( - &mut self, - predicates: ty::GenericPredicates<'tcx>, - ) -> ControlFlow { + fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> Self::Result { self.skeleton().visit_clauses(predicates.predicates) } - fn visit_clauses( - &mut self, - clauses: &[(ty::Clause<'tcx>, Span)], - ) -> ControlFlow { + fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result { self.skeleton().visit_clauses(clauses) } } @@ -120,36 +108,42 @@ impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V> where V: DefIdVisitor<'tcx> + ?Sized, { - fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow { + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> V::Result { let TraitRef { def_id, args, .. } = trait_ref; - self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?; - if V::SHALLOW { ControlFlow::Continue(()) } else { args.visit_with(self) } + try_visit!(self.def_id_visitor.visit_def_id( + def_id, + "trait", + &trait_ref.print_only_trait_path() + )); + if V::SHALLOW { V::Result::output() } else { args.visit_with(self) } } - fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow { + fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> V::Result { let tcx = self.def_id_visitor.tcx(); let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx); - self.visit_trait(trait_ref)?; + try_visit!(self.visit_trait(trait_ref)); if V::SHALLOW { - ControlFlow::Continue(()) + V::Result::output() } else { - assoc_args.iter().try_for_each(|arg| arg.visit_with(self)) + V::Result::from_branch( + assoc_args.iter().try_for_each(|arg| arg.visit_with(self).branch()), + ) } } - fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> ControlFlow { + fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> V::Result { match clause.kind().skip_binder() { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { self.visit_trait(trait_ref) } ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { - term.visit_with(self)?; + try_visit!(term.visit_with(self)); self.visit_projection_ty(projection_ty) } ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self), - ty::ClauseKind::RegionOutlives(..) => ControlFlow::Continue(()), + ty::ClauseKind::RegionOutlives(..) => V::Result::output(), ty::ClauseKind::ConstArgHasType(ct, ty) => { - ct.visit_with(self)?; + try_visit!(ct.visit_with(self)); ty.visit_with(self) } ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self), @@ -157,8 +151,11 @@ where } } - fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow { - clauses.into_iter().try_for_each(|&(clause, _span)| self.visit_clause(clause)) + fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> V::Result { + for &(clause, _) in clauses { + try_visit!(self.visit_clause(clause)); + } + V::Result::output() } } @@ -166,13 +163,13 @@ impl<'tcx, V> TypeVisitor> for DefIdVisitorSkeleton<'_, 'tcx, V> where V: DefIdVisitor<'tcx> + ?Sized, { - type BreakTy = V::BreakTy; + type Result = V::Result; - fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> Self::Result { self.visit_clause(p.as_clause().unwrap()) } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { let tcx = self.def_id_visitor.tcx(); // GenericArgs are not visited here because they are visited below // in `super_visit_with`. @@ -183,16 +180,16 @@ where | ty::Closure(def_id, ..) | ty::CoroutineClosure(def_id, ..) | ty::Coroutine(def_id, ..) => { - self.def_id_visitor.visit_def_id(def_id, "type", &ty)?; + try_visit!(self.def_id_visitor.visit_def_id(def_id, "type", &ty)); if V::SHALLOW { - return ControlFlow::Continue(()); + return V::Result::output(); } // Default type visitor doesn't visit signatures of fn types. // Something like `fn() -> Priv {my_func}` is considered a private type even if // `my_func` is public, so we need to visit signatures. if let ty::FnDef(..) = ty.kind() { // FIXME: this should probably use `args` from `FnDef` - tcx.fn_sig(def_id).instantiate_identity().visit_with(self)?; + try_visit!(tcx.fn_sig(def_id).instantiate_identity().visit_with(self)); } // Inherent static methods don't have self type in args. // Something like `fn() {my_method}` type of the method @@ -200,7 +197,9 @@ where // so we need to visit the self type additionally. if let Some(assoc_item) = tcx.opt_associated_item(def_id) { if let Some(impl_def_id) = assoc_item.impl_container(tcx) { - tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)?; + try_visit!( + tcx.type_of(impl_def_id).instantiate_identity().visit_with(self) + ); } } } @@ -211,10 +210,10 @@ where // as visible/reachable even if `Type` is private. // Ideally, associated types should be instantiated in the same way as // free type aliases, but this isn't done yet. - return ControlFlow::Continue(()); + return V::Result::output(); } - self.def_id_visitor.visit_def_id( + try_visit!(self.def_id_visitor.visit_def_id( data.def_id, match kind { ty::Inherent | ty::Projection => "associated type", @@ -222,15 +221,17 @@ where ty::Opaque => unreachable!(), }, &LazyDefPathStr { def_id: data.def_id, tcx }, - )?; + )); // This will also visit args if necessary, so we don't need to recurse. return if V::SHALLOW { - ControlFlow::Continue(()) + V::Result::output() } else if kind == ty::Projection { self.visit_projection_ty(data) } else { - data.args.iter().try_for_each(|arg| arg.visit_with(self)) + V::Result::from_branch( + data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()), + ) }; } ty::Dynamic(predicates, ..) => { @@ -245,7 +246,7 @@ where } }; let ty::ExistentialTraitRef { def_id, args: _ } = trait_ref; - self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?; + try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)); } } ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { @@ -258,7 +259,7 @@ where // through the trait list (default type visitor doesn't visit those traits). // All traits in the list are considered the "primary" part of the type // and are visited by shallow visitors. - self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())?; + try_visit!(self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())); } } // These types don't have their own def-ids (but may have subcomponents @@ -285,10 +286,10 @@ where } } - if V::SHALLOW { ControlFlow::Continue(()) } else { ty.super_visit_with(self) } + if V::SHALLOW { V::Result::output() } else { ty.super_visit_with(self) } } - fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result { let tcx = self.def_id_visitor.tcx(); tcx.expand_abstract_consts(c).super_visit_with(self) } @@ -316,16 +317,10 @@ impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx> fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn visit_def_id( - &mut self, - def_id: DefId, - _kind: &str, - _descr: &dyn fmt::Display, - ) -> ControlFlow { + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) { if let Some(def_id) = def_id.as_local() { self.min = VL::new_min(self, def_id); } - ControlFlow::Continue(()) } } @@ -836,12 +831,7 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> fn tcx(&self) -> TyCtxt<'tcx> { self.ev.tcx } - fn visit_def_id( - &mut self, - def_id: DefId, - _kind: &str, - _descr: &dyn fmt::Display, - ) -> ControlFlow { + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) { if let Some(def_id) = def_id.as_local() { // All effective visibilities except `reachable_through_impl_trait` are limited to // nominal visibility. If any type or trait is leaked farther than that, it will @@ -850,7 +840,6 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> .then(|| self.ev.tcx.local_visibility(def_id)); self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level); } - ControlFlow::Continue(()) } } @@ -1076,8 +1065,8 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { } impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> { - type BreakTy = (); - fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> ControlFlow<()> { + type Result = ControlFlow<()>; + fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> Self::Result { self.span = span; value.visit_with(&mut self.skeleton()) } @@ -1233,6 +1222,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { } impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { + type Result = ControlFlow<()>; fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1241,7 +1231,7 @@ impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { def_id: DefId, kind: &str, descr: &dyn fmt::Display, - ) -> ControlFlow { + ) -> Self::Result { if self.check_def_id(def_id, kind, descr) { ControlFlow::Break(()) } else { @@ -1407,6 +1397,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { + type Result = ControlFlow<()>; fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1415,7 +1406,7 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { def_id: DefId, kind: &str, descr: &dyn fmt::Display, - ) -> ControlFlow { + ) -> Self::Result { if self.check_def_id(def_id, kind, descr) { ControlFlow::Break(()) } else { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 9bfca0f179880..d3a6885fe9147 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1336,7 +1336,6 @@ 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 { @@ -1368,12 +1367,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut redundant_spans: Vec<_> = redundant_span.present_items().collect(); redundant_spans.sort(); redundant_spans.dedup(); + let is_preload = self.extern_prelude_get(target, false).is_some(); + let (msg, diag) = if is_preload { + ( + "already exists in the extern prelude", + BuiltinLintDiagnostics::RedundantImportRemove(import.use_span), + ) + } else { + ( + "imported redundantly", + BuiltinLintDiagnostics::RedundantImport(redundant_spans, source), + ) + }; self.lint_buffer.buffer_lint_with_diagnostic( UNUSED_IMPORTS, id, import.span, - format!("the item `{source}` is imported redundantly"), - BuiltinLintDiagnostics::RedundantImport(redundant_spans, source), + format!("the item `{source}` is {msg}"), + diag, ); } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 85db8ba8618e1..9c464db094f19 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -13,7 +13,7 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; -use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; +use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{ diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 09fb6aa5d8f98..6a76d78b33f3d 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -898,19 +898,6 @@ impl Session { } pub fn should_prefer_remapped_for_codegen(&self) -> bool { - // bail out, if any of the requested crate types aren't: - // "compiled executables or libraries" - for crate_type in &self.opts.crate_types { - match crate_type { - CrateType::Executable - | CrateType::Dylib - | CrateType::Rlib - | CrateType::Staticlib - | CrateType::Cdylib => continue, - CrateType::ProcMacro => return false, - } - } - let has_split_debuginfo = match self.split_debuginfo() { SplitDebuginfo::Off => false, SplitDebuginfo::Packed => true, diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 00ce9fbe7585b..3a58d41fcd0a4 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" bitflags = "2.4.1" itertools = "0.11.0" rustc_ast = { path = "../rustc_ast" } +rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 7c1bfebef2cd0..fd3d62d1321e2 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -18,6 +18,7 @@ #![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(associated_type_bounds)] +#![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(extract_if)] diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 98d28f10a5441..22f52c273625f 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -648,8 +648,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } impl<'tcx> TypeVisitor> for ContainsTermOrNotNameable<'_, 'tcx> { - type BreakTy = (); - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + type Result = ControlFlow<()>; + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { match *t.kind() { ty::Infer(ty::TyVar(vid)) => { if let ty::TermKind::Ty(term) = self.term.unpack() @@ -672,7 +672,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { match c.kind() { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { if let ty::TermKind::Const(term) = self.term.unpack() diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 52b900af85328..9e3e6a4676efb 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -1,15 +1,16 @@ -/// An infrastructure to mechanically analyse proof trees. -/// -/// It is unavoidable that this representation is somewhat -/// lossy as it should hide quite a few semantically relevant things, -/// e.g. canonicalization and the order of nested goals. -/// -/// @lcnr: However, a lot of the weirdness here is not strictly necessary -/// and could be improved in the future. This is mostly good enough for -/// coherence right now and was annoying to implement, so I am leaving it -/// as is until we start using it for something else. -use std::ops::ControlFlow; - +//! An infrastructure to mechanically analyse proof trees. +//! +//! It is unavoidable that this representation is somewhat +//! lossy as it should hide quite a few semantically relevant things, +//! e.g. canonicalization and the order of nested goals. +//! +//! @lcnr: However, a lot of the weirdness here is not strictly necessary +//! and could be improved in the future. This is mostly good enough for +//! coherence right now and was annoying to implement, so I am leaving it +//! as is until we start using it for something else. + +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use rustc_infer::infer::InferCtxt; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{inspect, QueryResult}; @@ -53,10 +54,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { /// to also use it to compute the most relevant goal /// for fulfillment errors. Will do that once we actually /// need it. - pub fn visit_nested>( - &self, - visitor: &mut V, - ) -> ControlFlow { + pub fn visit_nested>(&self, visitor: &mut V) -> V::Result { // HACK: An arbitrary cutoff to avoid dealing with overflow and cycles. if self.goal.depth <= 10 { let infcx = self.goal.infcx; @@ -75,17 +73,18 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { for &goal in &instantiated_goals { let (_, proof_tree) = infcx.evaluate_root_goal(goal, GenerateProofTree::Yes); let proof_tree = proof_tree.unwrap(); - visitor.visit_goal(&InspectGoal::new( + try_visit!(visitor.visit_goal(&InspectGoal::new( infcx, self.goal.depth + 1, &proof_tree, - ))?; + ))); } - ControlFlow::Continue(()) - })?; + V::Result::output() + }) + } else { + V::Result::output() } - ControlFlow::Continue(()) } } @@ -202,9 +201,9 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { /// The public API to interact with proof trees. pub trait ProofTreeVisitor<'tcx> { - type BreakTy; + type Result: VisitorResult = (); - fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow; + fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> Self::Result; } #[extension(pub trait ProofTreeInferCtxtExt<'tcx>)] @@ -213,7 +212,7 @@ impl<'tcx> InferCtxt<'tcx> { &self, goal: Goal<'tcx, ty::Predicate<'tcx>>, visitor: &mut V, - ) -> ControlFlow { + ) -> V::Result { self.probe(|_| { let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes); let proof_tree = proof_tree.unwrap(); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 68111c4cc1fdc..176647a4b15f8 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -474,7 +474,7 @@ fn plug_infer_with_placeholders<'tcx>( } impl<'tcx> TypeVisitor> for PlugInferWithPlaceholder<'_, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { let ty = self.infcx.shallow_resolve(ty); if ty.is_ty_var() { let Ok(InferOk { value: (), obligations }) = @@ -496,13 +496,12 @@ fn plug_infer_with_placeholders<'tcx>( bug!("we always expect to be able to plug an infer var with placeholder") }; assert_eq!(obligations, &[]); - ControlFlow::Continue(()) } else { - ty.super_visit_with(self) + ty.super_visit_with(self); } } - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, ct: ty::Const<'tcx>) { let ct = self.infcx.shallow_resolve(ct); if ct.is_ct_infer() { let Ok(InferOk { value: (), obligations }) = @@ -519,13 +518,12 @@ fn plug_infer_with_placeholders<'tcx>( bug!("we always expect to be able to plug an infer var with placeholder") }; assert_eq!(obligations, &[]); - ControlFlow::Continue(()) } else { - ct.super_visit_with(self) + ct.super_visit_with(self); } } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::ReVar(vid) = *r { let r = self .infcx @@ -555,7 +553,6 @@ fn plug_infer_with_placeholders<'tcx>( assert_eq!(obligations, &[]); } } - ControlFlow::Continue(()) } } @@ -868,12 +865,12 @@ impl<'tcx, F, E> TypeVisitor> for OrphanChecker<'tcx, F> where F: FnMut(Ty<'tcx>) -> Result, E>, { - type BreakTy = OrphanCheckEarlyExit<'tcx, E>; - fn visit_region(&mut self, _r: ty::Region<'tcx>) -> ControlFlow { + type Result = ControlFlow>; + fn visit_region(&mut self, _r: ty::Region<'tcx>) -> Self::Result { ControlFlow::Continue(()) } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { // Need to lazily normalize here in with `-Znext-solver=coherence`. let ty = match (self.lazily_normalize_ty)(ty) { Ok(ty) => ty, @@ -996,7 +993,7 @@ where /// As these should be quite rare as const arguments and especially rare as impl /// parameters, allowing uncovered const parameters in impls seems more useful /// than allowing `impl Trait for i32` to compile. - fn visit_const(&mut self, _c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, _c: ty::Const<'tcx>) -> Self::Result { ControlFlow::Continue(()) } } @@ -1026,18 +1023,17 @@ struct AmbiguityCausesVisitor<'a, 'tcx> { } impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { - type BreakTy = !; - fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow { + fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) { let infcx = goal.infcx(); for cand in goal.candidates() { - cand.visit_nested(self)?; + cand.visit_nested(self); } // When searching for intercrate ambiguity causes, we only need to look // at ambiguous goals, as for others the coherence unknowable candidate // was irrelevant. match goal.result() { Ok(Certainty::Maybe(_)) => {} - Ok(Certainty::Yes) | Err(NoSolution) => return ControlFlow::Continue(()), + Ok(Certainty::Yes) | Err(NoSolution) => return, } let Goal { param_env, predicate } = goal.goal(); @@ -1054,7 +1050,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { { proj.projection_ty.trait_ref(infcx.tcx) } - _ => return ControlFlow::Continue(()), + _ => return, }; // Add ambiguity causes for reservation impls. @@ -1154,8 +1150,6 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { if let Some(ambiguity_cause) = ambiguity_cause { self.causes.insert(ambiguity_cause); } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 189e1ba54bc36..7f0f9a12d6a05 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_span::Span; -use std::ops::ControlFlow; use crate::traits::ObligationCtxt; @@ -170,8 +169,7 @@ fn satisfied_from_param_env<'tcx>( } impl<'a, 'tcx> TypeVisitor> for Visitor<'a, 'tcx> { - type BreakTy = (); - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { debug!("is_const_evaluatable: candidate={:?}", c); if self.infcx.probe(|_| { let ocx = ObligationCtxt::new(self.infcx); @@ -187,7 +185,7 @@ fn satisfied_from_param_env<'tcx>( } if let ty::ConstKind::Expr(e) = c.kind() { - e.visit_with(self) + e.visit_with(self); } else { // FIXME(generic_const_exprs): This doesn't recurse into `>::ASSOC`'s args. // This is currently unobservable as `>::ASSOC` creates an anon const @@ -196,7 +194,6 @@ fn satisfied_from_param_env<'tcx>( // If we start allowing directly writing `ConstKind::Expr` without an intermediate anon const // this will be incorrect. It might be worth investigating making `predicates_of` elaborate // all of the `ConstEvaluatable` bounds rather than having a visitor here. - ControlFlow::Continue(()) } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 0796cb57d979c..0515b09ae46a0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -152,9 +152,9 @@ impl ArgKind { struct HasNumericInferVisitor; impl<'tcx> ty::TypeVisitor> for HasNumericInferVisitor { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) { ControlFlow::Break(()) } else { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 62933bce76b77..7a930937255b9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -416,9 +416,59 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { let trait_predicate = bound_predicate.rebind(trait_predicate); let trait_predicate = self.resolve_vars_if_possible(trait_predicate); - let trait_ref = trait_predicate.to_poly_trait_ref(); - if let Some(guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) { + // Let's use the root obligation as the main message, when we care about the + // most general case ("X doesn't implement Pattern<'_>") over the case that + // happened to fail ("char doesn't implement Fn(&mut char)"). + // + // We rely on a few heuristics to identify cases where this root + // obligation is more important than the leaf obligation: + let (main_trait_predicate, o) = if let ty::PredicateKind::Clause( + ty::ClauseKind::Trait(root_pred) + ) = root_obligation.predicate.kind().skip_binder() + && !trait_predicate.self_ty().skip_binder().has_escaping_bound_vars() + && !root_pred.self_ty().has_escaping_bound_vars() + // The type of the leaf predicate is (roughly) the same as the type + // from the root predicate, as a proxy for "we care about the root" + // FIXME: this doesn't account for trivial derefs, but works as a first + // approximation. + && ( + // `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait` + self.can_eq( + obligation.param_env, + trait_predicate.self_ty().skip_binder(), + root_pred.self_ty().peel_refs(), + ) + // `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator` + || self.can_eq( + obligation.param_env, + trait_predicate.self_ty().skip_binder(), + root_pred.self_ty(), + ) + ) + // The leaf trait and the root trait are different, so as to avoid + // talking about `&mut T: Trait` and instead remain talking about + // `T: Trait` instead + && trait_predicate.def_id() != root_pred.def_id() + // The root trait is not `Unsize`, as to avoid talking about it in + // `tests/ui/coercion/coerce-issue-49593-box-never.rs`. + && Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait() + { + ( + self.resolve_vars_if_possible( + root_obligation.predicate.kind().rebind(root_pred), + ), + root_obligation, + ) + } else { + (trait_predicate, &obligation) + }; + let trait_ref = main_trait_predicate.to_poly_trait_ref(); + + if let Some(guar) = self.emit_specialized_closure_kind_error( + &obligation, + trait_ref, + ) { return guar; } @@ -459,8 +509,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { notes, parent_label, append_const_msg, - } = self.on_unimplemented_note(trait_ref, &obligation, &mut long_ty_file); - + } = self.on_unimplemented_note(trait_ref, o, &mut long_ty_file); let have_alt_message = message.is_some() || label.is_some(); let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); let is_unsize = @@ -483,7 +532,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }; let err_msg = self.get_standard_error_message( - &trait_predicate, + &main_trait_predicate, message, predicate_is_const, append_const_msg, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 32447aca390a4..cc8b8f72cf359 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -435,8 +435,8 @@ fn is_impossible_associated_item( trait_item_def_id: DefId, } impl<'tcx> ty::TypeVisitor> for ReferencesOnlyParentGenerics<'tcx> { - type BreakTy = (); - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + type Result = ControlFlow<()>; + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { // If this is a parameter from the trait item's own generics, then bail if let ty::Param(param) = t.kind() && let param_def_id = self.generics.type_param(param, self.tcx).def_id @@ -446,7 +446,7 @@ fn is_impossible_associated_item( } t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { if let ty::ReEarlyParam(param) = r.kind() && let param_def_id = self.generics.region_param(¶m, self.tcx).def_id && self.tcx.parent(param_def_id) == self.trait_item_def_id @@ -455,7 +455,7 @@ fn is_impossible_associated_item( } ControlFlow::Continue(()) } - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { if let ty::ConstKind::Param(param) = ct.kind() && let param_def_id = self.generics.const_param(¶m, self.tcx).def_id && self.tcx.parent(param_def_id) == self.trait_item_def_id diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 7b715984c2b27..1816b98a636c6 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -834,9 +834,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( } impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { match t.kind() { ty::Param(_) => { if t == self.tcx.types.self_param { @@ -887,7 +887,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( } } - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { // Constants can only influence object safety if they are generic and reference `Self`. // This is only possible for unevaluated constants, so we walk these here. self.tcx.expand_abstract_consts(ct).super_visit_with(self) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index e5f8e33686099..c520e699bf542 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -18,8 +18,6 @@ use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableEx use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; use rustc_span::DUMMY_SP; -use std::ops::ControlFlow; - use super::NoSolution; pub use rustc_middle::traits::query::NormalizationResult; @@ -123,28 +121,23 @@ struct MaxEscapingBoundVarVisitor { } impl<'tcx> TypeVisitor> for MaxEscapingBoundVarVisitor { - fn visit_binder>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { self.outer_index.shift_in(1); - let result = t.super_visit_with(self); + t.super_visit_with(self); self.outer_index.shift_out(1); - result } #[inline] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { if t.outer_exclusive_binder() > self.outer_index { self.escaping = self .escaping .max(t.outer_exclusive_binder().as_usize() - self.outer_index.as_usize()); } - ControlFlow::Continue(()) } #[inline] - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { match *r { ty::ReBound(debruijn, _) if debruijn > self.outer_index => { self.escaping = @@ -152,16 +145,14 @@ impl<'tcx> TypeVisitor> for MaxEscapingBoundVarVisitor { } _ => {} } - ControlFlow::Continue(()) } - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, ct: ty::Const<'tcx>) { if ct.outer_exclusive_binder() > self.outer_index { self.escaping = self .escaping .max(ct.outer_exclusive_binder().as_usize() - self.outer_index.as_usize()); } - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index e6b42f15d5140..b89406ca02332 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -53,9 +53,9 @@ impl<'tcx> Search<'tcx> { } impl<'tcx> TypeVisitor> for Search<'tcx> { - type BreakTy = Ty<'tcx>; + type Result = ControlFlow>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { debug!("Search visiting ty: {:?}", ty); let (adt_def, args) = match *ty.kind() { diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index 066016231fa39..3d0ad31747ff7 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -5,13 +5,14 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -rustc_data_structures = { path = "../rustc_data_structures"} -rustc_hir = { path = "../rustc_hir", optional = true} -rustc_infer = { path = "../rustc_infer", optional = true} -rustc_macros = { path = "../rustc_macros", optional = true} -rustc_middle = { path = "../rustc_middle", optional = true} -rustc_span = { path = "../rustc_span", optional = true} -rustc_target = { path = "../rustc_target", optional = true} +rustc_ast_ir = { path = "../rustc_ast_ir", optional = true } +rustc_data_structures = { path = "../rustc_data_structures" } +rustc_hir = { path = "../rustc_hir", optional = true } +rustc_infer = { path = "../rustc_infer", optional = true } +rustc_macros = { path = "../rustc_macros", optional = true } +rustc_middle = { path = "../rustc_middle", optional = true } +rustc_span = { path = "../rustc_span", optional = true } +rustc_target = { path = "../rustc_target", optional = true } tracing = "0.1" # tidy-alphabetical-end @@ -23,6 +24,7 @@ rustc = [ "rustc_middle", "rustc_span", "rustc_target", + "rustc_ast_ir", ] [dev-dependencies] diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index f8eb82da8f688..2a30bd5d53907 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start itertools = "0.11" +rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 86c7551882aab..85337f07cdc8a 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -8,7 +8,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::Span; use rustc_trait_selection::traits::check_args_compatible; -use std::ops::ControlFlow; use crate::errors::{DuplicateArg, NotParam}; @@ -185,16 +184,15 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> { #[instrument(skip(self), ret, level = "trace")] - fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> ControlFlow { + fn visit(&mut self, span: Span, value: impl TypeVisitable>) { self.visit_spanned(span, value); - ControlFlow::Continue(()) } } impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { #[instrument(skip(self), ret, level = "trace")] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - t.super_visit_with(self)?; + fn visit_ty(&mut self, t: Ty<'tcx>) { + t.super_visit_with(self); match t.kind() { ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => { self.visit_opaque_ty(alias_ty); @@ -203,7 +201,7 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { self.tcx .type_of(alias_ty.def_id) .instantiate(self.tcx, alias_ty.args) - .visit_with(self)?; + .visit_with(self); } ty::Alias(ty::Projection, alias_ty) => { // This avoids having to do normalization of `Self::AssocTy` by only @@ -235,11 +233,11 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { ); if check_args_compatible(self.tcx, assoc, impl_args) { - return self - .tcx + self.tcx .type_of(assoc.def_id) .instantiate(self.tcx, impl_args) .visit_with(self); + return; } else { self.tcx.dcx().span_delayed_bug( self.tcx.def_span(assoc.def_id), @@ -252,7 +250,7 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { } ty::Adt(def, _) if def.did().is_local() => { if !self.seen.insert(def.did().expect_local()) { - return ControlFlow::Continue(()); + return; } for variant in def.variants().iter() { for field in variant.fields.iter() { @@ -271,7 +269,6 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { } _ => trace!(kind=?t.kind()), } - ControlFlow::Continue(()) } } @@ -279,20 +276,18 @@ struct ImplTraitInAssocTypeCollector<'tcx>(OpaqueTypeCollector<'tcx>); impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for ImplTraitInAssocTypeCollector<'tcx> { #[instrument(skip(self), ret, level = "trace")] - fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> ControlFlow { + fn visit(&mut self, span: Span, value: impl TypeVisitable>) { let old = self.0.span; self.0.span = Some(span); value.visit_with(self); self.0.span = old; - - ControlFlow::Continue(()) } } impl<'tcx> TypeVisitor> for ImplTraitInAssocTypeCollector<'tcx> { #[instrument(skip(self), ret, level = "trace")] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - t.super_visit_with(self)?; + fn visit_ty(&mut self, t: Ty<'tcx>) { + t.super_visit_with(self); match t.kind() { ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => { self.0.visit_opaque_ty(alias_ty); @@ -347,7 +342,6 @@ impl<'tcx> TypeVisitor> for ImplTraitInAssocTypeCollector<'tcx> { } _ => trace!(kind=?t.kind()), } - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 38cc558380cd8..5527d853e3048 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -1,27 +1,23 @@ //! This module contains helpers for walking all types of //! a signature, while preserving spans as much as possible -use std::ops::ControlFlow; - +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use rustc_hir::{def::DefKind, def_id::LocalDefId}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; use rustc_type_ir::visit::TypeVisitable; pub trait SpannedTypeVisitor<'tcx> { - type BreakTy = !; - fn visit( - &mut self, - span: Span, - value: impl TypeVisitable>, - ) -> ControlFlow; + type Result: VisitorResult = (); + fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> Self::Result; } pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( tcx: TyCtxt<'tcx>, item: LocalDefId, visitor: &mut V, -) -> ControlFlow { +) -> V::Result { let kind = tcx.def_kind(item); trace!(?kind); match kind { @@ -30,12 +26,12 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( let ty_sig = tcx.fn_sig(item).instantiate_identity(); let hir_sig = tcx.hir_node_by_def_id(item).fn_decl().unwrap(); // Walk over the inputs and outputs manually in order to get good spans for them. - visitor.visit(hir_sig.output.span(), ty_sig.output()); + try_visit!(visitor.visit(hir_sig.output.span(), ty_sig.output())); for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) { - visitor.visit(hir.span, ty.map_bound(|x| *x))?; + try_visit!(visitor.visit(hir.span, ty.map_bound(|x| *x))); } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } // Walk over the type behind the alias @@ -44,32 +40,32 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { // Associated types in traits don't necessarily have a type that we can visit - visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())?; + try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())); } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } DefKind::OpaqueTy => { for (pred, span) in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } // Look at field types DefKind::Struct | DefKind::Union | DefKind::Enum => { let span = tcx.def_ident_span(item).unwrap(); let ty = tcx.type_of(item).instantiate_identity(); - visitor.visit(span, ty); + try_visit!(visitor.visit(span, ty)); let ty::Adt(def, args) = ty.kind() else { span_bug!(span, "invalid type for {kind:?}: {:#?}", ty.kind()) }; for field in def.all_fields() { let span = tcx.def_ident_span(field.did).unwrap(); let ty = field.ty(tcx, args); - visitor.visit(span, ty); + try_visit!(visitor.visit(span, ty)); } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } // These are not part of a public API, they can only appear as hidden types, and there @@ -80,20 +76,20 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( if of_trait { let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span; let args = &tcx.impl_trait_ref(item).unwrap().instantiate_identity().args[1..]; - visitor.visit(span, args)?; + try_visit!(visitor.visit(span, args)); } let span = match tcx.hir_node_by_def_id(item).ty() { Some(ty) => ty.span, _ => tcx.def_span(item), }; - visitor.visit(span, tcx.type_of(item).instantiate_identity()); + try_visit!(visitor.visit(span, tcx.type_of(item).instantiate_identity())); for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } DefKind::TraitAlias | DefKind::Trait => { for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } | DefKind::Variant @@ -116,5 +112,5 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( | DefKind::Mod | DefKind::Use => {} } - ControlFlow::Continue(()) + V::Result::output() } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index b725eda33ce89..48d9a5e27b7eb 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -174,17 +174,13 @@ struct ImplTraitInTraitFinder<'a, 'tcx> { } impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { - fn visit_binder>>( - &mut self, - binder: &ty::Binder<'tcx, T>, - ) -> std::ops::ControlFlow { + fn visit_binder>>(&mut self, binder: &ty::Binder<'tcx, T>) { self.depth.shift_in(1); - let binder = binder.super_visit_with(self); + binder.super_visit_with(self); self.depth.shift_out(1); - binder } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind() && let Some( ty::ImplTraitInTraitData::Trait { fn_def_id, .. } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 5bc2bfe28939c..ad18ef249842f 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -1,6 +1,7 @@ +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use std::fmt; use std::hash::Hash; -use std::ops::ControlFlow; use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; @@ -107,9 +108,9 @@ impl> TypeVisitable for Canonical where I::CanonicalVars: TypeVisitable, { - fn visit_with>(&self, folder: &mut F) -> ControlFlow { - self.value.visit_with(folder)?; - self.max_universe.visit_with(folder)?; + fn visit_with>(&self, folder: &mut F) -> F::Result { + try_visit!(self.value.visit_with(folder)); + try_visit!(self.max_universe.visit_with(folder)); self.variables.visit_with(folder) } } @@ -137,7 +138,7 @@ impl TypeVisitable for CanonicalVarInfo where I::Ty: TypeVisitable, { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { self.kind.visit_with(visitor) } } @@ -251,13 +252,13 @@ impl TypeVisitable for CanonicalVarKind where I::Ty: TypeVisitable, { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) | CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) - | CanonicalVarKind::Effect => ControlFlow::Continue(()), + | CanonicalVarKind::Effect => V::Result::output(), CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => { ty.visit_with(visitor) } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 94ccbcbd8a570..ac7683a47ce9a 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -21,12 +21,14 @@ use std::hash::Hash; #[cfg(not(feature = "nightly"))] use std::sync::Arc as Lrc; +#[macro_use] +pub mod visit; + #[cfg(feature = "nightly")] pub mod codec; pub mod fold; pub mod ty_info; pub mod ty_kind; -pub mod visit; #[macro_use] mod macros; diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index 231546287d027..7dcc8851a43f2 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -25,9 +25,9 @@ macro_rules! TrivialTypeTraversalImpls { fn visit_with>( &self, _: &mut F) - -> ::std::ops::ControlFlow + -> F::Result { - ::std::ops::ControlFlow::Continue(()) + ::output() } } )+ diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 8c4d0fda6af64..a0759f7df7fdd 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,5 +1,6 @@ +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use std::fmt; -use std::ops::ControlFlow; use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; @@ -91,14 +92,14 @@ where I::TypeOutlivesPredicate: TypeVisitable, I::RegionOutlivesPredicate: TypeVisitable, { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { ClauseKind::Trait(p) => p.visit_with(visitor), ClauseKind::RegionOutlives(p) => p.visit_with(visitor), ClauseKind::TypeOutlives(p) => p.visit_with(visitor), ClauseKind::Projection(p) => p.visit_with(visitor), ClauseKind::ConstArgHasType(c, t) => { - c.visit_with(visitor)?; + try_visit!(c.visit_with(visitor)); t.visit_with(visitor) } ClauseKind::WellFormed(p) => p.visit_with(visitor), @@ -205,21 +206,21 @@ where I::NormalizesTo: TypeVisitable, ClauseKind: TypeVisitable, { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { PredicateKind::Clause(p) => p.visit_with(visitor), PredicateKind::ObjectSafe(d) => d.visit_with(visitor), PredicateKind::Subtype(s) => s.visit_with(visitor), PredicateKind::Coerce(s) => s.visit_with(visitor), PredicateKind::ConstEquate(a, b) => { - a.visit_with(visitor)?; + try_visit!(a.visit_with(visitor)); b.visit_with(visitor) } - PredicateKind::Ambiguous => ControlFlow::Continue(()), + PredicateKind::Ambiguous => V::Result::output(), PredicateKind::NormalizesTo(p) => p.visit_with(visitor), PredicateKind::AliasRelate(a, b, d) => { - a.visit_with(visitor)?; - b.visit_with(visitor)?; + try_visit!(a.visit_with(visitor)); + try_visit!(b.visit_with(visitor)); d.visit_with(visitor) } } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 00f49a07f9d81..de8f56618d000 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,3 +1,4 @@ +use rustc_ast_ir::try_visit; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] @@ -831,8 +832,8 @@ impl TypeVisitable for TypeAndMut where I::Ty: TypeVisitable, { - fn visit_with>(&self, visitor: &mut V) -> std::ops::ControlFlow { - self.ty.visit_with(visitor)?; + fn visit_with>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.ty.visit_with(visitor)); self.mutbl.visit_with(visitor) } } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 638fb9f7fa9db..839e75dba4cbf 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -41,6 +41,8 @@ //! - u.visit_with(visitor) //! ``` +use rustc_ast_ir::visit::VisitorResult; +use rustc_ast_ir::{try_visit, walk_visitable_list}; use rustc_index::{Idx, IndexVec}; use std::fmt; use std::ops::ControlFlow; @@ -63,7 +65,7 @@ pub trait TypeVisitable: fmt::Debug + Clone { /// that calls a visitor method specifically for that type (such as /// `V::visit_ty`). This is where control transfers from `TypeVisitable` to /// `TypeVisitor`. - fn visit_with>(&self, visitor: &mut V) -> ControlFlow; + fn visit_with>(&self, visitor: &mut V) -> V::Result; } // This trait is implemented for types of interest. @@ -74,7 +76,7 @@ pub trait TypeSuperVisitable: TypeVisitable { /// that method. For example, in `MyVisitor::visit_ty(ty)`, it is valid to /// call `ty.super_visit_with(self)`, but any other visiting should be done /// with `xyz.visit_with(self)`. - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow; + fn super_visit_with>(&self, visitor: &mut V) -> V::Result; } /// This trait is implemented for every visiting traversal. There is a visit @@ -82,33 +84,30 @@ pub trait TypeSuperVisitable: TypeVisitable { /// that recurses into the type's fields in a non-custom fashion. pub trait TypeVisitor: Sized { #[cfg(feature = "nightly")] - type BreakTy = !; + type Result: VisitorResult = (); #[cfg(not(feature = "nightly"))] - type BreakTy; + type Result: VisitorResult; - fn visit_binder>( - &mut self, - t: &I::Binder, - ) -> ControlFlow { + fn visit_binder>(&mut self, t: &I::Binder) -> Self::Result { t.super_visit_with(self) } - fn visit_ty(&mut self, t: I::Ty) -> ControlFlow { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { t.super_visit_with(self) } // The default region visitor is a no-op because `Region` is non-recursive // and has no `super_visit_with` method to call. - fn visit_region(&mut self, _r: I::Region) -> ControlFlow { - ControlFlow::Continue(()) + fn visit_region(&mut self, _r: I::Region) -> Self::Result { + Self::Result::output() } - fn visit_const(&mut self, c: I::Const) -> ControlFlow { + fn visit_const(&mut self, c: I::Const) -> Self::Result { c.super_visit_with(self) } - fn visit_predicate(&mut self, p: I::Predicate) -> ControlFlow { + fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result { p.super_visit_with(self) } } @@ -117,8 +116,8 @@ pub trait TypeVisitor: Sized { // Traversal implementations. impl, U: TypeVisitable> TypeVisitable for (T, U) { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.0.visit_with(visitor)?; + fn visit_with>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.0.visit_with(visitor)); self.1.visit_with(visitor) } } @@ -126,24 +125,24 @@ impl, U: TypeVisitable> TypeVisitable for impl, B: TypeVisitable, C: TypeVisitable> TypeVisitable for (A, B, C) { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.0.visit_with(visitor)?; - self.1.visit_with(visitor)?; + fn visit_with>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.0.visit_with(visitor)); + try_visit!(self.1.visit_with(visitor)); self.2.visit_with(visitor) } } impl> TypeVisitable for Option { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { Some(v) => v.visit_with(visitor), - None => ControlFlow::Continue(()), + None => V::Result::output(), } } } impl, E: TypeVisitable> TypeVisitable for Result { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { Ok(v) => v.visit_with(visitor), Err(e) => e.visit_with(visitor), @@ -152,20 +151,21 @@ impl, E: TypeVisitable> TypeVisitable for } impl> TypeVisitable for Lrc { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { (**self).visit_with(visitor) } } impl> TypeVisitable for Box { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { (**self).visit_with(visitor) } } impl> TypeVisitable for Vec { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } @@ -173,20 +173,23 @@ impl> TypeVisitable for Vec { // case, because we can't return a new slice. But note that there are a couple // of trivial impls of `TypeFoldable` for specific slice types elsewhere. impl> TypeVisitable for &[T] { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } impl> TypeVisitable for Box<[T]> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } impl, Ix: Idx> TypeVisitable for IndexVec { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } @@ -366,12 +369,9 @@ impl std::fmt::Debug for HasTypeFlagsVisitor { // is important for anonymization of binders in `TyCtxt::erase_regions`. We // specifically detect this case in `visit_binder`. impl TypeVisitor for HasTypeFlagsVisitor { - type BreakTy = FoundFlags; + type Result = ControlFlow; - fn visit_binder>( - &mut self, - t: &I::Binder, - ) -> ControlFlow { + fn visit_binder>(&mut self, t: &I::Binder) -> Self::Result { // If we're looking for the HAS_BINDER_VARS flag, check if the // binder has vars. This won't be present in the binder's bound // value, so we need to check here too. @@ -383,7 +383,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_ty(&mut self, t: I::Ty) -> ControlFlow { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { // Note: no `super_visit_with` call. let flags = t.flags(); if flags.intersects(self.flags) { @@ -394,7 +394,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_region(&mut self, r: I::Region) -> ControlFlow { + fn visit_region(&mut self, r: I::Region) -> Self::Result { // Note: no `super_visit_with` call, as usual for `Region`. let flags = r.flags(); if flags.intersects(self.flags) { @@ -405,7 +405,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_const(&mut self, c: I::Const) -> ControlFlow { + fn visit_const(&mut self, c: I::Const) -> Self::Result { // Note: no `super_visit_with` call. if c.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) @@ -415,7 +415,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_predicate(&mut self, predicate: I::Predicate) -> ControlFlow { + fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result { // Note: no `super_visit_with` call. if predicate.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) @@ -459,12 +459,9 @@ struct HasEscapingVarsVisitor { } impl TypeVisitor for HasEscapingVarsVisitor { - type BreakTy = FoundEscapingVars; + type Result = ControlFlow; - fn visit_binder>( - &mut self, - t: &I::Binder, - ) -> ControlFlow { + fn visit_binder>(&mut self, t: &I::Binder) -> Self::Result { self.outer_index.shift_in(1); let result = t.super_visit_with(self); self.outer_index.shift_out(1); @@ -472,7 +469,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } #[inline] - fn visit_ty(&mut self, t: I::Ty) -> ControlFlow { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { // If the outer-exclusive-binder is *strictly greater* than // `outer_index`, that means that `t` contains some content // bound at `outer_index` or above (because @@ -486,7 +483,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } #[inline] - fn visit_region(&mut self, r: I::Region) -> ControlFlow { + fn visit_region(&mut self, r: I::Region) -> Self::Result { // If the region is bound by `outer_index` or anything outside // of outer index, then it escapes the binders we have // visited. @@ -497,7 +494,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } } - fn visit_const(&mut self, ct: I::Const) -> ControlFlow { + fn visit_const(&mut self, ct: I::Const) -> Self::Result { // If the outer-exclusive-binder is *strictly greater* than // `outer_index`, that means that `ct` contains some content // bound at `outer_index` or above (because @@ -511,7 +508,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } #[inline] - fn visit_predicate(&mut self, predicate: I::Predicate) -> ControlFlow { + fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result { if predicate.outer_exclusive_binder() > self.outer_index { ControlFlow::Break(FoundEscapingVars) } else { @@ -523,9 +520,9 @@ impl TypeVisitor for HasEscapingVarsVisitor { struct HasErrorVisitor; impl TypeVisitor for HasErrorVisitor { - type BreakTy = I::ErrorGuaranteed; + type Result = ControlFlow; - fn visit_ty(&mut self, t: ::Ty) -> ControlFlow { + fn visit_ty(&mut self, t: ::Ty) -> Self::Result { if let ty::Error(guar) = t.kind() { ControlFlow::Break(guar) } else { @@ -533,7 +530,7 @@ impl TypeVisitor for HasErrorVisitor { } } - fn visit_const(&mut self, c: ::Const) -> ControlFlow { + fn visit_const(&mut self, c: ::Const) -> Self::Result { if let ty::ConstKind::Error(guar) = c.kind() { ControlFlow::Break(guar) } else { @@ -541,7 +538,7 @@ impl TypeVisitor for HasErrorVisitor { } } - fn visit_region(&mut self, r: ::Region) -> ControlFlow { + fn visit_region(&mut self, r: ::Region) -> Self::Result { if let ty::ReError(guar) = r.kind() { ControlFlow::Break(guar) } else { diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index af2e422e8a00c..6dd3069034d85 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -30,8 +30,7 @@ use crate::task::{Context, Poll}; #[lang = "future_trait"] #[diagnostic::on_unimplemented( label = "`{Self}` is not a future", - message = "`{Self}` is not a future", - note = "{Self} must be a future or must implement `IntoFuture` to be awaited" + message = "`{Self}` is not a future" )] pub trait Future { /// The type of value produced on completion. diff --git a/library/core/src/future/into_future.rs b/library/core/src/future/into_future.rs index 38c654e76b46c..eb5a9b72dd0f2 100644 --- a/library/core/src/future/into_future.rs +++ b/library/core/src/future/into_future.rs @@ -100,6 +100,11 @@ use crate::future::Future; /// ``` #[stable(feature = "into_future", since = "1.64.0")] #[rustc_diagnostic_item = "IntoFuture"] +#[diagnostic::on_unimplemented( + label = "`{Self}` is not a future", + message = "`{Self}` is not a future", + note = "{Self} must be a future or must implement `IntoFuture` to be awaited" +)] pub trait IntoFuture { /// The output that the future will produce on completion. #[stable(feature = "into_future", since = "1.64.0")] diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 0d1cf7941fb69..d89801bce2b6d 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -236,6 +236,49 @@ pub trait FromIterator: Sized { /// ``` #[rustc_diagnostic_item = "IntoIterator"] #[rustc_skip_array_during_method_dispatch] +#[rustc_on_unimplemented( + on( + _Self = "core::ops::range::RangeTo", + label = "if you meant to iterate until a value, add a starting value", + note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \ + bounded `Range`: `0..end`" + ), + on( + _Self = "core::ops::range::RangeToInclusive", + label = "if you meant to iterate until a value (including it), add a starting value", + note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \ + to have a bounded `RangeInclusive`: `0..=end`" + ), + on( + _Self = "[]", + label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`" + ), + on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"), + on( + _Self = "alloc::vec::Vec", + label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`" + ), + on( + _Self = "&str", + label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" + ), + on( + _Self = "alloc::string::String", + label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" + ), + on( + _Self = "{integral}", + note = "if you want to iterate between `start` until a value `end`, use the exclusive range \ + syntax `start..end` or the inclusive range syntax `start..=end`" + ), + on( + _Self = "{float}", + note = "if you want to iterate between `start` until a value `end`, use the exclusive range \ + syntax `start..end` or the inclusive range syntax `start..=end`" + ), + label = "`{Self}` is not an iterator", + message = "`{Self}` is not an iterator" +)] #[stable(feature = "rust1", since = "1.0.0")] pub trait IntoIterator { /// The type of the elements being iterated over. diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 3267cea38b743..e1904ed220cb4 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -28,42 +28,11 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} #[rustc_on_unimplemented( on( _Self = "core::ops::range::RangeTo", - label = "if you meant to iterate until a value, add a starting value", - note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \ - bounded `Range`: `0..end`" + note = "you might have meant to use a bounded `Range`" ), on( _Self = "core::ops::range::RangeToInclusive", - label = "if you meant to iterate until a value (including it), add a starting value", - note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \ - to have a bounded `RangeInclusive`: `0..=end`" - ), - on( - _Self = "[]", - label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`" - ), - on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"), - on( - _Self = "alloc::vec::Vec", - label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`" - ), - on( - _Self = "&str", - label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" - ), - on( - _Self = "alloc::string::String", - label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`" - ), - on( - _Self = "{integral}", - note = "if you want to iterate between `start` until a value `end`, use the exclusive range \ - syntax `start..end` or the inclusive range syntax `start..=end`" - ), - on( - _Self = "{float}", - note = "if you want to iterate between `start` until a value `end`, use the exclusive range \ - syntax `start..end` or the inclusive range syntax `start..=end`" + note = "you might have meant to use a bounded `RangeInclusive`" ), label = "`{Self}` is not an iterator", message = "`{Self}` is not an iterator" diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 45193c11e1d6b..00e75ec9a2540 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1092,7 +1092,7 @@ impl AtomicBool { /// Returns a mutable pointer to the underlying [`bool`]. /// - /// Doing non-atomic reads and writes on the resulting integer can be a data race. + /// Doing non-atomic reads and writes on the resulting boolean can be a data race. /// This method is mostly useful for FFI, where the function signature may use /// `*mut bool` instead of `&AtomicBool`. /// @@ -2031,7 +2031,7 @@ impl AtomicPtr { /// Returns a mutable pointer to the underlying pointer. /// - /// Doing non-atomic reads and writes on the resulting integer can be a data race. + /// Doing non-atomic reads and writes on the resulting pointer can be a data race. /// This method is mostly useful for FFI, where the function signature may use /// `*mut *mut T` instead of `&AtomicPtr`. /// diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index b54f2db88ffc9..8a1ba436f7261 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -209,7 +209,7 @@ impl<'a> scoped_cell::ApplyL<'a> for BridgeStateL { thread_local! { static BRIDGE_STATE: scoped_cell::ScopedCell = - scoped_cell::ScopedCell::new(BridgeState::NotConnected); + const { scoped_cell::ScopedCell::new(BridgeState::NotConnected) }; } impl BridgeState<'_> { diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 8736d1806fbe9..0dbd4bac85c9f 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -223,7 +223,7 @@ thread_local! { /// This is required as the thread-local state in the proc_macro client does /// not handle being re-entered, and will invalidate all `Symbol`s when /// entering a nested macro. - static ALREADY_RUNNING_SAME_THREAD: Cell = Cell::new(false); + static ALREADY_RUNNING_SAME_THREAD: Cell = const { Cell::new(false) }; } /// Keep `ALREADY_RUNNING_SAME_THREAD` (see also its documentation) diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index efd06c8df6e29..813ede0641530 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -70,7 +70,7 @@ fn test_named_thread_truncation() { } #[cfg(any( - target_os = "windows", + all(target_os = "windows", not(target_vendor = "win7")), target_os = "linux", target_os = "macos", target_os = "ios", diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs index 514015af0455c..b8baad18cc8db 100644 --- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs @@ -22,9 +22,9 @@ fn get_enum_ty(enum_ty: Ty<'_>) -> Option> { } impl<'tcx> TypeVisitor> for ContainsTyVisitor { - type BreakTy = Ty<'tcx>; + type Result = ControlFlow>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { self.level += 1; if self.level == 1 { t.super_visit_with(self) diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index f9cc5f191253a..06229ac938f9a 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -141,9 +141,9 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, struct ContainsRegion; impl TypeVisitor> for ContainsRegion { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow { + fn visit_region(&mut self, _: ty::Region<'_>) -> Self::Result { ControlFlow::Break(()) } } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 6762c88300503..6e011a28bb7bc 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -916,8 +916,8 @@ pub fn for_each_top_level_late_bound_region( f: F, } impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow> TypeVisitor> for V { - type BreakTy = B; - fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow { + type Result = ControlFlow; + fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result { if let RegionKind::ReBound(idx, bound) = r.kind() && idx.as_u32() == self.index { @@ -926,7 +926,7 @@ pub fn for_each_top_level_late_bound_region( ControlFlow::Continue(()) } } - fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) -> ControlFlow { + fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) -> Self::Result { self.index += 1; let res = t.super_visit_with(self); self.index -= 1; diff --git a/tests/ui/associated-types/substs-ppaux.normal.stderr b/tests/ui/associated-types/substs-ppaux.normal.stderr index 93118616f02c7..a2647f6683531 100644 --- a/tests/ui/associated-types/substs-ppaux.normal.stderr +++ b/tests/ui/associated-types/substs-ppaux.normal.stderr @@ -70,13 +70,12 @@ help: use parentheses to call this function LL | let x: () = foo::<'static>(); | ++ -error[E0277]: the size for values of type `str` cannot be known at compilation time +error[E0277]: the trait bound `str: Foo<'_, '_, u8>` is not satisfied --> $DIR/substs-ppaux.rs:49:6 | LL | >::bar; - | ^^^ doesn't have a size known at compile-time + | ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>` | - = help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>` note: required for `str` to implement `Foo<'_, '_, u8>` --> $DIR/substs-ppaux.rs:11:17 | diff --git a/tests/ui/associated-types/substs-ppaux.rs b/tests/ui/associated-types/substs-ppaux.rs index d32cdd2465863..077ca764e241f 100644 --- a/tests/ui/associated-types/substs-ppaux.rs +++ b/tests/ui/associated-types/substs-ppaux.rs @@ -47,6 +47,6 @@ fn foo<'z>() where &'z (): Sized { //[normal]~| found fn item `fn() {foo::<'static>}` >::bar; - //[verbose]~^ ERROR the size for values of type - //[normal]~^^ ERROR the size for values of type + //[verbose]~^ ERROR the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied + //[normal]~^^ ERROR the trait bound `str: Foo<'_, '_, u8>` is not satisfied } diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr index 13d3156fb8018..d32f44ccd6412 100644 --- a/tests/ui/associated-types/substs-ppaux.verbose.stderr +++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr @@ -70,13 +70,12 @@ help: use parentheses to call this function LL | let x: () = foo::<'static>(); | ++ -error[E0277]: the size for values of type `str` cannot be known at compilation time +error[E0277]: the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied --> $DIR/substs-ppaux.rs:49:6 | LL | >::bar; - | ^^^ doesn't have a size known at compile-time + | ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>` | - = help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>` note: required for `str` to implement `Foo<'?0, '?1, u8>` --> $DIR/substs-ppaux.rs:11:17 | diff --git a/tests/ui/async-await/async-error-span.stderr b/tests/ui/async-await/async-error-span.stderr index 2ec968ffc0307..44f1583f4cc33 100644 --- a/tests/ui/async-await/async-error-span.stderr +++ b/tests/ui/async-await/async-error-span.stderr @@ -5,7 +5,6 @@ LL | fn get_future() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future | = help: the trait `Future` is not implemented for `()` - = note: () must be a future or must implement `IntoFuture` to be awaited error[E0282]: type annotations needed --> $DIR/async-error-span.rs:13:9 diff --git a/tests/ui/async-await/coroutine-not-future.stderr b/tests/ui/async-await/coroutine-not-future.stderr index 130c5ef526b39..580217fb4f821 100644 --- a/tests/ui/async-await/coroutine-not-future.stderr +++ b/tests/ui/async-await/coroutine-not-future.stderr @@ -49,7 +49,6 @@ LL | takes_future(returns_coroutine()); | required by a bound introduced by this call | = help: the trait `Future` is not implemented for `impl Coroutine` - = note: impl Coroutine must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `takes_future` --> $DIR/coroutine-not-future.rs:17:26 | @@ -69,7 +68,6 @@ LL | | }); | |_____^ `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future | = help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` - = note: {coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `takes_future` --> $DIR/coroutine-not-future.rs:17:26 | diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs index 2bbe82270bd06..5baa4f10c448a 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.rs @@ -17,5 +17,5 @@ impl Signed for i32 { } fn main() { is_defaulted::<&'static i32>(); is_defaulted::<&'static u32>(); - //~^ ERROR `u32: Signed` is not satisfied + //~^ ERROR the trait bound `&'static u32: Defaulted` is not satisfied } diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr index e699422ae2b86..47bb1a059be5a 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `u32: Signed` is not satisfied +error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied --> $DIR/typeck-default-trait-impl-precedence.rs:19:20 | LL | is_defaulted::<&'static u32>(); - | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted` + | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `&'static u32`, which is required by `&'static u32: Defaulted` | note: required for `&'static u32` to implement `Defaulted` --> $DIR/typeck-default-trait-impl-precedence.rs:10:19 diff --git a/tests/ui/codegen/duplicated-path-in-error.rs b/tests/ui/codegen/duplicated-path-in-error.rs new file mode 100644 index 0000000000000..cff20dd9bd639 --- /dev/null +++ b/tests/ui/codegen/duplicated-path-in-error.rs @@ -0,0 +1,7 @@ +//@ only-linux +//@ compile-flags: -Zcodegen-backend=/non-existing-one.so + +// This test ensures that the error of the "not found dylib" doesn't duplicate +// the path of the dylib. + +fn main() {} diff --git a/tests/ui/codegen/duplicated-path-in-error.stderr b/tests/ui/codegen/duplicated-path-in-error.stderr new file mode 100644 index 0000000000000..d0d34e2f93468 --- /dev/null +++ b/tests/ui/codegen/duplicated-path-in-error.stderr @@ -0,0 +1,2 @@ +error: couldn't load codegen backend /non-existing-one.so: cannot open shared object file: No such file or directory + diff --git a/tests/ui/coroutine/gen_block_is_no_future.stderr b/tests/ui/coroutine/gen_block_is_no_future.stderr index f9e23e45b4435..fb2f2ba559775 100644 --- a/tests/ui/coroutine/gen_block_is_no_future.stderr +++ b/tests/ui/coroutine/gen_block_is_no_future.stderr @@ -5,7 +5,6 @@ LL | fn foo() -> impl std::future::Future { | ^^^^^^^^^^^^^^^^^^^^^^^^ `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` is not a future | = help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21}` - = note: {gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:21} must be a future or must implement `IntoFuture` to be awaited error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr index 7fc726409ce40..5e62221628d26 100644 --- a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -74,7 +74,6 @@ LL | fn use_for() where i32: Iterator { | ^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable diff --git a/tests/ui/for/issue-20605.current.stderr b/tests/ui/for/issue-20605.current.stderr index c8d39afdeb957..9e706601ef507 100644 --- a/tests/ui/for/issue-20605.current.stderr +++ b/tests/ui/for/issue-20605.current.stderr @@ -1,4 +1,4 @@ -error[E0277]: the size for values of type `dyn Iterator` cannot be known at compilation time +error[E0277]: `dyn Iterator` is not an iterator --> $DIR/issue-20605.rs:5:17 | LL | for item in *things { *item = 0 } diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr index a44faa5491d3d..f9c3848476c88 100644 --- a/tests/ui/for/issue-20605.next.stderr +++ b/tests/ui/for/issue-20605.next.stderr @@ -1,8 +1,10 @@ -error[E0277]: the trait bound `dyn Iterator: IntoIterator` is not satisfied +error[E0277]: `dyn Iterator` is not an iterator --> $DIR/issue-20605.rs:5:17 | LL | for item in *things { *item = 0 } - | ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` + | ^^^^^^^ `dyn Iterator` is not an iterator + | + = help: the trait `IntoIterator` is not implemented for `dyn Iterator` error: the type ` as IntoIterator>::IntoIter` is not well-formed --> $DIR/issue-20605.rs:5:17 diff --git a/tests/ui/for/issue-20605.rs b/tests/ui/for/issue-20605.rs index 4a9f62b6612ae..1c01de967ccc8 100644 --- a/tests/ui/for/issue-20605.rs +++ b/tests/ui/for/issue-20605.rs @@ -3,8 +3,8 @@ fn changer<'a>(mut things: Box>) { for item in *things { *item = 0 } - //[current]~^ ERROR the size for values of type - //[next]~^^ ERROR the trait bound `dyn Iterator: IntoIterator` is not satisfied + //[current]~^ ERROR `dyn Iterator` is not an iterator + //[next]~^^ ERROR `dyn Iterator` is not an iterator //[next]~| ERROR the type ` as IntoIterator>::IntoIter` is not well-formed //[next]~| ERROR the type `&mut as IntoIterator>::IntoIter` is not well-formed //[next]~| ERROR the type `Option<< as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed diff --git a/tests/ui/impl-trait/issues/issue-83919.stderr b/tests/ui/impl-trait/issues/issue-83919.stderr index 200257235feae..b0bd6ed116bca 100644 --- a/tests/ui/impl-trait/issues/issue-83919.stderr +++ b/tests/ui/impl-trait/issues/issue-83919.stderr @@ -5,7 +5,6 @@ LL | fn get_fut(&self) -> Self::Fut { | ^^^^^^^^^ `{integer}` is not a future | = help: the trait `Future` is not implemented for `{integer}` - = note: {integer} must be a future or must implement `IntoFuture` to be awaited error: aborting due to 1 previous error 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.edition2015.stderr b/tests/ui/imports/redundant-import-issue-121915-2015.edition2015.stderr new file mode 100644 index 0000000000000..af3e4d54ec234 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915-2015.edition2015.stderr @@ -0,0 +1,14 @@ +error: the item `aux_issue_121915` is already exists in the extern prelude + --> $DIR/redundant-import-issue-121915-2015.rs:10:9 + | +LL | use aux_issue_121915; + | ^^^^^^^^^^^^^^^^ help: remove this import + | +note: the lint level is defined here + --> $DIR/redundant-import-issue-121915-2015.rs:8:8 + | +LL | #[deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + 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..79b5110e3eb01 --- /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 already exists in the extern prelude + 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..05bdccd1d49cf --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915-2015.stderr @@ -0,0 +1,14 @@ +error: the item `aux_issue_121915` is already exists in the extern prelude + --> $DIR/redundant-import-issue-121915-2015.rs:8:9 + | +LL | use aux_issue_121915; + | ----^^^^^^^^^^^^^^^^- help: remove this import + | +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.edition2015.stderr b/tests/ui/imports/redundant-import-issue-121915.edition2015.stderr new file mode 100644 index 0000000000000..17e094b6b5028 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915.edition2015.stderr @@ -0,0 +1,9 @@ +error[E0432]: unresolved import `aux_issue_121915` + --> $DIR/redundant-import-issue-121915.rs:10:9 + | +LL | use aux_issue_121915; + | ^^^^^^^^^^^^^^^^ no `aux_issue_121915` in the root + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/redundant-import-issue-121915.edition2018.stderr b/tests/ui/imports/redundant-import-issue-121915.edition2018.stderr new file mode 100644 index 0000000000000..a9aacc5360463 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915.edition2018.stderr @@ -0,0 +1,14 @@ +error: the item `aux_issue_121915` is already exists in the extern prelude + --> $DIR/redundant-import-issue-121915.rs:9:9 + | +LL | use aux_issue_121915; + | ----^^^^^^^^^^^^^^^^- help: remove this import + | +note: the lint level is defined here + --> $DIR/redundant-import-issue-121915.rs:7:8 + | +LL | #[deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/redundant-import-issue-121915.edition2021.stderr b/tests/ui/imports/redundant-import-issue-121915.edition2021.stderr new file mode 100644 index 0000000000000..a9aacc5360463 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915.edition2021.stderr @@ -0,0 +1,14 @@ +error: the item `aux_issue_121915` is already exists in the extern prelude + --> $DIR/redundant-import-issue-121915.rs:9:9 + | +LL | use aux_issue_121915; + | ----^^^^^^^^^^^^^^^^- help: remove this import + | +note: the lint level is defined here + --> $DIR/redundant-import-issue-121915.rs:7: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..6eb8c2cbd92a2 --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915.rs @@ -0,0 +1,12 @@ +//@ revisions: edition2018 edition2021 +//@ [edition2018] edition:2018 +//@ [edition2021] edition:2021 +//@ compile-flags: --extern aux_issue_121915 +//@ aux-build: aux-issue-121915.rs + +#[deny(unused_imports)] +fn main() { + use aux_issue_121915; + //~^ ERROR the item `aux_issue_121915` is already exists in the extern prelude + aux_issue_121915::item(); +} diff --git a/tests/ui/issues-71798.stderr b/tests/ui/issues-71798.stderr index 829d0a02ec90b..52dd14ccb0a14 100644 --- a/tests/ui/issues-71798.stderr +++ b/tests/ui/issues-71798.stderr @@ -14,7 +14,6 @@ LL | *x | -- return type was inferred to be `u32` here | = help: the trait `Future` is not implemented for `u32` - = note: u32 must be a future or must implement `IntoFuture` to be awaited error: aborting due to 2 previous errors diff --git a/tests/ui/iterators/bound.stderr b/tests/ui/iterators/bound.stderr index e5ed19f3731ca..915f0496716e9 100644 --- a/tests/ui/iterators/bound.stderr +++ b/tests/ui/iterators/bound.stderr @@ -5,7 +5,6 @@ LL | struct T(S); | ^^^^^ `u8` is not an iterator | = help: the trait `Iterator` is not implemented for `u8` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` note: required by a bound in `S` --> $DIR/bound.rs:1:13 | diff --git a/tests/ui/iterators/vec-on-unimplemented.fixed b/tests/ui/iterators/vec-on-unimplemented.fixed new file mode 100644 index 0000000000000..cc46bd67f9a8e --- /dev/null +++ b/tests/ui/iterators/vec-on-unimplemented.fixed @@ -0,0 +1,5 @@ +//@ run-rustfix +fn main() { + let _ = vec![true, false].into_iter().map(|v| !v).collect::>(); + //~^ ERROR no method named `map` found for struct `Vec` in the current scope +} diff --git a/tests/ui/iterators/vec-on-unimplemented.rs b/tests/ui/iterators/vec-on-unimplemented.rs index 42b5d36bfad4a..7367fd4c9cd78 100644 --- a/tests/ui/iterators/vec-on-unimplemented.rs +++ b/tests/ui/iterators/vec-on-unimplemented.rs @@ -1,4 +1,5 @@ +//@ run-rustfix fn main() { - vec![true, false].map(|v| !v).collect::>(); - //~^ ERROR `Vec` is not an iterator + let _ = vec![true, false].map(|v| !v).collect::>(); + //~^ ERROR no method named `map` found for struct `Vec` in the current scope } diff --git a/tests/ui/iterators/vec-on-unimplemented.stderr b/tests/ui/iterators/vec-on-unimplemented.stderr index 29b19d5e3b45b..d6f4bfa1cdebe 100644 --- a/tests/ui/iterators/vec-on-unimplemented.stderr +++ b/tests/ui/iterators/vec-on-unimplemented.stderr @@ -1,14 +1,13 @@ -error[E0599]: `Vec` is not an iterator - --> $DIR/vec-on-unimplemented.rs:2:23 +error[E0599]: no method named `map` found for struct `Vec` in the current scope + --> $DIR/vec-on-unimplemented.rs:3:31 | -LL | vec![true, false].map(|v| !v).collect::>(); - | ^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` +LL | let _ = vec![true, false].map(|v| !v).collect::>(); + | ^^^ `Vec` is not an iterator | - = note: the following trait bounds were not satisfied: - `Vec: Iterator` - which is required by `&mut Vec: Iterator` - `[bool]: Iterator` - which is required by `&mut [bool]: Iterator` +help: call `.into_iter()` first + | +LL | let _ = vec![true, false].into_iter().map(|v| !v).collect::>(); + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/kindck/kindck-impl-type-params-2.rs b/tests/ui/kindck/kindck-impl-type-params-2.rs index 8950fc51e643c..8b0771985dc3f 100644 --- a/tests/ui/kindck/kindck-impl-type-params-2.rs +++ b/tests/ui/kindck/kindck-impl-type-params-2.rs @@ -11,5 +11,5 @@ fn take_param(foo: &T) { } fn main() { let x: Box<_> = Box::new(3); take_param(&x); - //~^ ERROR the trait bound `Box<{integer}>: Copy` is not satisfied + //~^ ERROR the trait bound `Box<{integer}>: Foo` is not satisfied } diff --git a/tests/ui/kindck/kindck-impl-type-params-2.stderr b/tests/ui/kindck/kindck-impl-type-params-2.stderr index 46c0bda95352f..a7d169d3ac4ae 100644 --- a/tests/ui/kindck/kindck-impl-type-params-2.stderr +++ b/tests/ui/kindck/kindck-impl-type-params-2.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied +error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied --> $DIR/kindck-impl-type-params-2.rs:13:16 | LL | take_param(&x); diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr index a85815d8cc498..979525ff40735 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied +error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | take_param(&x); diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr index 687660fe7eea3..30f90b88160e5 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied +error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | take_param(&x); diff --git a/tests/ui/kindck/kindck-send-object.rs b/tests/ui/kindck/kindck-send-object.rs index 6411e688b4aa6..f5d44246efe5a 100644 --- a/tests/ui/kindck/kindck-send-object.rs +++ b/tests/ui/kindck/kindck-send-object.rs @@ -10,7 +10,7 @@ trait Message : Send { } fn object_ref_with_static_bound_not_ok() { assert_send::<&'static (dyn Dummy + 'static)>(); - //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277] + //~^ ERROR `&'static (dyn Dummy + 'static)` cannot be sent between threads safely [E0277] } fn box_object_with_no_bound_not_ok<'a>() { diff --git a/tests/ui/kindck/kindck-send-object.stderr b/tests/ui/kindck/kindck-send-object.stderr index 0fc9cb14c7d46..9f1ff4f3644cc 100644 --- a/tests/ui/kindck/kindck-send-object.stderr +++ b/tests/ui/kindck/kindck-send-object.stderr @@ -1,10 +1,10 @@ -error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely +error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads safely --> $DIR/kindck-send-object.rs:12:19 | LL | assert_send::<&'static (dyn Dummy + 'static)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` + = help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object.rs:5:18 diff --git a/tests/ui/kindck/kindck-send-object1.rs b/tests/ui/kindck/kindck-send-object1.rs index 0ce3995dccc9a..76a9fc6019abc 100644 --- a/tests/ui/kindck/kindck-send-object1.rs +++ b/tests/ui/kindck/kindck-send-object1.rs @@ -8,7 +8,7 @@ trait Dummy { } // careful with object types, who knows what they close over... fn test51<'a>() { assert_send::<&'a dyn Dummy>(); - //~^ ERROR `(dyn Dummy + 'a)` cannot be shared between threads safely [E0277] + //~^ ERROR `&'a (dyn Dummy + 'a)` cannot be sent between threads safely [E0277] } fn test52<'a>() { assert_send::<&'a (dyn Dummy + Sync)>(); diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr index 39343b9993b5a..f2aa814676fc3 100644 --- a/tests/ui/kindck/kindck-send-object1.stderr +++ b/tests/ui/kindck/kindck-send-object1.stderr @@ -1,10 +1,10 @@ -error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely +error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely --> $DIR/kindck-send-object1.rs:10:19 | LL | assert_send::<&'a dyn Dummy>(); - | ^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely + | ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send` + = help: the trait `Sync` is not implemented for `&'a (dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send` = note: required for `&'a (dyn Dummy + 'a)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object1.rs:5:18 diff --git a/tests/ui/kindck/kindck-send-object2.rs b/tests/ui/kindck/kindck-send-object2.rs index b797588e446d6..d37074e657462 100644 --- a/tests/ui/kindck/kindck-send-object2.rs +++ b/tests/ui/kindck/kindck-send-object2.rs @@ -5,7 +5,7 @@ trait Dummy { } fn test50() { assert_send::<&'static dyn Dummy>(); - //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277] + //~^ ERROR `&'static (dyn Dummy + 'static)` cannot be sent between threads safely [E0277] } fn test53() { diff --git a/tests/ui/kindck/kindck-send-object2.stderr b/tests/ui/kindck/kindck-send-object2.stderr index 758a517e12885..cd4d74360f867 100644 --- a/tests/ui/kindck/kindck-send-object2.stderr +++ b/tests/ui/kindck/kindck-send-object2.stderr @@ -1,10 +1,10 @@ -error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely +error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads safely --> $DIR/kindck-send-object2.rs:7:19 | LL | assert_send::<&'static dyn Dummy>(); - | ^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` + = help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object2.rs:3:18 diff --git a/tests/ui/methods/issues/issue-94581.fixed b/tests/ui/methods/issues/issue-94581.fixed new file mode 100644 index 0000000000000..ff2bbeba27cbb --- /dev/null +++ b/tests/ui/methods/issues/issue-94581.fixed @@ -0,0 +1,8 @@ +//@ run-rustfix +fn get_slice() -> &'static [i32] { + &[1, 2, 3, 4] +} + +fn main() { + let _sqsum: i32 = get_slice().into_iter().map(|i| i * i).sum(); //~ ERROR [E0599] +} diff --git a/tests/ui/methods/issues/issue-94581.rs b/tests/ui/methods/issues/issue-94581.rs index df393e91db084..535d3249eb910 100644 --- a/tests/ui/methods/issues/issue-94581.rs +++ b/tests/ui/methods/issues/issue-94581.rs @@ -1,7 +1,8 @@ +//@ run-rustfix fn get_slice() -> &'static [i32] { &[1, 2, 3, 4] } fn main() { - let sqsum = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599] + let _sqsum: i32 = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599] } diff --git a/tests/ui/methods/issues/issue-94581.stderr b/tests/ui/methods/issues/issue-94581.stderr index ae7446d483352..d04d6ca5e3cd3 100644 --- a/tests/ui/methods/issues/issue-94581.stderr +++ b/tests/ui/methods/issues/issue-94581.stderr @@ -1,14 +1,13 @@ -error[E0599]: `&'static [i32]` is not an iterator - --> $DIR/issue-94581.rs:6:29 +error[E0599]: no method named `map` found for reference `&'static [i32]` in the current scope + --> $DIR/issue-94581.rs:7:35 | -LL | let sqsum = get_slice().map(|i| i * i).sum(); - | ^^^ `&'static [i32]` is not an iterator; try calling `.iter()` +LL | let _sqsum: i32 = get_slice().map(|i| i * i).sum(); + | ^^^ `&'static [i32]` is not an iterator | - = note: the following trait bounds were not satisfied: - `&'static [i32]: Iterator` - which is required by `&mut &'static [i32]: Iterator` - `[i32]: Iterator` - which is required by `&mut [i32]: Iterator` +help: call `.into_iter()` first + | +LL | let _sqsum: i32 = get_slice().into_iter().map(|i| i * i).sum(); + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs index 8567d812e4fb2..29793e9f7347d 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs @@ -14,7 +14,7 @@ struct PriorityQueueEntry { //~^ ERROR can't compare `PriorityQueue` with `PriorityQueue` //~| ERROR the trait bound `PriorityQueue: Eq` is not satisfied //~| ERROR can't compare `T` with `T` -//~| ERROR `BinaryHeap>` is not an iterator +//~| ERROR no method named `cmp` found for struct `BinaryHeap>` //~| ERROR no field `height` on type `&PriorityQueue` struct PriorityQueue(BinaryHeap>); diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index 6fa639877d3b1..0fe560afcb5d3 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -46,15 +46,12 @@ LL | struct PriorityQueue(BinaryHeap>); = help: the trait `PartialOrd<_>` is not implemented for `BinaryHeap>` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0599]: `BinaryHeap>` is not an iterator +error[E0599]: no method named `cmp` found for struct `BinaryHeap>` in the current scope --> $DIR/issue-104884-trait-impl-sugg-err.rs:13:22 | LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ `BinaryHeap>` is not an iterator | - = note: the following trait bounds were not satisfied: - `BinaryHeap>: Iterator` - which is required by `&mut BinaryHeap>: Iterator` = note: this error originates in the derive macro `AddImpl` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0609]: no field `height` on type `&PriorityQueue` diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs index 5053c115b4537..c9dc1c6e6498b 100644 --- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs +++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs @@ -17,5 +17,5 @@ fn stuff(_: T) {} fn main() { stuff(1u8); - //~^ the trait bound `u8: Foo` is not satisfied + //~^ the trait bound `u8: Bar` is not satisfied } diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr index 99d318a793364..284dacf7000bd 100644 --- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr +++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `u8: Foo` is not satisfied +error[E0277]: the trait bound `u8: Bar` is not satisfied --> $DIR/feature-gate-do_not_recommend.rs:19:11 | LL | stuff(1u8); diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index ec9826819c0e5..05e087fd9f9a6 100644 --- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -7,7 +7,6 @@ LL | bar(foo); | required by a bound introduced by this call | = help: the trait `Future` is not implemented for fn item `fn() -> impl Future {foo}` - = note: fn() -> impl Future {foo} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | @@ -27,7 +26,6 @@ LL | bar(async_closure); | required by a bound introduced by this call | = help: the trait `Future` is not implemented for `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` - = note: {async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | diff --git a/tests/ui/suggestions/issue-104961.fixed b/tests/ui/suggestions/issue-104961.fixed index a4047def341e8..5def21b506e1c 100644 --- a/tests/ui/suggestions/issue-104961.fixed +++ b/tests/ui/suggestions/issue-104961.fixed @@ -2,12 +2,12 @@ fn foo(x: &str) -> bool { x.starts_with(&("hi".to_string() + " you")) - //~^ ERROR expected a `FnMut(char)` closure, found `String` + //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277] } fn foo2(x: &str) -> bool { x.starts_with(&"hi".to_string()) - //~^ ERROR expected a `FnMut(char)` closure, found `String` + //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277] } fn main() { diff --git a/tests/ui/suggestions/issue-104961.rs b/tests/ui/suggestions/issue-104961.rs index 9d02f570c84c5..a09b8a887114c 100644 --- a/tests/ui/suggestions/issue-104961.rs +++ b/tests/ui/suggestions/issue-104961.rs @@ -2,12 +2,12 @@ fn foo(x: &str) -> bool { x.starts_with("hi".to_string() + " you") - //~^ ERROR expected a `FnMut(char)` closure, found `String` + //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277] } fn foo2(x: &str) -> bool { x.starts_with("hi".to_string()) - //~^ ERROR expected a `FnMut(char)` closure, found `String` + //~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277] } fn main() { diff --git a/tests/ui/suggestions/issue-104961.stderr b/tests/ui/suggestions/issue-104961.stderr index 7e795a74c9000..3c5f86817f3a4 100644 --- a/tests/ui/suggestions/issue-104961.stderr +++ b/tests/ui/suggestions/issue-104961.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected a `FnMut(char)` closure, found `String` +error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied --> $DIR/issue-104961.rs:4:19 | LL | x.starts_with("hi".to_string() + " you") @@ -6,7 +6,6 @@ LL | x.starts_with("hi".to_string() + " you") | | | required by a bound introduced by this call | - = note: the trait bound `String: Pattern<'_>` is not satisfied = note: required for `String` to implement `Pattern<'_>` note: required by a bound in `core::str::::starts_with` --> $SRC_DIR/core/src/str/mod.rs:LL:COL @@ -15,7 +14,7 @@ help: consider borrowing here LL | x.starts_with(&("hi".to_string() + " you")) | ++ + -error[E0277]: expected a `FnMut(char)` closure, found `String` +error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied --> $DIR/issue-104961.rs:9:19 | LL | x.starts_with("hi".to_string()) @@ -23,7 +22,6 @@ LL | x.starts_with("hi".to_string()) | | | required by a bound introduced by this call | - = note: the trait bound `String: Pattern<'_>` is not satisfied = note: required for `String` to implement `Pattern<'_>` note: required by a bound in `core::str::::starts_with` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/suggestions/issue-62843.stderr b/tests/ui/suggestions/issue-62843.stderr index f3a9f6b7913aa..84ab4a0edd39c 100644 --- a/tests/ui/suggestions/issue-62843.stderr +++ b/tests/ui/suggestions/issue-62843.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected a `FnMut(char)` closure, found `String` +error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied --> $DIR/issue-62843.rs:4:32 | LL | println!("{:?}", line.find(pattern)); @@ -6,7 +6,6 @@ LL | println!("{:?}", line.find(pattern)); | | | required by a bound introduced by this call | - = note: the trait bound `String: Pattern<'_>` is not satisfied = note: required for `String` to implement `Pattern<'_>` note: required by a bound in `core::str::::find` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/suggestions/slice-issue-87994.rs b/tests/ui/suggestions/slice-issue-87994.rs index ecb7f54ea250a..5a2574fff8af8 100644 --- a/tests/ui/suggestions/slice-issue-87994.rs +++ b/tests/ui/suggestions/slice-issue-87994.rs @@ -1,16 +1,16 @@ fn main() { let v = vec![1i32, 2, 3]; for _ in v[1..] { - //~^ ERROR [i32]` is not an iterator [E0277] - //~^^ ERROR known at compilation time + //~^ ERROR `[i32]` is not an iterator [E0277] + //~| ERROR `[i32]` is not an iterator [E0277] } struct K { n: i32, } let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }]; for i2 in v2[1..] { - //~^ ERROR [K]` is not an iterator [E0277] - //~^^ ERROR known at compilation time + //~^ ERROR `[K]` is not an iterator [E0277] + //~| ERROR `[K]` is not an iterator [E0277] i2.n = 2; } } diff --git a/tests/ui/suggestions/slice-issue-87994.stderr b/tests/ui/suggestions/slice-issue-87994.stderr index 656f71eb8773e..22ad5d352120d 100644 --- a/tests/ui/suggestions/slice-issue-87994.stderr +++ b/tests/ui/suggestions/slice-issue-87994.stderr @@ -13,7 +13,7 @@ LL | for _ in &v[1..] { LL | for _ in &mut v[1..] { | ++++ -error[E0277]: the size for values of type `[i32]` cannot be known at compilation time +error[E0277]: `[i32]` is not an iterator --> $DIR/slice-issue-87994.rs:3:12 | LL | for _ in v[1..] { @@ -21,6 +21,7 @@ LL | for _ in v[1..] { | = note: the trait bound `[i32]: IntoIterator` is not satisfied = note: required for `[i32]` to implement `IntoIterator` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider borrowing here | LL | for _ in &v[1..] { @@ -43,7 +44,7 @@ LL | for i2 in &v2[1..] { LL | for i2 in &mut v2[1..] { | ++++ -error[E0277]: the size for values of type `[K]` cannot be known at compilation time +error[E0277]: `[K]` is not an iterator --> $DIR/slice-issue-87994.rs:11:13 | LL | for i2 in v2[1..] { @@ -51,6 +52,7 @@ LL | for i2 in v2[1..] { | = note: the trait bound `[K]: IntoIterator` is not satisfied = note: required for `[K]` to implement `IntoIterator` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider borrowing here | LL | for i2 in &v2[1..] { diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr index 6b2f330e1a36d..3b6994b45d109 100644 --- a/tests/ui/suggestions/suggest-remove-refs-5.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr @@ -1,10 +1,10 @@ -error[E0277]: `Vec` is not an iterator +error[E0277]: `&mut &mut &mut &mut Vec` is not an iterator --> $DIR/suggest-remove-refs-5.rs:4:14 | LL | for _ in &mut &mut v {} - | ^^^^^^^^^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` + | ^^^^^^^^^^^ `&mut &mut &mut &mut Vec` is not an iterator | - = help: the trait `Iterator` is not implemented for `Vec`, which is required by `&mut &mut &mut &mut Vec: IntoIterator` + = help: the trait `Iterator` is not implemented for `&mut &mut &mut &mut Vec`, which is required by `&mut &mut &mut &mut Vec: IntoIterator` = note: required for `&mut Vec` to implement `Iterator` = note: 3 redundant requirements hidden = note: required for `&mut &mut &mut &mut Vec` to implement `Iterator` @@ -15,13 +15,13 @@ LL ~ let v = &mut Vec::::new(); LL ~ for _ in v {} | -error[E0277]: `[u8; 1]` is not an iterator +error[E0277]: `&mut &mut &mut [u8; 1]` is not an iterator --> $DIR/suggest-remove-refs-5.rs:7:14 | LL | for _ in &mut v {} - | ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()` + | ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator | - = help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator` + = help: the trait `Iterator` is not implemented for `&mut &mut &mut [u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator` = note: required for `&mut [u8; 1]` to implement `Iterator` = note: 2 redundant requirements hidden = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator` diff --git a/tests/ui/traits/alias/cross-crate.rs b/tests/ui/traits/alias/cross-crate.rs index 207216f73bf9f..376819485482e 100644 --- a/tests/ui/traits/alias/cross-crate.rs +++ b/tests/ui/traits/alias/cross-crate.rs @@ -12,6 +12,6 @@ fn use_alias() {} fn main() { use_alias::(); use_alias::>(); - //~^ ERROR `Rc` cannot be sent between threads safely [E0277] - //~^^ ERROR `Rc` cannot be shared between threads safely [E0277] + //~^ ERROR the trait bound `Rc: SendSync` is not satisfied [E0277] + //~| ERROR the trait bound `Rc: SendSync` is not satisfied [E0277] } diff --git a/tests/ui/traits/alias/cross-crate.stderr b/tests/ui/traits/alias/cross-crate.stderr index fd614b4bcd58a..52eb7e44f44fe 100644 --- a/tests/ui/traits/alias/cross-crate.stderr +++ b/tests/ui/traits/alias/cross-crate.stderr @@ -1,10 +1,9 @@ -error[E0277]: `Rc` cannot be sent between threads safely +error[E0277]: the trait bound `Rc: SendSync` is not satisfied --> $DIR/cross-crate.rs:14:17 | LL | use_alias::>(); - | ^^^^^^^ `Rc` cannot be sent between threads safely + | ^^^^^^^ the trait `Send` is not implemented for `Rc`, which is required by `Rc: SendSync` | - = help: the trait `Send` is not implemented for `Rc`, which is required by `Rc: SendSync` = note: required for `Rc` to implement `SendSync` note: required by a bound in `use_alias` --> $DIR/cross-crate.rs:10:17 @@ -12,13 +11,12 @@ note: required by a bound in `use_alias` LL | fn use_alias() {} | ^^^^^^^^ required by this bound in `use_alias` -error[E0277]: `Rc` cannot be shared between threads safely +error[E0277]: the trait bound `Rc: SendSync` is not satisfied --> $DIR/cross-crate.rs:14:17 | LL | use_alias::>(); - | ^^^^^^^ `Rc` cannot be shared between threads safely + | ^^^^^^^ the trait `Sync` is not implemented for `Rc`, which is required by `Rc: SendSync` | - = help: the trait `Sync` is not implemented for `Rc`, which is required by `Rc: SendSync` = note: required for `Rc` to implement `SendSync` note: required by a bound in `use_alias` --> $DIR/cross-crate.rs:10:17 diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs index d254c0ae3ef92..bffa856bbeebb 100644 --- a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs +++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs @@ -7,5 +7,5 @@ trait IteratorAlias = Iterator; fn f(_: impl IteratorAlias) {} fn main() { - f(()) //~ `()` is not an iterator + f(()) //~ ERROR the trait bound `(): IteratorAlias` is not satisfied } diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr index 1e4f4cb70463c..c73c2f680329c 100644 --- a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr +++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr @@ -1,12 +1,11 @@ -error[E0277]: `()` is not an iterator +error[E0277]: the trait bound `(): IteratorAlias` is not satisfied --> $DIR/issue-108072-unmet-trait-alias-bound.rs:10:7 | LL | f(()) - | - ^^ `()` is not an iterator + | - ^^ the trait `Iterator` is not implemented for `()`, which is required by `(): IteratorAlias` | | | required by a bound introduced by this call | - = help: the trait `Iterator` is not implemented for `()`, which is required by `(): IteratorAlias` = note: required for `()` to implement `IteratorAlias` note: required by a bound in `f` --> $DIR/issue-108072-unmet-trait-alias-bound.rs:7:14 diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr index 629ccac49c56a..17fced307ed1f 100644 --- a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr +++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr @@ -6,7 +6,7 @@ LL | auto trait Magic: Copy {} | | | auto traits cannot have super traits or lifetime bounds -error[E0277]: the trait bound `NoClone: Copy` is not satisfied +error[E0277]: the trait bound `NoClone: Magic` is not satisfied --> $DIR/supertrait-auto-trait.rs:16:23 | LL | let (a, b) = copy(NoClone); diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 6c019f59b0992..5bc79d9cee856 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -93,7 +93,6 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` error[E0277]: `i32` is not an iterator --> $DIR/issue-50480.rs:14:33 @@ -102,7 +101,6 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` error[E0277]: `i32` is not an iterator --> $DIR/issue-50480.rs:3:28 @@ -111,7 +109,6 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` error[E0277]: `i32` is not an iterator --> $DIR/issue-50480.rs:11:10 @@ -120,7 +117,6 @@ LL | #[derive(Clone, Copy)] | ^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `i32` is not an iterator @@ -133,7 +129,6 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 13 previous errors diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.fixed b/tests/ui/traits/suggest-dereferences/root-obligation.fixed index eecd52304ff66..072296c6b154d 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.fixed +++ b/tests/ui/traits/suggest-dereferences/root-obligation.fixed @@ -4,7 +4,7 @@ fn get_vowel_count(string: &str) -> usize { string .chars() .filter(|c| "aeiou".contains(*c)) - //~^ ERROR expected a `Fn(char)` closure, found `char` + //~^ ERROR the trait bound `&char: Pattern<'_>` is not satisfied .count() } diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.rs b/tests/ui/traits/suggest-dereferences/root-obligation.rs index d58193f121382..e7025fe082541 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.rs +++ b/tests/ui/traits/suggest-dereferences/root-obligation.rs @@ -4,7 +4,7 @@ fn get_vowel_count(string: &str) -> usize { string .chars() .filter(|c| "aeiou".contains(c)) - //~^ ERROR expected a `Fn(char)` closure, found `char` + //~^ ERROR the trait bound `&char: Pattern<'_>` is not satisfied .count() } diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr index a41330373be1a..56f95e207158a 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr +++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr @@ -1,12 +1,11 @@ -error[E0277]: expected a `Fn(char)` closure, found `char` +error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied --> $DIR/root-obligation.rs:6:38 | LL | .filter(|c| "aeiou".contains(c)) - | -------- ^ expected an `Fn(char)` closure, found `char` + | -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>` | | | required by a bound introduced by this call | - = help: the trait `Fn<(char,)>` is not implemented for `char`, which is required by `&char: Pattern<'_>` = note: required for `&char` to implement `FnOnce<(char,)>` = note: required for `&char` to implement `Pattern<'_>` note: required by a bound in `core::str::::contains`