<commit_before>// Copyright (c) Microsoft Corporation.  All Rights Reserved.  See License.txt in the project root for license information.

/// Primary relations on types and signatures, with the exception of
/// constraint solving and method overload resolution.
module internal FSharp.Compiler.TypeRelations

open FSharp.Compiler.AbstractIL.Internal 
open FSharp.Compiler.AbstractIL.Internal.Library 
open FSharp.Compiler.ErrorLogger
open FSharp.Compiler.Tast
open FSharp.Compiler.Tastops
open FSharp.Compiler.TcGlobals
open FSharp.Compiler.Infos
open FSharp.Compiler.PrettyNaming

/// Implements a :> b without coercion based on finalized (no type variable) types
// QUERY: This relation is approximate and not part of the language specification. 
//
//  Some appropriate uses: 
//     patcompile.fs: IsDiscrimSubsumedBy (approximate warning for redundancy of 'isinst' patterns)
//     tc.fs: TcRuntimeTypeTest (approximate warning for redundant runtime type tests)
//     tc.fs: TcExnDefnCore (error for bad exception abbreviation)
//     ilxgen.fs: GenCoerce (omit unnecessary castclass or isinst instruction)
//
let rec TypeDefinitelySubsumesTypeNoCoercion ndeep g amap m ty1 ty2 = 
  if ndeep > 100 then error(InternalError("recursive class hierarchy (detected in TypeDefinitelySubsumesTypeNoCoercion), ty1 = " + (DebugPrint.showType ty1), m))
  if ty1 === ty2 then true 
  // QUERY : quadratic
  elif typeEquiv g ty1 ty2 then true
  else
    let ty1 = stripTyEqns g ty1
    let ty2 = stripTyEqns g ty2
    match ty1, ty2 with 
    | TType_app (tc1, l1), TType_app (tc2, l2) when tyconRefEq g tc1 tc2  ->  
        List.lengthsEqAndForall2 (typeEquiv g) l1 l2
    | TType_ucase (tc1, l1), TType_ucase (tc2, l2) when g.unionCaseRefEq tc1 tc2  ->  
        List.lengthsEqAndForall2 (typeEquiv g) l1 l2
    | TType_tuple (tupInfo1, l1), TType_tuple (tupInfo2, l2)     -> 
        evalTupInfoIsStruct tupInfo1 = evalTupInfoIsStruct tupInfo2 && 
        List.lengthsEqAndForall2 (typeEquiv g) l1 l2 
    | TType_fun (d1, r1), TType_fun (d2, r2)   -> 
        typeEquiv g d1 d2 && typeEquiv g r1 r2
    | TType_measure measure1, TType_measure measure2 ->
        measureEquiv g measure1 measure2
    | _ ->  
        (typeEquiv g ty1 g.obj_ty && isRefTy g ty2) || (* F# reference types are subtypes of type 'obj' *)
        (isAppTy g ty2 &&
         isRefTy g ty2 && 

         ((match GetSuperTypeOfType g amap m ty2 with 
           | None -> false
           | Some ty -> TypeDefinitelySubsumesTypeNoCoercion (ndeep+1) g amap m ty1 ty) ||

           (isInterfaceTy g ty1 &&
            ty2 |> GetImmediateInterfacesOfType SkipUnrefInterfaces.Yes g amap m 
                |> List.exists (TypeDefinitelySubsumesTypeNoCoercion (ndeep+1) g amap m ty1))))



type CanCoerce = CanCoerce | NoCoerce

/// The feasible equivalence relation. Part of the language spec.
let rec TypesFeasiblyEquiv ndeep g amap m ty1 ty2 = 

    if ndeep > 100 then error(InternalError("recursive class hierarchy (detected in TypeFeasiblySubsumesType), ty1 = " + (DebugPrint.showType ty1), m));
    let ty1 = stripTyEqns g ty1<commit_msg>Remove redundant code (#6625)<commit_after>// Copyright (c) Microsoft Corporation.  All Rights Reserved.  See License.txt in the project root for license information.

/// Primary relations on types and signatures, with the exception of
/// constraint solving and method overload resolution.
module internal FSharp.Compiler.TypeRelations

open FSharp.Compiler.AbstractIL.Internal 
open FSharp.Compiler.AbstractIL.Internal.Library 
open FSharp.Compiler.ErrorLogger
open FSharp.Compiler.Tast
open FSharp.Compiler.Tastops
open FSharp.Compiler.TcGlobals
open FSharp.Compiler.Infos
open FSharp.Compiler.PrettyNaming

/// Implements a :> b without coercion based on finalized (no type variable) types
// Note: This relation is approximate and not part of the language specification. 
//
//  Some appropriate uses: 
//     patcompile.fs: IsDiscrimSubsumedBy (approximate warning for redundancy of 'isinst' patterns)
//     tc.fs: TcRuntimeTypeTest (approximate warning for redundant runtime type tests)
//     tc.fs: TcExnDefnCore (error for bad exception abbreviation)
//     ilxgen.fs: GenCoerce (omit unnecessary castclass or isinst instruction)
//
let rec TypeDefinitelySubsumesTypeNoCoercion ndeep g amap m ty1 ty2 = 
  if ndeep > 100 then error(InternalError("recursive class hierarchy (detected in TypeDefinitelySubsumesTypeNoCoercion), ty1 = " + (DebugPrint.showType ty1), m))
  if ty1 === ty2 then true 
  elif typeEquiv g ty1 ty2 then true
  else
    let ty1 = stripTyEqns g ty1
    let ty2 = stripTyEqns g ty2
    // F# reference types are subtypes of type 'obj'
    (typeEquiv g ty1 g.obj_ty && isRefTy g ty2) ||
    // Follow the supertype chain
    (isAppTy g ty2 &&
     isRefTy g ty2 && 

     ((match GetSuperTypeOfType g amap m ty2 with 
       | None -> false
       | Some ty -> TypeDefinitelySubsumesTypeNoCoercion (ndeep+1) g amap m ty1 ty) ||

       // Follow the interface hierarchy
       (isInterfaceTy g ty1 &&
        ty2 |> GetImmediateInterfacesOfType SkipUnrefInterfaces.Yes g amap m 
            |> List.exists (TypeDefinitelySubsumesTypeNoCoercion (ndeep+1) g amap m ty1))))

type CanCoerce = CanCoerce | NoCoerce

/// The feasible equivalence relation. Part of the language spec.
let rec TypesFeasiblyEquiv ndeep g amap m ty1 ty2 = 

    if ndeep > 100 then error(InternalError("recursive class hierarchy (detected in TypeFeasiblySubsumesType), ty1 = " + (DebugPrint.showType ty1), m));
    let ty1 = stripTyEqns g ty1
{'fraction_non_alphanumeric': 0.07820927723840346, 'fraction_numerical': 0.02067601582164689, 'mean_word_length': 3.468273092369478, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4502358', 'n_tokens_mistral': 1844, 'n_tokens_neox': 1722, 'n_words': 592}