Repository: dotnet/runtime
File: src/coreclr/tools/Common/Compiler/DevirtualizationManager.cs (C#)

Code before:
                                // We cannot resolve the interface as we don't know with exact enough detail which interface
                                // of multiple possible interfaces is being called.
                                devirtualizationDetail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_MULTIPLE_IMPL;
                                return null;
                            }
                        }
                    }
                }

                if (!implType.CanCastTo(declMethod.OwningType))
                {
                    devirtualizationDetail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_FAILED_CAST;
                    return null;
                }

                impl = implType.ResolveInterfaceMethodTargetWithVariance(declMethod);

                if (impl != null)
                {
                    impl = implType.FindVirtualFunctionTargetMethodOnObjectType(impl);

                    // We need to bring the original instantiation back so that we can still try devirtualizing
                    // when the method is a generic virtual method
                    if (impl != null && originalDeclMethod.HasInstantiation)
                    {
                        // We may end up with a method that has subsituted type parameters, so we need to instantiate
                        // on the method definition
                        impl = impl.GetMethodDefinition().MakeInstantiatedMethod(originalDeclMethod.Instantiation);
                    }
                }
                else
                {
                    // This isn't the correct lookup algorithm for variant default interface methods
                    // but as we will drop any results we find in any case, it doesn't matter much.
                    // Non-variant dispatch can simply use ResolveInterfaceMethodToDefaultImplementationOnType
                    // but that implementation currently cannot handle variance.

                    MethodDesc defaultInterfaceDispatchDeclMethod = null;
                    foreach (TypeDesc iface in implType.RuntimeInterfaces)
                    {
                        if (iface == declMethod.OwningType)
                        {
                            defaultInterfaceDispatchDeclMethod = declMethod;
                            break;
                        }
                        if (iface.HasSameTypeDefinition(declMethod.OwningType) && iface.CanCastTo(declMethod.OwningType))
                        {
                            defaultInterfaceDispatchDeclMethod = iface.FindMethodOnTypeWithMatchingTypicalMethod(declMethod);
                            // Prefer to find the exact match, so don't break immediately
                        }
                    }

Review comment (suggestion):
Spelling error: "subsituted" should be "substituted".
```suggestion
                        // We may end up with a method that has substituted type parameters, so we need to instantiate
```

Code after:
                                // We cannot resolve the interface as we don't know with exact enough detail which interface
                                // of multiple possible interfaces is being called.
                                devirtualizationDetail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_MULTIPLE_IMPL;
                                return null;
                            }
                        }
                    }
                }

                if (!implType.CanCastTo(declMethod.OwningType))
                {
                    devirtualizationDetail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_FAILED_CAST;
                    return null;
                }

                impl = implType.ResolveInterfaceMethodTargetWithVariance(declMethod);

                if (impl != null)
                {
                    impl = implType.FindVirtualFunctionTargetMethodOnObjectType(impl);

                    // We need to bring the original instantiation back so that we can still try devirtualizing
                    // when the method is a generic virtual method
                    if (impl != null && originalDeclMethod.HasInstantiation)
                    {
                        // We may end up with a method that has substituted type parameters, so we need to instantiate
                        // on the method definition
                        impl = impl.GetMethodDefinition().MakeInstantiatedMethod(originalDeclMethod.Instantiation);
                    }
                }
                else
                {
                    // This isn't the correct lookup algorithm for variant default interface methods
                    // but as we will drop any results we find in any case, it doesn't matter much.
                    // Non-variant dispatch can simply use ResolveInterfaceMethodToDefaultImplementationOnType
                    // but that implementation currently cannot handle variance.

                    MethodDesc defaultInterfaceDispatchDeclMethod = null;
                    foreach (TypeDesc iface in implType.RuntimeInterfaces)
                    {
                        if (iface == declMethod.OwningType)
                        {
                            defaultInterfaceDispatchDeclMethod = declMethod;
                            break;
                        }
                        if (iface.HasSameTypeDefinition(declMethod.OwningType) && iface.CanCastTo(declMethod.OwningType))
                        {
                            defaultInterfaceDispatchDeclMethod = iface.FindMethodOnTypeWithMatchingTypicalMethod(declMethod);
                            // Prefer to find the exact match, so don't break immediately
                        }
                    }