Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Ergonomic ref counting #134797

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

spastorino
Copy link
Member

@spastorino spastorino commented Dec 26, 2024

Opening this now so @nikomatsakis can start taking a look at it. Going to write a proper description when the PR is done.

For this first version I'd need to:

  • review the handling of spans in Expr::Use which right now is not 100% ok
  • document things a little bit better
  • add a lot of tests

For following versions we need to implement optimizations, copy optimization post monomorphization and last use optimization.

This is an experimental version of ergonomic ref counting

RFC: rust-lang/rfcs#3680
Tracking issue: #132290
Project goal: rust-lang/rust-project-goals#107

r? @nikomatsakis

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Dec 26, 2024
@spastorino spastorino force-pushed the ergonomic-ref-counting-1 branch from e4e8ad3 to b003b20 Compare December 26, 2024 19:43
@rust-log-analyzer

This comment has been minimized.

@spastorino spastorino force-pushed the ergonomic-ref-counting-1 branch from b003b20 to 94d4dde Compare December 26, 2024 20:47
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@spastorino spastorino force-pushed the ergonomic-ref-counting-1 branch from 42e6956 to 0aaedb8 Compare December 27, 2024 03:55
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@spastorino spastorino force-pushed the ergonomic-ref-counting-1 branch from f9a2abe to 0c29a0b Compare December 27, 2024 13:14
@rust-log-analyzer

This comment has been minimized.

@spastorino spastorino force-pushed the ergonomic-ref-counting-1 branch from 0c29a0b to b82e779 Compare December 27, 2024 14:35
Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very close! First round of feedback.

/// Desugar `<expr>.use` into:
/// ```ignore (pseudo-rust)
/// <expr>.clone()
/// ```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is out of date

/// ```
fn lower_expr_use(&mut self, use_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> {
let expr = self.lower_expr(expr);
let span = self.mark_span_with_reason(DesugaringKind::Use, use_kw_span, None);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want this DesugaringKind anymore

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was taking a quick look at this, this is used for diagnostic purposes, see for instance https://github.com/spastorino/rust/blob/b82e779259706ceb63fbd38fa5c9d8b9b632149a/compiler/rustc_borrowck/src/diagnostics/mod.rs#L1200-L1207
Do you meant to say that .use doesn't move so this error is not important. Also my code doesn't completely handles the DesugaringKind, so or I should remove if this error shouldn't happen or I should do the actual handling of it :).

let place = unpack!(block = this.as_place(block, expr));
let ty = place.ty(&this.local_decls, this.tcx).ty;

let success = this.cfg.start_new_block();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is going to change in future commits, but it needs a comment. Just something like

// Convert `expr.use` to a call like `Clone::clone(&expr)`

would go a long way

@@ -1331,6 +1332,12 @@ impl<'a> Parser<'a> {
return Ok(self.mk_await_expr(self_arg, lo));
}

if self.eat_keyword(exp!(Use)) {
let use_span = self.prev_token.span;
self.psess.gated_spans.gate(sym::ergonomic_clones, use_span);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it normal to gate in the parser like this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it is, I am not sure what's most common

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I've seen in code it is and this is what @compiler-errors what asking me to do in a previous review. Can you confirm Michael?.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not only is it "normal", it's literally imperative to gate in the parser to make sure that we don't accidentally stabilize the syntax in cfg'd code. Please make sure that there is a test that validates that this still gives an error when the code has #[cfg(any())].

@@ -1175,6 +1176,7 @@ impl DesugaringKind {
DesugaringKind::CondTemporary => "`if` or `while` condition",
DesugaringKind::Async => "`async` block or function",
DesugaringKind::Await => "`await` expression",
DesugaringKind::Use => "`use` expression",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this

@@ -1685,10 +1687,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
//
// If the data will be moved out of this place, then the place will be truncated
// at the first Deref in `adjust_for_move_closure` and then moved into the closure.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you can extend this comment with the example I wrote in Zulip? I think it would help future readers.

@@ -367,6 +367,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
self.consume_exprs(args)?;
}

hir::ExprKind::Use(expr, _) => {
self.consume_expr(expr)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm-- I just realized, this is.... not necessarily correct. Not necessarily wrong either. This says that expr will be moved, but the true behavior is that expr will be moved unless it implements UseCloned. So this should be adjusted later on to take that into account.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do something like consume_copy_or_borrow? if UseCloned borrow, if copy Copy and move otherwise.

@@ -2339,8 +2357,10 @@ fn determine_capture_info(
}
} else {
// We select the CaptureKind which ranks higher based the following priority order:
// ByValue > MutBorrow > UniqueImmBorrow > ImmBorrow
// ByUse > ByValue > MutBorrow > UniqueImmBorrow > ImmBorrow
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, the ordering of ByUse and ByValue seems unclear to me, but I also expect that you never see them together? Maybe we should say (ty::UpvarCapture::ByUse, ty::UpvarCapture::ByMove) => bug! (and vice versa) instead. -- I'd probably change the code here to not use _ but explicitly say (ByValue, ByRef(_)) => lhs, etc.

Rvalue::Use(Operand::Copy(place)),
);
block.unit()
} else if this.infcx.type_is_use_cloned_modulo_regions(this.param_env, ty) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this same logic needs to go into the ExprUseVisitor-- note that consume_expr I think already tests whether the expression is "copy" or not, so that is covered

#[cfg_attr(not(bootstrap), lang = "use_cloned")]
#[rustc_diagnostic_item = "UseCloned"]
#[rustc_trivial_field_reads]
pub trait UseCloned: Clone {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be "marker"

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 27, 2024
@spastorino
Copy link
Member Author

I've pushed some tests and I've found some parsing errors, a diagnostic ICE and another issue that needs handling during borrowck. CI is going to be red but is fine as this is not yet done.

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-llvm-18 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
#22 exporting to docker image format
#22 sending tarball 27.9s done
#22 DONE 34.3s
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-18]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Starting the server...
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-18', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-18/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---
---- [ui] tests/ui/ergonomic-clones/closure/nested.rs stdout ----

error: test compilation failed although it shouldn't!
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/ergonomic-clones/closure/nested.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(FALSE)" "-O" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/ergonomic-clones/closure/nested/a" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers"
--- stderr -------------------------------
error: expected identifier, found `||`
##[error]  --> /checkout/tests/ui/ergonomic-clones/closure/nested.rs:20:7
   |
   |
LL |   use || { use || { use || { Foo } } };

error: aborting due to 1 previous error
------------------------------------------



---- [ui] tests/ui/ergonomic-clones/closure/expect-region.rs stdout ----

error: Error: expected failure status (Some(1)) but received status Some(101).
status: exit status: 101
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/ergonomic-clones/closure/expect-region.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/ergonomic-clones/closure/expect-region" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers"
--- stderr -------------------------------
error: lifetime may not live long enough
##[error]  --> /checkout/tests/ui/ergonomic-clones/closure/expect-region.rs:18:34
   |
   |
LL | fn expect_bound_supply_named<'x>() {
   |                              -- lifetime `'x` defined here
...
LL |     closure_expecting_bound(use |x: &'x u32| {
   |                                  ^  - let's call the lifetime of this reference `'1`
   |                                  |
   |                                  requires that `'1` must outlive `'x`
##[error]error: internal compiler error: compiler/rustc_borrowck/src/lib.rs:1408:29: closures should only capture user variables or references to user variables

thread 'rustc' panicked at compiler/rustc_borrowck/src/lib.rs:1408:29:
Box<dyn Any>
Box<dyn Any>
stack backtrace:
   0: std::panicking::begin_panic::<rustc_errors::ExplicitBug>
   1: <rustc_errors::diagnostic::BugAbort as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
   3: rustc_middle::ty::context::tls::with_opt::<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}
   4: rustc_middle::ty::context::tls::with_context_opt::<rustc_middle::ty::context::tls::with_opt<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}, !>
   5: rustc_middle::util::bug::bug_fmt
   5: rustc_middle::util::bug::bug_fmt
   6: <rustc_borrowck::MirBorrowckCtxt as rustc_mir_dataflow::framework::visitor::ResultsVisitor<rustc_borrowck::dataflow::Borrowck>>::visit_after_early_statement_effect
   7: <rustc_mir_dataflow::framework::direction::Forward as rustc_mir_dataflow::framework::direction::Direction>::visit_results_in_block::<rustc_borrowck::dataflow::Borrowck, rustc_borrowck::MirBorrowckCtxt>
   8: rustc_mir_dataflow::framework::visitor::visit_results::<rustc_borrowck::dataflow::Borrowck, core::iter::adapters::map::Map<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::mir::BasicBlock>, rustc_middle::mir::traversal::reverse_postorder::{closure#0}>, rustc_borrowck::do_mir_borrowck::{closure#2}>, rustc_borrowck::MirBorrowckCtxt>
   9: rustc_borrowck::do_mir_borrowck
  10: rustc_borrowck::mir_borrowck
      [... omitted 2 frames ...]
  11: <rustc_middle::hir::map::Map>::par_body_owners::<rustc_interface::passes::run_required_analyses::{closure#2}::{closure#0}>::{closure#0}
  12: <rustc_session::session::Session>::time::<(), rustc_interface::passes::run_required_analyses::{closure#2}>
  13: rustc_interface::passes::analysis
      [... omitted 2 frames ...]
  14: <rustc_middle::ty::context::TyCtxt>::create_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2}::{closure#0}>
  15: <rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2} as core::ops::function::FnOnce<(&rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, &std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2})>>::call_once::{shim:vtable#0}
  16: <alloc::boxed::Box<dyn for<'a> core::ops::function::FnOnce<(&'a rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, &'a std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt<'a>>, &'a rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena<'a>>, &'a rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena<'a>>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}), Output = core::option::Option<rustc_interface::queries::Linker>>> as core::ops::function::FnOnce<(&rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, &std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2})>>::call_once
  18: <scoped_tls::ScopedKey<rustc_span::SessionGlobals>>::set::<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}::{closure#0}, ()>
  19: rustc_span::create_session_globals_then::<(), rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}::{closure#0}>
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.


note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: please make sure that you have updated to the latest nightly

note: rustc 1.85.0-nightly (ac95a9834 2024-12-27) running on x86_64-unknown-linux-gnu

note: compiler flags: -Z threads=1 -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/cargo -Z ignore-directory-in-diagnostics-source-blocks=/checkout/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0
query stack during panic:
query stack during panic:
#0 [mir_borrowck] borrow-checking `expect_bound_supply_named`
end of query stack
error: aborting due to 2 previous errors
------------------------------------------



---- [ui] tests/ui/ergonomic-clones/closure/mutation.rs stdout ----

error: Error: expected failure status (Some(1)) but received status Some(101).
status: exit status: 101
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/ergonomic-clones/closure/mutation.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/ergonomic-clones/closure/mutation" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers"
--- stderr -------------------------------
##[error]error: internal compiler error: compiler/rustc_borrowck/src/lib.rs:1408:29: closures should only capture user variables or references to user variables

thread 'rustc' panicked at compiler/rustc_borrowck/src/lib.rs:1408:29:
thread 'rustc' panicked at compiler/rustc_borrowck/src/lib.rs:1408:29:
Box<dyn Any>
stack backtrace:
   0: std::panicking::begin_panic::<rustc_errors::ExplicitBug>
   1: <rustc_errors::diagnostic::BugAbort as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
   3: rustc_middle::ty::context::tls::with_opt::<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}
   4: rustc_middle::ty::context::tls::with_context_opt::<rustc_middle::ty::context::tls::with_opt<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}, !>
   5: rustc_middle::util::bug::bug_fmt
   5: rustc_middle::util::bug::bug_fmt
   6: <rustc_borrowck::MirBorrowckCtxt as rustc_mir_dataflow::framework::visitor::ResultsVisitor<rustc_borrowck::dataflow::Borrowck>>::visit_after_early_statement_effect
   7: <rustc_mir_dataflow::framework::direction::Forward as rustc_mir_dataflow::framework::direction::Direction>::visit_results_in_block::<rustc_borrowck::dataflow::Borrowck, rustc_borrowck::MirBorrowckCtxt>
   8: rustc_mir_dataflow::framework::visitor::visit_results::<rustc_borrowck::dataflow::Borrowck, core::iter::adapters::map::Map<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::mir::BasicBlock>, rustc_middle::mir::traversal::reverse_postorder::{closure#0}>, rustc_borrowck::do_mir_borrowck::{closure#2}>, rustc_borrowck::MirBorrowckCtxt>
   9: rustc_borrowck::do_mir_borrowck
  10: rustc_borrowck::mir_borrowck
      [... omitted 2 frames ...]
  11: <rustc_middle::hir::map::Map>::par_body_owners::<rustc_interface::passes::run_required_analyses::{closure#2}::{closure#0}>::{closure#0}
  12: <rustc_session::session::Session>::time::<(), rustc_interface::passes::run_required_analyses::{closure#2}>
  13: rustc_interface::passes::analysis
      [... omitted 2 frames ...]
  14: <rustc_middle::ty::context::TyCtxt>::create_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2}::{closure#0}>
  15: <rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2} as core::ops::function::FnOnce<(&rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, &std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2})>>::call_once::{shim:vtable#0}
  16: <alloc::boxed::Box<dyn for<'a> core::ops::function::FnOnce<(&'a rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, &'a std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt<'a>>, &'a rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena<'a>>, &'a rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena<'a>>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}), Output = core::option::Option<rustc_interface::queries::Linker>>> as core::ops::function::FnOnce<(&rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, &std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2})>>::call_once
  18: <scoped_tls::ScopedKey<rustc_span::SessionGlobals>>::set::<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}::{closure#0}, ()>
  19: rustc_span::create_session_globals_then::<(), rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}::{closure#0}>
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.


note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: please make sure that you have updated to the latest nightly

note: rustc 1.85.0-nightly (ac95a9834 2024-12-27) running on x86_64-unknown-linux-gnu

note: compiler flags: -Z threads=1 -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/cargo -Z ignore-directory-in-diagnostics-source-blocks=/checkout/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0
query stack during panic:
query stack during panic:
#0 [mir_borrowck] borrow-checking `main`
end of query stack
error: aborting due to 1 previous error
------------------------------------------



---- [ui] tests/ui/ergonomic-clones/closure/immutable-outer-variable.rs stdout ----

error: failed to compile fixed code
status: exit status: 101
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/ergonomic-clones/closure/immutable-outer-variable.fixed" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/ergonomic-clones/closure/immutable-outer-variable/a" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers"
--- stderr -------------------------------
##[error]error: internal compiler error: compiler/rustc_borrowck/src/lib.rs:1408:29: closures should only capture user variables or references to user variables

thread 'rustc' panicked at compiler/rustc_borrowck/src/lib.rs:1408:29:
thread 'rustc' panicked at compiler/rustc_borrowck/src/lib.rs:1408:29:
Box<dyn Any>
stack backtrace:
   0: std::panicking::begin_panic::<rustc_errors::ExplicitBug>
   1: <rustc_errors::diagnostic::BugAbort as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee
   3: rustc_middle::ty::context::tls::with_opt::<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}
   4: rustc_middle::ty::context::tls::with_context_opt::<rustc_middle::ty::context::tls::with_opt<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}, !>
   5: rustc_middle::util::bug::bug_fmt
   5: rustc_middle::util::bug::bug_fmt
   6: <rustc_borrowck::MirBorrowckCtxt as rustc_mir_dataflow::framework::visitor::ResultsVisitor<rustc_borrowck::dataflow::Borrowck>>::visit_after_early_statement_effect
   7: <rustc_mir_dataflow::framework::direction::Forward as rustc_mir_dataflow::framework::direction::Direction>::visit_results_in_block::<rustc_borrowck::dataflow::Borrowck, rustc_borrowck::MirBorrowckCtxt>
   8: rustc_mir_dataflow::framework::visitor::visit_results::<rustc_borrowck::dataflow::Borrowck, core::iter::adapters::map::Map<core::iter::adapters::map::Map<core::slice::iter::Iter<rustc_middle::mir::BasicBlock>, rustc_middle::mir::traversal::reverse_postorder::{closure#0}>, rustc_borrowck::do_mir_borrowck::{closure#2}>, rustc_borrowck::MirBorrowckCtxt>
   9: rustc_borrowck::do_mir_borrowck
  10: rustc_borrowck::mir_borrowck
      [... omitted 2 frames ...]
  11: <rustc_middle::hir::map::Map>::par_body_owners::<rustc_interface::passes::run_required_analyses::{closure#2}::{closure#0}>::{closure#0}
  12: <rustc_session::session::Session>::time::<(), rustc_interface::passes::run_required_analyses::{closure#2}>
  13: rustc_interface::passes::analysis
      [... omitted 2 frames ...]
  14: <rustc_middle::ty::context::TyCtxt>::create_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2}::{closure#0}>
  15: <rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2} as core::ops::function::FnOnce<(&rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, &std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2})>>::call_once::{shim:vtable#0}
  16: <alloc::boxed::Box<dyn for<'a> core::ops::function::FnOnce<(&'a rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, &'a std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt<'a>>, &'a rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena<'a>>, &'a rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena<'a>>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}), Output = core::option::Option<rustc_interface::queries::Linker>>> as core::ops::function::FnOnce<(&rustc_session::session::Session, rustc_middle::ty::context::CurrentGcx, &std::sync::once_lock::OnceLock<rustc_middle::ty::context::GlobalCtxt>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_middle::arena::Arena>, &rustc_data_structures::sync::worker_local::WorkerLocal<rustc_hir::Arena>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2})>>::call_once
  18: <scoped_tls::ScopedKey<rustc_span::SessionGlobals>>::set::<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}::{closure#0}, ()>
  19: rustc_span::create_session_globals_then::<(), rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}::{closure#0}>
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.


note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: please make sure that you have updated to the latest nightly

note: rustc 1.85.0-nightly (ac95a9834 2024-12-27) running on x86_64-unknown-linux-gnu

note: compiler flags: -Z threads=1 -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/cargo -Z ignore-directory-in-diagnostics-source-blocks=/checkout/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0
query stack during panic:
query stack during panic:
#0 [mir_borrowck] borrow-checking `main`
end of query stack
error: aborting due to 1 previous error
------------------------------------------

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants