Roslyn: Tuple item name not inferred from "value"

Created on 4 Dec 2020  路  2Comments  路  Source: dotnet/roslyn

Version Used:
16.8.2

Steps to Reproduce:

https://sharplab.io/#v2:C4LgTgrgdgNAJiA1AHwAICYCMBYAUKgBgAJVMAWAbjzwyIGE8BvPI1kzANhLKIFkBDAJZQAFAEoWbZrjaz2xAG78ANhACmRALxEARDqoy5rUsQBG/AM5qAIoLBqAxsAD2YAJ5bd+yUbr8HABZqIiJKqmowROZWtvZOrm5ikQDWWgB8RMkAdGHqRIiZWdE2do4u7pH8cABWEBbAAGKCymoACvzAAX6BamIGsgC+PkTDAA5ggkrAGqRc9lXOUMoetk6Ci/zuADwiJplqbpF7xbFlCUnyGVW19U0t7Z3dQZ5QagDuRKvA61Cbbjt7ZIHI6YMyWEpxcqJEEENLiAzDYTTMC/ZTsLh7J5qLYAFThOP2hxIAFZcTCMg5nABbUYQaaRL4/P5ky5EOCCNYbdwSQysaRGVidMDOD5QCDKZT9NhDXADIA=

using System;
using System.Collections.Generic;

class C
{
    static void Main()
    {
        string value = "";
        string baseDirectory = "";
        Cache((value, baseDirectory), k => k.value + k.baseDirectory, adjustFilePathCache);
    }

    private static readonly Dictionary<(string key, string baseDirectory), string> adjustFilePathCache = new Dictionary<(string key, string baseDirectory), string>();

    internal static string Cache<T>(T key, Func<T, string> compute, Dictionary<T, string> dictionary)
    {
        throw null;
    }
}

Expected Behavior:
Should compile?

Actual Behavior:

error CS1061: '(string, string baseDirectory)' does not contain a definition for 'value' and no accessible extension method 'value' accepting a first argument of type '(string, string baseDirectory)' could be found (are you missing a using directive or an assembly reference?)
Area-Compilers untriaged

Most helpful comment

@KirillOsenkov This behavior sounds reasonable to me.

The generic type T of the static Cache method is used in two places:

  1. In the first parameter of the method, which is T key, and the tuple passed to it is (value, baseDirectory).
  2. In the key of the dictionary (the 3rd parameter), which is Dictionary<T, string> dictionary, and the dictionary have the key as (string key, string baseDirectory).

So, what should the compile infer the name of the first item? value or key? the compiler here preferred to choose none of them, and call it Item1.

For the second tuple item, because both are called baseDirectory, the compiler inferred the name correctly.

Here is a compiling version after making the name of the first item consistent:

https://sharplab.io/#v2:C4LgTgrgdgNAJiA1AHwAICYCMBYAUKgBgAJVMAWAbjzwyIGE8BvPI1kzANhLKIFkBDAJZQAFAEoWbZrjaz2xAG78ANhACmRALxEARDqoy5rUsQBG/AM5qAIoLBqAxsAD2YAJ5bd+yUbr8HABZqIiJKqmowROZWtvZOrm5ikQDWWgB8RMkAdGHqRIiZWdE2do4u7pH8cABWEBbAAGKCymoACvzAAX6BamIGsgC+PkTDAA5ggkrAGqRc9lXOUMoetk6Ci/zuADwiJkS5EfJRliVx5YmRJhlVtfVNLe2d3UGeUGoA7kSrwOtQm247PYHS6YMwnWJlBJJeRpcQGYbCaZgP7KdhcPbPNRbAAqsOxmTUbkuAFYcSCCBkHM4ALajCDTSLfX7/MkwohwQRrDbuCSGVjSIysTpgZyfKAQZTKfpsIa4AZAA===

All 2 comments

@KirillOsenkov This behavior sounds reasonable to me.

The generic type T of the static Cache method is used in two places:

  1. In the first parameter of the method, which is T key, and the tuple passed to it is (value, baseDirectory).
  2. In the key of the dictionary (the 3rd parameter), which is Dictionary<T, string> dictionary, and the dictionary have the key as (string key, string baseDirectory).

So, what should the compile infer the name of the first item? value or key? the compiler here preferred to choose none of them, and call it Item1.

For the second tuple item, because both are called baseDirectory, the compiler inferred the name correctly.

Here is a compiling version after making the name of the first item consistent:

https://sharplab.io/#v2:C4LgTgrgdgNAJiA1AHwAICYCMBYAUKgBgAJVMAWAbjzwyIGE8BvPI1kzANhLKIFkBDAJZQAFAEoWbZrjaz2xAG78ANhACmRALxEARDqoy5rUsQBG/AM5qAIoLBqAxsAD2YAJ5bd+yUbr8HABZqIiJKqmowROZWtvZOrm5ikQDWWgB8RMkAdGHqRIiZWdE2do4u7pH8cABWEBbAAGKCymoACvzAAX6BamIGsgC+PkTDAA5ggkrAGqRc9lXOUMoetk6Ci/zuADwiJkS5EfJRliVx5YmRJhlVtfVNLe2d3UGeUGoA7kSrwOtQm247PYHS6YMwnWJlBJJeRpcQGYbCaZgP7KdhcPbPNRbAAqsOxmTUbkuAFYcSCCBkHM4ALajCDTSLfX7/MkwohwQRrDbuCSGVjSIysTpgZyfKAQZTKfpsIa4AZAA===

Ah, makes sense, thanks for the explanation!

Was this page helpful?
0 / 5 - 0 ratings