Skip to content

TypeResolution: Abolish TypeResolutionStage::Contextual #39652

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Nov 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions include/swift/AST/TypeResolutionStage.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ enum class TypeResolutionStage : uint8_t {
/// Produces a complete interface type where all member references have been
/// resolved.
Interface,

/// Produces a contextual type involving archetypes within the context of
/// the type.
Contextual,
};

/// Display a type resolution stage.
Expand Down
8 changes: 6 additions & 2 deletions include/swift/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -4037,9 +4037,12 @@ class ConstraintSystem {
/// parent type by introducing fresh type variables for generic parameters
/// and constructing a bound generic type from these type variables.
///
/// \param isTypeResolution Whether we are in the process of resolving a type.
///
/// \returns The opened type.
Type openUnboundGenericType(GenericTypeDecl *decl, Type parentTy,
ConstraintLocatorBuilder locator);
ConstraintLocatorBuilder locator,
bool isTypeResolution);

/// Replace placeholder types with fresh type variables, and unbound generic
/// types with bound generic types whose generic args are fresh type
Expand Down Expand Up @@ -5275,7 +5278,8 @@ class OpenUnboundGenericType {

Type operator()(UnboundGenericType *unboundTy) const {
return cs.openUnboundGenericType(unboundTy->getDecl(),
unboundTy->getParent(), locator);
unboundTy->getParent(), locator,
/*isTypeResolution=*/true);
}
};

Expand Down
2 changes: 1 addition & 1 deletion include/swift/Subsystems.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ namespace swift {
/// emitted.
void performWholeModuleTypeChecking(SourceFile &SF);

/// Resolve the given \c TypeRepr to a contextual type.
/// Resolve the given \c TypeRepr to an interface type.
///
/// This is used when dealing with partial source files (e.g. SIL parsing,
/// code completion).
Expand Down
7 changes: 4 additions & 3 deletions lib/AST/GenericEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ Optional<Type> GenericEnvironment::getMappingIfPresent(

Type GenericEnvironment::mapTypeIntoContext(GenericEnvironment *env,
Type type) {
assert(!type->hasArchetype() && "already have a contextual type");
assert((!type->hasArchetype() || type->hasOpenedExistential()) &&
"already have a contextual type");
assert((env || !type->hasTypeParameter()) &&
"no generic environment provided for type with type parameters");

Expand Down Expand Up @@ -230,8 +231,8 @@ Type QueryInterfaceTypeSubstitutions::operator()(SubstitutableType *type) const{
Type GenericEnvironment::mapTypeIntoContext(
Type type,
LookupConformanceFn lookupConformance) const {
assert(!type->hasOpenedExistential() &&
"Opened existentials are special and so are you");
assert((!type->hasArchetype() || type->hasOpenedExistential()) &&
"already have a contextual type");

Type result = type.subst(QueryInterfaceTypeSubstitutions(this),
lookupConformance,
Expand Down
4 changes: 0 additions & 4 deletions lib/AST/TypeCheckRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,6 @@ void swift::simple_display(llvm::raw_ostream &out,
case TypeResolutionStage::Interface:
out << "interface";
break;

case TypeResolutionStage::Contextual:
out << "contextual";
break;
}
}

Expand Down
2 changes: 2 additions & 0 deletions lib/AST/TypeRepr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ void AttributedTypeRepr::printAttrs(ASTPrinter &Printer,

if (hasAttr(TAK_async))
Printer.printSimpleAttr("@async") << " ";
if (hasAttr(TAK_opened))
Printer.printSimpleAttr("@opened") << " ";
}

IdentTypeRepr *IdentTypeRepr::create(ASTContext &C,
Expand Down
6 changes: 4 additions & 2 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1580,11 +1580,13 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
/*GenericParams=*/nullptr,
CurDeclContext,
/*ProduceDiagnostics=*/false);
ParsedTypeLoc.setType(ty);
if (!ParsedTypeLoc.isError()) {
if (!ty->hasError()) {
ParsedTypeLoc.setType(CurDeclContext->mapTypeIntoContext(ty));
return true;
}

ParsedTypeLoc.setType(ty);

// It doesn't type check as a type, so see if it's a qualifying module name.
if (auto *ITR = dyn_cast<IdentTypeRepr>(ParsedTypeLoc.getTypeRepr())) {
const auto &componentRange = ITR->getComponentRange();
Expand Down
2 changes: 1 addition & 1 deletion lib/IDE/ExprContextAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ void swift::ide::collectPossibleReturnTypesFromContext(
const_cast<DeclContext *>(DC), /*diagnostics=*/false);

if (!type->hasError()) {
candidates.push_back(type);
candidates.push_back(DC->mapTypeIntoContext(type));
return;
}
}
Expand Down
71 changes: 43 additions & 28 deletions lib/SIL/Parser/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ namespace {

Type performTypeResolution(TypeRepr *TyR, bool IsSILType,
GenericEnvironment *GenericEnv,
GenericParamList *GenericParams);
GenericParamList *GenericParams) const;

void convertRequirements(ArrayRef<RequirementRepr> From,
SmallVectorImpl<Requirement> &To);
Expand Down Expand Up @@ -915,9 +915,8 @@ void SILParser::convertRequirements(ArrayRef<RequirementRepr> From,
// Use parser lexical scopes to resolve references
// to the generic parameters.
auto ResolveToInterfaceType = [&](TypeRepr *TyR) -> Type {
return performTypeResolution(TyR, /*IsSILType=*/false,
ContextGenericEnv, ContextGenericParams)
->mapTypeOutOfContext();
return performTypeResolution(TyR, /*IsSILType=*/false, ContextGenericEnv,
ContextGenericParams);
};

for (auto &Req : From) {
Expand Down Expand Up @@ -1187,7 +1186,7 @@ static bool parseDeclSILOptional(bool *isTransparent,

Type SILParser::performTypeResolution(TypeRepr *TyR, bool IsSILType,
GenericEnvironment *GenericEnv,
GenericParamList *GenericParams) {
GenericParamList *GenericParams) const {
if (GenericEnv == nullptr)
GenericEnv = ContextGenericEnv;

Expand Down Expand Up @@ -1251,26 +1250,26 @@ bool SILParser::parseASTType(CanType &result,
ParserResult<TypeRepr> parsedType = P.parseType();
if (parsedType.isNull()) return true;

bool wantInterfaceType = true;
bool wantContextualType = false;
if (genericEnv == nullptr) {
genericEnv = ContextGenericEnv;
wantInterfaceType = false;
wantContextualType = true;
}
if (genericParams == nullptr)
genericParams = ContextGenericParams;

bindSILGenericParams(parsedType.get());

const auto resolvedType =
performTypeResolution(parsedType.get(), /*isSILType=*/false,
genericEnv, genericParams);
auto resolvedType = performTypeResolution(
parsedType.get(), /*isSILType=*/false, genericEnv, genericParams);
if (wantContextualType && genericEnv) {
resolvedType = genericEnv->mapTypeIntoContext(resolvedType);
}

if (resolvedType->hasError())
return true;

if (wantInterfaceType)
result = resolvedType->mapTypeOutOfContext()->getCanonicalType();
else
result = resolvedType->getCanonicalType();
result = resolvedType->getCanonicalType();

return false;
}
Expand Down Expand Up @@ -1363,9 +1362,12 @@ bool SILParser::parseSILType(SILType &Result,
auto *attrRepr =
P.applyAttributeToType(
TyR.get(), attrs, specifier, specifierLoc, isolatedLoc);
const auto Ty =
performTypeResolution(attrRepr, /*IsSILType=*/true,
OuterGenericEnv, OuterGenericParams);
auto Ty = performTypeResolution(attrRepr, /*IsSILType=*/true, OuterGenericEnv,
OuterGenericParams);
if (OuterGenericEnv) {
Ty = OuterGenericEnv->mapTypeIntoContext(Ty);
}

if (Ty->hasError())
return true;

Expand Down Expand Up @@ -1930,9 +1932,12 @@ bool SILParser::parseSubstitutions(SmallVectorImpl<ParsedSubstitution> &parsed,
if (TyR.isNull())
return true;

const auto Ty =
performTypeResolution(TyR.get(), /*IsSILType=*/false,
GenericEnv, GenericParams);
auto Ty = performTypeResolution(TyR.get(), /*IsSILType=*/false, GenericEnv,
GenericParams);
if (GenericEnv) {
Ty = GenericEnv->mapTypeIntoContext(Ty);
}

if (Ty->hasError())
return true;
parsed.push_back({Loc, Ty});
Expand Down Expand Up @@ -2321,9 +2326,8 @@ bool SILParser::parseSILDeclRef(SILDeclRef &Member, bool FnTypeRequired) {
genericParams = fnType->getGenericParams();
}

const auto Ty =
performTypeResolution(TyR.get(), /*IsSILType=*/false,
genericEnv, genericParams);
const auto Ty = performTypeResolution(TyR.get(), /*IsSILType=*/false,
genericEnv, genericParams);
if (Ty->hasError())
return true;

Expand Down Expand Up @@ -6841,9 +6845,12 @@ ProtocolConformanceRef SILParser::parseProtocolConformanceHelper(
if (witnessParams == nullptr)
witnessParams = ContextGenericParams;

const auto ConformingTy =
performTypeResolution(TyR.get(), /*IsSILType=*/false,
witnessEnv, witnessParams);
auto ConformingTy = performTypeResolution(TyR.get(), /*IsSILType=*/false,
witnessEnv, witnessParams);
if (witnessEnv) {
ConformingTy = witnessEnv->mapTypeIntoContext(ConformingTy);
}

if (ConformingTy->hasError())
return ProtocolConformanceRef();

Expand Down Expand Up @@ -6957,13 +6964,17 @@ static bool parseSILWitnessTableEntry(
if (TyR.isNull())
return true;

const auto Ty =
auto Ty =
swift::performTypeResolution(TyR.get(), P.Context,
/*isSILMode=*/false,
/*isSILType=*/false,
witnessEnv,
witnessParams,
&P.SF);
if (witnessEnv) {
Ty = witnessEnv->mapTypeIntoContext(Ty);
}

if (Ty->hasError())
return true;

Expand Down Expand Up @@ -7018,12 +7029,16 @@ static bool parseSILWitnessTableEntry(
if (TyR.isNull())
return true;

const auto Ty =
auto Ty =
swift::performTypeResolution(TyR.get(), P.Context,
/*isSILMode=*/false,
/*isSILType=*/false,
witnessEnv, witnessParams,
&P.SF);
if (witnessEnv) {
Ty = witnessEnv->mapTypeIntoContext(Ty);
}

if (Ty->hasError())
return true;

Expand Down
7 changes: 4 additions & 3 deletions lib/Sema/CSBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1818,9 +1818,10 @@ bool TypeVarBindingProducer::computeNext() {
// always preserved.
auto *BGT = type->castTo<BoundGenericType>();
auto dstLocator = TypeVar->getImpl().getLocator();
auto newType = CS.openUnboundGenericType(BGT->getDecl(), BGT->getParent(),
dstLocator)
->reconstituteSugar(/*recursive=*/false);
auto newType =
CS.openUnboundGenericType(BGT->getDecl(), BGT->getParent(),
dstLocator, /*isTypeResolution=*/false)
->reconstituteSugar(/*recursive=*/false);
addNewBinding(binding.withType(newType));
}

Expand Down
13 changes: 5 additions & 8 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1321,10 +1321,8 @@ namespace {
// Introduce type variables for unbound generics.
const auto genericOpener = OpenUnboundGenericType(CS, locator);
const auto placeholderHandler = HandlePlaceholderType(CS, locator);
const auto result = TypeResolution::forContextual(CS.DC, resCtx,
genericOpener,
placeholderHandler)
.resolveType(repr);
const auto result = TypeResolution::resolveContextualType(
repr, CS.DC, resCtx, genericOpener, placeholderHandler);
if (result->hasError()) {
return Type();
}
Expand Down Expand Up @@ -1597,13 +1595,12 @@ namespace {
auto *const locator = CS.getConstraintLocator(expr);
const auto options =
TypeResolutionOptions(TypeResolverContext::InExpression);
for (size_t i = 0, size = specializations.size(); i < size; ++i) {
const auto resolution = TypeResolution::forContextual(
CS.DC, options,
for (size_t i = 0, e = specializations.size(); i < e; ++i) {
const auto result = TypeResolution::resolveContextualType(
specializations[i], CS.DC, options,
// Introduce type variables for unbound generics.
OpenUnboundGenericType(CS, locator),
HandlePlaceholderType(CS, locator));
const auto result = resolution.resolveType(specializations[i]);
if (result->hasError())
return Type();

Expand Down
18 changes: 8 additions & 10 deletions lib/Sema/CSSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1098,16 +1098,14 @@ void ConstraintSystem::shrink(Expr *expr) {
auto *const typeRepr = coerceExpr->getCastTypeRepr();

if (typeRepr && isSuitableCollection(typeRepr)) {
const auto coercionType =
TypeResolution::forContextual(
CS.DC, None,
// FIXME: Should we really be unconditionally complaining
// about unbound generics and placeholders here? For
// example:
// let foo: [Array<Float>] = [[0], [1], [2]] as [Array]
// let foo: [Array<Float>] = [[0], [1], [2]] as [Array<_>]
/*unboundTyOpener*/ nullptr, /*placeholderHandler*/ nullptr)
.resolveType(typeRepr);
const auto coercionType = TypeResolution::resolveContextualType(
typeRepr, CS.DC, None,
// FIXME: Should we really be unconditionally complaining
// about unbound generics and placeholders here? For
// example:
// let foo: [Array<Float>] = [[0], [1], [2]] as [Array]
// let foo: [Array<Float>] = [[0], [1], [2]] as [Array<_>]
/*unboundTyOpener*/ nullptr, /*placeholderHandler*/ nullptr);

// Looks like coercion type is invalid, let's skip this sub-tree.
if (coercionType->hasError())
Expand Down
Loading