# Proposal: Syntactic Sugar for Disambiguating Conflicting Trait Methods

**URL:** <https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694>\
**Category:** language design\
**Created:** [November 7, 2025, 10:14pm UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694 "2025-11-07T22:14:59Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![syudoer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/syudoer/32/13763_2.png) [@syudoer](https://internals.rust-lang.org/u/syudoer)\
**Post date:** [November 7, 2025, 10:15pm UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/1 "2025-11-07T22:15:00Z")

</div>

I'm not an experienced Rust developer, I'm just learning the language, but here we're discussing syntactic sugar, so I don't think specific expertise is required.

## Problem

```rust
#[derive(Debug, Clone)]
struct AnB {
    a: u32,
    b: u32
}

trait ArithmeticallyAddable {
    fn add(&self) -> u32;
}

trait Concatenatable {
    fn add(&self) -> u32;
}

impl ArithmeticallyAddable for AnB {
    fn add(&self) -> u32 {
        self.a + self.b
    }
}

impl Concatenatable for AnB {
    fn add(&self) -> u32 {
        match (self.a.to_string() + &self.b.to_string() as &str).parse::<u32>() {
            Ok(v) => v,
            Err(..) => 67,
        }
    }
}

fn main() {
    let a = 2;
    let b = 2;
    let anb = AnB {a:a, b:b};
    println!("{a} + {b} = {} if ArithmeticallyAddable::add was called", ArithmeticallyAddable::add(&anb));
    println!("{a} + {b} = { } if Concatenatable::add was called", Concatenatable::add(&anb));
}

```

This is how a name conflict in Rust is usually handled when it occurs. Quite ordinary code, but the used syntax strongly differs from the standard `anb.add()`. First, this is no longer a method call, second, here you need to specify that `anb` is passed explicitly as an immutable reference (&self), whereas in `anb.add()` the compiler specifies this automatically. `(&v as &dyn Trait).method()` solves the first but not the second, plus it's cumbersome, and `v.Trait::method()` simply does not exist in Rust, which is reasonable (UPDATE: actually it's not, `v.Something::something_else` seems never to be used in Rust).

For such an idiomatic language as Rust, where everything is logical (or supposed to be), it's odd that the penalty for poor naming is not just an additional specification of the specific trait whose method is used, but a complete change in the method call syntax, as well as a requirement to do manual work the compiler would handle.

## Proposed Solution

1. Currently syntax `(v as Trait).method()` results in an error `expected a type, found a trait`. If replaced with ambiguous method name resolution, no existing code would break.

2. For multiple use, `use Trait::method for Type;` should make `method` from `Trait` the default option for all values of type `Type` across the scope.

Show some activity under the topic if you have any ideas or you simply agree with the fact that this should be added to the language

## UPDATE

At first glance, `v.<Trait::method>()` looked as ugly to me as `v.Trait::method()`, but I looked at it again and realized that it's clean and straightforward. It changes only the source of the ambiguity -- the method name - and clarifies that there's nothing called `Trait`, only `<Trait::method>` as a single symbol, so...

## Proposed Solution No. 2

1. `v.<Trait::method>()` is used for a single use

2. For multiple uses, `use Trait::method for Type;` makes `method` from `Trait` the default option for all values of type `Type` across the scope. Specifying exact variables is also possible, e.g., `use Trait::method for v;`.

3. The `Trait` symbol comes from the scope.

---

<div class="post-metadata">

**Author:** ![jdahlstrom](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdahlstrom/32/3351_2.png) [@jdahlstrom](https://internals.rust-lang.org/u/jdahlstrom)\
**Post date:** [November 7, 2025, 10:21pm UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/2 "2025-11-07T22:21:03Z")

</div>

I think adopting the C++ `foo.Bar::baz()` would actually not be a bad option.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [November 7, 2025, 11:00pm UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/3 "2025-11-07T23:00:37Z")

</div>

The worry I'd have with `(foo as Itertools).intersperse(3)` is that it _looks_ like you should be able to do `let x = foo as Itertools; x.intersperse(3)`, so if that doesn't work I'm not a fan.

(Having `as impl Itertools` or something maybe could perhaps reasonably be made to work, but wouldn't solve the disambiguation problem because there result -- whether that way or `as impl Iterator` -- could still be called with methods from both traits. It would, I suppose, at least block calling _inherent_ methods, if that was the goal.)

So I also prefer something like `foo.Bar::bar()`. I've also spelled it as `foo.<Bar::bar>()` before in sketches, aping the full desugaring of `<Foo as Bar>::bar(&foo)`.

There's a big question here either way whether what's there is a full _path_, just an _ident_ that's already `use`d, or something that works even with `use MyTrait as _;` that's not actually putting anything in the namespace despite it allowing resolution.

---

<div class="post-metadata">

**Author:** ![syudoer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/syudoer/32/13763_2.png) [@syudoer](https://internals.rust-lang.org/u/syudoer)\
**Post date:** [November 7, 2025, 11:44pm UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/4 "2025-11-07T23:44:39Z")

</div>

As for `let x = foo as Trait`, it should convert `foo: &Type` into `x: &dyn Trait` (preserving the same mutability) or throw an error if foo is an owned value.

By the way, this approach makes it crystal clear where the `Trait` symbol comes from: you're explicitly bringing it into scope yourself and using it by the name you’ve set in the line `use bimbumlib::bambammodule::SuperLongAndCompletelyUselessNameOfTheTrait as Whatever`.

---

<div class="post-metadata">

**Author:** ![HjVT](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hjvt/32/10365_2.png) [@HjVT](https://internals.rust-lang.org/u/HjVT)\
**Post date:** [November 8, 2025, 12:40am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/5 "2025-11-08T00:40:33Z")

</div>

Do you know that `dyn Trait` used to be spelled `Trait`? Your idea here goes in the opposite direction, and implicitly turns on dynamic dispatch.

---

<div class="post-metadata">

**Author:** ![syudoer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/syudoer/32/13763_2.png) [@syudoer](https://internals.rust-lang.org/u/syudoer)\
**Post date:** [November 8, 2025, 1:13am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/6 "2025-11-08T01:13:14Z")

</div>

You are right. I think `dyn` is not necessary for `(foo as Trait).method()` (like in `<Foo as Trait>`), but `dyn` must be added, and foo must be a reference to be stored or passed. Traits cannot be owned values, so it would be obvious that `(&mut foo as dyn Trait)` is a `&mut dyn Trait`.

---

<div class="post-metadata">

**Author:** ![HjVT](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hjvt/32/10365_2.png) [@HjVT](https://internals.rust-lang.org/u/HjVT)\
**Post date:** [November 8, 2025, 1:39am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/7 "2025-11-08T01:39:24Z")

</div>

I think having `foo as Trait` turn `foo` into an existential is better.

But that's not very interesting. What I think is pretty interesting, is that if we had higher kinded polymorphism, this literally could've been a library function like

```rust
fn as_impl<trait T>(val: impl T) -> impl T {
    val
}

```

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [November 8, 2025, 1:55am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/8 "2025-11-08T01:55:47Z")

</div>

> [@syudoer](#):
>
> As for `let x = foo as Trait`, it should convert `foo: &Type` into `x: &dyn Trait` (preserving the same mutability) or throw an error if foo is an owned value.

This would limit you to [`dyn`-compatible](https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility) traits and their `Self: ?Sized` methods.

And why would you want `as` for this instead of `let x: &dyn Trait = foo`?

---

<div class="post-metadata">

**Author:** ![syudoer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/syudoer/32/13763_2.png) [@syudoer](https://internals.rust-lang.org/u/syudoer)\
**Post date:** [November 8, 2025, 2:37am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/9 "2025-11-08T02:37:49Z")

</div>

I was distracted. My current proposal is to leave the `as` keyword as it is and use `foo.<bar::baz>()` for a single use (because it only covers the method name part, which was the initial problem) and use `bar::baz for foo1` or `use bar::baz for Foo` for multiple uses. The trait symbol should come from the scope and not from `Foo` or anywhere else.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [November 9, 2025, 2:26am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/10 "2025-11-09T02:26:41Z")

</div>

A `use Trait for Type` syntax has the same problem as CSS's `!important` — raising the priority level by one only helps that once. Once you have two high priority trait impls, how you you specify which is higher priority for _their_ overlap?

The `var.<Trait::method>()` has the problem that `<path>` indicates an item in the _type_ namespace, whereas `Trait::method` is in the _expression_ namespace. A more "correct" spelling of this turbofish variant might then be `var.<Trait>::method()`. This _could_ be an improvement over `Trait::method(&var)`… but if so, not by much. And the edit difference from `var<Trait>::method()` is scary for diagnostics.\[1\]

As awkward as the `var.(Trait::method)()` syntax feels, I still feel like it's the least bad option available.\[2\] The `(path)` form clearly takes an expression item. And as a bonus, it can take _any_ expression, making it possible to invoke any function expression in LTR `.` pipelining with method autoref semantics, when that's desirable.

* * *

1. Did you mean:

2. And yes, I'm immediately violating my own concern about edit difference from `var(Trait::method)()`, which even is more likely to be potentially valid, since types don't use snake\_case names, but functions do. My counter to that is that the turbofish is a very common stumbling block for new developers, since other languages decide to just make syntax work without the turbofish. We want to empower diagnostics to realize that error and recover parsing reasonably. `var.(func)` doesn't have that same significant parsing drift between the "typo" options, meaning it's "just" recovery by looking in the other namespace.

---

<div class="post-metadata">

**Author:** ![sahnehaeubchen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sahnehaeubchen/32/9709_2.png) [@sahnehaeubchen](https://internals.rust-lang.org/u/sahnehaeubchen)\
**Post date:** [November 9, 2025, 8:31am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/11 "2025-11-09T08:31:11Z")

</div>

I agree. But the syntax should probably be `value as impl Trait` to make it more distinct from `dyn Trait`.

---

<div class="post-metadata">

**Author:** ![HjVT](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hjvt/32/10365_2.png) [@HjVT](https://internals.rust-lang.org/u/HjVT)\
**Post date:** [November 9, 2025, 9:21am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/12 "2025-11-09T09:21:50Z")

</div>

Ah, that is starting to smell familiar.

Here's some recent discussion on enabling use of arbitrary functions in method chains:

[Zulip topic](https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lang/topic/Vibe.20check.20on.20a.20minimal.20pipeline.20operator/with/545409008)

---

<div class="post-metadata">

**Author:** ![Ratatouille](https://avatars.discourse-cdn.com/v4/letter/r/57b2e6/32.png) [@Ratatouille](https://internals.rust-lang.org/u/Ratatouille)\
**Post date:** [November 10, 2025, 9:11am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/13 "2025-11-10T09:11:53Z")

</div>

Yet again we've converged on the same solution:

[https://internals.rust-lang.org/t/weird-syntax-idea-s-for-umcs/19200](https://internals.rust-lang.org/t/weird-syntax-idea-s-for-umcs/19200)

Btw some time ago I made for myself a simple prototype of this idea:

[https://crates.io/crates/pipei](https://crates.io/crates/pipei)

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [November 10, 2025, 6:50pm UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/14 "2025-11-10T18:50:53Z")

</div>

Pondering: it'd also be nice if whatever we did here allowed "calling base" in an implementation, too. Today if you want to have an impl _sometimes_ handle it but otherwise fallback to the provided one, it's annoying.

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [November 10, 2025, 7:01pm UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/15 "2025-11-10T19:01:04Z")

</div>

Well, there's a separate RFC PR for that [RFC: calling default trait methods from overriding impls by adamcrume · Pull Request #3329 · rust-lang/rfcs · GitHub](https://github.com/rust-lang/rfcs/pull/3329)

---

<div class="post-metadata">

**Author:** ![bettertree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bettertree/32/14062_2.png) [@bettertree](https://internals.rust-lang.org/u/bettertree)\
**Post date:** [January 31, 2026, 9:11am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/16 "2026-01-31T09:11:03Z")

</div>

A syntax concern: There is also `<Type as Trait>::AssociatedType` which is inconsistent with the syntax `x.<Trait::method>()`. Also the `<Trait::method>` gives me the instinct that this is using the trait method "as a whole", e.g. `x.<get_auth_state()>()` or using the trait method to create a closure. (By the way, if `x.<Trait::method>()`, why not `x.<Trait::method()>`?) For these two reasons I'd go for a syntax like `(x for Trait).method()`.

---

<div class="post-metadata">

**Author:** ![bettertree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bettertree/32/14062_2.png) [@bettertree](https://internals.rust-lang.org/u/bettertree)\
**Post date:** [January 31, 2026, 11:10am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/17 "2026-01-31T11:10:51Z")

</div>

On the other hand, `x.<Trait::method>()` works better with chaining, equally does (now unproposed here) `x.Trait::method()`

See also: [Idea: Paths in method names - #30 by CAD97](https://internals.rust-lang.org/t/idea-paths-in-method-names/6834/30) (part of: [Idea: Paths in method names](https://internals.rust-lang.org/t/idea-paths-in-method-names/6834))

---

<div class="post-metadata">

**Author:** ![bettertree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bettertree/32/14062_2.png) [@bettertree](https://internals.rust-lang.org/u/bettertree)\
**Post date:** [January 31, 2026, 11:24am UTC](https://internals.rust-lang.org/t/proposal-syntactic-sugar-for-disambiguating-conflicting-trait-methods/23694/18 "2026-01-31T11:24:09Z")

</div>

I'm also thinking of `x.<Trait>::method()` (yes I know it's mentioned before). It (or current syntax) can coexist with my flavor `(x for Trait).method()` since both have their advantages(?)

```rust
give()
    .me()
    .a()
    .foo()
    .<Trait>::method();

```

It has a syntactical advantage that doesn't have this problem:

> [@bettertree](#):
>
> `<Trait::method>` gives me the instinct that this is using the trait method "as a whole"

* * *

> [@CAD97](#):
>
> This _could_ be an improvement over `Trait::method(&var)`… but if so, not by much.

There's a reasonably significant difference, two most obvious of which is that it's naturally read from left to right and auto-deref semantics work.

* * *

Edit:

Looks like OP has already started an RFC.

> <https://github.com/rust-lang/rfcs/pull/3913>
>
> This RFC proposes two new forms of method call syntax for method name disambigua…tion that keep the receiver on the left and preserve chaining. In doing so, it takes a step towards making implicit selection between trait methods and inherent implementations optional.
> 
> An example of a chain of calls using proposed syntax:
> \`\`\`rust
> obj
> .Self::chain()
> .\<Trait1\>::of()
> .\<Trait2\>::method()
> .\<Trait1\>::calls();
> \`\`\`
> 
> \> \[!IMPORTANT\]  
> \> When responding to RFCs, try to use inline review comments (it is possible to leave an inline review comment for the entire file at the top) instead of direct comments for normal comments and keep normal comments for procedural matters like starting FCPs.
> \>
> \> This keeps the discussion more organized.
> 
> 
> \[Rendered\](https://github.com/syudoer/rust-rfcs/blob/rfc2/text/3913-natural-method-disambiguation.md)

Posting a link to the RFC saves readers' time looking for the follow-ups of the Pre-RFC.
