Skip to content

implement Move trait prototype#156018

Draft
nia-e wants to merge 3 commits intorust-lang:mainfrom
nia-e:move-trait
Draft

implement Move trait prototype#156018
nia-e wants to merge 3 commits intorust-lang:mainfrom
nia-e:move-trait

Conversation

@nia-e
Copy link
Copy Markdown
Member

@nia-e nia-e commented Apr 30, 2026

View all comments

Add a barebones implementation for Move (#149607), pending some diagnostics changes & tests.

r? lcnr

@rustbot rustbot added 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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Apr 30, 2026
@nia-e
Copy link
Copy Markdown
Member Author

nia-e commented Apr 30, 2026

@bors try @rust-timer queue

@rust-timer

This comment was marked as off-topic.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Apr 30, 2026
@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Apr 30, 2026
implement `Move` trait prototype
@nia-e
Copy link
Copy Markdown
Member Author

nia-e commented Apr 30, 2026

(tests are broken, mostly due to diagnostics changing)

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment was marked as outdated.

@rust-log-analyzer

This comment has been minimized.

@lcnr
Copy link
Copy Markdown
Contributor

lcnr commented May 1, 2026

the zerovec changes rely on a need candidate preference change 🤔 :3

what i've done in https://github.com/rust-lang/rust/pull/146201/changes#diff-34d5893dd95fe09f9a0fd3341efacd1c21853bb34ba29d9d79bb9af26bb8a0a0

let key = self.infcx.param_env.and(type_op::prove_predicate::ProvePredicate { predicate });
let op = CustomTypeOp::new(
|ocx| {
let res = type_op::QueryTypeOp::perform_locally_with_next_solver(ocx, key, span);
Copy link
Copy Markdown
Contributor

@lcnr lcnr May 1, 2026

Choose a reason for hiding this comment

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

if you look at what perform_locally_with_next_solver, it should just be the thing you do in the error path anyways 🤔 🤷

actually, we could make scrape_region_constraints generic over the expected errors, and have a FallibleCustomTypeOp which uses it while expecting potential errors. Instead instead of always emitting a delayed bug if there are errors, scrape_region_constraints would just report the failures as proper type errors 🤔 that seems nicer to me

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

right, ok - wasn't sure if that level of overhaul was on the table. it was kind of difficult to recreate the predicate in scrape_region_constraints (thus me doing it this way) but if i can mess with it that makes my life easier :D

Comment thread compiler/rustc_borrowck/src/type_check/mod.rs
Comment thread compiler/rustc_hir_analysis/src/check/wfcheck.rs Outdated
Comment on lines +262 to +264
if find_attr!(tcx, crate, RustcNoImplicitBounds) {
return;
}
Copy link
Copy Markdown
Contributor

@lcnr lcnr May 1, 2026

Choose a reason for hiding this comment

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

want to move this out into add_implicit_bounds?

View changes since the review

let relaxed_bounds = collect_relaxed_bounds(hir_bounds, context);
self.reject_duplicate_relaxed_bounds(relaxed_bounds);

let Some(move_did) = tcx.lang_items().move_trait() else {
Copy link
Copy Markdown
Contributor

@lcnr lcnr May 1, 2026

Choose a reason for hiding this comment

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

I'd just always require_lang_item :3 requiring core to provide the trait definition for Move seems innocent enough

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

that's what I tried initially, but it means we need to add Move in a quadrillion tests that don't depend on core 🫠

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we should have some mini_core somewhere that most such tests should use 😅

are there still proper #[no_core] tests that don't use an existing mini_core?


if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res
&& (tcx.is_lang_item(def_id, hir::LangItem::Sized) || tcx.is_default_trait(def_id))
&& (tcx.is_lang_item(def_id, hir::LangItem::Sized) || tcx.is_implicit_trait(def_id))
Copy link
Copy Markdown
Contributor

@lcnr lcnr May 1, 2026

Choose a reason for hiding this comment

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

isn't Sized an implicit trait

View changes since the review

}

// Don't use `add_implicit_bounds` directly to skip adding `Sized`.
self.add_implicit_move_bound(
Copy link
Copy Markdown
Contributor

@lcnr lcnr May 1, 2026

Choose a reason for hiding this comment

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

hmm, I'd prefer add_implicit_bound here, because otherwise we have to do that when adding Forget later on

View changes since the review

}

pub fn is_implicit_trait(self, def_id: DefId) -> bool {
self.is_default_trait(def_id) || matches!(self.as_lang_item(def_id), Some(LangItem::Move))
Copy link
Copy Markdown
Contributor

@lcnr lcnr May 1, 2026

Choose a reason for hiding this comment

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

why are we not treating Sized as an implicit trait?

View changes since the review

Copy link
Copy Markdown
Member Author

@nia-e nia-e May 1, 2026

Choose a reason for hiding this comment

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

Sized is weird enough (sometimes the bound is Sized, sometimes MetaSized etc) that i thought it made more sense to treat it separately. like, arguably MetaSized should also be an implicit trait but that would change behaviour at most callsites i think.

though i realise this is kinda confusing naming given that I also wrote add_implicit_trait_bounds that does add sized...

}

// Backward compatibility for default auto traits.
// Backward compatibility for default auto traits & `Move`.
Copy link
Copy Markdown
Contributor

@lcnr lcnr May 1, 2026

Choose a reason for hiding this comment

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

this is somewhat meh, Move is a default auto trait 😅 ✨ , just not add default_auto_trait

View changes since the review

Copy link
Copy Markdown
Member

@fmease fmease May 1, 2026

Choose a reason for hiding this comment

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

In general, this PR doesn't seem to use the "infrastructure" provided by internal feature more_maybe_bounds unlike earlier experiments.

I lack the context, so I don't know why that's done this way. However, if the "proper" Move and Forget default auto traits won't use all the preexisting MMB lowering routines, then I'd rather remove that internal feature entirely since it's evidently being supplanted (and also won't be needed anymore anyway as its purpose was to experiment with new default bounds).

Maintaining two incredibly similar but still somehow distinct features (default vs. "implicit") is somewhat meh I dare say. We probably want to notify Vadim then who is the owner of MMB IIRC.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yeah, I agree. Ripping out that feature in favor of actually having individual traits seems good to me. Reusing these features doesn't simplify adding new traits. Having one non-sized trait is nice to properly handle things though

@rust-bors

This comment has been minimized.

nia-e and others added 2 commits May 4, 2026 10:15
@rust-log-analyzer

This comment has been minimized.

@nia-e
Copy link
Copy Markdown
Member Author

nia-e commented May 4, 2026

curious what the perf hit is without doing any special handling. should actually work this time :D

@bors try @rust-timer queue

@rust-timer

This comment was marked as duplicate.

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request May 4, 2026
implement `Move` trait prototype
@rust-log-analyzer
Copy link
Copy Markdown
Collaborator

The job aarch64-gnu-llvm-21-2 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
##[endgroup]
Executing "/scripts/stage_2_test_set2.sh"
+ /scripts/stage_2_test_set2.sh
+ '[' 1 == 1 ']'
+ echo 'PR_CI_JOB set; skipping tidy'
+ SKIP_TIDY='--skip tidy'
+ ../x.py --stage 2 test --skip tidy --skip tests --skip coverage-map --skip coverage-run --skip library --skip tidyselftest
PR_CI_JOB set; skipping tidy
##[group]Building bootstrap
    Finished `dev` profile [unoptimized] target(s) in 0.04s
##[endgroup]
---

---- mem::type_info::test_dynamic_traits stdout ----
---- mem::type_info::test_dynamic_traits stderr ----

thread 'main' (42926) panicked at coretests/tests/mem/type_info.rs:351:9:
assertion `left == right` failed: unexpected ids.
actual: [TypeId(0x2368d8aac880aa5e8af6ea7b9bd44478), TypeId(0xa703e7ee78e1de459f0217897fb1d77d)]
expected: [TypeId(0x9fd5e516394cc91858af702d0feb0200)]
  left: {TypeId(0xa703e7ee78e1de459f0217897fb1d77d), TypeId(0x2368d8aac880aa5e8af6ea7b9bd44478)}
 right: {TypeId(0x9fd5e516394cc91858af702d0feb0200)}
stack backtrace:
   0: __rustc::rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::panicking::assert_failed_inner
   3: core::panicking::assert_failed::<std::collections::hash::set::HashSet<core::any::TypeId>, std::collections::hash::set::HashSet<core::any::TypeId>>
---
    mem::type_info::test_dynamic_traits

test result: FAILED. 2448 passed; 2 failed; 6 ignored; 0 measured; 0 filtered out; finished in 3.59s

error: test failed, to rerun pass `-p coretests --test coretests`
env -u RUSTC_WRAPPER CARGO_ENCODED_RUSTDOCFLAGS="-Zannotate-moves\u{1f}-Zrandomize-layout\u{1f}-Zunstable-options\u{1f}--check-cfg=cfg(bootstrap)\u{1f}-Wrustdoc::invalid_codeblock_attributes\u{1f}--crate-version\u{1f}1.97.0-nightly\t(023179164\t2026-05-04)" CARGO_ENCODED_RUSTFLAGS="-Zannotate-moves\u{1f}-Zrandomize-layout\u{1f}-Zunstable-options\u{1f}--check-cfg=cfg(bootstrap)\u{1f}-Zmacro-backtrace\u{1f}-Csplit-debuginfo=off\u{1f}-Clink-arg=-L/usr/lib/llvm-21/lib\u{1f}-Cllvm-args=-import-instr-limit=10\u{1f}-Clink-args=-Wl,-z,origin\u{1f}-Clink-args=-Wl,-rpath,$ORIGIN/../lib\u{1f}-Alinker-messages\u{1f}--cap-lints=allow\u{1f}--cfg\u{1f}randomized_layouts" RUSTC="/checkout/obj/build/aarch64-unknown-linux-gnu/stage2-codegen/cg_clif/dist/rustc-clif" RUSTDOC="/checkout/obj/build/aarch64-unknown-linux-gnu/stage2-codegen/cg_clif/dist/rustdoc-clif" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage0/bin/cargo" "test" "--manifest-path" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2-codegen/cg_clif/build/sysroot_tests/Cargo.toml" "--target-dir" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2-codegen/cg_clif/build/sysroot_tests_target" "--locked" "--target" "aarch64-unknown-linux-gnu" "-p" "coretests" "-p" "alloctests" "--tests" "--" "-q" exited with status ExitStatus(unix_wait_status(25856))
Bootstrap failed while executing `--stage 2 test --skip tidy --skip tests --skip coverage-map --skip coverage-run --skip library --skip tidyselftest`
Command `/checkout/obj/build/aarch64-unknown-linux-gnu/stage0/bin/cargo run -Zwarnings --target aarch64-unknown-linux-gnu -Zbinary-dep-depinfo -j 4 -Zroot-dir=/checkout --locked --color=always --profile=release --manifest-path /checkout/compiler/rustc_codegen_cranelift/build_system/Cargo.toml -- test --download-dir /checkout/obj/build/cg_clif_download --out-dir /checkout/obj/build/aarch64-unknown-linux-gnu/stage2-codegen/cg_clif --no-unstable-features --use-backend cranelift --sysroot llvm --skip-test testsuite.extended_sysroot [workdir=/checkout/compiler/rustc_codegen_cranelift]` failed with exit code 1
Created at: src/bootstrap/src/core/build_steps/test.rs:3955:25
Executed at: src/bootstrap/src/core/build_steps/test.rs:4000:26

--- BACKTRACE vvv
   0: std::backtrace_rs::backtrace::libunwind::trace
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/std/src/../../backtrace/src/backtrace/libunwind.rs:117:9
   1: std::backtrace_rs::backtrace::trace_unsynchronized::<<std::backtrace::Backtrace>::create::{closure#0}>
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/std/src/../../backtrace/src/backtrace/mod.rs:66:14
   2: <std::backtrace::Backtrace>::create
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/std/src/backtrace.rs:331:13
   3: <bootstrap::utils::exec::DeferredCommand>::finish_process
             at /checkout/src/bootstrap/src/utils/exec.rs:939:17
   4: <bootstrap::utils::exec::DeferredCommand>::wait_for_output::<&bootstrap::utils::exec::ExecutionContext>
             at /checkout/src/bootstrap/src/utils/exec.rs:831:21
   5: <bootstrap::utils::exec::ExecutionContext>::run
             at /checkout/src/bootstrap/src/utils/exec.rs:741:45
   6: <bootstrap::utils::exec::BootstrapCommand>::run::<&bootstrap::core::builder::Builder>
             at /checkout/src/bootstrap/src/utils/exec.rs:339:27
   7: <bootstrap::core::build_steps::test::CodegenCranelift as bootstrap::core::builder::Step>::run
             at /checkout/src/bootstrap/src/core/build_steps/test.rs:4000:26
   8: <bootstrap::core::builder::Builder>::ensure::<bootstrap::core::build_steps::test::CodegenCranelift>
             at /checkout/src/bootstrap/src/core/builder/mod.rs:1595:36
   9: <bootstrap::core::build_steps::test::CodegenCranelift as bootstrap::core::builder::Step>::make_run
             at /checkout/src/bootstrap/src/core/build_steps/test.rs:3941:17
  10: <bootstrap::core::builder::StepDescription>::maybe_run
             at /checkout/src/bootstrap/src/core/builder/mod.rs:476:13
  11: bootstrap::core::builder::cli_paths::match_paths_to_steps_and_run
             at /checkout/src/bootstrap/src/core/builder/cli_paths.rs:141:22
  12: <bootstrap::core::builder::Builder>::run_step_descriptions
             at /checkout/src/bootstrap/src/core/builder/mod.rs:1138:9
  13: <bootstrap::core::builder::Builder>::execute_cli
             at /checkout/src/bootstrap/src/core/builder/mod.rs:1117:14
  14: <bootstrap::Build>::build
             at /checkout/src/bootstrap/src/lib.rs:803:25
  15: bootstrap::main
             at /checkout/src/bootstrap/src/bin/main.rs:130:11
  16: <fn() as core::ops::function::FnOnce<()>>::call_once
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/core/src/ops/function.rs:250:5
  17: std::sys::backtrace::__rust_begin_short_backtrace::<fn(), ()>
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/std/src/sys/backtrace.rs:166:18
  18: std::rt::lang_start::<()>::{closure#0}
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/std/src/rt.rs:206:18
  19: <&dyn core::ops::function::Fn<(), Output = i32> + core::panic::unwind_safe::RefUnwindSafe + core::marker::Sync as core::ops::function::FnOnce<()>>::call_once
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/core/src/ops/function.rs:287:21
  20: std::panicking::catch_unwind::do_call::<&dyn core::ops::function::Fn<(), Output = i32> + core::panic::unwind_safe::RefUnwindSafe + core::marker::Sync, i32>
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/std/src/panicking.rs:581:40
  21: std::panicking::catch_unwind::<i32, &dyn core::ops::function::Fn<(), Output = i32> + core::panic::unwind_safe::RefUnwindSafe + core::marker::Sync>
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/std/src/panicking.rs:544:19
  22: std::panic::catch_unwind::<&dyn core::ops::function::Fn<(), Output = i32> + core::panic::unwind_safe::RefUnwindSafe + core::marker::Sync, i32>
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/std/src/panic.rs:359:14
  23: std::rt::lang_start_internal::{closure#0}
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/std/src/rt.rs:175:24
  24: std::panicking::catch_unwind::do_call::<std::rt::lang_start_internal::{closure#0}, isize>
             at /rustc/ef0fb8a2563200e322fa4419f09f65a63742038c/library/std/src/panicking.rs:581:40
---
  31: __libc_start_main
  32: _start


Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:28:23
  local time: Mon May  4 09:01:53 UTC 2026
  network time: Mon, 04 May 2026 09:01:54 GMT
##[error]Process completed with exit code 1.
##[group]Run echo "disk usage:"

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented May 4, 2026

☀️ Try build successful (CI)
Build commit: 9c60331 (9c603315e0adb72715fc54133efdc043d7bf0e2d, parent: a51f3a89b2fffc6ce38f484d7cbf9dc25b0fe791)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (9c60331): comparison URL.

Overall result: ❌✅ regressions and improvements - please read:

Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf.

Next, please: If you can, justify the regressions found in this try perf run in writing along with @rustbot label: +perf-regression-triaged. If not, fix the regressions and do another perf run. Neutral or positive results will clear the label automatically.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
5.1% [0.3%, 51.1%] 245
Regressions ❌
(secondary)
128.6% [0.0%, 7221.7%] 265
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.9% [-17.5%, -0.0%] 17
All ❌✅ (primary) 5.1% [0.3%, 51.1%] 245

Max RSS (memory usage)

Results (primary 2.6%, secondary 178.2%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
2.6% [0.6%, 7.1%] 82
Regressions ❌
(secondary)
202.0% [0.7%, 1687.2%] 46
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-4.3% [-7.6%, -1.7%] 6
All ❌✅ (primary) 2.6% [0.6%, 7.1%] 82

Cycles

Results (primary 8.9%, secondary 407.1%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
9.0% [1.9%, 41.6%] 107
Regressions ❌
(secondary)
428.5% [1.8%, 13106.3%] 136
Improvements ✅
(primary)
-2.6% [-2.6%, -2.6%] 1
Improvements ✅
(secondary)
-8.6% [-16.0%, -1.0%] 7
All ❌✅ (primary) 8.9% [-2.6%, 41.6%] 108

Binary size

Results (primary 0.4%, secondary 0.5%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
0.4% [0.0%, 1.7%] 58
Regressions ❌
(secondary)
0.5% [0.0%, 2.0%] 58
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.4% [0.0%, 1.7%] 58

Bootstrap: 501.019s -> 515.163s (2.82%)
Artifact size: 396.46 MiB -> 393.92 MiB (-0.64%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels May 4, 2026
}
} else if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) = context
&& move_tr
{
Copy link
Copy Markdown
Contributor

@lcnr lcnr May 4, 2026

Choose a reason for hiding this comment

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

hmm, could u do a separate if tcx.features().move_trait() { match context { exhaustivethingy } }

View changes since the review

Comment on lines +1870 to +1874
let mut sized_candidates = candidates.iter().filter(|c| {
matches!(c.candidate, SizedCandidate)
|| (is_default_auto_trait
&& matches!(c.candidate, AutoImplCandidate | ImplCandidate(..)))
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yeah 👍

please add a UI test for this and add use revisions to also test it in the new trait solver (and also add this preference there)

i think maintainability-wise, do we want to do

is_default_auto_trait && c.candidate.is_impl_candidate()`

fn winnow_candidates(
&mut self,
has_non_region_infer: bool,
is_default_auto_trait: bool,
Copy link
Copy Markdown
Contributor

@lcnr lcnr May 4, 2026

Choose a reason for hiding this comment

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

merge with CandidatePreferenceMode

View changes since the review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

perf-regression Performance regression. 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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants