From 228a7bb91809fefa7eee61f4ec5960e4a263563f Mon Sep 17 00:00:00 2001 From: Mahmoud Mazouz Date: Sun, 18 May 2025 15:37:18 +0200 Subject: [PATCH 01/15] Fix typos in "Libraries and Metadata" --- .../src/backend/libs-and-metadata.md | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md b/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md index 513df1650c387..eeb2af5e6bc8b 100644 --- a/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md +++ b/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md @@ -28,8 +28,8 @@ format is specific to `rustc`, and may change over time. This file contains: [`-C embed-bitcode=no`][embed-bitcode] CLI option to improve compile times and reduce disk space if LTO is not needed. * `rustc` [metadata], in a file named `lib.rmeta`. -* A symbol table, which is generally a list of symbols with offsets to the - object file that contain that symbol. This is pretty standard for archive +* A symbol table, which is essentially a list of symbols with offsets to the + object files that contain that symbol. This is pretty standard for archive files. [archive file]: https://en.wikipedia.org/wiki/Ar_(Unix) @@ -46,12 +46,11 @@ A `dylib` is a platform-specific shared library. It includes the `rustc` ### rmeta -An `rmeta` file is custom binary format that contains the [metadata] for the -crate. This file can be used for fast "checks" of a project by skipping all -code generation (as is done with `cargo check`), collecting enough information -for documentation (as is done with `cargo doc`), or for -[pipelining](#pipelining). This file is created if the -[`--emit=metadata`][emit] CLI option is used. +An `rmeta` file is a custom binary format that contains the [metadata] for the +crate. This file can be used for fast "checks" of a project by skipping all code +generation (as is done with `cargo check`), collecting enough information for +documentation (as is done with `cargo doc`), or for [pipelining](#pipelining). +This file is created if the [`--emit=metadata`][emit] CLI option is used. `rmeta` files do not support linking, since they do not contain compiled object files. @@ -60,8 +59,8 @@ object files. ## Metadata -The metadata contains a wide swath of different elements. This guide will not -go into detail of every field it contains. You are encouraged to browse the +The metadata contains a wide swath of different elements. This guide will not go +into detail about every field it contains. You are encouraged to browse the [`CrateRoot`] definition to get a sense of the different elements it contains. Everything about metadata encoding and decoding is in the [`rustc_metadata`] package. @@ -122,9 +121,9 @@ much more. By default, all Rust symbols are mangled and incorporate the stable crate id. This allows multiple versions of the same crate to be included together. Cargo -automatically generates `-C metadata` hashes based on a variety of factors, -like the package version, source, and the target kind (a lib and test can have -the same crate name, so they need to be disambiguated). +automatically generates `-C metadata` hashes based on a variety of factors, like +the package version, source, and target kind (a lib and test can have the same +crate name, so they need to be disambiguated). [`StableCrateId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.StableCrateId.html [`StableCrateId::new`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.StableCrateId.html#method.new @@ -154,7 +153,7 @@ will also look at the [sysroot] to find dependencies. As crates are loaded, they are kept in the [`CStore`] with the crate metadata wrapped in the [`CrateMetadata`] struct. After resolution and expansion, the -`CStore` will make its way into the [`GlobalCtxt`] for the rest of +`CStore` will make its way into the [`GlobalCtxt`] for the rest of the compilation. [name resolution]: ../name-resolution.md From 34ee7e206f5e9cc06991ac5fe3732fd3b3149169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 18 May 2025 20:01:47 +0200 Subject: [PATCH 02/15] Exclude issues with an associated PR from the "What should I work on" GH query --- src/doc/rustc-dev-guide/src/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index 8bf14bef2a033..0e5b32a06f898 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -89,7 +89,7 @@ filtering the search to areas you're interested in. For example: Not all important or beginner work has issue labels. See below for how to find work that isn't labelled. -[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+ +[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+-linked:pr+ [Triage]: ./contributing.md#issue-triage ### Recurring work From 70ead0af5be34bf03a9313be20fa610668b41340 Mon Sep 17 00:00:00 2001 From: The rustc-dev-guide Cronjob Bot Date: Mon, 19 May 2025 04:10:52 +0000 Subject: [PATCH 03/15] Preparing for merge from rustc --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 5e4266f61da2a..0d889a5d5b991 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -414482f6a0d4e7290f614300581a0b55442552a3 +e42bbfe1f7c26f8760a99c4b1f27d33aba1040bb From 686f0fa8a2bf4e0971b97b18c0308caa28b247ee Mon Sep 17 00:00:00 2001 From: Stan Manilov Date: Mon, 19 May 2025 14:41:19 +0300 Subject: [PATCH 04/15] Remove unused references and simplify one --- src/doc/rustc-dev-guide/src/rustc-driver/intro.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/intro.md b/src/doc/rustc-dev-guide/src/rustc-driver/intro.md index 40500e6bc7a5f..a3684397b2995 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/intro.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/intro.md @@ -7,8 +7,8 @@ It acts as the glue for running the various phases of the compiler in the correc using the interface defined in the [`rustc_interface`] crate. Where possible, using [`rustc_driver`] rather than [`rustc_interface`] is recommended. The main entry point of [`rustc_driver`] is [`rustc_driver::run_compiler`][rd_rc]. -This builder accepts the same command-line args as rustc as well as an implementation of [`Callbacks`][cb] and a couple of other optional options. -[`Callbacks`][cb] is a `trait` that allows for custom compiler configuration, +This builder accepts the same command-line args as rustc as well as an implementation of [`Callbacks`] and a couple of other optional options. +[`Callbacks`] is a `trait` that allows for custom compiler configuration, as well as allowing custom code to run after different phases of the compilation. ## `rustc_interface` @@ -33,14 +33,8 @@ specifically [`rustc_driver_impl::run_compiler`][rdi_rc] [`Compiler`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Compiler.html [`rustc_driver`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/ [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html -[`Session`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html -[`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/source_map/struct.SourceMap.html -[`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html -[Appendix A]: appendix/stupid-stats.html -[cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html +[`Callbacks`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html [example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-interface-example.rs [i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html [rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html [rdi_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.run_compiler.html -[stupid-stats]: https://github.com/nrc/stupid-stats -[`nightly-rustc`]: https://doc.rust-lang.org/nightly/nightly-rustc/ From 114367587c3b0910682d7c56e70e20ca13e4789b Mon Sep 17 00:00:00 2001 From: Stan Manilov Date: Mon, 19 May 2025 14:44:36 +0300 Subject: [PATCH 05/15] Make run instructions first Better, because then one knows how to run the examples. --- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 31119496e754a..a7b76233d1978 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -134,9 +134,9 @@ - [Command-line arguments](./cli.md) - [rustc_driver and rustc_interface](./rustc-driver/intro.md) + - [Remarks on perma-unstable features](./rustc-driver/remarks-on-perma-unstable-features.md) - [Example: Type checking](./rustc-driver/interacting-with-the-ast.md) - [Example: Getting diagnostics](./rustc-driver/getting-diagnostics.md) - - [Remarks on perma-unstable features](./rustc-driver/remarks-on-perma-unstable-features.md) - [Errors and lints](diagnostics.md) - [Diagnostic and subdiagnostic structs](./diagnostics/diagnostic-structs.md) - [Translation](./diagnostics/translation.md) From 4f45f0442ba616bc15111df3f50bec5e3078a334 Mon Sep 17 00:00:00 2001 From: Stan Manilov Date: Mon, 19 May 2025 17:32:29 +0300 Subject: [PATCH 06/15] Update link to Forge guide on new flags --- src/doc/rustc-dev-guide/src/cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/cli.md b/src/doc/rustc-dev-guide/src/cli.md index 408ae20700430..4c77007ea4415 100644 --- a/src/doc/rustc-dev-guide/src/cli.md +++ b/src/doc/rustc-dev-guide/src/cli.md @@ -28,6 +28,6 @@ adding a new command-line argument. unstable-options` flag. [cli-docs]: https://doc.rust-lang.org/rustc/command-line-arguments.html -[forge guide for new options]: https://forge.rust-lang.org/compiler/new_option.html +[forge guide for new options]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#compiler-flags [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/ [`parse_bool`]: https://github.com/rust-lang/rust/blob/e5335592e78354e33d798d20c04bcd677c1df62d/src/librustc_session/options.rs#L307-L313 From db1ac980818078ce3fb49b8cf0607464126da199 Mon Sep 17 00:00:00 2001 From: Josh Gunter <59844337+jagunter@users.noreply.github.com> Date: Sun, 18 May 2025 14:23:53 -0700 Subject: [PATCH 07/15] Fixed possible ICE in annotate_mut_binding_to_immutable_binding --- compiler/rustc_hir_typeck/src/demand.rs | 14 +++++----- tests/crashes/140823.rs | 9 ------- tests/ui/fn/coerce-suggestion-infer-region.rs | 26 +++++++++++++++++++ .../fn/coerce-suggestion-infer-region.stderr | 12 +++++++++ 4 files changed, 46 insertions(+), 15 deletions(-) delete mode 100644 tests/crashes/140823.rs create mode 100644 tests/ui/fn/coerce-suggestion-infer-region.rs create mode 100644 tests/ui/fn/coerce-suggestion-infer-region.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index d1bc54ed73ead..8182851a015bf 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -84,7 +84,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.annotate_expected_due_to_let_ty(err, expr, error); self.annotate_loop_expected_due_to_inference(err, expr, error); - if self.annotate_mut_binding_to_immutable_binding(err, expr, error) { + if self.annotate_mut_binding_to_immutable_binding(err, expr, expr_ty, expected, error) { return; } @@ -799,17 +799,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Detect the following case /// /// ```text - /// fn change_object(mut a: &Ty) { + /// fn change_object(mut b: &Ty) { /// let a = Ty::new(); /// b = a; /// } /// ``` /// - /// where the user likely meant to modify the value behind there reference, use `a` as an out + /// where the user likely meant to modify the value behind there reference, use `b` as an out /// parameter, instead of mutating the local binding. When encountering this we suggest: /// /// ```text - /// fn change_object(a: &'_ mut Ty) { + /// fn change_object(b: &'_ mut Ty) { /// let a = Ty::new(); /// *b = a; /// } @@ -818,13 +818,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diag<'_>, expr: &hir::Expr<'_>, + expr_ty: Ty<'tcx>, + expected: Ty<'tcx>, error: Option>, ) -> bool { - if let Some(TypeError::Sorts(ExpectedFound { expected, found })) = error + if let Some(TypeError::Sorts(ExpectedFound { .. })) = error && let ty::Ref(_, inner, hir::Mutability::Not) = expected.kind() // The difference between the expected and found values is one level of borrowing. - && self.can_eq(self.param_env, *inner, found) + && self.can_eq(self.param_env, *inner, expr_ty) // We have an `ident = expr;` assignment. && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) = diff --git a/tests/crashes/140823.rs b/tests/crashes/140823.rs deleted file mode 100644 index ca2d683beedb2..0000000000000 --- a/tests/crashes/140823.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #140823 - -struct Container { - data: T, -} - -fn ice(callback: Box)>) { - let fails: Box)> = callback; -} diff --git a/tests/ui/fn/coerce-suggestion-infer-region.rs b/tests/ui/fn/coerce-suggestion-infer-region.rs new file mode 100644 index 0000000000000..7edb828c97339 --- /dev/null +++ b/tests/ui/fn/coerce-suggestion-infer-region.rs @@ -0,0 +1,26 @@ +//! Functions with a mismatch between the expected and found type where the difference is a +//! reference may trigger analysis for additional help. In this test the expected type will be +//! &'a Container<&'a u8> and the found type will be Container<&'?0 u8>. +//! +//! This test exercises a scenario where the found type being analyzed contains an inference region +//! variable ('?0). This cannot be used in comparisons because the variable no longer exists by the +//! time the later analysis is performed. +//! +//! This is a regression test of #140823 + +trait MyFn

{} + +struct Container { + data: T, +} + +struct Desugared { + callback: Box MyFn<&'a Container<&'a u8>>>, +} + +fn test(callback: Box MyFn>>) -> Desugared { + Desugared { callback } + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/fn/coerce-suggestion-infer-region.stderr b/tests/ui/fn/coerce-suggestion-infer-region.stderr new file mode 100644 index 0000000000000..9dd0fcf76ce19 --- /dev/null +++ b/tests/ui/fn/coerce-suggestion-infer-region.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/coerce-suggestion-infer-region.rs:22:17 + | +LL | Desugared { callback } + | ^^^^^^^^ expected `Box>>`, found `Box>>` + | + = note: expected struct `Box<(dyn for<'a> MyFn<&'a Container<&'a u8>> + 'static)>` + found struct `Box<(dyn for<'a> MyFn> + 'static)>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 4a99cbbf6b1e5074017d49a14cf37259d7c82e50 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Mon, 19 May 2025 21:14:28 +0700 Subject: [PATCH 08/15] Warning when dependency crate has async drop types, and the feature is disabled - typo fixed --- compiler/rustc_metadata/messages.ftl | 2 +- tests/ui/async-await/async-drop/dependency-dropped.rs | 2 +- .../async-drop/dependency-dropped.without_feature.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index cac8f34b0fa0d..bccffe3924373 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -2,7 +2,7 @@ metadata_as_needed_compatibility = linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds metadata_async_drop_types_in_dependency = - found async drop types in dependecy `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}` + found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}` .help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used metadata_bad_panic_strategy = diff --git a/tests/ui/async-await/async-drop/dependency-dropped.rs b/tests/ui/async-await/async-drop/dependency-dropped.rs index c8670be4e8baa..d7f415e19aadf 100644 --- a/tests/ui/async-await/async-drop/dependency-dropped.rs +++ b/tests/ui/async-await/async-drop/dependency-dropped.rs @@ -5,7 +5,7 @@ //@ edition:2021 #![cfg_attr(with_feature, feature(async_drop))] -//[without_feature]~^ WARN found async drop types in dependecy `async_drop_dep`, but async_drop feature is disabled for `dependency_dropped` +//[without_feature]~^ WARN found async drop types in dependency `async_drop_dep`, but async_drop feature is disabled for `dependency_dropped` #![allow(incomplete_features)] diff --git a/tests/ui/async-await/async-drop/dependency-dropped.without_feature.stderr b/tests/ui/async-await/async-drop/dependency-dropped.without_feature.stderr index 56e49568e1004..96a4572055c60 100644 --- a/tests/ui/async-await/async-drop/dependency-dropped.without_feature.stderr +++ b/tests/ui/async-await/async-drop/dependency-dropped.without_feature.stderr @@ -1,4 +1,4 @@ -warning: found async drop types in dependecy `async_drop_dep`, but async_drop feature is disabled for `dependency_dropped` +warning: found async drop types in dependency `async_drop_dep`, but async_drop feature is disabled for `dependency_dropped` --> $DIR/dependency-dropped.rs:7:1 | LL | #![cfg_attr(with_feature, feature(async_drop))] From 0c0b2cbcb597bac8cf7fa34b99d5dbe7a35419e1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 20 May 2025 14:01:58 +1000 Subject: [PATCH 09/15] Remove unused return value from `lower_node`. --- compiler/rustc_ast_lowering/src/item.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index f48a571b86a7d..9a9068ec7478e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -70,7 +70,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } } - pub(super) fn lower_node(&mut self, def_id: LocalDefId) -> hir::MaybeOwner<'hir> { + pub(super) fn lower_node(&mut self, def_id: LocalDefId) { let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); if let hir::MaybeOwner::Phantom = owner { let node = self.ast_index[def_id]; @@ -82,8 +82,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { AstOwner::ForeignItem(item) => self.lower_foreign_item(item), } } - - self.owners[def_id] } #[instrument(level = "debug", skip(self, c))] From 7c62e78cf95daf69f8b0bec232f48fec6c8b935c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 20 May 2025 14:04:24 +1000 Subject: [PATCH 10/15] Hoist `ItemLowerer` out of a loop. --- compiler/rustc_ast_lowering/src/lib.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 19095f2e01e54..422e79ca82ffd 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -444,14 +444,14 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { tcx.definitions_untracked().def_index_count(), ); + let mut lowerer = item::ItemLowerer { + tcx, + resolver: &mut resolver, + ast_index: &ast_index, + owners: &mut owners, + }; for def_id in ast_index.indices() { - item::ItemLowerer { - tcx, - resolver: &mut resolver, - ast_index: &ast_index, - owners: &mut owners, - } - .lower_node(def_id); + lowerer.lower_node(def_id); } drop(ast_index); From 8a927e63ff5b7de37ed91d5cc616009f7fed0dce Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 20 May 2025 14:13:33 +1000 Subject: [PATCH 11/15] Inline and remove `lower_*` methods. They are all short and have a single call site. --- compiler/rustc_ast_lowering/src/item.rs | 46 ++++++++++--------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9a9068ec7478e..e98d6c50ee791 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -76,37 +76,27 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { let node = self.ast_index[def_id]; match node { AstOwner::NonOwner => {} - AstOwner::Crate(c) => self.lower_crate(c), - AstOwner::Item(item) => self.lower_item(item), - AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(item, ctxt), - AstOwner::ForeignItem(item) => self.lower_foreign_item(item), + AstOwner::Crate(c) => { + debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID); + self.with_lctx(CRATE_NODE_ID, |lctx| { + let module = lctx.lower_mod(&c.items, &c.spans); + // FIXME(jdonszelman): is dummy span ever a problem here? + lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP); + hir::OwnerNode::Crate(module) + }) + } + AstOwner::Item(item) => { + self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) + } + AstOwner::AssocItem(item, ctxt) => { + self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt)) + } + AstOwner::ForeignItem(item) => self.with_lctx(item.id, |lctx| { + hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)) + }), } } } - - #[instrument(level = "debug", skip(self, c))] - fn lower_crate(&mut self, c: &Crate) { - debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID); - self.with_lctx(CRATE_NODE_ID, |lctx| { - let module = lctx.lower_mod(&c.items, &c.spans); - // FIXME(jdonszelman): is dummy span ever a problem here? - lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP); - hir::OwnerNode::Crate(module) - }) - } - - #[instrument(level = "debug", skip(self))] - fn lower_item(&mut self, item: &Item) { - self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) - } - - fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { - self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt)) - } - - fn lower_foreign_item(&mut self, item: &ForeignItem) { - self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) - } } impl<'hir> LoweringContext<'_, 'hir> { From c343b2a47c29bdfe4c611ba74f9c9e455f12539b Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 19 May 2025 23:18:08 -0700 Subject: [PATCH 12/15] `gather_locals`: only visit guard pattern guards when checking the guard When checking a pattern with guards in it, `GatherLocalsVisitor` will visit both the pattern (when type-checking the let, arm, or param containing it) and the guard expression (when checking the guard itself). This keeps it from visiting the guard when visiting the pattern, since otherwise it would gather locals from the guard twice, which would lead to a delayed bug: "evaluated expression more than once". --- compiler/rustc_hir_typeck/src/gather_locals.rs | 7 ++++++- .../only-gather-locals-once.rs | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 956671fc66ed2..7d99b0e78694e 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -218,7 +218,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { ); } let old_outermost_fn_param_pat = self.outermost_fn_param_pat.take(); - intravisit::walk_pat(self, p); + if let PatKind::Guard(subpat, _) = p.kind { + // We'll visit the guard when checking it. Don't gather its locals twice. + self.visit_pat(subpat); + } else { + intravisit::walk_pat(self, p); + } self.outermost_fn_param_pat = old_outermost_fn_param_pat; } diff --git a/tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs b/tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs new file mode 100644 index 0000000000000..7bb39ca7bb987 --- /dev/null +++ b/tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs @@ -0,0 +1,15 @@ +//@ check-pass +//! Test that `GatherLocalsVisitor` only visits expressions in guard patterns when checking the +//! expressions, and not a second time when visiting the pattern. If locals are declared inside the +//! the guard expression, it would ICE if visited twice ("evaluated expression more than once"). + +#![feature(guard_patterns)] +#![expect(incomplete_features)] + +fn main() { + match (0,) { + // FIXME(guard_patterns): liveness lints don't work yet; this will ICE without the `_`. + (_ if { let _x = false; _x },) => {} + _ => {} + } +} From 7e7c2c3947089834791a9d302f76947c00300b7d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 5 Apr 2025 18:06:47 +0000 Subject: [PATCH 13/15] Just error on recursive opaque ty in HIR typeck --- compiler/rustc_hir_typeck/src/writeback.rs | 70 +++++++++++++++++- .../impl-trait/issues/issue-100075-2.stderr | 15 ++-- .../ui/impl-trait/issues/issue-100075.stderr | 5 +- tests/ui/impl-trait/issues/issue-103599.rs | 5 +- .../ui/impl-trait/issues/issue-103599.stderr | 13 +++- tests/ui/impl-trait/issues/issue-87450.rs | 4 +- tests/ui/impl-trait/issues/issue-87450.stderr | 18 ++--- .../recursive-impl-trait-type-indirect.stderr | 73 ++++--------------- ...recursive-in-exhaustiveness.current.stderr | 53 +++----------- .../recursive-in-exhaustiveness.next.stderr | 18 ++--- .../impl-trait/recursive-in-exhaustiveness.rs | 6 +- .../infinite-cycle-involving-weak.rs | 2 +- .../infinite-cycle-involving-weak.stderr | 6 +- .../match-upvar-discriminant-of-opaque.rs} | 6 +- .../match-upvar-discriminant-of-opaque.stderr | 9 +++ .../recursive-fn-tait.rs | 2 +- .../recursive-fn-tait.stderr | 11 +-- .../recursive-tait-conflicting-defn-2.rs | 2 +- .../recursive-tait-conflicting-defn-2.stderr | 9 +-- .../recursive-tait-conflicting-defn.rs | 2 +- .../recursive-tait-conflicting-defn.stderr | 11 +-- 21 files changed, 157 insertions(+), 183 deletions(-) rename tests/{crashes/139817.rs => ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.rs} (62%) create mode 100644 tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.stderr diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 9be041f75d769..b2497cb0de16b 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -9,17 +9,21 @@ //! which creates a new `TypeckResults` which doesn't contain any inference variables. use std::mem; +use std::ops::ControlFlow; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::ExtendUnord; -use rustc_errors::ErrorGuaranteed; +use rustc_errors::{E0720, ErrorGuaranteed}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, InferKind, Visitor}; use rustc_hir::{self as hir, AmbigArg, HirId}; use rustc_infer::traits::solve::Goal; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; use rustc_middle::ty::{ - self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, fold_regions, + self, DefiningScopeKind, OpaqueHiddenType, Ty, TyCtxt, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + fold_regions, }; use rustc_span::{Span, sym}; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; @@ -595,6 +599,35 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { entry.span = prev.span.substitute_dummy(hidden_type.span); } } + + let recursive_opaques: Vec<_> = self + .typeck_results + .concrete_opaque_types + .iter() + .filter(|&(&def_id, hidden_ty)| { + hidden_ty + .ty + .visit_with(&mut HasRecursiveOpaque { + def_id, + seen: Default::default(), + opaques: &self.typeck_results.concrete_opaque_types, + tcx, + }) + .is_break() + }) + .map(|(def_id, hidden_ty)| (*def_id, hidden_ty.span)) + .collect(); + for (def_id, span) in recursive_opaques { + let guar = self + .fcx + .dcx() + .struct_span_err(span, "cannot resolve opaque type") + .with_code(E0720) + .emit(); + self.typeck_results + .concrete_opaque_types + .insert(def_id, OpaqueHiddenType { span, ty: Ty::new_error(tcx, guar) }); + } } fn visit_field_id(&mut self, hir_id: HirId) { @@ -959,3 +992,34 @@ impl<'tcx> TypeFolder> for EagerlyNormalizeConsts<'tcx> { self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct) } } + +struct HasRecursiveOpaque<'a, 'tcx> { + def_id: LocalDefId, + seen: FxHashSet, + opaques: &'a FxIndexMap>, + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> TypeVisitor> for HasRecursiveOpaque<'_, 'tcx> { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { + if let ty::Alias(ty::Opaque, alias_ty) = *t.kind() + && let Some(def_id) = alias_ty.def_id.as_local() + { + if self.def_id == def_id { + return ControlFlow::Break(()); + } + + if self.seen.insert(def_id) + && let Some(hidden_ty) = self.opaques.get(&def_id) + { + ty::EarlyBinder::bind(hidden_ty.ty) + .instantiate(self.tcx, alias_ty.args) + .visit_with(self)?; + } + } + + t.super_visit_with(self) + } +} diff --git a/tests/ui/impl-trait/issues/issue-100075-2.stderr b/tests/ui/impl-trait/issues/issue-100075-2.stderr index b3b6967750705..554c3ea34331e 100644 --- a/tests/ui/impl-trait/issues/issue-100075-2.stderr +++ b/tests/ui/impl-trait/issues/issue-100075-2.stderr @@ -1,3 +1,9 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/issue-100075-2.rs:1:23 + | +LL | fn opaque(t: T) -> impl Sized { + | ^^^^^^^^^^ + warning: function cannot return without recursing --> $DIR/issue-100075-2.rs:1:1 | @@ -10,15 +16,6 @@ LL | opaque(Some(t)) = help: a `loop` may express intention better if this is on purpose = note: `#[warn(unconditional_recursion)]` on by default -error[E0720]: cannot resolve opaque type - --> $DIR/issue-100075-2.rs:1:23 - | -LL | fn opaque(t: T) -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | opaque(Some(t)) - | --------------- returning here with type `impl Sized` - error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/issues/issue-100075.stderr b/tests/ui/impl-trait/issues/issue-100075.stderr index 7596348923693..bca2874b2b4b1 100644 --- a/tests/ui/impl-trait/issues/issue-100075.stderr +++ b/tests/ui/impl-trait/issues/issue-100075.stderr @@ -2,10 +2,7 @@ error[E0720]: cannot resolve opaque type --> $DIR/issue-100075.rs:13:37 | LL | fn _g(t: &'static T) -> &'static impl Marker { - | ^^^^^^^^^^^ recursive opaque type -... -LL | return _g(t); - | ----- returning here with type `&impl Marker` + | ^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issues/issue-103599.rs b/tests/ui/impl-trait/issues/issue-103599.rs index 62741a7454cee..e674ce3cbdf8f 100644 --- a/tests/ui/impl-trait/issues/issue-103599.rs +++ b/tests/ui/impl-trait/issues/issue-103599.rs @@ -1,9 +1,8 @@ -//@ check-pass - trait T {} fn wrap(x: impl T) -> impl T { - //~^ WARN function cannot return without recursing + //~^ ERROR cannot resolve opaque type + //~| WARN function cannot return without recursing wrap(wrap(x)) } diff --git a/tests/ui/impl-trait/issues/issue-103599.stderr b/tests/ui/impl-trait/issues/issue-103599.stderr index 82038c1dceb37..9878b12044f70 100644 --- a/tests/ui/impl-trait/issues/issue-103599.stderr +++ b/tests/ui/impl-trait/issues/issue-103599.stderr @@ -1,14 +1,21 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/issue-103599.rs:3:23 + | +LL | fn wrap(x: impl T) -> impl T { + | ^^^^^^ + warning: function cannot return without recursing - --> $DIR/issue-103599.rs:5:1 + --> $DIR/issue-103599.rs:3:1 | LL | fn wrap(x: impl T) -> impl T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing -LL | +... LL | wrap(wrap(x)) | ------- recursive call site | = help: a `loop` may express intention better if this is on purpose = note: `#[warn(unconditional_recursion)]` on by default -warning: 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/issues/issue-87450.rs b/tests/ui/impl-trait/issues/issue-87450.rs index 983ef7cfbe0af..5a7759af1119f 100644 --- a/tests/ui/impl-trait/issues/issue-87450.rs +++ b/tests/ui/impl-trait/issues/issue-87450.rs @@ -3,8 +3,8 @@ fn bar() -> impl Fn() { } fn foo() -> impl Fn() { - //~^ WARNING 5:1: 5:22: function cannot return without recursing [unconditional_recursion] - //~| ERROR 5:13: 5:22: cannot resolve opaque type [E0720] + //~^ WARN function cannot return without recursing + //~| ERROR cannot resolve opaque type wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo()))))))) } diff --git a/tests/ui/impl-trait/issues/issue-87450.stderr b/tests/ui/impl-trait/issues/issue-87450.stderr index 9567e09651d6c..f0f8b5859c031 100644 --- a/tests/ui/impl-trait/issues/issue-87450.stderr +++ b/tests/ui/impl-trait/issues/issue-87450.stderr @@ -1,3 +1,9 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/issue-87450.rs:5:13 + | +LL | fn foo() -> impl Fn() { + | ^^^^^^^^^ + warning: function cannot return without recursing --> $DIR/issue-87450.rs:5:1 | @@ -10,18 +16,6 @@ LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo()))))))) = help: a `loop` may express intention better if this is on purpose = note: `#[warn(unconditional_recursion)]` on by default -error[E0720]: cannot resolve opaque type - --> $DIR/issue-87450.rs:5:13 - | -LL | fn foo() -> impl Fn() { - | ^^^^^^^^^ recursive opaque type -... -LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo()))))))) - | ----------------------------------------------- returning here with type `impl Fn()` -... -LL | fn wrap(f: impl Fn()) -> impl Fn() { - | --------- returning this opaque type `impl Fn()` - error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr index 2d2731e4368f5..af84375c74766 100644 --- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr +++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr @@ -2,112 +2,67 @@ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:6:22 | LL | fn option(i: i32) -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | if i < 0 { None } else { Some((option(i - 1), i)) } - | ---- ------------------------ returning here with type `Option<(impl Sized, i32)>` - | | - | returning here with type `Option<(impl Sized, i32)>` + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:11:15 | LL | fn tuple() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | (tuple(),) - | ---------- returning here with type `(impl Sized,)` + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:16:15 | LL | fn array() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | [array()] - | --------- returning here with type `[impl Sized; 1]` + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:21:13 | LL | fn ptr() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | &ptr() as *const _ - | ------------------ returning here with type `*const impl Sized` + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:26:16 | LL | fn fn_ptr() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | fn_ptr as fn() -> _ - | ------------------- returning here with type `fn() -> impl Sized` + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:31:25 | -LL | fn closure_capture() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | / move || { -LL | | x; - | | - closure captures itself here -LL | | } - | |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:34:5: 34:12}` +LL | fn closure_capture() -> impl Sized { + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:39:29 | -LL | fn closure_ref_capture() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | / move || { -LL | | &x; - | | - closure captures itself here -LL | | } - | |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:42:5: 42:12}` +LL | fn closure_ref_capture() -> impl Sized { + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:47:21 | LL | fn closure_sig() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | || closure_sig() - | ---------------- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:49:5: 49:7}` + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:52:23 | LL | fn coroutine_sig() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | || coroutine_sig() - | ------------------ returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7}` + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:57:27 | -LL | fn coroutine_capture() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | / move || { -LL | | yield; -LL | | x; - | | - coroutine captures itself here -LL | | } - | |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:62:5: 62:12}` +LL | fn coroutine_capture() -> impl Sized { + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:68:35 | LL | fn substs_change() -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -LL | -LL | (substs_change::<&T>(),) - | ------------------------ returning here with type `(impl Sized,)` + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-impl-trait-type-indirect.rs:78:26 diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr index 42dbc7c91607f..080c328464153 100644 --- a/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr +++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr @@ -1,56 +1,21 @@ -warning: function cannot return without recursing - --> $DIR/recursive-in-exhaustiveness.rs:17:1 +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-in-exhaustiveness.rs:17:22 | LL | fn build(x: T) -> impl Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing -LL | -LL | let (x,) = (build(x),); - | -------- recursive call site - | - = help: a `loop` may express intention better if this is on purpose - = note: `#[warn(unconditional_recursion)]` on by default - -warning: function cannot return without recursing - --> $DIR/recursive-in-exhaustiveness.rs:27:1 - | -LL | fn build2(x: T) -> impl Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing -... -LL | let (x,) = (build2(x),); - | --------- recursive call site - | - = help: a `loop` may express intention better if this is on purpose + | ^^^^^^^^^^ error[E0720]: cannot resolve opaque type --> $DIR/recursive-in-exhaustiveness.rs:27:23 | LL | fn build2(x: T) -> impl Sized { - | ^^^^^^^^^^ recursive opaque type -... -LL | (build2(x),) - | ------------ returning here with type `(impl Sized,)` + | ^^^^^^^^^^ -warning: function cannot return without recursing - --> $DIR/recursive-in-exhaustiveness.rs:40:1 - | -LL | fn build3(x: T) -> impl Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing -LL | -LL | let (x,) = (build3((x,)),); - | ------------ recursive call site - | - = help: a `loop` may express intention better if this is on purpose - -error[E0792]: expected generic type parameter, found `(T,)` - --> $DIR/recursive-in-exhaustiveness.rs:49:5 +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-in-exhaustiveness.rs:39:23 | LL | fn build3(x: T) -> impl Sized { - | - this generic parameter must be used with a generic type parameter -... -LL | build3(x) - | ^^^^^^^^^ + | ^^^^^^^^^^ -error: aborting due to 2 previous errors; 3 warnings emitted +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0720, E0792. -For more information about an error, try `rustc --explain E0720`. +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr index 4c3d5aa8fb8f0..a3609b93cb3a8 100644 --- a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr +++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr @@ -5,19 +5,19 @@ LL | let (x,) = (build(x),); | ^^^^^^^^ cannot satisfy `impl Sized == _` error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _` - --> $DIR/recursive-in-exhaustiveness.rs:31:6 + --> $DIR/recursive-in-exhaustiveness.rs:30:6 | LL | (build2(x),) | ^^^^^^^^^ types differ error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _` - --> $DIR/recursive-in-exhaustiveness.rs:31:5 + --> $DIR/recursive-in-exhaustiveness.rs:30:5 | LL | (build2(x),) | ^^^^^^^^^^^^ types differ error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time - --> $DIR/recursive-in-exhaustiveness.rs:31:5 + --> $DIR/recursive-in-exhaustiveness.rs:30:5 | LL | (build2(x),) | ^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -26,13 +26,13 @@ LL | (build2(x),) = note: tuples must have a statically known size to be initialized error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _` - --> $DIR/recursive-in-exhaustiveness.rs:42:17 + --> $DIR/recursive-in-exhaustiveness.rs:41:17 | LL | let (x,) = (build3((x,)),); | ^^^^^^^^^^^^ types differ error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time - --> $DIR/recursive-in-exhaustiveness.rs:42:16 + --> $DIR/recursive-in-exhaustiveness.rs:41:16 | LL | let (x,) = (build3((x,)),); | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -41,7 +41,7 @@ LL | let (x,) = (build3((x,)),); = note: tuples must have a statically known size to be initialized error[E0308]: mismatched types - --> $DIR/recursive-in-exhaustiveness.rs:42:16 + --> $DIR/recursive-in-exhaustiveness.rs:41:16 | LL | fn build3(x: T) -> impl Sized { | ---------- the found opaque type @@ -53,7 +53,7 @@ LL | let (x,) = (build3((x,)),); found tuple `(impl Sized,)` error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _` - --> $DIR/recursive-in-exhaustiveness.rs:42:17 + --> $DIR/recursive-in-exhaustiveness.rs:41:17 | LL | let (x,) = (build3((x,)),); | ^^^^^^^^^^^^ types differ @@ -61,13 +61,13 @@ LL | let (x,) = (build3((x,)),); = note: the return type of a function must have a statically known size error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _` - --> $DIR/recursive-in-exhaustiveness.rs:42:16 + --> $DIR/recursive-in-exhaustiveness.rs:41:16 | LL | let (x,) = (build3((x,)),); | ^^^^^^^^^^^^^^^ types differ error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _` - --> $DIR/recursive-in-exhaustiveness.rs:42:17 + --> $DIR/recursive-in-exhaustiveness.rs:41:17 | LL | let (x,) = (build3((x,)),); | ^^^^^^^^^^^^ types differ diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs index 58944533686cc..fa8fa0e81743b 100644 --- a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs +++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs @@ -15,7 +15,7 @@ // We unfortunately accept this today, and due to how opaque type relating is implemented // in the NLL type relation, this defines `Opaque = T`. fn build(x: T) -> impl Sized { - //[current]~^ WARN function cannot return without recursing + //[current]~^ ERROR cannot resolve opaque type let (x,) = (build(x),); //[next]~^ ERROR type annotations needed build(x) @@ -26,7 +26,6 @@ fn build(x: T) -> impl Sized { // Not allowed today. Detected as recursive. fn build2(x: T) -> impl Sized { //[current]~^ ERROR cannot resolve opaque type - //[current]~| WARN function cannot return without recursing let (x,) = (build2(x),); (build2(x),) //[next]~^ ERROR type mismatch resolving @@ -38,7 +37,7 @@ fn build2(x: T) -> impl Sized { // // Not allowed today. Detected as not defining. fn build3(x: T) -> impl Sized { - //[current]~^ WARN function cannot return without recursing + //[current]~^ ERROR cannot resolve opaque type let (x,) = (build3((x,)),); //[next]~^ ERROR type mismatch resolving //[next]~| ERROR type mismatch resolving @@ -47,7 +46,6 @@ fn build3(x: T) -> impl Sized { //[next]~| ERROR the size for values of type //[next]~| ERROR mismatched types build3(x) - //[current]~^ ERROR expected generic type parameter, found `(T,)` } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs index ef6871bec7c42..0aaee5d1764e1 100644 --- a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs +++ b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs @@ -1,10 +1,10 @@ #![feature(type_alias_impl_trait)] type T = impl Copy; -//~^ ERROR cannot resolve opaque type #[define_opaque(T)] fn foo() -> T { + //~^ ERROR cannot resolve opaque type None::<&'static T> } diff --git a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr index d820df472f95b..426a6c29fff66 100644 --- a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr +++ b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr @@ -1,8 +1,8 @@ error[E0720]: cannot resolve opaque type - --> $DIR/infinite-cycle-involving-weak.rs:3:10 + --> $DIR/infinite-cycle-involving-weak.rs:6:13 | -LL | type T = impl Copy; - | ^^^^^^^^^ cannot resolve opaque type +LL | fn foo() -> T { + | ^ error: aborting due to 1 previous error diff --git a/tests/crashes/139817.rs b/tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.rs similarity index 62% rename from tests/crashes/139817.rs rename to tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.rs index d439ed4cacbd6..f4e2cb0c037b4 100644 --- a/tests/crashes/139817.rs +++ b/tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.rs @@ -1,8 +1,12 @@ -//@ known-bug: #139817 +#![feature(type_alias_impl_trait)] + fn enum_upvar() { type T = impl Copy; let foo: T = Some((42, std::marker::PhantomData::)); let x = move || match foo { None => (), + //~^ ERROR cannot resolve opaque type }; } + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.stderr b/tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.stderr new file mode 100644 index 0000000000000..2bfce2d63a8ee --- /dev/null +++ b/tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.stderr @@ -0,0 +1,9 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/match-upvar-discriminant-of-opaque.rs:7:9 + | +LL | None => (), + | ^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs b/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs index 94597adfed04f..fe354cc65452b 100644 --- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs +++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs @@ -13,7 +13,7 @@ pub fn add( n: Diff, m: Diff, ) -> Diff { - //~^ ERROR concrete type differs + //~^ ERROR cannot resolve opaque type move |x: usize| m(n(x)) } diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr index 59ff991761247..847f1cc6c2eb6 100644 --- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr @@ -1,14 +1,9 @@ -error: concrete type differs from previous defining opaque type use +error[E0720]: cannot resolve opaque type --> $DIR/recursive-fn-tait.rs:15:6 | LL | ) -> Diff { - | ^^^^ expected `{closure@$DIR/recursive-fn-tait.rs:8:5: 8:16}`, got `{closure@$DIR/recursive-fn-tait.rs:17:5: 17:20}` - | -note: previous use here - --> $DIR/recursive-fn-tait.rs:7:18 - | -LL | pub fn lift() -> Diff { - | ^^^^ + | ^^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs index 858f2a2feb678..7803b3b78db83 100644 --- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs @@ -13,7 +13,7 @@ fn transform() -> impl std::fmt::Display { } #[define_opaque(Op)] fn bad() -> Op { - //~^ ERROR concrete type differs from previous defining opaque type use + //~^ ERROR cannot resolve opaque type transform::() } diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr index e527b5bc7f8f8..837df7f5d4340 100644 --- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr @@ -1,14 +1,9 @@ -error: concrete type differs from previous defining opaque type use +error[E0720]: cannot resolve opaque type --> $DIR/recursive-tait-conflicting-defn-2.rs:15:13 | LL | fn bad() -> Op { - | ^^ expected `&&str`, got `impl std::fmt::Display` - | -note: previous use here - --> $DIR/recursive-tait-conflicting-defn-2.rs:7:13 - | -LL | fn foo() -> Op { | ^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0720`. diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs index 90581a98a3468..d66ceda523498 100644 --- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs @@ -23,7 +23,7 @@ pub fn test() -> TestImpl { #[define_opaque(TestImpl)] fn make_option2() -> Option { - //~^ ERROR concrete type differs from previous defining opaque type use + //~^ ERROR cannot resolve opaque type let inner = make_option().unwrap(); Some(B { inner }) } diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr index 256f13b622179..c7a3381d61588 100644 --- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr @@ -1,14 +1,9 @@ -error: concrete type differs from previous defining opaque type use +error[E0720]: cannot resolve opaque type --> $DIR/recursive-tait-conflicting-defn.rs:25:22 | LL | fn make_option2() -> Option { - | ^^^^^^^^^^^^^^^^ expected `A`, got `B` - | -note: previous use here - --> $DIR/recursive-tait-conflicting-defn.rs:20:18 - | -LL | pub fn test() -> TestImpl { - | ^^^^^^^^ + | ^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0720`. From 47b9e373cba69d66da9f91345219ff4f07eba84a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 28 Apr 2025 19:41:37 +0000 Subject: [PATCH 14/15] Revert "Fix stack overflow in exhaustiveness due to recursive HIR opaque type values" This reverts commit b08e9c2a60f4dbab4bdaa733727947b3395de329. --- compiler/rustc_pattern_analysis/src/rustc.rs | 40 +++----------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index a89d01dcbbe4a..d9f1888bfd9ad 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -1,6 +1,5 @@ use std::fmt; use std::iter::once; -use std::ops::ControlFlow; use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx}; use rustc_arena::DroplessArena; @@ -12,8 +11,7 @@ use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ - self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, VariantDef, + self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -137,22 +135,11 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { /// Returns the hidden type corresponding to this key if the body under analysis is allowed to /// know it. fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option> { - if let Some(hidden_ty) = self.typeck_results.concrete_opaque_types.get(&key.def_id) { - let ty = ty::EarlyBinder::bind(hidden_ty.ty).instantiate(self.tcx, key.args); - if ty.visit_with(&mut RecursiveOpaque { def_id: key.def_id.into() }).is_continue() { - Some(ty) - } else { - // HACK: We skip revealing opaque types which recursively expand - // to themselves. This is because we may infer hidden types like - // `Opaque = Opaque>` or `Opaque = Opaque<(T,)>` - // in hir typeck. - None - } - } else { - None - } + self.typeck_results + .concrete_opaque_types + .get(&key.def_id) + .map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args)) } - // This can take a non-revealed `Ty` because it reveals opaques itself. pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { !ty.inhabited_predicate(self.tcx).apply_revealing_opaque( @@ -1177,20 +1164,3 @@ fn detect_mixed_deref_pat_ctors<'p, 'tcx>( } Ok(()) } - -struct RecursiveOpaque { - def_id: DefId, -} -impl<'tcx> TypeVisitor> for RecursiveOpaque { - type Result = ControlFlow<()>; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { - if let ty::Alias(ty::Opaque, alias_ty) = t.kind() { - if alias_ty.def_id == self.def_id { - return ControlFlow::Break(()); - } - } - - if t.has_opaque_types() { t.super_visit_with(self) } else { ControlFlow::Continue(()) } - } -} From 1d8db54f7634363d93232a412b265d0d196c0bb8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 20 May 2025 10:24:21 +0000 Subject: [PATCH 15/15] Add tick to RePlaceholder debug output --- compiler/rustc_type_ir/src/region_kind.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index eae3213ead0d0..1b5d04e6025fa 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -193,7 +193,7 @@ impl fmt::Debug for RegionKind { ReVar(vid) => write!(f, "{vid:?}"), - RePlaceholder(placeholder) => write!(f, "{placeholder:?}"), + RePlaceholder(placeholder) => write!(f, "'{placeholder:?}"), // Use `'{erased}` as the output instead of `'erased` so that its more obviously distinct from // a `ReEarlyParam` named `'erased`. Technically that would print as `'erased/#IDX` so this is