Skip to content

Strange inference failure with Arc::new_cyclic #139736

Open
@Sky9x

Description

@Sky9x

I tried this code (playground):

#![allow(unused)]

use std::sync::Arc;
use tokio_util::task::AbortOnDropHandle;

pub struct Foo {
    thing: Thing,
    task: AbortOnDropHandle<()>,
}

impl Foo {
    pub fn new() -> Arc<Self> {
        // Fix 1: replace `<_>` with `<Self>`
        Arc::<_>::new_cyclic(|weak| {
            let weak = weak.clone();
            let handler = async move {
                async { /* ... */ }.await; // waiting for some event

                if let Some(this) = weak.upgrade() {
                    // "Fix" 2: comment out this line
                    this.thing.do_thing();
                }
            };

            Foo {
                thing: Thing,
                task: AbortOnDropHandle::new(tokio::spawn(handler)),
            }
        })
    }
}

struct Thing;

impl Thing {
    fn do_thing() { unimplemented!() }
}

I expected to see this happen: It compiles

Instead, this happened: It does not compile

I find it very strange the type inference is unable to figure out that
a. new_cyclic returns an Arc<Self>
b. the closure returns a Foo

I find it even stranger that commenting out the line where the inner value is used ("Fix" 2) makes it compile.

Compiler Error:

   Compiling playground v0.0.1 (/playground)
error[E0282]: type annotations needed for `&std::sync::Weak<_>`
  --> src/lib.rs:14:31
   |
14 |         Arc::<_>::new_cyclic(|weak| {
   |                               ^^^^
...
21 |                     this.thing.do_thing();
   |                     ---------- type must be known at this point
   |
help: consider giving this closure parameter an explicit type, where the type for type parameter `T` is specified
   |
14 |         Arc::<_>::new_cyclic(|weak: &std::sync::Weak<T>| {
   |                                   +++++++++++++++++++++

error[E0609]: no field `thing` on type `Arc<_>`
  --> src/lib.rs:21:26
   |
21 |                     this.thing.do_thing();
   |                          ^^^^^ unknown field

Some errors have detailed explanations: E0282, E0609.
For more information about an error, try `rustc --explain E0282`.
error: could not compile `playground` (lib) due to 2 previous errors

rustc version:

rustc 1.88.0-nightly (9ffde4b08 2025-04-12)
binary: rustc
commit-hash: 9ffde4b089fe8e43d5891eb517001df27a8443ff
commit-date: 2025-04-12
host: x86_64-unknown-linux-gnu
release: 1.88.0-nightly
LLVM version: 20.1.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inferenceArea: Type inferenceC-discussionCategory: Discussion or questions that doesn't represent real issues.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions