Skip to content

Commit

Permalink
Sync to upstream/release/615 (#1175)
Browse files Browse the repository at this point in the history
# What's changed?

* Luau allocation scheme was changed to handle allocations in 513-1024
byte range internally without falling back to global allocator
* coroutine/thread creation no longer requires any global allocations,
making it up to 15% faster (vs libc malloc)
* table construction for 17-32 keys or 33-64 array elements is up to 30%
faster (vs libc malloc)

### New Type Solver

* Cyclic unary negation type families are reduced to `number` when
possible
* Class types are skipped when searching for free types in unifier to
improve performance
* Fixed issues with table type inference when metatables are present
* Improved inference of iteration loop types
* Fixed an issue with bidirectional inference of method calls
* Type simplification will now preserve error suppression markers

### Native Code Generation

* Fixed TAG_VECTOR skip optimization to not break instruction use counts
(broken optimization wasn't included in 614)
* Fixed missing side-effect when optimizing generic loop preparation
instruction

---

### Internal Contributors

Co-authored-by: Aaron Weiss <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Lily Brown <[email protected]>
Co-authored-by: Vyacheslav Egorov <[email protected]>

---------

Co-authored-by: Aaron Weiss <[email protected]>
Co-authored-by: Alexander McCord <[email protected]>
Co-authored-by: Andy Friesen <[email protected]>
Co-authored-by: Vighnesh <[email protected]>
Co-authored-by: Aviral Goel <[email protected]>
Co-authored-by: David Cope <[email protected]>
Co-authored-by: Lily Brown <[email protected]>
  • Loading branch information
8 people authored Mar 1, 2024
1 parent cc51e61 commit 443903a
Show file tree
Hide file tree
Showing 46 changed files with 2,448 additions and 405 deletions.
11 changes: 6 additions & 5 deletions Analysis/src/BuiltinDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,16 +764,17 @@ TypeId makeStringMetatable(NotNull<BuiltinTypes> builtinTypes)
const TypeId numberType = builtinTypes->numberType;
const TypeId booleanType = builtinTypes->booleanType;
const TypeId stringType = builtinTypes->stringType;
const TypeId anyType = builtinTypes->anyType;

const TypeId optionalNumber = arena->addType(UnionType{{nilType, numberType}});
const TypeId optionalString = arena->addType(UnionType{{nilType, stringType}});
const TypeId optionalBoolean = arena->addType(UnionType{{nilType, booleanType}});

const TypePackId oneStringPack = arena->addTypePack({stringType});
const TypePackId anyTypePack = arena->addTypePack(TypePackVar{VariadicTypePack{anyType}, true});
const TypePackId anyTypePack = builtinTypes->anyTypePack;

FunctionType formatFTV{arena->addTypePack(TypePack{{stringType}, anyTypePack}), oneStringPack};
const TypePackId variadicTailPack = FFlag::DebugLuauDeferredConstraintResolution ? builtinTypes->unknownTypePack : anyTypePack;

FunctionType formatFTV{arena->addTypePack(TypePack{{stringType}, variadicTailPack}), oneStringPack};
formatFTV.magicFunction = &magicFunctionFormat;
const TypeId formatFn = arena->addType(formatFTV);
attachDcrMagicFunction(formatFn, dcrMagicFunctionFormat);
Expand Down Expand Up @@ -820,13 +821,13 @@ TypeId makeStringMetatable(NotNull<BuiltinTypes> builtinTypes)
{"split", {makeFunction(*arena, stringType, {}, {}, {optionalString}, {},
{arena->addType(TableType{{}, TableIndexer{numberType, stringType}, TypeLevel{}, TableState::Sealed})})}},
{"pack", {arena->addType(FunctionType{
arena->addTypePack(TypePack{{stringType}, anyTypePack}),
arena->addTypePack(TypePack{{stringType}, variadicTailPack}),
oneStringPack,
})}},
{"packsize", {makeFunction(*arena, stringType, {}, {}, {}, {}, {numberType})}},
{"unpack", {arena->addType(FunctionType{
arena->addTypePack(TypePack{{stringType, stringType, optionalNumber}}),
anyTypePack,
variadicTailPack,
})}},
};

Expand Down
8 changes: 2 additions & 6 deletions Analysis/src/ConstraintGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2270,10 +2270,6 @@ std::tuple<TypeId, TypeId, RefinementId> ConstraintGenerator::checkBinary(
if (!key)
return {leftType, rightType, nullptr};

auto augmentForErrorSupression = [&](TypeId ty) -> TypeId {
return arena->addType(UnionType{{ty, builtinTypes->errorType}});
};

TypeId discriminantTy = builtinTypes->neverType;
if (typeguard->type == "nil")
discriminantTy = builtinTypes->nilType;
Expand All @@ -2288,9 +2284,9 @@ std::tuple<TypeId, TypeId, RefinementId> ConstraintGenerator::checkBinary(
else if (typeguard->type == "buffer")
discriminantTy = builtinTypes->bufferType;
else if (typeguard->type == "table")
discriminantTy = augmentForErrorSupression(builtinTypes->tableType);
discriminantTy = builtinTypes->tableType;
else if (typeguard->type == "function")
discriminantTy = augmentForErrorSupression(builtinTypes->functionType);
discriminantTy = builtinTypes->functionType;
else if (typeguard->type == "userdata")
{
// For now, we don't really care about being accurate with userdata if the typeguard was using typeof.
Expand Down
96 changes: 41 additions & 55 deletions Analysis/src/ConstraintSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,11 @@ struct FreeTypeSearcher : TypeOnceVisitor
result->push_back({ty, location});
return false;
}

bool visit(TypeId, const ClassType&) override
{
return false;
}
};

} // namespace
Expand Down Expand Up @@ -672,13 +677,13 @@ bool ConstraintSolver::tryDispatch(const IterableConstraint& c, NotNull<const Co
return false;
};

auto [iteratorTypes, iteratorTail] = flatten(c.iterator);
if (iteratorTail && isBlocked(*iteratorTail))
return block_(*iteratorTail);
TypePack iterator = extendTypePack(*arena, builtinTypes, c.iterator, 3);
if (iterator.head.size() < 3 && iterator.tail && isBlocked(*iterator.tail))
return block_(*iterator.tail);

{
bool blocked = false;
for (TypeId t : iteratorTypes)
for (TypeId t : iterator.head)
{
if (isBlocked(t))
{
Expand All @@ -691,35 +696,32 @@ bool ConstraintSolver::tryDispatch(const IterableConstraint& c, NotNull<const Co
return false;
}

if (0 == iteratorTypes.size())
if (0 == iterator.head.size())
{
Anyification anyify{arena, constraint->scope, builtinTypes, &iceReporter, errorRecoveryType(), errorRecoveryTypePack()};
std::optional<TypePackId> anyified = anyify.substitute(c.variables);
LUAU_ASSERT(anyified);
unify(constraint, *anyified, c.variables);
unify(constraint, builtinTypes->anyTypePack, c.variables);

return true;
}

TypeId nextTy = follow(iteratorTypes[0]);
TypeId nextTy = follow(iterator.head[0]);
if (get<FreeType>(nextTy))
return block_(nextTy);

if (get<FunctionType>(nextTy))
{
TypeId tableTy = builtinTypes->nilType;
if (iteratorTypes.size() >= 2)
tableTy = iteratorTypes[1];
if (iterator.head.size() >= 2)
tableTy = iterator.head[1];

TypeId firstIndexTy = builtinTypes->nilType;
if (iteratorTypes.size() >= 3)
firstIndexTy = iteratorTypes[2];
if (iterator.head.size() >= 3)
firstIndexTy = iterator.head[2];

return tryDispatchIterableFunction(nextTy, tableTy, firstIndexTy, c, constraint, force);
}

else
return tryDispatchIterableTable(iteratorTypes[0], c, constraint, force);
return tryDispatchIterableTable(iterator.head[0], c, constraint, force);

return true;
}
Expand Down Expand Up @@ -1174,10 +1176,14 @@ bool ConstraintSolver::tryDispatch(const FunctionCheckConstraint& c, NotNull<con
const std::vector<TypeId> expectedArgs = flatten(ftv->argTypes).first;
const std::vector<TypeId> argPackHead = flatten(argsPack).first;

for (size_t i = 0; i < c.callSite->args.size && i < expectedArgs.size() && i < argPackHead.size(); ++i)
// If this is a self call, the types will have more elements than the AST call.
// We don't attempt to perform bidirectional inference on the self type.
const size_t typeOffset = c.callSite->self ? 1 : 0;

for (size_t i = 0; i < c.callSite->args.size && i + typeOffset < expectedArgs.size() && i + typeOffset < argPackHead.size(); ++i)
{
const TypeId expectedArgTy = follow(expectedArgs[i]);
const TypeId actualArgTy = follow(argPackHead[i]);
const TypeId expectedArgTy = follow(expectedArgs[i + typeOffset]);
const TypeId actualArgTy = follow(argPackHead[i + typeOffset]);
const AstExpr* expr = c.callSite->args.data[i];

(*c.astExpectedTypes)[expr] = expectedArgTy;
Expand Down Expand Up @@ -1375,7 +1381,7 @@ bool ConstraintSolver::tryDispatch(const SetPropConstraint& c, NotNull<const Con
}

auto bind = [&](TypeId a, TypeId b) {
bindBlockedType(a, b, c.subjectType, constraint->location);
bindBlockedType(a, b, subjectType, constraint->location);
};

if (existingPropType)
Expand All @@ -1387,6 +1393,8 @@ bool ConstraintSolver::tryDispatch(const SetPropConstraint& c, NotNull<const Con
return true;
}

const TypeId originalSubjectType = subjectType;

if (auto mt = get<MetatableType>(subjectType))
subjectType = follow(mt->table);

Expand Down Expand Up @@ -1419,7 +1427,7 @@ bool ConstraintSolver::tryDispatch(const SetPropConstraint& c, NotNull<const Con
}
}

bind(c.resultType, subjectType);
bind(c.resultType, originalSubjectType);
unblock(c.resultType, constraint->location);
return true;
}
Expand Down Expand Up @@ -1802,21 +1810,15 @@ bool ConstraintSolver::tryDispatchIterableTable(TypeId iteratorTy, const Iterabl
}

TypeId nextFn = iterRets.head[0];
TypeId table = iterRets.head.size() == 2 ? iterRets.head[1] : freshType(arena, builtinTypes, constraint->scope);

if (std::optional<TypeId> instantiatedNextFn = instantiate(builtinTypes, arena, NotNull{&limits}, constraint->scope, nextFn))
{
const TypeId firstIndex = freshType(arena, builtinTypes, constraint->scope);

// nextTy : (iteratorTy, indexTy?) -> (indexTy, valueTailTy...)
const TypePackId nextArgPack = arena->addTypePack({table, arena->addType(UnionType{{firstIndex, builtinTypes->nilType}})});
const TypePackId valueTailTy = arena->addTypePack(FreeTypePack{constraint->scope});
const TypePackId nextRetPack = arena->addTypePack(TypePack{{firstIndex}, valueTailTy});

const TypeId expectedNextTy = arena->addType(FunctionType{nextArgPack, nextRetPack});
unify(constraint, *instantiatedNextFn, expectedNextTy);
const FunctionType* nextFn = get<FunctionType>(*instantiatedNextFn);
LUAU_ASSERT(nextFn);
const TypePackId nextRetPack = nextFn->retTypes;

pushConstraint(constraint->scope, constraint->location, UnpackConstraint{c.variables, nextRetPack});
return true;
}
else
{
Expand Down Expand Up @@ -1864,31 +1866,13 @@ bool ConstraintSolver::tryDispatchIterableFunction(
return false;
}

TypeId firstIndex;
TypeId retIndex;
if (isNil(firstIndexTy) || isOptional(firstIndexTy))
{
// FIXME freshType is suspect here
firstIndex = arena->addType(UnionType{{freshType(arena, builtinTypes, constraint->scope), builtinTypes->nilType}});
retIndex = firstIndex;
}
else
{
firstIndex = firstIndexTy;
retIndex = arena->addType(UnionType{{firstIndexTy, builtinTypes->nilType}});
}

// nextTy : (tableTy, indexTy?) -> (indexTy?, valueTailTy...)
const TypePackId nextArgPack = arena->addTypePack({tableTy, firstIndex});
const TypePackId valueTailTy = arena->addTypePack(FreeTypePack{constraint->scope});
const TypePackId nextRetPack = arena->addTypePack(TypePack{{retIndex}, valueTailTy});
const FunctionType* nextFn = get<FunctionType>(nextTy);
// If this does not hold, we should've never called `tryDispatchIterableFunction` in the first place.
LUAU_ASSERT(nextFn);
const TypePackId nextRetPack = nextFn->retTypes;

const TypeId expectedNextTy = arena->addType(FunctionType{TypeLevel{}, constraint->scope, nextArgPack, nextRetPack});
bool ok = unify(constraint, nextTy, expectedNextTy);

// if there are no errors from unifying the two, we can pass forward the expected type as our selected resolution.
if (ok)
(*c.astForInNextTypes)[c.nextAstFragment] = expectedNextTy;
// the type of the `nextAstFragment` is the `nextTy`.
(*c.astForInNextTypes)[c.nextAstFragment] = nextTy;

auto it = begin(nextRetPack);
std::vector<TypeId> modifiedNextRetHead;
Expand Down Expand Up @@ -1988,7 +1972,7 @@ std::pair<std::vector<TypeId>, std::optional<TypeId>> ConstraintSolver::lookupTa
return {{}, result};
}
}
else if (auto mt = get<MetatableType>(subjectType))
else if (auto mt = get<MetatableType>(subjectType); mt && context == ValueContext::RValue)
{
auto [blocked, result] = lookupTableProp(mt->table, propName, context, suppressSimplification, seen);
if (!blocked.empty() || result)
Expand Down Expand Up @@ -2023,6 +2007,8 @@ std::pair<std::vector<TypeId>, std::optional<TypeId>> ConstraintSolver::lookupTa
else
return lookupTableProp(indexType, propName, context, suppressSimplification, seen);
}
else if (get<MetatableType>(mtt))
return lookupTableProp(mtt, propName, context, suppressSimplification, seen);
}
else if (auto ct = get<ClassType>(subjectType))
{
Expand Down
8 changes: 5 additions & 3 deletions Analysis/src/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,8 @@ ModulePtr check(const SourceModule& sourceModule, Mode mode, const std::vector<R
result->name = sourceModule.name;
result->humanReadableName = sourceModule.humanReadableName;

result->mode = sourceModule.mode.value_or(Mode::NoCheck);

result->internalTypes.owningModule = result.get();
result->interfaceTypes.owningModule = result.get();

Expand Down Expand Up @@ -1199,7 +1201,7 @@ ModulePtr check(const SourceModule& sourceModule, Mode mode, const std::vector<R
cg.visitModuleRoot(sourceModule.root);
result->errors = std::move(cg.errors);

ConstraintSolver cs{NotNull{&normalizer}, NotNull(cg.rootScope), borrowConstraints(cg.constraints), result->humanReadableName, moduleResolver,
ConstraintSolver cs{NotNull{&normalizer}, NotNull(cg.rootScope), borrowConstraints(cg.constraints), result->name, moduleResolver,
requireCycles, logger.get(), limits};

if (options.randomizeConstraintResolutionSeed)
Expand Down Expand Up @@ -1294,8 +1296,8 @@ ModulePtr Frontend::check(const SourceModule& sourceModule, Mode mode, std::vect
catch (const InternalCompilerError& err)
{
InternalCompilerError augmented = err.location.has_value()
? InternalCompilerError{err.message, sourceModule.humanReadableName, *err.location}
: InternalCompilerError{err.message, sourceModule.humanReadableName};
? InternalCompilerError{err.message, sourceModule.name, *err.location}
: InternalCompilerError{err.message, sourceModule.name};
throw augmented;
}
}
Expand Down
2 changes: 2 additions & 0 deletions Analysis/src/OverloadResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ std::pair<OverloadResolver::Analysis, ErrorVec> OverloadResolver::checkOverload_
*/

Location argLocation;
if (reason.superPath.components.size() <= 1)
break;

if (const Luau::TypePath::Index* pathIndexComponent = get_if<Luau::TypePath::Index>(&reason.superPath.components.at(1)))
{
Expand Down
24 changes: 21 additions & 3 deletions Analysis/src/Simplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1033,9 +1033,17 @@ TypeId TypeSimplifier::intersectIntersectionWithType(TypeId left, TypeId right)

std::optional<TypeId> TypeSimplifier::basicIntersect(TypeId left, TypeId right)
{
if (get<AnyType>(left))
if (get<AnyType>(left) && get<ErrorType>(right))
return right;
if (get<AnyType>(right) && get<ErrorType>(left))
return left;
if (get<AnyType>(left))
return arena->addType(UnionType{{right, builtinTypes->errorType}});
if (get<AnyType>(right))
return arena->addType(UnionType{{left, builtinTypes->errorType}});
if (get<UnknownType>(left))
return right;
if (get<UnknownType>(right))
return left;
if (get<NeverType>(left))
return left;
Expand Down Expand Up @@ -1120,9 +1128,17 @@ TypeId TypeSimplifier::intersect(TypeId left, TypeId right)
left = simplify(left);
right = simplify(right);

if (get<AnyType>(left))
if (get<AnyType>(left) && get<ErrorType>(right))
return right;
if (get<AnyType>(right) && get<ErrorType>(left))
return left;
if (get<AnyType>(left))
return arena->addType(UnionType{{right, builtinTypes->errorType}});
if (get<AnyType>(right))
return arena->addType(UnionType{{left, builtinTypes->errorType}});
if (get<UnknownType>(left))
return right;
if (get<UnknownType>(right))
return left;
if (get<NeverType>(left))
return left;
Expand Down Expand Up @@ -1278,9 +1294,11 @@ TypeId TypeSimplifier::simplify(TypeId ty, DenseHashSet<TypeId>& seen)
{
TypeId negatedTy = follow(nt->ty);
if (get<AnyType>(negatedTy))
return arena->addType(UnionType{{builtinTypes->neverType, builtinTypes->errorType}});
else if (get<UnknownType>(negatedTy))
return builtinTypes->neverType;
else if (get<NeverType>(negatedTy))
return builtinTypes->anyType;
return builtinTypes->unknownType;
if (auto nnt = get<NegationType>(negatedTy))
return simplify(nnt->ty, seen);
}
Expand Down
2 changes: 1 addition & 1 deletion Analysis/src/Subtyping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ SubtypingResult Subtyping::isCovariantWith(SubtypingEnvironment& env, TypePackId

if (TypePackId* other = env.mappedGenericPacks.find(*superTail))
// TODO: TypePath can't express "slice of a pack + its tail".
results.push_back(isCovariantWith(env, *other, subTailPack).withSuperComponent(TypePath::PackField::Tail));
results.push_back(isContravariantWith(env, subTailPack, *other).withSuperComponent(TypePath::PackField::Tail));
else
env.mappedGenericPacks.try_insert(*superTail, subTailPack);

Expand Down
11 changes: 10 additions & 1 deletion Analysis/src/TypeChecker2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,16 @@ struct TypeChecker2
return;
else if (isOptional(fnTy))
{
reportError(OptionalValueAccess{fnTy}, call->func->location);
switch (shouldSuppressErrors(NotNull{&normalizer}, fnTy))
{
case ErrorSuppression::Suppress:
break;
case ErrorSuppression::NormalizationFailed:
reportError(NormalizationTooComplex{}, call->func->location);
// fallthrough intentional
case ErrorSuppression::DoNotSuppress:
reportError(OptionalValueAccess{fnTy}, call->func->location);
}
return;
}

Expand Down
Loading

0 comments on commit 443903a

Please sign in to comment.