Skip to content

Commit

Permalink
Sync to upstream/release/511 (#324)
Browse files Browse the repository at this point in the history
- TableOperations lint now includes a warning for table.create(N, {}) (which is likely a mistake since the table is shared by all entries)
- Type checker now type checks #v when v is a union
- Parser now rejects sources that consists of a single unfinished long comment
- Work around significant MSVC 2022 performance regression, bringing it more or less in line with MSVC 2019
- Compiler now predicts array size for newly allocated tables when the table is filled in a short loop
- Small improvements in compilation throughput (~2% faster)
- Implement paged sweeper for GC which improves sweep throughput 2-3x and reduces memory consumption by 8 bytes per object (once it is stabilized we will see additional 8 bytes per object of savings)
- Improve Repl Tab completion
- Repl now supports -i (interactive mode to run code in context of a script's environment) and -On (to control optimization flags)
  • Loading branch information
zeux authored Jan 21, 2022
1 parent 478a3da commit 8fe95c9
Show file tree
Hide file tree
Showing 36 changed files with 1,274 additions and 215 deletions.
4 changes: 4 additions & 0 deletions Analysis/include/Luau/TypeVar.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once

#include "Luau/DenseHash.h"
#include "Luau/Predicate.h"
#include "Luau/Unifiable.h"
#include "Luau/Variant.h"
Expand Down Expand Up @@ -499,6 +500,9 @@ bool maybeGeneric(const TypeId ty);
// Checks if a type is of the form T1|...|Tn where one of the Ti is a singleton
bool maybeSingleton(TypeId ty);

// Checks if the length operator can be applied on the value of type
bool hasLength(TypeId ty, DenseHashSet<TypeId>& seen, int* recursionCount);

struct SingletonTypes
{
const TypeId nilType;
Expand Down
15 changes: 15 additions & 0 deletions Analysis/src/Linter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <math.h>
#include <limits.h>

LUAU_FASTFLAGVARIABLE(LuauLintTableCreateTable, false)

namespace Luau
{

Expand Down Expand Up @@ -2153,6 +2155,19 @@ class LintTableOperations : AstVisitor
"table.move uses index 0 but arrays are 1-based; did you mean 1 instead?");
}

if (FFlag::LuauLintTableCreateTable && func->index == "create" && node->args.size == 2)
{
// table.create(n, {...})
if (args[1]->is<AstExprTable>())
emitWarning(*context, LintWarning::Code_TableOperations, args[1]->location,
"table.create with a table literal will reuse the same object for all elements; consider using a for loop instead");

// table.create(n, {...} :: ?)
if (AstExprTypeAssertion* as = args[1]->as<AstExprTypeAssertion>(); as && as->expr->is<AstExprTable>())
emitWarning(*context, LintWarning::Code_TableOperations, as->expr->location,
"table.create with a table literal will reuse the same object for all elements; consider using a for loop instead");
}

return true;
}

Expand Down
27 changes: 19 additions & 8 deletions Analysis/src/TypeInfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ LUAU_FASTFLAGVARIABLE(DebugLuauFreezeDuringUnification, false)
LUAU_FASTFLAGVARIABLE(LuauRecursiveTypeParameterRestriction, false)
LUAU_FASTFLAGVARIABLE(LuauIfElseBranchTypeUnion, false)
LUAU_FASTFLAGVARIABLE(LuauIfElseExpectedType2, false)
LUAU_FASTFLAGVARIABLE(LuauLengthOnCompositeType, false)
LUAU_FASTFLAGVARIABLE(LuauQuantifyInPlace2, false)
LUAU_FASTFLAGVARIABLE(LuauSealExports, false)
LUAU_FASTFLAGVARIABLE(LuauSingletonTypes, false)
Expand Down Expand Up @@ -2066,17 +2067,27 @@ ExprResult<TypeId> TypeChecker::checkExpr(const ScopePtr& scope, const AstExprUn
if (get<ErrorTypeVar>(operandType))
return {errorRecoveryType(scope)};

if (get<AnyTypeVar>(operandType))
return {numberType}; // Not strictly correct: metatables permit overriding this

if (auto p = get<PrimitiveTypeVar>(operandType))
if (FFlag::LuauLengthOnCompositeType)
{
if (p->type == PrimitiveTypeVar::String)
return {numberType};
DenseHashSet<TypeId> seen{nullptr};

if (!hasLength(operandType, seen, &recursionCount))
reportError(TypeError{expr.location, NotATable{operandType}});
}
else
{
if (get<AnyTypeVar>(operandType))
return {numberType}; // Not strictly correct: metatables permit overriding this

if (!getTableType(operandType))
reportError(TypeError{expr.location, NotATable{operandType}});
if (auto p = get<PrimitiveTypeVar>(operandType))
{
if (p->type == PrimitiveTypeVar::String)
return {numberType};
}

if (!getTableType(operandType))
reportError(TypeError{expr.location, NotATable{operandType}});
}

return {numberType};

Expand Down
46 changes: 46 additions & 0 deletions Analysis/src/TypeVar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Luau/Common.h"
#include "Luau/DenseHash.h"
#include "Luau/Error.h"
#include "Luau/RecursionCounter.h"
#include "Luau/StringUtils.h"
#include "Luau/ToString.h"
#include "Luau/TypeInfer.h"
Expand All @@ -19,6 +20,8 @@

LUAU_FASTINTVARIABLE(LuauTypeMaximumStringifierLength, 500)
LUAU_FASTINTVARIABLE(LuauTableTypeMaximumStringifierLength, 0)
LUAU_FASTINT(LuauTypeInferRecursionLimit)
LUAU_FASTFLAG(LuauLengthOnCompositeType)
LUAU_FASTFLAGVARIABLE(LuauMetatableAreEqualRecursion, false)
LUAU_FASTFLAGVARIABLE(LuauRefactorTagging, false)
LUAU_FASTFLAG(LuauErrorRecoveryType)
Expand Down Expand Up @@ -326,6 +329,49 @@ bool maybeSingleton(TypeId ty)
return false;
}

bool hasLength(TypeId ty, DenseHashSet<TypeId>& seen, int* recursionCount)
{
LUAU_ASSERT(FFlag::LuauLengthOnCompositeType);

RecursionLimiter _rl(recursionCount, FInt::LuauTypeInferRecursionLimit);

ty = follow(ty);

if (seen.contains(ty))
return true;

if (isPrim(ty, PrimitiveTypeVar::String) || get<AnyTypeVar>(ty) || get<TableTypeVar>(ty) || get<MetatableTypeVar>(ty))
return true;

if (auto uty = get<UnionTypeVar>(ty))
{
seen.insert(ty);

for (TypeId part : uty->options)
{
if (!hasLength(part, seen, recursionCount))
return false;
}

return true;
}

if (auto ity = get<IntersectionTypeVar>(ty))
{
seen.insert(ty);

for (TypeId part : ity->parts)
{
if (hasLength(part, seen, recursionCount))
return true;
}

return false;
}

return false;
}

FunctionTypeVar::FunctionTypeVar(TypePackId argTypes, TypePackId retType, std::optional<FunctionDefinition> defn, bool hasSelf)
: argTypes(argTypes)
, retType(retType)
Expand Down
6 changes: 6 additions & 0 deletions Analysis/src/Unifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

LUAU_FASTINT(LuauTypeInferRecursionLimit);
LUAU_FASTINT(LuauTypeInferTypePackLoopLimit);
LUAU_FASTFLAGVARIABLE(LuauCommittingTxnLogFreeTpPromote, false)
LUAU_FASTFLAG(LuauUseCommittingTxnLog)
LUAU_FASTINTVARIABLE(LuauTypeInferIterationLimit, 2000);
LUAU_FASTFLAGVARIABLE(LuauTableSubtypingVariance2, false);
Expand Down Expand Up @@ -99,6 +100,11 @@ struct PromoteTypeLevels

bool operator()(TypePackId tp, const FreeTypePack&)
{
// Surprise, it's actually a BoundTypePack that hasn't been committed yet.
// Calling getMutable on this will trigger an assertion.
if (FFlag::LuauCommittingTxnLogFreeTpPromote && FFlag::LuauUseCommittingTxnLog && !log.is<FreeTypePack>(tp))
return true;

promote(tp, FFlag::LuauUseCommittingTxnLog ? log.getMutable<FreeTypePack>(tp) : getMutable<FreeTypePack>(tp));
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion Ast/include/Luau/Ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -1265,7 +1265,8 @@ struct hash<Luau::AstName>
size_t operator()(const Luau::AstName& value) const
{
// note: since operator== uses pointer identity, hashing function uses it as well
return value.value ? std::hash<const void*>()(value.value) : 0;
// the hasher is the same as DenseHashPointer (DenseHash.h)
return (uintptr_t(value.value) >> 4) ^ (uintptr_t(value.value) >> 9);
}
};

Expand Down
8 changes: 4 additions & 4 deletions Ast/include/Luau/DenseHash.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
namespace Luau
{

// Internal implementation of DenseHashSet and DenseHashMap
namespace detail
{

struct DenseHashPointer
{
size_t operator()(const void* key) const
Expand All @@ -24,6 +20,10 @@ struct DenseHashPointer
}
};

// Internal implementation of DenseHashSet and DenseHashMap
namespace detail
{

template<typename T>
using DenseHashDefault = std::conditional_t<std::is_pointer_v<T>, DenseHashPointer, std::hash<T>>;

Expand Down
20 changes: 17 additions & 3 deletions Ast/src/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ LUAU_FASTFLAGVARIABLE(LuauFixAmbiguousErrorRecoveryInAssign, false)
LUAU_FASTFLAGVARIABLE(LuauParseSingletonTypes, false)
LUAU_FASTFLAGVARIABLE(LuauParseTypeAliasDefaults, false)
LUAU_FASTFLAGVARIABLE(LuauParseRecoverTypePackEllipsis, false)
LUAU_FASTFLAGVARIABLE(LuauStartingBrokenComment, false)

namespace Luau
{
Expand Down Expand Up @@ -174,10 +175,23 @@ ParseResult Parser::parse(const char* buffer, size_t bufferSize, AstNameTable& n
const Lexeme::Type type = p.lexer.current().type;
const Location loc = p.lexer.current().location;

p.lexer.next();
if (FFlag::LuauStartingBrokenComment)
{
if (options.captureComments)
p.commentLocations.push_back(Comment{type, loc});

if (type == Lexeme::BrokenComment)
break;

if (options.captureComments)
p.commentLocations.push_back(Comment{type, loc});
p.lexer.next();
}
else
{
p.lexer.next();

if (options.captureComments)
p.commentLocations.push_back(Comment{type, loc});
}
}

p.lexer.setSkipComments(true);
Expand Down
Loading

0 comments on commit 8fe95c9

Please sign in to comment.