2021-10-29 21:25:12 +01:00
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
# include "Luau/Error.h"
2022-04-07 21:53:47 +01:00
# include "Luau/Clone.h"
2022-12-02 10:46:05 +00:00
# include "Luau/Common.h"
2022-12-09 18:07:25 +00:00
# include "Luau/FileResolver.h"
2021-10-29 21:25:12 +01:00
# include "Luau/StringUtils.h"
# include "Luau/ToString.h"
# include <stdexcept>
2022-12-02 10:46:05 +00:00
# include <type_traits>
2021-10-29 21:25:12 +01:00
2022-12-02 10:46:05 +00:00
LUAU_FASTFLAGVARIABLE ( LuauTypeMismatchInvarianceInError , false )
2022-10-27 23:22:49 +01:00
2022-09-15 23:13:58 +01:00
static std : : string wrongNumberOfArgsString (
size_t expectedCount , std : : optional < size_t > maximumCount , size_t actualCount , const char * argPrefix = nullptr , bool isVariadic = false )
2021-11-05 02:07:18 +00:00
{
2021-12-02 23:20:08 +00:00
std : : string s = " expects " ;
2021-11-05 02:07:18 +00:00
2021-12-02 23:20:08 +00:00
if ( isVariadic )
s + = " at least " ;
2021-11-05 02:07:18 +00:00
2021-12-02 23:20:08 +00:00
s + = std : : to_string ( expectedCount ) + " " ;
2021-11-05 02:07:18 +00:00
2022-09-15 23:13:58 +01:00
if ( maximumCount & & expectedCount ! = * maximumCount )
s + = " to " + std : : to_string ( * maximumCount ) + " " ;
2021-11-05 02:07:18 +00:00
if ( argPrefix )
s + = std : : string ( argPrefix ) + " " ;
s + = " argument " ;
2022-09-15 23:13:58 +01:00
if ( ( maximumCount ? * maximumCount : expectedCount ) ! = 1 )
2021-11-05 02:07:18 +00:00
s + = " s " ;
s + = " , but " ;
if ( actualCount = = 0 )
{
s + = " none " ;
}
else
{
if ( actualCount < expectedCount )
s + = " only " ;
s + = std : : to_string ( actualCount ) ;
}
s + = ( actualCount = = 1 ) ? " is " : " are " ;
s + = " specified " ;
return s ;
}
2021-10-29 21:25:12 +01:00
namespace Luau
{
struct ErrorConverter
{
2022-06-24 02:44:07 +01:00
FileResolver * fileResolver = nullptr ;
2021-10-29 21:25:12 +01:00
std : : string operator ( ) ( const Luau : : TypeMismatch & tm ) const
{
2022-03-24 21:49:08 +00:00
std : : string givenTypeName = Luau : : toString ( tm . givenType ) ;
std : : string wantedTypeName = Luau : : toString ( tm . wantedType ) ;
std : : string result ;
2022-04-21 22:04:22 +01:00
if ( givenTypeName = = wantedTypeName )
2022-03-24 21:49:08 +00:00
{
2022-04-21 22:04:22 +01:00
if ( auto givenDefinitionModule = getDefinitionModuleName ( tm . givenType ) )
2022-03-24 21:49:08 +00:00
{
2022-04-21 22:04:22 +01:00
if ( auto wantedDefinitionModule = getDefinitionModuleName ( tm . wantedType ) )
2022-03-24 21:49:08 +00:00
{
2022-10-21 18:33:43 +01:00
if ( fileResolver ! = nullptr )
2022-06-24 02:44:07 +01:00
{
std : : string givenModuleName = fileResolver - > getHumanReadableModuleName ( * givenDefinitionModule ) ;
std : : string wantedModuleName = fileResolver - > getHumanReadableModuleName ( * wantedDefinitionModule ) ;
result = " Type ' " + givenTypeName + " ' from ' " + givenModuleName + " ' could not be converted into ' " + wantedTypeName +
" ' from ' " + wantedModuleName + " ' " ;
}
else
{
result = " Type ' " + givenTypeName + " ' from ' " + * givenDefinitionModule + " ' could not be converted into ' " + wantedTypeName +
" ' from ' " + * wantedDefinitionModule + " ' " ;
}
2022-03-24 21:49:08 +00:00
}
}
}
2022-04-21 22:04:22 +01:00
if ( result . empty ( ) )
2022-03-24 21:49:08 +00:00
result = " Type ' " + givenTypeName + " ' could not be converted into ' " + wantedTypeName + " ' " ;
2021-11-12 02:12:39 +00:00
2022-12-02 10:46:05 +00:00
2021-11-12 02:12:39 +00:00
if ( tm . error )
{
result + = " \n caused by: \n " ;
if ( ! tm . reason . empty ( ) )
2021-12-10 21:17:10 +00:00
result + = tm . reason + " " ;
2021-11-12 02:12:39 +00:00
2022-10-21 18:33:43 +01:00
result + = Luau : : toString ( * tm . error , TypeErrorToStringOptions { fileResolver } ) ;
2021-11-12 02:12:39 +00:00
}
else if ( ! tm . reason . empty ( ) )
{
result + = " ; " + tm . reason ;
}
2022-12-02 10:46:05 +00:00
else if ( FFlag : : LuauTypeMismatchInvarianceInError & & tm . context = = TypeMismatch : : InvariantContext )
{
result + = " in an invariant context " ;
}
2021-11-12 02:12:39 +00:00
return result ;
2021-10-29 21:25:12 +01:00
}
std : : string operator ( ) ( const Luau : : UnknownSymbol & e ) const
{
switch ( e . context )
{
case UnknownSymbol : : Binding :
return " Unknown global ' " + e . name + " ' " ;
case UnknownSymbol : : Type :
return " Unknown type ' " + e . name + " ' " ;
}
LUAU_ASSERT ( ! " Unexpected context for UnknownSymbol " ) ;
return " " ;
}
std : : string operator ( ) ( const Luau : : UnknownProperty & e ) const
{
TypeId t = follow ( e . table ) ;
2023-01-03 17:33:19 +00:00
if ( get < TableType > ( t ) )
2021-10-29 21:25:12 +01:00
return " Key ' " + e . key + " ' not found in table ' " + Luau : : toString ( t ) + " ' " ;
2023-01-03 17:33:19 +00:00
else if ( get < ClassType > ( t ) )
2021-10-29 21:25:12 +01:00
return " Key ' " + e . key + " ' not found in class ' " + Luau : : toString ( t ) + " ' " ;
else
return " Type ' " + Luau : : toString ( e . table ) + " ' does not have key ' " + e . key + " ' " ;
}
std : : string operator ( ) ( const Luau : : NotATable & e ) const
{
return " Expected type table, got ' " + Luau : : toString ( e . ty ) + " ' instead " ;
}
std : : string operator ( ) ( const Luau : : CannotExtendTable & e ) const
{
switch ( e . context )
{
case Luau : : CannotExtendTable : : Property :
return " Cannot add property ' " + e . prop + " ' to table ' " + Luau : : toString ( e . tableType ) + " ' " ;
case Luau : : CannotExtendTable : : Metatable :
return " Cannot add metatable to table ' " + Luau : : toString ( e . tableType ) + " ' " ;
case Luau : : CannotExtendTable : : Indexer :
return " Cannot add indexer to table ' " + Luau : : toString ( e . tableType ) + " ' " ;
}
LUAU_ASSERT ( ! " Unknown context " ) ;
return " " ;
}
std : : string operator ( ) ( const Luau : : OnlyTablesCanHaveMethods & e ) const
{
return " Cannot add method to non-table type ' " + Luau : : toString ( e . tableType ) + " ' " ;
}
std : : string operator ( ) ( const Luau : : DuplicateTypeDefinition & e ) const
{
2022-09-29 23:11:54 +01:00
std : : string s = " Redefinition of type ' " + e . name + " ' " ;
if ( e . previousLocation )
s + = " , previously defined at line " + std : : to_string ( e . previousLocation - > begin . line + 1 ) ;
return s ;
2021-10-29 21:25:12 +01:00
}
std : : string operator ( ) ( const Luau : : CountMismatch & e ) const
{
2021-11-05 02:42:00 +00:00
const std : : string expectedS = e . expected = = 1 ? " " : " s " ;
const std : : string actualS = e . actual = = 1 ? " " : " s " ;
const std : : string actualVerb = e . actual = = 1 ? " is " : " are " ;
2021-10-29 21:25:12 +01:00
switch ( e . context )
{
case CountMismatch : : Return :
2021-11-18 22:21:07 +00:00
return " Expected to return " + std : : to_string ( e . expected ) + " value " + expectedS + " , but " + std : : to_string ( e . actual ) + " " +
actualVerb + " returned here " ;
2022-09-29 23:11:54 +01:00
case CountMismatch : : FunctionResult :
2021-11-05 02:42:00 +00:00
// It is alright if right hand side produces more values than the
// left hand side accepts. In this context consider only the opposite case.
2022-09-29 23:11:54 +01:00
return " Function only returns " + std : : to_string ( e . expected ) + " value " + expectedS + " , but " + std : : to_string ( e . actual ) + " " +
actualVerb + " required here " ;
case CountMismatch : : ExprListResult :
return " Expression list has " + std : : to_string ( e . expected ) + " value " + expectedS + " , but " + std : : to_string ( e . actual ) + " " +
actualVerb + " required here " ;
2021-10-29 21:25:12 +01:00
case CountMismatch : : Arg :
2022-09-15 23:13:58 +01:00
if ( ! e . function . empty ( ) )
return " Argument count mismatch. Function ' " + e . function + " ' " +
wrongNumberOfArgsString ( e . expected , e . maximum , e . actual , /*argPrefix*/ nullptr , e . isVariadic ) ;
else
return " Argument count mismatch. Function " +
wrongNumberOfArgsString ( e . expected , e . maximum , e . actual , /*argPrefix*/ nullptr , e . isVariadic ) ;
2021-10-29 21:25:12 +01:00
}
LUAU_ASSERT ( ! " Unknown context " ) ;
return " " ;
}
std : : string operator ( ) ( const Luau : : FunctionDoesNotTakeSelf & ) const
{
return std : : string ( " This function does not take self. Did you mean to use a dot instead of a colon? " ) ;
}
std : : string operator ( ) ( const Luau : : FunctionRequiresSelf & e ) const
{
2022-05-20 00:46:52 +01:00
return " This function must be called with self. Did you mean to use a colon instead of a dot? " ;
2021-10-29 21:25:12 +01:00
}
std : : string operator ( ) ( const Luau : : OccursCheckFailed & ) const
{
return " Type contains a self-recursive construct that cannot be resolved " ;
}
std : : string operator ( ) ( const Luau : : UnknownRequire & e ) const
{
2021-11-05 02:07:18 +00:00
if ( e . modulePath . empty ( ) )
return " Unknown require: unsupported path " ;
else
return " Unknown require: " + e . modulePath ;
2021-10-29 21:25:12 +01:00
}
std : : string operator ( ) ( const Luau : : IncorrectGenericParameterCount & e ) const
{
std : : string name = e . name ;
2021-12-02 23:20:08 +00:00
if ( ! e . typeFun . typeParams . empty ( ) | | ! e . typeFun . typePackParams . empty ( ) )
2021-10-29 21:25:12 +01:00
{
name + = " < " ;
bool first = true ;
2022-01-14 16:06:31 +00:00
for ( auto param : e . typeFun . typeParams )
2021-10-29 21:25:12 +01:00
{
if ( first )
first = false ;
else
name + = " , " ;
2022-01-14 16:06:31 +00:00
name + = toString ( param . ty ) ;
2021-10-29 21:25:12 +01:00
}
2021-11-05 02:07:18 +00:00
2022-01-14 16:06:31 +00:00
for ( auto param : e . typeFun . typePackParams )
2021-11-05 02:07:18 +00:00
{
2021-12-02 23:20:08 +00:00
if ( first )
first = false ;
else
name + = " , " ;
2022-01-14 16:06:31 +00:00
name + = toString ( param . tp ) ;
2021-11-05 02:07:18 +00:00
}
2021-10-29 21:25:12 +01:00
name + = " > " ;
}
2021-12-02 23:20:08 +00:00
if ( e . typeFun . typeParams . size ( ) ! = e . actualParameters )
2021-11-05 02:07:18 +00:00
return " Generic type ' " + name + " ' " +
2022-09-15 23:13:58 +01:00
wrongNumberOfArgsString ( e . typeFun . typeParams . size ( ) , std : : nullopt , e . actualParameters , " type " , ! e . typeFun . typePackParams . empty ( ) ) ;
2021-12-02 23:20:08 +00:00
return " Generic type ' " + name + " ' " +
2022-09-15 23:13:58 +01:00
wrongNumberOfArgsString ( e . typeFun . typePackParams . size ( ) , std : : nullopt , e . actualPackParameters , " type pack " , /*isVariadic*/ false ) ;
2021-10-29 21:25:12 +01:00
}
std : : string operator ( ) ( const Luau : : SyntaxError & e ) const
{
2022-04-14 22:57:15 +01:00
return e . message ;
2021-10-29 21:25:12 +01:00
}
std : : string operator ( ) ( const Luau : : CodeTooComplex & ) const
{
return " Code is too complex to typecheck! Consider simplifying the code around this area " ;
}
std : : string operator ( ) ( const Luau : : UnificationTooComplex & ) const
{
return " Internal error: Code is too complex to typecheck! Consider adding type annotations around this area " ;
}
std : : string operator ( ) ( const Luau : : UnknownPropButFoundLikeProp & e ) const
{
std : : string candidatesSuggestion = " Did you mean " ;
if ( e . candidates . size ( ) ! = 1 )
candidatesSuggestion + = " one of " ;
bool first = true ;
for ( Name name : e . candidates )
{
if ( first )
first = false ;
else
candidatesSuggestion + = " , " ;
candidatesSuggestion + = " ' " + name + " ' " ;
}
std : : string s = " Key ' " + e . key + " ' not found in " ;
TypeId t = follow ( e . table ) ;
2023-01-03 17:33:19 +00:00
if ( get < ClassType > ( t ) )
2021-10-29 21:25:12 +01:00
s + = " class " ;
else
s + = " table " ;
s + = " ' " + toString ( e . table ) + " '. " + candidatesSuggestion + " ? " ;
return s ;
}
std : : string operator ( ) ( const Luau : : GenericError & e ) const
{
return e . message ;
}
2022-06-24 02:44:07 +01:00
std : : string operator ( ) ( const Luau : : InternalError & e ) const
{
return e . message ;
}
2021-10-29 21:25:12 +01:00
std : : string operator ( ) ( const Luau : : CannotCallNonFunction & e ) const
{
return " Cannot call non-function " + toString ( e . ty ) ;
}
std : : string operator ( ) ( const Luau : : ExtraInformation & e ) const
{
return e . message ;
}
std : : string operator ( ) ( const Luau : : DeprecatedApiUsed & e ) const
{
return " The property . " + e . symbol + " is deprecated. Use . " + e . useInstead + " instead. " ;
}
std : : string operator ( ) ( const Luau : : ModuleHasCyclicDependency & e ) const
{
if ( e . cycle . empty ( ) )
return " Cyclic module dependency detected " ;
std : : string s = " Cyclic module dependency: " ;
bool first = true ;
for ( const ModuleName & name : e . cycle )
{
if ( first )
first = false ;
else
s + = " -> " ;
2023-05-25 21:46:51 +01:00
if ( fileResolver ! = nullptr )
2023-04-21 22:41:03 +01:00
s + = fileResolver - > getHumanReadableModuleName ( name ) ;
else
s + = name ;
2021-10-29 21:25:12 +01:00
}
return s ;
}
std : : string operator ( ) ( const Luau : : FunctionExitsWithoutReturning & e ) const
{
return " Not all codepaths in this function return ' " + toString ( e . expectedReturnType ) + " '. " ;
}
std : : string operator ( ) ( const Luau : : IllegalRequire & e ) const
{
return " Cannot require module " + e . moduleName + " : " + e . reason ;
}
std : : string operator ( ) ( const Luau : : MissingProperties & e ) const
{
std : : string s = " Table type ' " + toString ( e . subType ) + " ' not compatible with type ' " + toString ( e . superType ) + " ' because the former " ;
switch ( e . context )
{
case MissingProperties : : Missing :
s + = " is missing field " ;
break ;
case MissingProperties : : Extra :
s + = " has extra field " ;
break ;
}
if ( e . properties . size ( ) > 1 )
s + = " s " ;
s + = " " ;
for ( size_t i = 0 ; i < e . properties . size ( ) ; + + i )
{
if ( i > 0 )
s + = " , " ;
if ( i > 0 & & i = = e . properties . size ( ) - 1 )
s + = " and " ;
s + = " ' " + e . properties [ i ] + " ' " ;
}
return s ;
}
std : : string operator ( ) ( const Luau : : DuplicateGenericParameter & e ) const
{
return " Duplicate type parameter ' " + e . parameterName + " ' " ;
}
std : : string operator ( ) ( const Luau : : CannotInferBinaryOperation & e ) const
{
std : : string ss = " Unknown type used in " + toString ( e . op ) ;
switch ( e . kind )
{
case Luau : : CannotInferBinaryOperation : : Comparison :
ss + = " comparison " ;
break ;
case Luau : : CannotInferBinaryOperation : : Operation :
ss + = " operation " ;
}
if ( e . suggestedToAnnotate )
ss + = " ; consider adding a type annotation to ' " + * e . suggestedToAnnotate + " ' " ;
return ss ;
}
std : : string operator ( ) ( const Luau : : SwappedGenericTypeParameter & e ) const
{
switch ( e . kind )
{
case Luau : : SwappedGenericTypeParameter : : Type :
return " Variadic type parameter ' " + e . name + " ...' is used as a regular generic type; consider changing ' " + e . name + " ...' to ' " +
e . name + " ' in the generic argument list " ;
case Luau : : SwappedGenericTypeParameter : : Pack :
return " Generic type ' " + e . name + " ' is used as a variadic type parameter; consider changing ' " + e . name + " ' to ' " + e . name +
" ...' in the generic argument list " ;
default :
LUAU_ASSERT ( ! " Unknown kind " ) ;
return " " ;
}
}
std : : string operator ( ) ( const Luau : : OptionalValueAccess & e ) const
{
return " Value of type ' " + toString ( e . optional ) + " ' could be nil " ;
}
std : : string operator ( ) ( const Luau : : MissingUnionProperty & e ) const
{
std : : string ss = " Key ' " + e . key + " ' is missing from " ;
bool first = true ;
for ( auto ty : e . missing )
{
if ( first )
first = false ;
else
ss + = " , " ;
ss + = " ' " + toString ( ty ) + " ' " ;
}
return ss + " in the type ' " + toString ( e . type ) + " ' " ;
}
2021-12-10 21:17:10 +00:00
std : : string operator ( ) ( const TypesAreUnrelated & e ) const
{
return " Cannot cast ' " + toString ( e . left ) + " ' into ' " + toString ( e . right ) + " ' because the types are unrelated " ;
}
2022-04-14 22:57:15 +01:00
std : : string operator ( ) ( const NormalizationTooComplex & ) const
{
return " Code is too complex to typecheck! Consider simplifying the code around this area " ;
}
2022-10-27 23:22:49 +01:00
std : : string operator ( ) ( const TypePackMismatch & e ) const
{
return " Type pack ' " + toString ( e . givenTp ) + " ' could not be converted into ' " + toString ( e . wantedTp ) + " ' " ;
}
2022-12-02 10:46:05 +00:00
std : : string operator ( ) ( const DynamicPropertyLookupOnClassesUnsafe & e ) const
{
return " Attempting a dynamic property access on type ' " + Luau : : toString ( e . ty ) + " ' is unsafe and may cause exceptions at runtime " ;
}
2023-05-12 13:15:01 +01:00
std : : string operator ( ) ( const UninhabitedTypeFamily & e ) const
{
return " Type family instance " + Luau : : toString ( e . ty ) + " is uninhabited " ;
}
std : : string operator ( ) ( const UninhabitedTypePackFamily & e ) const
{
return " Type pack family instance " + Luau : : toString ( e . tp ) + " is uninhabited " ;
}
2023-05-25 21:46:51 +01:00
std : : string operator ( ) ( const WhereClauseNeeded & e ) const
{
return " Type family instance " + Luau : : toString ( e . ty ) + " depends on generic function parameters but does not appear in the function signature; this construct cannot be type-checked at this time " ;
}
std : : string operator ( ) ( const PackWhereClauseNeeded & e ) const
{
return " Type pack family instance " + Luau : : toString ( e . tp ) + " depends on generic function parameters but does not appear in the function signature; this construct cannot be type-checked at this time " ;
}
2021-10-29 21:25:12 +01:00
} ;
struct InvalidNameChecker
{
std : : string invalidName = " %error-id% " ;
bool operator ( ) ( const Luau : : UnknownProperty & e ) const
{
return e . key = = invalidName ;
}
bool operator ( ) ( const Luau : : CannotExtendTable & e ) const
{
return e . prop = = invalidName ;
}
bool operator ( ) ( const Luau : : DuplicateTypeDefinition & e ) const
{
return e . name = = invalidName ;
}
template < typename T >
bool operator ( ) ( const T & other ) const
{
return false ;
}
} ;
2021-11-12 02:12:39 +00:00
TypeMismatch : : TypeMismatch ( TypeId wantedType , TypeId givenType )
: wantedType ( wantedType )
, givenType ( givenType )
{
}
TypeMismatch : : TypeMismatch ( TypeId wantedType , TypeId givenType , std : : string reason )
: wantedType ( wantedType )
, givenType ( givenType )
, reason ( reason )
{
}
2022-10-07 00:55:58 +01:00
TypeMismatch : : TypeMismatch ( TypeId wantedType , TypeId givenType , std : : string reason , std : : optional < TypeError > error )
2021-11-12 02:12:39 +00:00
: wantedType ( wantedType )
, givenType ( givenType )
, reason ( reason )
2022-10-07 00:55:58 +01:00
, error ( error ? std : : make_shared < TypeError > ( std : : move ( * error ) ) : nullptr )
2021-11-12 02:12:39 +00:00
{
}
2022-12-02 10:46:05 +00:00
TypeMismatch : : TypeMismatch ( TypeId wantedType , TypeId givenType , TypeMismatch : : Context context )
: wantedType ( wantedType )
, givenType ( givenType )
, context ( context )
{
}
TypeMismatch : : TypeMismatch ( TypeId wantedType , TypeId givenType , std : : string reason , TypeMismatch : : Context context )
: wantedType ( wantedType )
, givenType ( givenType )
, context ( context )
, reason ( reason )
{
}
TypeMismatch : : TypeMismatch ( TypeId wantedType , TypeId givenType , std : : string reason , std : : optional < TypeError > error , TypeMismatch : : Context context )
: wantedType ( wantedType )
, givenType ( givenType )
, context ( context )
, reason ( reason )
, error ( error ? std : : make_shared < TypeError > ( std : : move ( * error ) ) : nullptr )
{
}
2021-10-29 21:25:12 +01:00
bool TypeMismatch : : operator = = ( const TypeMismatch & rhs ) const
{
2021-11-12 02:12:39 +00:00
if ( ! ! error ! = ! ! rhs . error )
return false ;
if ( error & & ! ( * error = = * rhs . error ) )
return false ;
2022-12-02 10:46:05 +00:00
return * wantedType = = * rhs . wantedType & & * givenType = = * rhs . givenType & & reason = = rhs . reason & & context = = rhs . context ;
2021-10-29 21:25:12 +01:00
}
bool UnknownSymbol : : operator = = ( const UnknownSymbol & rhs ) const
{
return name = = rhs . name ;
}
bool UnknownProperty : : operator = = ( const UnknownProperty & rhs ) const
{
return * table = = * rhs . table & & key = = rhs . key ;
}
bool NotATable : : operator = = ( const NotATable & rhs ) const
{
return ty = = rhs . ty ;
}
bool CannotExtendTable : : operator = = ( const CannotExtendTable & rhs ) const
{
return * tableType = = * rhs . tableType & & prop = = rhs . prop & & context = = rhs . context ;
}
bool OnlyTablesCanHaveMethods : : operator = = ( const OnlyTablesCanHaveMethods & rhs ) const
{
return * tableType = = * rhs . tableType ;
}
bool DuplicateTypeDefinition : : operator = = ( const DuplicateTypeDefinition & rhs ) const
{
return name = = rhs . name & & previousLocation = = rhs . previousLocation ;
}
bool CountMismatch : : operator = = ( const CountMismatch & rhs ) const
{
2022-09-15 23:13:58 +01:00
return expected = = rhs . expected & & maximum = = rhs . maximum & & actual = = rhs . actual & & context = = rhs . context & & function = = rhs . function ;
2021-10-29 21:25:12 +01:00
}
bool FunctionDoesNotTakeSelf : : operator = = ( const FunctionDoesNotTakeSelf & ) const
{
return true ;
}
bool FunctionRequiresSelf : : operator = = ( const FunctionRequiresSelf & e ) const
{
2022-05-20 00:46:52 +01:00
return true ;
2021-10-29 21:25:12 +01:00
}
bool OccursCheckFailed : : operator = = ( const OccursCheckFailed & ) const
{
return true ;
}
bool UnknownRequire : : operator = = ( const UnknownRequire & rhs ) const
{
return modulePath = = rhs . modulePath ;
}
bool IncorrectGenericParameterCount : : operator = = ( const IncorrectGenericParameterCount & rhs ) const
{
if ( name ! = rhs . name )
return false ;
if ( typeFun . type ! = rhs . typeFun . type )
return false ;
if ( typeFun . typeParams . size ( ) ! = rhs . typeFun . typeParams . size ( ) )
return false ;
2021-12-02 23:20:08 +00:00
if ( typeFun . typePackParams . size ( ) ! = rhs . typeFun . typePackParams . size ( ) )
return false ;
2021-11-05 02:07:18 +00:00
2021-10-29 21:25:12 +01:00
for ( size_t i = 0 ; i < typeFun . typeParams . size ( ) ; + + i )
2021-11-05 02:07:18 +00:00
{
2022-01-14 16:06:31 +00:00
if ( typeFun . typeParams [ i ] . ty ! = rhs . typeFun . typeParams [ i ] . ty )
2021-10-29 21:25:12 +01:00
return false ;
2021-11-05 02:07:18 +00:00
}
2021-12-02 23:20:08 +00:00
for ( size_t i = 0 ; i < typeFun . typePackParams . size ( ) ; + + i )
2021-11-05 02:07:18 +00:00
{
2022-01-14 16:06:31 +00:00
if ( typeFun . typePackParams [ i ] . tp ! = rhs . typeFun . typePackParams [ i ] . tp )
2021-12-02 23:20:08 +00:00
return false ;
2021-11-05 02:07:18 +00:00
}
2021-10-29 21:25:12 +01:00
return true ;
}
bool SyntaxError : : operator = = ( const SyntaxError & rhs ) const
{
return message = = rhs . message ;
}
bool CodeTooComplex : : operator = = ( const CodeTooComplex & ) const
{
return true ;
}
bool UnificationTooComplex : : operator = = ( const UnificationTooComplex & ) const
{
return true ;
}
bool UnknownPropButFoundLikeProp : : operator = = ( const UnknownPropButFoundLikeProp & rhs ) const
{
return * table = = * rhs . table & & key = = rhs . key & & candidates . size ( ) = = rhs . candidates . size ( ) & &
std : : equal ( candidates . begin ( ) , candidates . end ( ) , rhs . candidates . begin ( ) ) ;
}
bool GenericError : : operator = = ( const GenericError & rhs ) const
{
return message = = rhs . message ;
}
2022-06-24 02:44:07 +01:00
bool InternalError : : operator = = ( const InternalError & rhs ) const
{
return message = = rhs . message ;
}
2021-10-29 21:25:12 +01:00
bool CannotCallNonFunction : : operator = = ( const CannotCallNonFunction & rhs ) const
{
return ty = = rhs . ty ;
}
bool ExtraInformation : : operator = = ( const ExtraInformation & rhs ) const
{
return message = = rhs . message ;
}
bool DeprecatedApiUsed : : operator = = ( const DeprecatedApiUsed & rhs ) const
{
return symbol = = rhs . symbol & & useInstead = = rhs . useInstead ;
}
bool FunctionExitsWithoutReturning : : operator = = ( const FunctionExitsWithoutReturning & rhs ) const
{
return expectedReturnType = = rhs . expectedReturnType ;
}
int TypeError : : code ( ) const
{
2022-12-02 10:46:05 +00:00
return minCode ( ) + int ( data . index ( ) ) ;
}
int TypeError : : minCode ( )
{
return 1000 ;
}
TypeErrorSummary TypeError : : summary ( ) const
{
return TypeErrorSummary { location , moduleName , code ( ) } ;
2021-10-29 21:25:12 +01:00
}
bool TypeError : : operator = = ( const TypeError & rhs ) const
{
return location = = rhs . location & & data = = rhs . data ;
}
bool ModuleHasCyclicDependency : : operator = = ( const ModuleHasCyclicDependency & rhs ) const
{
return cycle . size ( ) = = rhs . cycle . size ( ) & & std : : equal ( cycle . begin ( ) , cycle . end ( ) , rhs . cycle . begin ( ) ) ;
}
bool IllegalRequire : : operator = = ( const IllegalRequire & rhs ) const
{
return moduleName = = rhs . moduleName & & reason = = rhs . reason ;
}
bool MissingProperties : : operator = = ( const MissingProperties & rhs ) const
{
return * superType = = * rhs . superType & & * subType = = * rhs . subType & & properties . size ( ) = = rhs . properties . size ( ) & &
std : : equal ( properties . begin ( ) , properties . end ( ) , rhs . properties . begin ( ) ) & & context = = rhs . context ;
}
bool DuplicateGenericParameter : : operator = = ( const DuplicateGenericParameter & rhs ) const
{
return parameterName = = rhs . parameterName ;
}
bool CannotInferBinaryOperation : : operator = = ( const CannotInferBinaryOperation & rhs ) const
{
return op = = rhs . op & & suggestedToAnnotate = = rhs . suggestedToAnnotate & & kind = = rhs . kind ;
}
bool SwappedGenericTypeParameter : : operator = = ( const SwappedGenericTypeParameter & rhs ) const
{
return name = = rhs . name & & kind = = rhs . kind ;
}
bool OptionalValueAccess : : operator = = ( const OptionalValueAccess & rhs ) const
{
return * optional = = * rhs . optional ;
}
bool MissingUnionProperty : : operator = = ( const MissingUnionProperty & rhs ) const
{
if ( missing . size ( ) ! = rhs . missing . size ( ) )
return false ;
for ( size_t i = 0 ; i < missing . size ( ) ; + + i )
{
if ( * missing [ i ] ! = * rhs . missing [ i ] )
return false ;
}
return * type = = * rhs . type & & key = = rhs . key ;
}
2021-12-10 21:17:10 +00:00
bool TypesAreUnrelated : : operator = = ( const TypesAreUnrelated & rhs ) const
{
return left = = rhs . left & & right = = rhs . right ;
}
2022-10-27 23:22:49 +01:00
bool TypePackMismatch : : operator = = ( const TypePackMismatch & rhs ) const
{
return * wantedTp = = * rhs . wantedTp & & * givenTp = = * rhs . givenTp ;
}
2022-12-02 10:46:05 +00:00
bool DynamicPropertyLookupOnClassesUnsafe : : operator = = ( const DynamicPropertyLookupOnClassesUnsafe & rhs ) const
{
return ty = = rhs . ty ;
}
2023-05-12 13:15:01 +01:00
bool UninhabitedTypeFamily : : operator = = ( const UninhabitedTypeFamily & rhs ) const
{
return ty = = rhs . ty ;
}
bool UninhabitedTypePackFamily : : operator = = ( const UninhabitedTypePackFamily & rhs ) const
{
return tp = = rhs . tp ;
}
2023-05-25 21:46:51 +01:00
bool WhereClauseNeeded : : operator = = ( const WhereClauseNeeded & rhs ) const
{
return ty = = rhs . ty ;
}
bool PackWhereClauseNeeded : : operator = = ( const PackWhereClauseNeeded & rhs ) const
{
return tp = = rhs . tp ;
}
2021-10-29 21:25:12 +01:00
std : : string toString ( const TypeError & error )
{
2022-06-24 02:44:07 +01:00
return toString ( error , TypeErrorToStringOptions { } ) ;
}
std : : string toString ( const TypeError & error , TypeErrorToStringOptions options )
{
ErrorConverter converter { options . fileResolver } ;
2021-10-29 21:25:12 +01:00
return Luau : : visit ( converter , error . data ) ;
}
bool containsParseErrorName ( const TypeError & error )
{
return Luau : : visit ( InvalidNameChecker { } , error . data ) ;
}
2021-11-12 02:12:39 +00:00
template < typename T >
2022-04-14 22:57:15 +01:00
void copyError ( T & e , TypeArena & destArena , CloneState cloneState )
2021-10-29 21:25:12 +01:00
{
auto clone = [ & ] ( auto & & ty ) {
2022-04-14 22:57:15 +01:00
return : : Luau : : clone ( ty , destArena , cloneState ) ;
2021-10-29 21:25:12 +01:00
} ;
auto visitErrorData = [ & ] ( auto & & e ) {
2022-04-14 22:57:15 +01:00
copyError ( e , destArena , cloneState ) ;
2021-11-12 02:12:39 +00:00
} ;
2021-10-29 21:25:12 +01:00
2021-11-12 02:12:39 +00:00
if constexpr ( false )
{
}
else if constexpr ( std : : is_same_v < T , TypeMismatch > )
{
e . wantedType = clone ( e . wantedType ) ;
e . givenType = clone ( e . givenType ) ;
2021-10-29 21:25:12 +01:00
2021-11-12 02:12:39 +00:00
if ( e . error )
visit ( visitErrorData , e . error - > data ) ;
}
else if constexpr ( std : : is_same_v < T , UnknownSymbol > )
{
}
else if constexpr ( std : : is_same_v < T , UnknownProperty > )
{
e . table = clone ( e . table ) ;
}
else if constexpr ( std : : is_same_v < T , NotATable > )
{
e . ty = clone ( e . ty ) ;
}
else if constexpr ( std : : is_same_v < T , CannotExtendTable > )
{
e . tableType = clone ( e . tableType ) ;
}
else if constexpr ( std : : is_same_v < T , OnlyTablesCanHaveMethods > )
{
e . tableType = clone ( e . tableType ) ;
}
else if constexpr ( std : : is_same_v < T , DuplicateTypeDefinition > )
{
}
else if constexpr ( std : : is_same_v < T , CountMismatch > )
{
}
else if constexpr ( std : : is_same_v < T , FunctionDoesNotTakeSelf > )
{
}
else if constexpr ( std : : is_same_v < T , FunctionRequiresSelf > )
{
}
else if constexpr ( std : : is_same_v < T , OccursCheckFailed > )
{
}
else if constexpr ( std : : is_same_v < T , UnknownRequire > )
{
}
else if constexpr ( std : : is_same_v < T , IncorrectGenericParameterCount > )
{
e . typeFun = clone ( e . typeFun ) ;
}
else if constexpr ( std : : is_same_v < T , SyntaxError > )
{
}
else if constexpr ( std : : is_same_v < T , CodeTooComplex > )
{
}
else if constexpr ( std : : is_same_v < T , UnificationTooComplex > )
{
}
else if constexpr ( std : : is_same_v < T , UnknownPropButFoundLikeProp > )
{
e . table = clone ( e . table ) ;
}
else if constexpr ( std : : is_same_v < T , GenericError > )
{
}
2022-06-24 02:44:07 +01:00
else if constexpr ( std : : is_same_v < T , InternalError > )
{
}
2021-11-12 02:12:39 +00:00
else if constexpr ( std : : is_same_v < T , CannotCallNonFunction > )
{
e . ty = clone ( e . ty ) ;
}
else if constexpr ( std : : is_same_v < T , ExtraInformation > )
{
}
else if constexpr ( std : : is_same_v < T , DeprecatedApiUsed > )
{
}
else if constexpr ( std : : is_same_v < T , ModuleHasCyclicDependency > )
{
}
else if constexpr ( std : : is_same_v < T , IllegalRequire > )
{
}
else if constexpr ( std : : is_same_v < T , FunctionExitsWithoutReturning > )
{
e . expectedReturnType = clone ( e . expectedReturnType ) ;
}
else if constexpr ( std : : is_same_v < T , DuplicateGenericParameter > )
{
}
else if constexpr ( std : : is_same_v < T , CannotInferBinaryOperation > )
{
}
else if constexpr ( std : : is_same_v < T , MissingProperties > )
{
e . superType = clone ( e . superType ) ;
e . subType = clone ( e . subType ) ;
}
else if constexpr ( std : : is_same_v < T , SwappedGenericTypeParameter > )
{
}
else if constexpr ( std : : is_same_v < T , OptionalValueAccess > )
{
e . optional = clone ( e . optional ) ;
}
else if constexpr ( std : : is_same_v < T , MissingUnionProperty > )
{
e . type = clone ( e . type ) ;
for ( auto & ty : e . missing )
ty = clone ( ty ) ;
}
2021-12-10 21:17:10 +00:00
else if constexpr ( std : : is_same_v < T , TypesAreUnrelated > )
{
e . left = clone ( e . left ) ;
e . right = clone ( e . right ) ;
}
2022-04-14 22:57:15 +01:00
else if constexpr ( std : : is_same_v < T , NormalizationTooComplex > )
{
}
2022-10-27 23:22:49 +01:00
else if constexpr ( std : : is_same_v < T , TypePackMismatch > )
{
e . wantedTp = clone ( e . wantedTp ) ;
e . givenTp = clone ( e . givenTp ) ;
}
2022-12-02 10:46:05 +00:00
else if constexpr ( std : : is_same_v < T , DynamicPropertyLookupOnClassesUnsafe > )
e . ty = clone ( e . ty ) ;
2023-05-12 13:15:01 +01:00
else if constexpr ( std : : is_same_v < T , UninhabitedTypeFamily > )
e . ty = clone ( e . ty ) ;
else if constexpr ( std : : is_same_v < T , UninhabitedTypePackFamily > )
e . tp = clone ( e . tp ) ;
2023-05-25 21:46:51 +01:00
else if constexpr ( std : : is_same_v < T , WhereClauseNeeded > )
e . ty = clone ( e . ty ) ;
else if constexpr ( std : : is_same_v < T , PackWhereClauseNeeded > )
e . tp = clone ( e . tp ) ;
2021-11-12 02:12:39 +00:00
else
static_assert ( always_false_v < T > , " Non-exhaustive type switch " ) ;
}
void copyErrors ( ErrorVec & errors , TypeArena & destArena )
{
2021-12-02 23:20:08 +00:00
CloneState cloneState ;
2021-11-12 02:12:39 +00:00
auto visitErrorData = [ & ] ( auto & & e ) {
2022-04-14 22:57:15 +01:00
copyError ( e , destArena , cloneState ) ;
2021-10-29 21:25:12 +01:00
} ;
2023-01-03 17:33:19 +00:00
LUAU_ASSERT ( ! destArena . types . isFrozen ( ) ) ;
2021-10-29 21:25:12 +01:00
LUAU_ASSERT ( ! destArena . typePacks . isFrozen ( ) ) ;
for ( TypeError & error : errors )
visit ( visitErrorData , error . data ) ;
}
2023-03-10 19:20:04 +00:00
void InternalErrorReporter : : ice ( const std : : string & message , const Location & location ) const
2021-10-29 21:25:12 +01:00
{
2022-10-13 23:59:53 +01:00
InternalCompilerError error ( message , moduleName , location ) ;
2021-10-29 21:25:12 +01:00
2022-10-13 23:59:53 +01:00
if ( onInternalError )
onInternalError ( error . what ( ) ) ;
2021-10-29 21:25:12 +01:00
2022-10-13 23:59:53 +01:00
throw error ;
2021-10-29 21:25:12 +01:00
}
2023-03-10 19:20:04 +00:00
void InternalErrorReporter : : ice ( const std : : string & message ) const
2021-10-29 21:25:12 +01:00
{
2022-10-13 23:59:53 +01:00
InternalCompilerError error ( message , moduleName ) ;
2021-10-29 21:25:12 +01:00
2022-10-13 23:59:53 +01:00
if ( onInternalError )
onInternalError ( error . what ( ) ) ;
2021-10-29 21:25:12 +01:00
2022-10-13 23:59:53 +01:00
throw error ;
2022-06-24 02:44:07 +01:00
}
const char * InternalCompilerError : : what ( ) const throw ( )
{
return this - > message . data ( ) ;
2021-10-29 21:25:12 +01:00
}
} // namespace Luau