From d0873c7a11e71a46ad58c1d152fb0599281d98df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 12 Feb 2024 16:24:31 +0100 Subject: [PATCH 01/15] constify a couple thread_local statics --- compiler/rustc_data_structures/src/sync/worker_local.rs | 2 +- compiler/rustc_errors/src/markdown/term.rs | 4 ++-- library/proc_macro/src/bridge/client.rs | 2 +- library/proc_macro/src/bridge/server.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs index b34d3dd904400..ba9f88b912eef 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/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 9255c3abc8a02..b6a75f72c749e 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -284,7 +284,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 2ea87d866ff3e..eee64e69b37b1 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -152,7 +152,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) From f0c93117ed0551392860ae049507d388272a052d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 29 Feb 2024 00:35:59 +0000 Subject: [PATCH 02/15] Use root obligation on E0277 for some cases When encountering trait bound errors that satisfy some heuristics that tell us that the relevant trait for the user comes from the root obligation and not the current obligation, we use the root predicate for the main message. This allows to talk about "X doesn't implement Pattern<'_>" over the most specific case that just happened to fail, like "char doesn't implement Fn(&mut char)" in `tests/ui/traits/suggest-dereferences/root-obligation.rs` The heuristics are: - 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" - 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 - the root trait is not `Unsize`, as to avoid talking about it in `tests/ui/coercion/coerce-issue-49593-box-never.rs`. ``` error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied --> $DIR/root-obligation.rs:6:38 | LL | .filter(|c| "aeiou".contains(c)) | -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>` | | | required by a bound introduced by this call | = note: required for `&char` to implement `FnOnce<(char,)>` = note: required for `&char` to implement `Pattern<'_>` note: required by a bound in `core::str::::contains` --> $SRC_DIR/core/src/str/mod.rs:LL:COL help: consider dereferencing here | LL | .filter(|c| "aeiou".contains(*c)) | + ``` Fix #79359, fix #119983, fix #118779, cc #118415 (the suggestion needs to change). --- .../error_reporting/type_err_ctxt_ext.rs | 51 +++++++++++++++++-- library/core/src/future/future.rs | 3 +- library/core/src/future/into_future.rs | 5 ++ library/core/src/iter/traits/collect.rs | 43 ++++++++++++++++ library/core/src/iter/traits/iterator.rs | 26 +--------- .../substs-ppaux.normal.stderr | 5 +- tests/ui/associated-types/substs-ppaux.rs | 4 +- .../substs-ppaux.verbose.stderr | 5 +- tests/ui/async-await/async-error-span.stderr | 1 - .../async-await/coroutine-not-future.stderr | 2 - .../typeck-default-trait-impl-precedence.rs | 2 +- ...ypeck-default-trait-impl-precedence.stderr | 4 +- .../coroutine/gen_block_is_no_future.stderr | 1 - .../feature-gate-trivial_bounds.stderr | 1 - tests/ui/for/issue-20605.current.stderr | 2 +- tests/ui/for/issue-20605.next.stderr | 6 ++- tests/ui/for/issue-20605.rs | 4 +- tests/ui/impl-trait/issues/issue-83919.stderr | 1 - tests/ui/issues-71798.stderr | 1 - tests/ui/iterators/bound.stderr | 1 - tests/ui/kindck/kindck-impl-type-params-2.rs | 2 +- .../kindck/kindck-impl-type-params-2.stderr | 2 +- .../kindck-inherited-copy-bound.curr.stderr | 2 +- ...copy-bound.object_safe_for_dispatch.stderr | 2 +- tests/ui/kindck/kindck-send-object.rs | 2 +- tests/ui/kindck/kindck-send-object.stderr | 6 +-- tests/ui/kindck/kindck-send-object1.rs | 2 +- tests/ui/kindck/kindck-send-object1.stderr | 6 +-- tests/ui/kindck/kindck-send-object2.rs | 2 +- tests/ui/kindck/kindck-send-object2.stderr | 6 +-- .../feature-gate-do_not_recommend.rs | 2 +- .../feature-gate-do_not_recommend.stderr | 2 +- ...rg-where-it-should-have-been-called.stderr | 2 - tests/ui/suggestions/issue-104961.fixed | 4 +- tests/ui/suggestions/issue-104961.rs | 4 +- tests/ui/suggestions/issue-104961.stderr | 6 +-- tests/ui/suggestions/issue-62843.stderr | 3 +- tests/ui/suggestions/slice-issue-87994.rs | 8 +-- tests/ui/suggestions/slice-issue-87994.stderr | 6 ++- .../suggestions/suggest-remove-refs-5.stderr | 12 ++--- tests/ui/traits/alias/cross-crate.rs | 4 +- tests/ui/traits/alias/cross-crate.stderr | 10 ++-- .../issue-108072-unmet-trait-alias-bound.rs | 2 +- ...ssue-108072-unmet-trait-alias-bound.stderr | 5 +- .../supertrait-auto-trait.stderr | 2 +- tests/ui/traits/issue-50480.stderr | 5 -- .../root-obligation.fixed | 2 +- .../suggest-dereferences/root-obligation.rs | 2 +- .../root-obligation.stderr | 5 +- 49 files changed, 166 insertions(+), 120 deletions(-) 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..6644ac48aece2 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,51 @@ 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() + // 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` + trait_predicate.self_ty().skip_binder() + == root_pred.self_ty().peel_refs() + // `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator` + || 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 +501,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 +524,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/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..74f9e7f94467e 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -28,15 +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`" + note = "you might have meant to use a bounded `RangeInclusive`" ), on( _Self = "[]", @@ -47,24 +43,6 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} _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" )] 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/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/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/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/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` From 89a3c198321f33b5c9efb54eb48d354c4bd5c614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 1 Mar 2024 21:37:56 +0000 Subject: [PATCH 03/15] Be more lax in `.into_iter()` suggestion when encountering `Iterator` methods on non-`Iterator` ``` error[E0599]: no method named `map` found for struct `Vec` in the current scope --> $DIR/vec-on-unimplemented.rs:3:23 | LL | vec![true, false].map(|v| !v).collect::>(); | ^^^ `Vec` is not an iterator | help: call `.into_iter()` first | LL | vec![true, false].into_iter().map(|v| !v).collect::>(); | ++++++++++++ ``` We used to provide some help through `rustc_on_unimplemented` on non-`impl Trait` and non-type-params, but this lets us get rid of some otherwise unnecessary conditions in the annotation on `Iterator`. --- compiler/rustc_hir_typeck/src/method/suggest.rs | 4 ++-- library/core/src/iter/traits/iterator.rs | 9 --------- tests/ui/iterators/vec-on-unimplemented.fixed | 5 +++++ tests/ui/iterators/vec-on-unimplemented.rs | 5 +++-- tests/ui/iterators/vec-on-unimplemented.stderr | 17 ++++++++--------- tests/ui/methods/issues/issue-94581.fixed | 8 ++++++++ tests/ui/methods/issues/issue-94581.rs | 3 ++- tests/ui/methods/issues/issue-94581.stderr | 17 ++++++++--------- .../issue-104884-trait-impl-sugg-err.rs | 2 +- .../issue-104884-trait-impl-sugg-err.stderr | 5 +---- 10 files changed, 38 insertions(+), 37 deletions(-) create mode 100644 tests/ui/iterators/vec-on-unimplemented.fixed create mode 100644 tests/ui/methods/issues/issue-94581.fixed 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/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 74f9e7f94467e..e1904ed220cb4 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -34,15 +34,6 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} _Self = "core::ops::range::RangeToInclusive", note = "you might have meant to use a bounded `RangeInclusive`" ), - 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()`" - ), label = "`{Self}` is not an iterator", message = "`{Self}` is not an iterator" )] 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/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` From 40f9dccad64c20fdcc91e5e0da15d8647465820f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 2 Mar 2024 01:52:27 +0000 Subject: [PATCH 04/15] Use `can_eq` instead of `Ty<'_> == Ty<'_>` --- .../traits/error_reporting/type_err_ctxt_ext.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) 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 6644ac48aece2..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 @@ -426,17 +426,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { 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` - trait_predicate.self_ty().skip_binder() - == root_pred.self_ty().peel_refs() + 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` - || trait_predicate.self_ty().skip_binder() - == root_pred.self_ty() + || 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 From 2f29740dd6777ded00f938c2cee3462aa434de96 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sat, 24 Feb 2024 15:22:42 -0500 Subject: [PATCH 05/15] Move visitor utils to `rustc_ast_ir` --- compiler/rustc_ast/src/visit.rs | 68 +-------------- compiler/rustc_ast_ir/src/lib.rs | 3 + compiler/rustc_ast_ir/src/visit.rs | 82 +++++++++++++++++++ .../rustc_ast_passes/src/ast_validation.rs | 3 +- .../src/deriving/default.rs | 3 +- compiler/rustc_expand/src/expand.rs | 3 +- compiler/rustc_hir/src/intravisit.rs | 3 +- .../rustc_hir_analysis/src/check/region.rs | 2 +- .../src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_lint/src/early.rs | 4 +- compiler/rustc_middle/src/hir/map/mod.rs | 3 +- compiler/rustc_resolve/src/late.rs | 2 +- 12 files changed, 99 insertions(+), 79 deletions(-) create mode 100644 compiler/rustc_ast_ir/src/visit.rs 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_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/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/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index ae01bf845751a..4a73ea5733949 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; 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_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_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 4057e9b8a0ef4..92167c2680af0 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::{ From d4b95ebe13cbeeb9d184ae462935459e4d479b3d Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sat, 24 Feb 2024 17:22:28 -0500 Subject: [PATCH 06/15] Convert `TypeVisitor` and `DefIdVisitor` to use `VisitorResult` --- Cargo.lock | 4 + .../rustc_const_eval/src/interpret/util.rs | 6 +- .../src/transform/check_consts/check.rs | 6 +- .../rustc_hir_analysis/src/check/check.rs | 5 +- .../src/check/compare_impl_item/refine.rs | 10 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 13 +- .../src/collect/resolve_bound_vars.rs | 13 +- .../src/constrained_generic_params.rs | 14 +- .../rustc_hir_analysis/src/variance/mod.rs | 13 +- compiler/rustc_hir_typeck/Cargo.toml | 1 + compiler/rustc_hir_typeck/src/closure.rs | 4 +- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 4 +- compiler/rustc_infer/Cargo.toml | 1 + .../src/infer/error_reporting/mod.rs | 4 +- .../nice_region_error/static_impl_trait.rs | 4 +- .../trait_impl_difference.rs | 5 +- .../rustc_infer/src/infer/opaque_types.rs | 22 +--- .../src/infer/outlives/for_liveness.rs | 31 ++--- .../src/traits/structural_impls.rs | 6 +- compiler/rustc_lint/src/types.rs | 8 +- compiler/rustc_macros/src/type_visitable.rs | 13 +- compiler/rustc_middle/src/macros.rs | 4 +- compiler/rustc_middle/src/traits/solve.rs | 20 +-- compiler/rustc_middle/src/ty/diagnostics.rs | 6 +- compiler/rustc_middle/src/ty/generic_args.rs | 11 +- compiler/rustc_middle/src/ty/mod.rs | 9 +- compiler/rustc_middle/src/ty/print/pretty.rs | 12 +- .../rustc_middle/src/ty/structural_impls.rs | 75 ++++------- compiler/rustc_middle/src/ty/sty.rs | 8 +- compiler/rustc_middle/src/ty/visit.rs | 46 +++---- .../rustc_monomorphize/src/polymorphize.rs | 15 +-- compiler/rustc_privacy/src/lib.rs | 121 ++++++++---------- compiler/rustc_trait_selection/Cargo.toml | 1 + .../src/solve/eval_ctxt/mod.rs | 6 +- .../src/traits/coherence.rs | 21 ++- .../src/traits/const_evaluatable.rs | 7 +- .../src/traits/error_reporting/mod.rs | 4 +- .../rustc_trait_selection/src/traits/mod.rs | 8 +- .../src/traits/object_safety.rs | 6 +- .../src/traits/query/normalize.rs | 19 +-- .../src/traits/structural_match.rs | 4 +- compiler/rustc_transmute/Cargo.toml | 16 ++- compiler/rustc_ty_utils/src/opaque_types.rs | 18 ++- compiler/rustc_ty_utils/src/ty.rs | 10 +- compiler/rustc_type_ir/src/canonical.rs | 15 ++- compiler/rustc_type_ir/src/lib.rs | 4 +- compiler/rustc_type_ir/src/macros.rs | 4 +- compiler/rustc_type_ir/src/predicate_kind.rs | 17 +-- compiler/rustc_type_ir/src/ty_kind.rs | 5 +- compiler/rustc_type_ir/src/visit.rs | 103 ++++++++------- .../clippy_lints/src/methods/useless_asref.rs | 4 +- .../clippy_utils/src/mir/possible_borrower.rs | 4 +- src/tools/clippy/clippy_utils/src/ty.rs | 6 +- 53 files changed, 346 insertions(+), 450 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a39e468e3d978..df516dc65a64a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3942,6 +3942,7 @@ version = "0.0.0" dependencies = [ "itertools 0.11.0", "rustc_ast", + "rustc_ast_ir", "rustc_attr", "rustc_data_structures", "rustc_errors", @@ -4010,6 +4011,7 @@ dependencies = [ name = "rustc_infer" version = "0.0.0" dependencies = [ + "rustc_ast_ir", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4604,6 +4606,7 @@ dependencies = [ "bitflags 2.4.2", "itertools 0.11.0", "rustc_ast", + "rustc_ast_ir", "rustc_attr", "rustc_data_structures", "rustc_errors", @@ -4642,6 +4645,7 @@ name = "rustc_transmute" version = "0.0.0" dependencies = [ "itertools 0.11.0", + "rustc_ast_ir", "rustc_data_structures", "rustc_hir", "rustc_infer", 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_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/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 4a73ea5733949..ad8ec1036efee 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -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_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/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_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_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 6fdb03c0babb5..883bc2699d1b4 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 bbe06c0935231..95f06048aa463 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::*; @@ -2657,9 +2657,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 @@ -2668,18 +2666,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_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..fc110afd8e49a 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(()) } } @@ -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_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/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/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 68111c4cc1fdc..20af016eb0056 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(()) } } 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/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/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 86c7551882aab..2b8c77de4f31f 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -193,8 +193,8 @@ impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'t 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 +203,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 +235,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 +252,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 +271,6 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { } _ => trace!(kind=?t.kind()), } - ControlFlow::Continue(()) } } @@ -291,8 +290,8 @@ impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for ImplTraitInAssocTypeCo 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 +346,6 @@ impl<'tcx> TypeVisitor> for ImplTraitInAssocTypeCollector<'tcx> { } _ => trace!(kind=?t.kind()), } - ControlFlow::Continue(()) } } 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/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; From 84d7ba0cedd80b59fd31dc95b2da94e0d4afe4b0 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sat, 24 Feb 2024 19:25:04 -0500 Subject: [PATCH 07/15] Convert `SpannedTypeVisitor` to use `VisitorResult` --- Cargo.lock | 1 + compiler/rustc_privacy/src/lib.rs | 4 +- compiler/rustc_ty_utils/Cargo.toml | 1 + compiler/rustc_ty_utils/src/opaque_types.rs | 8 +--- compiler/rustc_ty_utils/src/sig_types.rs | 42 ++++++++++----------- 5 files changed, 25 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df516dc65a64a..b5d851e8da7a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4661,6 +4661,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_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index fc110afd8e49a..fe3598616817b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1065,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()) } 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 2b8c77de4f31f..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,9 +184,8 @@ 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(()) } } @@ -278,13 +276,11 @@ 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(()) } } 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() } From e1e02a27f43d829e3d0166e1d9c42a30eb330b7d Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sat, 24 Feb 2024 19:38:58 -0500 Subject: [PATCH 08/15] Convert `ProofTreeVisitor` to use `VisitorResult` --- compiler/rustc_trait_selection/src/lib.rs | 1 + .../src/solve/inspect/analyse.rs | 47 +++++++++---------- .../src/traits/coherence.rs | 11 ++--- 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 00a2adccf64a5..a3465677fd200 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -17,6 +17,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![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/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 20af016eb0056..176647a4b15f8 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -1023,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(); @@ -1051,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. @@ -1151,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(()) } } From 25e56de259eb24bba0694e38940a1274280f744f Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 4 Mar 2024 10:24:23 +0800 Subject: [PATCH 09/15] Fix redundant import errors for preload extern crate --- compiler/rustc_lint/src/context/diagnostics.rs | 3 +++ compiler/rustc_lint_defs/src/lib.rs | 1 + compiler/rustc_resolve/src/imports.rs | 17 ++++++++++++++--- tests/ui/imports/auxiliary/aux-issue-121915.rs | 1 + ...-import-issue-121915-2015.edition2015.stderr | 14 ++++++++++++++ .../redundant-import-issue-121915-2015.rs | 11 +++++++++++ .../redundant-import-issue-121915-2015.stderr | 14 ++++++++++++++ ...ndant-import-issue-121915.edition2015.stderr | 9 +++++++++ ...ndant-import-issue-121915.edition2018.stderr | 14 ++++++++++++++ ...ndant-import-issue-121915.edition2021.stderr | 14 ++++++++++++++ .../ui/imports/redundant-import-issue-121915.rs | 12 ++++++++++++ 11 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 tests/ui/imports/auxiliary/aux-issue-121915.rs create mode 100644 tests/ui/imports/redundant-import-issue-121915-2015.edition2015.stderr create mode 100644 tests/ui/imports/redundant-import-issue-121915-2015.rs create mode 100644 tests/ui/imports/redundant-import-issue-121915-2015.stderr create mode 100644 tests/ui/imports/redundant-import-issue-121915.edition2015.stderr create mode 100644 tests/ui/imports/redundant-import-issue-121915.edition2018.stderr create mode 100644 tests/ui/imports/redundant-import-issue-121915.edition2021.stderr create mode 100644 tests/ui/imports/redundant-import-issue-121915.rs 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_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_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/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(); +} From a9a979839bbdfec48c75d618ab0dce8a953589b8 Mon Sep 17 00:00:00 2001 From: Sundeep KOKKONDA <56015745+sundeep-kokkonda@users.noreply.github.com> Date: Mon, 4 Mar 2024 08:18:54 +0530 Subject: [PATCH 10/15] Removing absolute path in proc-macro With rust 1.75 the absolute build path is embedding into '.rustc' section and which causes reproducibility issues. Detailed issue is here. https://github.com/rust-lang/rust/issues/120825#issuecomment-1964307219 With this change the 'absolute path' changed back to '/rust/$hash' format. --- compiler/rustc_session/src/session.rs | 13 ------------- 1 file changed, 13 deletions(-) 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, From 4146136d6dfd3a41f674b71bece81a33c74d824a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Feb 2024 17:43:07 +1100 Subject: [PATCH 11/15] Extract an arguments struct for `Builder::then_else_break` Most of this method's arguments are usually or always forwarded as-is to recursive invocations. Wrapping them in a dedicated struct allows us to document each struct field, and lets us use struct-update syntax to indicate which arguments are being modified when making a recursive call. --- .../rustc_mir_build/src/build/expr/into.rs | 8 +- .../rustc_mir_build/src/build/matches/mod.rs | 130 +++++++++--------- 2 files changed, 72 insertions(+), 66 deletions(-) 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 ) }); From 9eb927e025d37c4a04c1e147e94205736f02e8c3 Mon Sep 17 00:00:00 2001 From: roblabla Date: Mon, 4 Mar 2024 09:24:41 +0100 Subject: [PATCH 12/15] Don't run test_get_os_named_thread on win7 This test won't work on windows 7, as the Thread::set_name function is not implemented there (win7 does not provide a documented mechanism to set thread names). --- library/std/src/thread/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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", From 05e68facbb196126d01719111296f07bc264b915 Mon Sep 17 00:00:00 2001 From: Janggun Lee Date: Mon, 4 Mar 2024 22:15:05 +0900 Subject: [PATCH 13/15] Fix comment in Atomic{Ptr,Bool}::as_ptr. --- library/core/src/sync/atomic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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`. /// From 640e99ccc982586352b1ad94c350af3cbeff3c2e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 4 Mar 2024 14:30:46 +0100 Subject: [PATCH 14/15] Fix duplicated path in the "not found dylib" error --- compiler/rustc_metadata/src/creader.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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); From 5e6e140b0cf44079cd0f42ba8bfcbf874859dd68 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 4 Mar 2024 14:31:23 +0100 Subject: [PATCH 15/15] Add regression ui test for duplicated path in dylib error --- tests/ui/codegen/duplicated-path-in-error.rs | 7 +++++++ tests/ui/codegen/duplicated-path-in-error.stderr | 2 ++ 2 files changed, 9 insertions(+) create mode 100644 tests/ui/codegen/duplicated-path-in-error.rs create mode 100644 tests/ui/codegen/duplicated-path-in-error.stderr 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 +