diff --git a/include/swift/AST/ArchetypeBuilder.h b/include/swift/AST/ArchetypeBuilder.h index 5c83058bc15..cecfac857ae 100644 --- a/include/swift/AST/ArchetypeBuilder.h +++ b/include/swift/AST/ArchetypeBuilder.h @@ -30,12 +30,12 @@ namespace swift { class AbstractTypeParamDecl; class ArchetypeType; class AssociatedTypeDecl; +class Module; class Pattern; class ProtocolDecl; class Requirement; class RequirementRepr; class SourceLoc; -class TranslationUnit; class Type; class TypeRepr; class ASTContext; @@ -54,7 +54,7 @@ private: class InferRequirementsWalker; friend class InferRequirementsWalker; - TranslationUnit &TU; + Module &Mod; ASTContext &Context; DiagnosticEngine &Diags; struct Implementation; @@ -80,12 +80,11 @@ private: PotentialArchetype *T2); public: - ArchetypeBuilder(TranslationUnit &tu, DiagnosticEngine &diags); + ArchetypeBuilder(Module &mod, DiagnosticEngine &diags); /// Construct a new archtype builder. /// - /// \param tu The translation unit in which the builder will create - /// archetypes. + /// \param mod The module in which the builder will create archetypes. /// /// \param diags The diagnostics entity to use. /// @@ -97,7 +96,7 @@ public: /// to which the given type parameter conforms. The produces the final /// results of AbstractTypeParamDecl::getProtocols() for an associated type. ArchetypeBuilder( - TranslationUnit &tu, DiagnosticEngine &diags, + Module &mod, DiagnosticEngine &diags, std::function(ProtocolDecl *)> getInheritedProtocols, std::function(AbstractTypeParamDecl *)> @@ -105,8 +104,8 @@ public: ArchetypeBuilder(ArchetypeBuilder &&); ~ArchetypeBuilder(); - /// Retrieve the translation unit. - TranslationUnit &getTranslationUnit() const { return TU; } + /// Retrieve the module. + Module &getModule() const { return Mod; } /// \brief Add a new generic parameter for which there may be requirements. /// @@ -273,10 +272,10 @@ public: /// \brief Retrieve (or build) the archetype corresponding to the potential /// archetype. ArchetypeType *getArchetype(AssociatedTypeDecl * /*nullable*/ rootAssocTy, - TranslationUnit &tu); + Module &mod); /// Retrieve the associated type declaration for a given nested type. - AssociatedTypeDecl *getAssociatedType(TranslationUnit &tu, Identifier name); + AssociatedTypeDecl *getAssociatedType(Module &mod, Identifier name); void dump(llvm::raw_ostream &Out, unsigned Indent); diff --git a/include/swift/AST/LazyResolver.h b/include/swift/AST/LazyResolver.h index 3418747d61f..92019ee6bf6 100644 --- a/include/swift/AST/LazyResolver.h +++ b/include/swift/AST/LazyResolver.h @@ -21,6 +21,7 @@ namespace swift { +class DeclContext; class ExtensionDecl; class Identifier; class NominalTypeDecl; @@ -55,12 +56,14 @@ public: /// Resolve a member type. /// + /// \param dc The context in which to resolve the type. /// \param type The type in which we will search for the member type. /// \param name The name of the member type. /// /// \returns the member type, or an empty type if no such type could be /// found. - virtual Type resolveMemberType(Type type, Identifier name) = 0; + virtual Type resolveMemberType(DeclContext *dc, Type type, + Identifier name) = 0; /// Resolve the type and declaration attributes of a value. /// diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h index 42bb4382704..010340c4ad9 100644 --- a/include/swift/Subsystems.h +++ b/include/swift/Subsystems.h @@ -33,6 +33,7 @@ namespace swift { class TranslationUnit; class Component; class Decl; + class DeclContext; class SILModule; struct TypeLoc; class SILParserTUState; @@ -118,7 +119,7 @@ namespace swift { /// parsing, code completion). /// /// \returns false on success, true on error. - bool performTypeLocChecking(TranslationUnit *TU, TypeLoc &T, + bool performTypeLocChecking(TranslationUnit *TU, TypeLoc &T, DeclContext *DC, bool ProduceDiagnostics = true); /// Turn the given translation unit into SIL IR. The returned SILModule must diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 7d8adeab0d8..2730af5b022 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -560,8 +560,8 @@ specializeTypeWitnesses(ASTContext &ctx, /// Retrieve the explicit conformance of the given nominal type declaration /// to the given protocol. static std::tuple -findExplicitConformance(Module *module, NominalTypeDecl *nominal, - ProtocolDecl *protocol, LazyResolver *resolver) { +findExplicitConformance(NominalTypeDecl *nominal, ProtocolDecl *protocol, + LazyResolver *resolver) { // FIXME: Introduce a cache/lazy lookup structure to make this more efficient? // Walk the nominal type, its extensions, superclasses, and so on. @@ -726,7 +726,7 @@ LookupConformanceResult Module::lookupConformance(Type type, Decl *declaresConformance = nullptr; ProtocolConformance *nominalConformance = nullptr; std::tie(owningNominal, declaresConformance, nominalConformance) - = findExplicitConformance(this, nominal, protocol, resolver); + = findExplicitConformance(nominal, protocol, resolver); // If we didn't find an owning nominal, we don't conform. Cache the negative // result and return. diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 57792a3b82e..2193beef5bd 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1369,7 +1369,7 @@ Type Type::subst(Module *module, TypeSubstitutionMap &substitutions, // FIXME: This is a fallback. We want the above, conformance-based // result to be the only viable path. if (resolver) { - if (Type memberType = resolver->resolveMemberType(substParent, + if (Type memberType = resolver->resolveMemberType(module, substParent, substOrig->getName())) { return memberType; } diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index ef29c5dce69..759bbbc880d 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -434,7 +434,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks, /// \returns true on success, false on failure. bool typecheckParsedType() { assert(ParsedTypeLoc.getTypeRepr() && "should have a TypeRepr"); - return !performTypeLocChecking(TU, ParsedTypeLoc, false); + return !performTypeLocChecking(TU, ParsedTypeLoc, CurDeclContext, false); } public: diff --git a/lib/Parse/ParseSIL.cpp b/lib/Parse/ParseSIL.cpp index 7c19a000ddb..96198ecf242 100644 --- a/lib/Parse/ParseSIL.cpp +++ b/lib/Parse/ParseSIL.cpp @@ -578,7 +578,7 @@ bool SILParser::performTypeLocChecking(TypeLoc &T) { "Unexpected stage during parsing!"); llvm::SaveAndRestore ASTStage(P.TU->ASTStage, TranslationUnit::Parsed); - return swift::performTypeLocChecking(P.TU, T); + return swift::performTypeLocChecking(P.TU, T, P.TU); } /// Find the top-level ValueDecl or Module given a name. diff --git a/lib/Sema/ArchetypeBuilder.cpp b/lib/Sema/ArchetypeBuilder.cpp index eeed4190c96..69f0eac7381 100644 --- a/lib/Sema/ArchetypeBuilder.cpp +++ b/lib/Sema/ArchetypeBuilder.cpp @@ -95,11 +95,11 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(Identifier Name) auto ArchetypeBuilder::PotentialArchetype::getArchetype( AssociatedTypeDecl *rootAssocTy, - TranslationUnit &tu) + Module &mod) -> ArchetypeType * { // Retrieve the archetype from the representation of this set. if (Representative != this) - return getRepresentative()->getArchetype(rootAssocTy, tu); + return getRepresentative()->getArchetype(rootAssocTy, mod); AssociatedTypeDecl *assocType = rootAssocTy; if (!Archetype) { @@ -108,7 +108,7 @@ auto ArchetypeBuilder::PotentialArchetype::getArchetype( if (Parent) { assert(!rootAssocTy && "root associated type given for non-root archetype"); - ParentArchetype = Parent->getArchetype(nullptr, tu); + ParentArchetype = Parent->getArchetype(nullptr, mod); if (!ParentArchetype) return nullptr; @@ -116,7 +116,7 @@ auto ArchetypeBuilder::PotentialArchetype::getArchetype( // Find the protocol that has an associated type with this name. for (auto proto : ParentArchetype->getConformsTo()) { SmallVector decls; - if (tu.lookupQualified(proto->getDeclaredType(), Name, + if (mod.lookupQualified(proto->getDeclaredType(), Name, NL_VisitSupertypes, nullptr, decls)) { for (auto decl : decls) { assocType = dyn_cast(decl); @@ -138,7 +138,7 @@ auto ArchetypeBuilder::PotentialArchetype::getArchetype( SmallVector Protos(ConformsTo.begin(), ConformsTo.end()); - Archetype = ArchetypeType::getNew(tu.getASTContext(), ParentArchetype, + Archetype = ArchetypeType::getNew(mod.getASTContext(), ParentArchetype, assocType, Name, Protos, Superclass, Index); @@ -147,20 +147,20 @@ auto ArchetypeBuilder::PotentialArchetype::getArchetype( SmallVector, 4> FlatNestedTypes; for (auto Nested : NestedTypes) { FlatNestedTypes.push_back({ Nested.first, - Nested.second->getArchetype(nullptr, tu) }); + Nested.second->getArchetype(nullptr, mod) }); } - Archetype->setNestedTypes(tu.getASTContext(), FlatNestedTypes); + Archetype->setNestedTypes(mod.getASTContext(), FlatNestedTypes); } return Archetype; } AssociatedTypeDecl * -ArchetypeBuilder::PotentialArchetype::getAssociatedType(TranslationUnit &tu, +ArchetypeBuilder::PotentialArchetype::getAssociatedType(Module &mod, Identifier name) { for (auto proto : getRepresentative()->getConformsTo()) { SmallVector decls; - if (tu.lookupQualified(proto->getDeclaredType(), name, + if (mod.lookupQualified(proto->getDeclaredType(), name, NL_VisitSupertypes, nullptr, decls)) { for (auto decl : decls) { if (auto assocType = dyn_cast(decl)) @@ -225,8 +225,9 @@ struct ArchetypeBuilder::Implementation { SmallVector AllArchetypes; }; -ArchetypeBuilder::ArchetypeBuilder(TranslationUnit &tu, DiagnosticEngine &diags) - : TU(tu), Context(tu.getASTContext()), Diags(diags), Impl(new Implementation) +ArchetypeBuilder::ArchetypeBuilder(Module &mod, DiagnosticEngine &diags) + : Mod(mod), Context(mod.getASTContext()), Diags(diags), + Impl(new Implementation) { Impl->getInheritedProtocols = [](ProtocolDecl *protocol) { return protocol->getProtocols(); @@ -237,10 +238,11 @@ ArchetypeBuilder::ArchetypeBuilder(TranslationUnit &tu, DiagnosticEngine &diags) } ArchetypeBuilder::ArchetypeBuilder( - TranslationUnit &tu, DiagnosticEngine &diags, + Module &mod, DiagnosticEngine &diags, std::function(ProtocolDecl *)> getInheritedProtocols, - std::function(AbstractTypeParamDecl *)> getConformsTo) - : TU(tu), Context(tu.getASTContext()), Diags(diags), Impl(new Implementation) + std::function(AbstractTypeParamDecl*)> getConformsTo) + : Mod(mod), Context(mod.getASTContext()), Diags(diags), + Impl(new Implementation) { Impl->getInheritedProtocols = std::move(getInheritedProtocols); Impl->getConformsTo = std::move(getConformsTo); @@ -611,7 +613,7 @@ void ArchetypeBuilder::assignArchetypes() { // generic parameters). for (const auto& PA : Impl->PotentialArchetypes) { auto Archetype - = PA.second->getArchetype(dyn_cast(PA.first), TU); + = PA.second->getArchetype(dyn_cast(PA.first), Mod); Impl->PrimaryArchetypeMap[PA.first] = Archetype; } } diff --git a/lib/Sema/GenericTypeResolver.h b/lib/Sema/GenericTypeResolver.h index 200311dce30..c8faaee4104 100644 --- a/lib/Sema/GenericTypeResolver.h +++ b/lib/Sema/GenericTypeResolver.h @@ -53,6 +53,7 @@ public: /// \returns A type that refers to the dependent member type, or an error /// type if such a reference is ill-formed. virtual Type resolveDependentMemberType(Type baseTy, + DeclContext *DC, SourceRange baseRange, Identifier name, SourceLoc nameLoc) = 0; @@ -66,6 +67,7 @@ class DependentGenericTypeResolver : public GenericTypeResolver { virtual Type resolveGenericTypeParamType(GenericTypeParamType *gp); virtual Type resolveDependentMemberType(Type baseTy, + DeclContext *DC, SourceRange baseRange, Identifier name, SourceLoc nameLoc); @@ -80,6 +82,7 @@ class GenericTypeToArchetypeResolver : public GenericTypeResolver { virtual Type resolveGenericTypeParamType(GenericTypeParamType *gp); virtual Type resolveDependentMemberType(Type baseTy, + DeclContext *DC, SourceRange baseRange, Identifier name, SourceLoc nameLoc); @@ -103,6 +106,7 @@ public: virtual Type resolveGenericTypeParamType(GenericTypeParamType *gp); virtual Type resolveDependentMemberType(Type baseTy, + DeclContext *DC, SourceRange baseRange, Identifier name, SourceLoc nameLoc); @@ -126,6 +130,7 @@ public: virtual Type resolveGenericTypeParamType(GenericTypeParamType *gp); virtual Type resolveDependentMemberType(Type baseTy, + DeclContext *DC, SourceRange baseRange, Identifier name, SourceLoc nameLoc); diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 761cbb8a7df..d2244f5c3f2 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -285,8 +285,8 @@ OverloadSet *OverloadSet::getNew(ConstraintSystem &CS, } ConstraintSystem::ConstraintSystem(TypeChecker &tc, DeclContext *dc) - : TC(tc), DC(dc), Arena(tc.Context, Allocator) -{ + : TC(tc), DC(dc), Arena(tc.Context, Allocator) { + assert(DC && "context required"); } ConstraintSystem::~ConstraintSystem() { } @@ -354,7 +354,7 @@ LookupResult &ConstraintSystem::lookupMember(Type base, Identifier name) { base = base->getCanonicalType(); auto &result = MemberLookups[{base, name}]; if (!result) { - result = TC.lookupMember(base, name); + result = TC.lookupMember(base, name, DC); // If we aren't performing dynamic lookup, we're done. auto instanceTy = base->getRValueType(); @@ -825,7 +825,8 @@ getTypeForArchetype(ConstraintSystem &cs, ArchetypeType *archetype, // Look for this member type. // FIXME: Ambiguity check. auto &tc = cs.getTypeChecker(); - LookupTypeResult lookup = tc.lookupMemberType(parentTy, archetype->getName()); + LookupTypeResult lookup = tc.lookupMemberType(parentTy, archetype->getName(), + cs.DC); assert(lookup.size() == 1 && "Couldn't find archetype for member lookup"); auto type = lookup.front().second; mappedTypes[archetype] = type; @@ -964,7 +965,7 @@ Type ConstraintSystem::getTypeOfMemberReference(Type baseTy, ValueDecl *value, // When we have an associated type and the base type conforms to the // given protocol, use the type witness directly. ProtocolConformance *conformance = nullptr; - if (TC.conformsToProtocol(baseObjTy, ownerProtoTy->getDecl(), + if (TC.conformsToProtocol(baseObjTy, ownerProtoTy->getDecl(), DC, &conformance)) { // FIXME: Eventually, deal with default function/property definitions. if (auto assocType = dyn_cast(value)) { @@ -2287,7 +2288,7 @@ ConstraintSystem::simplifyConstructionConstraint(Type valueType, Type argType, return SolutionKind::Error; } - auto ctors = TC.lookupConstructors(valueType); + auto ctors = TC.lookupConstructors(valueType, DC); if (!ctors) { // If we are supposed to record failures, do so. if (shouldRecordFailures()) { @@ -2346,7 +2347,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( } // Check whether this type conforms to the protocol. - if (TC.conformsToProtocol(type, protocol)) + if (TC.conformsToProtocol(type, protocol, DC)) return SolutionKind::TriviallySolved; // FIXME: If we're dealing with _Nil, allow user conversions. This should be @@ -2458,7 +2459,7 @@ ConstraintSystem::simplifyMemberConstraint(const Constraint &constraint) { bool isExistential = instanceTy->isExistentialType(); if (name.str() == "init") { // Constructors have their own approach to name lookup. - auto ctors = TC.lookupConstructors(baseObjTy); + auto ctors = TC.lookupConstructors(baseObjTy, DC); if (!ctors) { recordFailure(constraint.getLocator(), Failure::DoesNotHaveMember, baseObjTy, name); @@ -2536,7 +2537,7 @@ ConstraintSystem::simplifyMemberConstraint(const Constraint &constraint) { // If we want member types only, use member type lookup. if (constraint.getKind() == ConstraintKind::TypeMember) { - auto lookup = TC.lookupMemberType(baseObjTy, name); + auto lookup = TC.lookupMemberType(baseObjTy, name, DC); if (!lookup) { // FIXME: Customize diagnostic to mention types. recordFailure(constraint.getLocator(), Failure::DoesNotHaveMember, @@ -2898,7 +2899,7 @@ static bool sameOverloadChoice(const OverloadChoice &x, } /// Compare two declarations to determine whether one is a witness of the other. -static Comparison compareWitnessAndRequirement(TypeChecker &tc, +static Comparison compareWitnessAndRequirement(TypeChecker &tc, DeclContext *dc, ValueDecl *decl1, ValueDecl *decl2) { // We only have a witness/requirement pair if exactly one of the declarations @@ -2935,7 +2936,7 @@ static Comparison compareWitnessAndRequirement(TypeChecker &tc, auto owningType = potentialWitness->getDeclContext()->getDeclaredTypeInContext(); ProtocolConformance *conformance = nullptr; - if (!tc.conformsToProtocol(owningType, proto, &conformance)) + if (!tc.conformsToProtocol(owningType, proto, dc, &conformance)) return Comparison::Unordered; // If the witness and the potential witness are not the same, there's no @@ -2951,7 +2952,7 @@ static Comparison compareWitnessAndRequirement(TypeChecker &tc, /// the second declaration. /// /// "Specialized" is essentially a form of subtyping, defined below. -static bool isDeclAsSpecializedAs(TypeChecker &tc, +static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc, ValueDecl *decl1, ValueDecl *decl2) { // If the kinds are different, there's nothing we can do. // FIXME: This is wrong for type declarations. @@ -2959,7 +2960,7 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, return false; // A witness is always more specialized than the requirement it satisfies. - switch (compareWitnessAndRequirement(tc, decl1, decl2)) { + switch (compareWitnessAndRequirement(tc, dc, decl1, decl2)) { case Comparison::Unordered: break; @@ -3020,15 +3021,17 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, auto funcTy1 = type1->castTo(); auto funcTy2 = type2->castTo(); auto &context = tc.Context; - return tc.isSubtypeOf(funcTy1->getInput(), funcTy2->getInput()) || + return tc.isSubtypeOf(funcTy1->getInput(), funcTy2->getInput(), dc) || (funcTy1->getInput()->getUnlabeledType(context)->isEqual( funcTy2->getInput()->getUnlabeledType(context)) && - tc.isSubtypeOf(funcTy1->getResult(), funcTy2->getResult())); + tc.isSubtypeOf(funcTy1->getResult(), funcTy2->getResult(), dc)); } -Comparison TypeChecker::compareDeclarations(ValueDecl *decl1, ValueDecl *decl2){ - bool decl1Better = isDeclAsSpecializedAs(*this, decl1, decl2); - bool decl2Better = isDeclAsSpecializedAs(*this, decl2, decl1); +Comparison TypeChecker::compareDeclarations(DeclContext *dc, + ValueDecl *decl1, + ValueDecl *decl2){ + bool decl1Better = isDeclAsSpecializedAs(*this, dc, decl1, decl2); + bool decl2Better = isDeclAsSpecializedAs(*this, dc, decl2, decl1); if (decl1Better == decl2Better) return Comparison::Unordered; @@ -3110,9 +3113,11 @@ SolutionCompareResult ConstraintSystem::compareSolutions( case OverloadChoiceKind::DeclViaDynamic: case OverloadChoiceKind::Decl: // Determine whether one declaration is more specialized than the other. - if (isDeclAsSpecializedAs(tc, choice1.getDecl(), choice2.getDecl())) + if (isDeclAsSpecializedAs(tc, cs.DC, + choice1.getDecl(), choice2.getDecl())) ++score1; - if (isDeclAsSpecializedAs(tc, choice2.getDecl(), choice1.getDecl())) + if (isDeclAsSpecializedAs(tc, cs.DC, + choice2.getDecl(), choice1.getDecl())) ++score2; break; } @@ -3549,7 +3554,7 @@ namespace { // Validate the result type, if present. if (closure->hasExplicitResultType() && - TC.validateType(closure->getExplicitResultTypeLoc())) { + TC.validateType(closure->getExplicitResultTypeLoc(), DC)) { expr->setType(ErrorType::get(TC.Context)); return { false, expr }; } @@ -3567,14 +3572,14 @@ namespace { Expr *walkToExprPost(Expr *expr) override { // Fold sequence expressions. if (auto seqExpr = dyn_cast(expr)) { - return TC.foldSequence(seqExpr); + return TC.foldSequence(seqExpr, DC); } // Type check the type in an array new expression. if (auto newArray = dyn_cast(expr)) { // FIXME: Check that the element type has a default constructor. - if (TC.validateType(newArray->getElementTypeLoc(), + if (TC.validateType(newArray->getElementTypeLoc(), DC, /*allowUnboundGenerics=*/true)) return nullptr; @@ -3601,7 +3606,7 @@ namespace { // Type check the type parameters in an UnresolvedSpecializeExpr. if (auto us = dyn_cast(expr)) { for (TypeLoc &type : us->getUnresolvedParams()) { - if (TC.validateType(type)) { + if (TC.validateType(type, DC)) { TC.diagnose(us->getLAngleLoc(), diag::while_parsing_as_left_angle_bracket); return nullptr; @@ -3612,7 +3617,7 @@ namespace { // Type check the type parameters in cast expressions. if (auto cast = dyn_cast(expr)) { - if (TC.validateType(cast->getCastTypeLoc())) + if (TC.validateType(cast->getCastTypeLoc(), DC)) return nullptr; return expr; } @@ -4323,19 +4328,21 @@ bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC, return false; } -bool TypeChecker::isSubtypeOf(Type type1, Type type2, bool &isTrivial) { - ConstraintSystem cs(*this, nullptr); +bool TypeChecker::isSubtypeOf(Type type1, Type type2, DeclContext *dc, + bool &isTrivial) { + ConstraintSystem cs(*this, dc); return cs.isSubtypeOf(type1, type2, isTrivial); } -bool TypeChecker::isConvertibleTo(Type type1, Type type2) { - ConstraintSystem cs(*this, nullptr); +bool TypeChecker::isConvertibleTo(Type type1, Type type2, DeclContext *dc) { + ConstraintSystem cs(*this, dc); bool isTrivial; return cs.isConvertibleTo(type1, type2, isTrivial); } -bool TypeChecker::isSubstitutableFor(Type type1, ArchetypeType *type2) { - ConstraintSystem cs(*this, nullptr); +bool TypeChecker::isSubstitutableFor(Type type1, ArchetypeType *type2, + DeclContext *dc) { + ConstraintSystem cs(*this, dc); llvm::DenseMap replacements; Type type2var = cs.openType(type2, type2, replacements); @@ -4652,6 +4659,7 @@ void ConstraintSystem::dump() { /// Determine the semantics of a checked cast operation. CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, Type toType, + DeclContext *dc, SourceLoc diagLoc, SourceRange diagFromRange, SourceRange diagToRange, @@ -4665,7 +4673,7 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, // If the from/to types are equivalent or implicitly convertible, // this should have been a coercion expression (b as A) rather than a // checked cast (a as! B). Complain. - if (fromType->isEqual(toType) || isConvertibleTo(fromType, toType)) { + if (fromType->isEqual(toType) || isConvertibleTo(fromType, toType, dc)) { return CheckedCastKind::InvalidCoercible; } @@ -4689,7 +4697,7 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, if (fromExistential) { if (toArchetype) { return CheckedCastKind::ExistentialToArchetype; - } else if (isConvertibleTo(toType, fromType)) { + } else if (isConvertibleTo(toType, fromType, dc)) { return CheckedCastKind::ExistentialToConcrete; } else { diagnose(diagLoc, @@ -4703,7 +4711,7 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, // - convert an archetype to a concrete type fulfilling its constraints. if (fromArchetype) { - if (!isSubstitutableFor(toType, fromType->castTo())) { + if (!isSubstitutableFor(toType, fromType->castTo(), dc)) { diagnose(diagLoc, diag::downcast_from_archetype_to_unrelated, origFromType, toType) @@ -4733,7 +4741,7 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, assert(!toExistential && "existentials should have been handled above"); // The destination type must be a subtype of the source type. - if (!isSubtypeOf(toType, fromType)) { + if (!isSubtypeOf(toType, fromType, dc)) { diagnose(diagLoc, diag::downcast_to_unrelated, origFromType, toType) .highlight(diagFromRange) .highlight(diagToRange); diff --git a/lib/Sema/TypeCheckConstraintsApply.cpp b/lib/Sema/TypeCheckConstraintsApply.cpp index 2a23c6a737d..edf4240dc01 100644 --- a/lib/Sema/TypeCheckConstraintsApply.cpp +++ b/lib/Sema/TypeCheckConstraintsApply.cpp @@ -61,7 +61,8 @@ Expr *Solution::specialize(Expr *expr, // FIXME: We'd like the type checker to ensure that this always // succeeds. ConformanceMap conformances; - if (tc.checkSubstitutions(substitutions, conformances, expr->getLoc(), + if (tc.checkSubstitutions(substitutions, conformances, + getConstraintSystem().DC, expr->getLoc(), &substitutions)) return nullptr; @@ -99,7 +100,8 @@ Type Solution::computeSubstitutions( // FIXME: We'd like the type checker to ensure that this always // succeeds. ConformanceMap conformances; - if (tc.checkSubstitutions(typeSubstitutions, conformances, SourceLoc(), + if (tc.checkSubstitutions(typeSubstitutions, conformances, + getConstraintSystem().DC, SourceLoc(), &typeSubstitutions)) return Type(); @@ -116,6 +118,8 @@ Type Solution::computeSubstitutions( /// /// \param tc The type check we're using. /// +/// \param dc The context in which we need a witness. +/// /// \param type The type whose witness to find. /// /// \param proto The protocol to which the type conforms. @@ -126,8 +130,8 @@ Type Solution::computeSubstitutions( /// have a requirement with the given name. /// /// \returns The named witness. -static FuncDecl *findNamedWitness(TypeChecker &tc, Type type, - ProtocolDecl *proto, +static FuncDecl *findNamedWitness(TypeChecker &tc, DeclContext *dc, + Type type, ProtocolDecl *proto, Identifier name, Diag<> diag) { // Find the named requirement. @@ -150,7 +154,7 @@ static FuncDecl *findNamedWitness(TypeChecker &tc, Type type, // Find the member used to satisfy the named requirement. ProtocolConformance *conformance = 0; - bool conforms = tc.conformsToProtocol(type, proto, &conformance); + bool conforms = tc.conformsToProtocol(type, proto, dc, &conformance); (void)conforms; assert(conforms && "Protocol conformance broken?"); @@ -171,6 +175,7 @@ static FuncDecl *findNamedWitness(TypeChecker &tc, Type type, /// as a result. /// /// \param tc The type checker we're using to perform the substitution. +/// \param dc The context in which we're performing the substitution. /// \param member The member we will be accessing after performing the /// conversion. /// \param objectTy The type of object in which we want to access the member, @@ -184,8 +189,8 @@ static FuncDecl *findNamedWitness(TypeChecker &tc, Type type, /// conversion. /// \param genericParams Will be set to the generic parameter list used for /// substitution. -static void substForBaseConversion(TypeChecker &tc, ValueDecl *member, - Type objectTy, +static void substForBaseConversion(TypeChecker &tc, DeclContext *dc, + ValueDecl *member, Type objectTy, MutableArrayRef otherTypes, SourceLoc loc, TypeSubstitutionMap &substitutions, @@ -304,7 +309,8 @@ namespace { ->castTo(); TypeSubstitutionMap substitutions; substitutions[selfArchetype] = baseTy; - resultTy = tc.substType(resultTy, substitutions); + resultTy = tc.substType(dc->getParentModule(), resultTy, + substitutions); if (!resultTy) return nullptr; } @@ -332,7 +338,7 @@ namespace { member->getDeclContext()->getDeclaredTypeInContext() }; - substForBaseConversion(tc, member, baseTy, otherTypes, memberLoc, + substForBaseConversion(tc, dc, member, baseTy, otherTypes, memberLoc, substitutions, conformances, genericParams); Type substTy = otherTypes[0]; containerTy = otherTypes[1]; @@ -690,7 +696,7 @@ namespace { TypeSubstitutionMap substitutions; ConformanceMap conformances; containerTy = subscript->getDeclContext()->getDeclaredTypeInContext(); - substForBaseConversion(tc, subscript, baseTy, containerTy, + substForBaseConversion(tc, dc, subscript, baseTy, containerTy, index->getStartLoc(), substitutions, conformances, genericParams); @@ -808,14 +814,14 @@ namespace { // For type-sugar reasons, prefer the spelling of the default literal // type. auto type = simplifyType(expr->getType()); - if (auto defaultType = tc.getDefaultType(protocol)) { + if (auto defaultType = tc.getDefaultType(protocol, dc)) { if (defaultType->isEqual(type)) type = defaultType; } if (auto floatProtocol = tc.getProtocol(expr->getLoc(), KnownProtocolKind::FloatLiteralConvertible)) { - if (auto defaultFloatType = tc.getDefaultType(floatProtocol)) { + if (auto defaultFloatType = tc.getDefaultType(floatProtocol, dc)) { if (defaultFloatType->isEqual(type)) type = defaultFloatType; } @@ -865,7 +871,7 @@ namespace { // For type-sugar reasons, prefer the spelling of the default literal // type. auto type = simplifyType(expr->getType()); - if (auto defaultType = tc.getDefaultType(protocol)) { + if (auto defaultType = tc.getDefaultType(protocol, dc)) { if (defaultType->isEqual(type)) type = defaultType; } @@ -910,7 +916,7 @@ namespace { // For type-sugar reasons, prefer the spelling of the default literal // type. auto type = simplifyType(expr->getType()); - if (auto defaultType = tc.getDefaultType(protocol)) { + if (auto defaultType = tc.getDefaultType(protocol, dc)) { if (defaultType->isEqual(type)) type = defaultType; } @@ -947,7 +953,7 @@ namespace { // For type-sugar reasons, prefer the spelling of the default literal // type. auto type = simplifyType(expr->getType()); - if (auto defaultType = tc.getDefaultType(protocol)) { + if (auto defaultType = tc.getDefaultType(protocol, dc)) { if (defaultType->isEqual(type)) type = defaultType; } @@ -992,7 +998,7 @@ namespace { // FIXME: Cache name, auto name = tc.Context.getIdentifier("convertFromStringInterpolation"); - auto member = findNamedWitness(tc, type, interpolationProto, name, + auto member = findNamedWitness(tc, dc, type, interpolationProto, name, diag::interpolation_broken_proto); // Build a reference to the convertFromStringInterpolation member. @@ -1410,7 +1416,8 @@ namespace { assert(arrayProto && "type-checked array literal w/o protocol?!"); ProtocolConformance *conformance = nullptr; - bool conforms = tc.conformsToProtocol(arrayTy, arrayProto, &conformance); + bool conforms = tc.conformsToProtocol(arrayTy, arrayProto, + cs.DC, &conformance); (void)conforms; assert(conforms && "Type does not conform to protocol?"); @@ -1446,7 +1453,7 @@ namespace { ProtocolConformance *conformance = nullptr; bool conforms = tc.conformsToProtocol(dictionaryTy, dictionaryProto, - &conformance); + cs.DC, &conformance); (void)conforms; assert(conforms && "Type does not conform to protocol?"); @@ -1591,7 +1598,7 @@ namespace { // FIXME: Assume the index type is DefaultIntegerLiteralType for now. auto intProto = tc.getProtocol(expr->getConstructionFunction()->getLoc(), KnownProtocolKind::IntegerLiteralConvertible); - Type intTy = tc.getDefaultType(intProto); + Type intTy = tc.getDefaultType(intProto, dc); Expr *constructionFn = expr->getConstructionFunction(); Type constructionTy = FunctionType::get(intTy, @@ -1725,7 +1732,7 @@ namespace { Type fromType = sub->getType(); - return tc.typeCheckCheckedCast(fromType, toType, + return tc.typeCheckCheckedCast(fromType, toType, dc, expr->getLoc(), sub->getSourceRange(), expr->getCastTypeLoc().getSourceRange(), @@ -2408,7 +2415,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, // so we don't insert a DerivedToBase conversion later. if (auto superRef = dyn_cast(expr)) { assert(tc.isSubtypeOf(fromLValue->getObjectType(), - toType->getRValueType()) + toType->getRValueType(), dc) && "coercing super expr to non-supertype?!"); fromLValue = LValueType::get(toType->getRValueType(), fromLValue->getQualifiers(), @@ -2529,7 +2536,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, bool failed = false; for (auto proto : protocols) { ProtocolConformance *conformance = nullptr; - if (!tc.conformsToProtocol(fromType, proto, &conformance)) { + if (!tc.conformsToProtocol(fromType, proto, cs.DC, &conformance)) { failed = true; break; } @@ -2713,7 +2720,7 @@ Expr *ExprRewriter::convertLiteral(Expr *literal, // Check whether this literal type conforms to the builtin protocol. ProtocolConformance *builtinConformance = nullptr; - if (tc.conformsToProtocol(type, builtinProtocol, &builtinConformance)) { + if (tc.conformsToProtocol(type, builtinProtocol, cs.DC, &builtinConformance)){ // Find the builtin argument type we'll use. Type argType; if (builtinLiteralType.is()) @@ -2752,7 +2759,7 @@ Expr *ExprRewriter::convertLiteral(Expr *literal, // This literal type must conform to the (non-builtin) protocol. assert(protocol && "requirements should have stopped recursion"); ProtocolConformance *conformance = nullptr; - bool conforms = tc.conformsToProtocol(type, protocol, &conformance); + bool conforms = tc.conformsToProtocol(type, protocol, cs.DC, &conformance); assert(conforms && "must conform to literal protocol"); (void)conforms; @@ -2882,14 +2889,14 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType, return finishApply(apply, openedType, locator); } -static void substForBaseConversion(TypeChecker &tc, ValueDecl *member, - Type objectTy, +static void substForBaseConversion(TypeChecker &tc, DeclContext *dc, + ValueDecl *member, Type objectTy, MutableArrayRef otherTypes, SourceLoc loc, TypeSubstitutionMap &substitutions, ConformanceMap &conformances, GenericParamList *&genericParams) { - ConstraintSystem cs(tc, nullptr); + ConstraintSystem cs(tc, dc); // The archetypes that have been opened up and replaced with type variables. llvm::DenseMap replacements; @@ -2917,7 +2924,7 @@ static void substForBaseConversion(TypeChecker &tc, ValueDecl *member, } // Finalize the set of protocol conformances. - failed = tc.checkSubstitutions(substitutions, conformances, loc, + failed = tc.checkSubstitutions(substitutions, conformances, dc, loc, &substitutions); assert(!failed && "Substitutions cannot fail?"); @@ -2925,7 +2932,7 @@ static void substForBaseConversion(TypeChecker &tc, ValueDecl *member, for (auto &otherType : otherTypes) { // Replace the already-opened archetypes in the requested "other" type with // their replacements. - otherType = tc.substType(otherType, substitutions); + otherType = tc.substType(dc->getParentModule(), otherType, substitutions); // If we have a polymorphic function type for which all of the generic // parameters have been replaced, make it monomorphic. @@ -3107,7 +3114,7 @@ Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc, if (auto metaType = type->getAs()) type = metaType->getInstanceType(); - auto witness = findNamedWitness(*this, type->getRValueType(), protocol, + auto witness = findNamedWitness(*this, dc, type->getRValueType(), protocol, name, brokenProtocolDiag); if (!witness) return nullptr; @@ -3198,10 +3205,10 @@ static Expr *convertViaBuiltinProtocol(const Solution &solution, // Look for the builtin name. If we don't have it, we need to call the // general name via the witness table. - auto witnesses = tc.lookupMember(type->getRValueType(), builtinName); + auto witnesses = tc.lookupMember(type->getRValueType(), builtinName, cs.DC); if (!witnesses) { // Find the witness we need to use. - auto witness = findNamedWitness(tc, type->getRValueType(), protocol, + auto witness = findNamedWitness(tc, cs.DC, type->getRValueType(), protocol, generalName, brokenProtocolDiag); // Form a reference to the general name. @@ -3227,7 +3234,7 @@ static Expr *convertViaBuiltinProtocol(const Solution &solution, // At this point, we must have a type with the builtin member. type = expr->getType(); - witnesses = tc.lookupMember(type->getRValueType(), builtinName); + witnesses = tc.lookupMember(type->getRValueType(), builtinName, cs.DC); if (!witnesses) { tc.diagnose(protocol->getLoc(), brokenProtocolDiag); return nullptr; @@ -3346,7 +3353,8 @@ int Solution::getFixedScore() const { continue; // Retrieve the default type for this literal protocol, if there is one. - auto defaultType = tc.getDefaultType(literalProtocol); + auto defaultType = tc.getDefaultType(literalProtocol, + getConstraintSystem().DC); if (!defaultType) continue; diff --git a/lib/Sema/TypeCheckConstraintsDiag.cpp b/lib/Sema/TypeCheckConstraintsDiag.cpp index c5fc024b284..adcc67e92a3 100644 --- a/lib/Sema/TypeCheckConstraintsDiag.cpp +++ b/lib/Sema/TypeCheckConstraintsDiag.cpp @@ -534,6 +534,7 @@ static bool diagnoseFailure(ConstraintSystem &cs, Failure &failure) { tc.conformsToProtocol(failure.getFirstType(), failure.getSecondType()->castTo() ->getDecl(), + cs.DC, nullptr, loc); if (targetLocator) diff --git a/lib/Sema/TypeCheckConstraintsSolver.cpp b/lib/Sema/TypeCheckConstraintsSolver.cpp index 48f551b40b9..25733cde100 100644 --- a/lib/Sema/TypeCheckConstraintsSolver.cpp +++ b/lib/Sema/TypeCheckConstraintsSolver.cpp @@ -498,7 +498,7 @@ getPotentialBindings(ConstraintSystem &cs, // that protocol. auto &tc = cs.getTypeChecker(); for (auto constraint : tvc.ConformsToConstraints) { - if (auto type = tc.getDefaultType(constraint->getProtocol())) { + if (auto type = tc.getDefaultType(constraint->getProtocol(), cs.DC)) { // For non-generic literal types, just check for exact types. if (!type->isUnspecializedGeneric()) { if (exactTypes.insert(type->getCanonicalType())) { @@ -613,7 +613,7 @@ static bool tryTypeVariableBindings(ConstraintSystem &cs, // Only do this for protocols that have default types, i.e., protocols // for literals. - if (!tc.getDefaultType(proto)) + if (!tc.getDefaultType(proto, cs.DC)) continue; KnownProtocolKind knownKind = *proto->getKnownProtocolKind(); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index b0820a343f2..70a99d66a97 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -200,8 +200,15 @@ static void validateAttributes(TypeChecker &TC, Decl *VD); /// This routine validates all of the types in the parsed inheritance clause, /// recording the superclass (if any and if allowed) as well as the protocols /// to which this type declaration conforms. -void TypeChecker::checkInheritanceClause(Decl *decl, +void TypeChecker::checkInheritanceClause(Decl *decl, DeclContext *DC, GenericTypeResolver *resolver) { + if (!DC) { + if (auto nominal = dyn_cast(decl)) + DC = nominal; + else + DC = decl->getDeclContext(); + } + // Establish a default generic type resolver. PartialGenericTypeToArchetypeResolver defaultResolver(*this); if (!resolver) @@ -237,7 +244,7 @@ void TypeChecker::checkInheritanceClause(Decl *decl, auto &inherited = inheritedClause[i]; // Validate the type. - if (validateType(inherited, /*allowUnboundGenerics=*/false, resolver)) { + if (validateType(inherited, DC, /*allowUnboundGenerics=*/false, resolver)) { inherited.setInvalidType(Context); continue; } @@ -598,9 +605,9 @@ static CanType getExtendedType(ExtensionDecl *ED) { /// Create a fresh archetype builder. /// FIXME: Duplicated with TypeCheckGeneric.cpp; this one should go away. -static ArchetypeBuilder createArchetypeBuilder(TypeChecker &TC) { +static ArchetypeBuilder createArchetypeBuilder(TypeChecker &TC, Module *mod) { return ArchetypeBuilder( - TC.TU, TC.Diags, + *mod, TC.Diags, [&](ProtocolDecl *protocol) -> ArrayRef { return TC.getDirectConformsTo(protocol); }, @@ -732,7 +739,7 @@ static void revertDependentPattern(Pattern *pattern, DeclContext *dc) { /// yet. static void checkGenericParamList(ArchetypeBuilder &builder, GenericParamList *genericParams, - TypeChecker &TC) { + TypeChecker &TC, DeclContext *DC) { assert(genericParams && "Missing generic parameters"); unsigned Depth = genericParams->getDepth(); @@ -745,7 +752,7 @@ static void checkGenericParamList(ArchetypeBuilder &builder, TypeParam->setDepth(Depth); // Check the constraints on the type parameter. - TC.checkInheritanceClause(TypeParam); + TC.checkInheritanceClause(TypeParam, DC); // Add the generic parameter to the builder. builder.addGenericParameter(TypeParam, Index++); @@ -765,12 +772,12 @@ static void checkGenericParamList(ArchetypeBuilder &builder, switch (Req.getKind()) { case RequirementKind::Conformance: { // Validate the types. - if (TC.validateType(Req.getSubjectLoc())) { + if (TC.validateType(Req.getSubjectLoc(), DC)) { Req.setInvalid(); continue; } - if (TC.validateType(Req.getConstraintLoc())) { + if (TC.validateType(Req.getConstraintLoc(), DC)) { Req.setInvalid(); continue; } @@ -800,12 +807,12 @@ static void checkGenericParamList(ArchetypeBuilder &builder, } case RequirementKind::SameType: - if (TC.validateType(Req.getFirstTypeLoc())) { + if (TC.validateType(Req.getFirstTypeLoc(), DC)) { Req.setInvalid(); continue; } - if (TC.validateType(Req.getSecondTypeLoc())) { + if (TC.validateType(Req.getSecondTypeLoc(), DC)) { Req.setInvalid(); continue; } @@ -878,13 +885,13 @@ static void finalizeGenericParamList(ArchetypeBuilder &builder, switch (Req.getKind()) { case RequirementKind::Conformance: { revertDependentTypeLoc(Req.getSubjectLoc(), dc); - if (TC.validateType(Req.getSubjectLoc())) { + if (TC.validateType(Req.getSubjectLoc(), dc)) { Req.setInvalid(); continue; } revertDependentTypeLoc(Req.getConstraintLoc(), dc); - if (TC.validateType(Req.getConstraintLoc())) { + if (TC.validateType(Req.getConstraintLoc(), dc)) { Req.setInvalid(); continue; } @@ -893,13 +900,13 @@ static void finalizeGenericParamList(ArchetypeBuilder &builder, case RequirementKind::SameType: revertDependentTypeLoc(Req.getFirstTypeLoc(), dc); - if (TC.validateType(Req.getFirstTypeLoc())) { + if (TC.validateType(Req.getFirstTypeLoc(), dc)) { Req.setInvalid(); continue; } revertDependentTypeLoc(Req.getSecondTypeLoc(), dc); - if (TC.validateType(Req.getSecondTypeLoc())) { + if (TC.validateType(Req.getSecondTypeLoc(), dc)) { Req.setInvalid(); continue; } @@ -965,17 +972,17 @@ public: //===--------------------------------------------------------------------===// template - void gatherExplicitConformances(DeclType *D, Type T) { + void gatherExplicitConformances(DeclType *D, DeclContext *DC, Type T) { SmallVector conformances; for (auto proto : D->getProtocols()) { ProtocolConformance *conformance = nullptr; // FIXME: Better location info - if (TC.conformsToProtocol(T, proto, &conformance, + if (TC.conformsToProtocol(T, proto, DC, &conformance, D->getStartLoc(), D)) { // For nominal types and extensions thereof, record conformance // to known protocols. if (auto kind = proto->getKnownProtocolKind()) - if (isa(D) || isa(D)) + if (isa((Decl *)D) || isa((Decl *)D)) TC.Context.recordConformance(kind.getValue(), D); } conformances.push_back(conformance); @@ -984,12 +991,16 @@ public: D->setConformances(D->getASTContext().AllocateCopy(conformances)); } + void checkExplicitConformance(NominalTypeDecl *D, Type T) { + gatherExplicitConformances(D, D, T); + } + void checkExplicitConformance(TypeDecl *D, Type T) { - gatherExplicitConformances(D, T); + gatherExplicitConformances(D, D->getDeclContext(), T); } void checkExplicitConformance(ExtensionDecl *D, Type T) { - gatherExplicitConformances(D, T); + gatherExplicitConformances(D, D, T); } //===--------------------------------------------------------------------===// @@ -1062,11 +1073,7 @@ public: } void visitPatternBindingDecl(PatternBindingDecl *PBD) { - bool DelayCheckingPattern = - TC.TU.Kind != TranslationUnit::Library && - TC.TU.Kind != TranslationUnit::SIL && - PBD->getDeclContext()->isModuleContext(); - if (IsSecondPass && !DelayCheckingPattern) { + if (IsSecondPass) { if (PBD->getInit() && PBD->getPattern()->hasType()) { Expr *Init = PBD->getInit(); Type DestTy = PBD->getPattern()->getType(); @@ -1099,7 +1106,7 @@ public: setBoundVarsTypeError(PBD->getPattern(), TC.Context); return; } - } else if (!IsFirstPass || !DelayCheckingPattern) { + } else { if (TC.typeCheckPattern(PBD->getPattern(), PBD->getDeclContext(), /*allowUnknownTypes*/false)) { @@ -1118,7 +1125,8 @@ public: assert(SD->getDeclContext()->isTypeContext() && "Decl parsing must prevent subscripts outside of types!"); - bool isInvalid = TC.validateType(SD->getElementTypeLoc()); + bool isInvalid = TC.validateType(SD->getElementTypeLoc(), + SD->getDeclContext()); isInvalid |= TC.typeCheckPattern(SD->getIndices(), SD->getDeclContext(), /*allowUnknownTypes*/false); @@ -1151,7 +1159,7 @@ public: void visitTypeAliasDecl(TypeAliasDecl *TAD) { if (!IsSecondPass) { - if (TC.validateType(TAD->getUnderlyingTypeLoc())) { + if (TC.validateType(TAD->getUnderlyingTypeLoc(), TAD->getDeclContext())) { TAD->setInvalid(); TAD->overwriteType(ErrorType::get(TC.Context)); TAD->getUnderlyingTypeLoc().setType(ErrorType::get(TC.Context)); @@ -1174,10 +1182,10 @@ public: // If there was no previous value, start from zero. if (!prevValue) { // The raw type must be integer literal convertible for this to work. - if (!TC.conformsToProtocol(rawTy, - TC.getProtocol(forElt->getLoc(), - KnownProtocolKind::IntegerLiteralConvertible))) - { + ProtocolDecl *ilcProto = + TC.getProtocol(forElt->getLoc(), + KnownProtocolKind::IntegerLiteralConvertible); + if (!TC.conformsToProtocol(rawTy, ilcProto, forElt->getDeclContext())) { TC.diagnose(forElt->getLoc(), diag::enum_non_integer_convertible_raw_type_no_value); return nullptr; @@ -1222,14 +1230,15 @@ public: // Check that the raw type is convertible from one of the primitive // literal protocols. bool literalConvertible = false; - for (auto literalProtocol : { + for (auto literalProtoKind : { KnownProtocolKind::IntegerLiteralConvertible, KnownProtocolKind::StringLiteralConvertible, KnownProtocolKind::FloatLiteralConvertible, KnownProtocolKind::CharacterLiteralConvertible}) { - if (TC.conformsToProtocol(rawTy, - TC.getProtocol(ED->getLoc(), literalProtocol))) { + ProtocolDecl *literalProto = + TC.getProtocol(ED->getLoc(), literalProtoKind); + if (TC.conformsToProtocol(rawTy, literalProto, ED->getDeclContext())){ literalConvertible = true; break; } @@ -1472,7 +1481,7 @@ public: bool badType = false; if (!FD->getBodyResultTypeLoc().isNull()) { - if (TC.validateType(FD->getBodyResultTypeLoc(), + if (TC.validateType(FD->getBodyResultTypeLoc(), FD->getDeclContext(), /*allowUnboundGenerics=*/false, resolver)) { badType = true; @@ -1535,21 +1544,25 @@ public: /// the corresponding operator declaration. void bindFuncDeclToOperator(FuncDecl *FD) { OperatorDecl *op = nullptr; - auto &TU = TC.TU; + auto &module = *FD->getModuleContext(); if (FD->isUnaryOperator()) { if (FD->getAttrs().isPrefix()) { - if (auto maybeOp = TU.lookupPrefixOperator(FD->getName(), FD->getLoc())) + if (auto maybeOp = module.lookupPrefixOperator(FD->getName(), + FD->getLoc())) op = *maybeOp; else return; } else if (FD->getAttrs().isPostfix()) { - if (auto maybeOp = TU.lookupPostfixOperator(FD->getName(),FD->getLoc())) + if (auto maybeOp = module.lookupPostfixOperator(FD->getName(), + FD->getLoc())) op = *maybeOp; else return; } else { - auto prefixOp = TU.lookupPrefixOperator(FD->getName(), FD->getLoc()); - auto postfixOp = TU.lookupPostfixOperator(FD->getName(), FD->getLoc()); + auto prefixOp = module.lookupPrefixOperator(FD->getName(), + FD->getLoc()); + auto postfixOp = module.lookupPostfixOperator(FD->getName(), + FD->getLoc()); // If we found both prefix and postfix, or neither prefix nor postfix, // complain. We can't fix this situation. @@ -1597,7 +1610,7 @@ public: static_cast(postfixOp)); } } else if (FD->isBinaryOperator()) { - if (auto maybeOp = TU.lookupInfixOperator(FD->getName(), FD->getLoc())) + if (auto maybeOp = module.lookupInfixOperator(FD->getName(), FD->getLoc())) op = *maybeOp; else { // FIXME: Add Fix-It introducing an operator declaration? @@ -1649,8 +1662,9 @@ public: isInvalid = true; else { // Create a fresh archetype builder. - ArchetypeBuilder builder = createArchetypeBuilder(TC); - checkGenericParamList(builder, gp, TC); + ArchetypeBuilder builder = + createArchetypeBuilder(TC, FD->getModuleContext()); + checkGenericParamList(builder, gp, TC, FD->getDeclContext()); // Infer requirements from parameter patterns. for (auto pattern : FD->getArgParamPatterns()) { @@ -1718,13 +1732,13 @@ public: Type ElemTy = UD->getDeclaredTypeInContext(); if (!ED->getArgumentTypeLoc().isNull()) - if (TC.validateType(ED->getArgumentTypeLoc())) { + if (TC.validateType(ED->getArgumentTypeLoc(), ED->getDeclContext())) { ED->overwriteType(ErrorType::get(TC.Context)); ED->setInvalid(); return; } if (!ED->getResultTypeLoc().isNull()) { - if (TC.validateType(ED->getResultTypeLoc())) { + if (TC.validateType(ED->getResultTypeLoc(), ED->getDeclContext())) { ED->overwriteType(ErrorType::get(TC.Context)); ED->setInvalid(); return; @@ -1856,8 +1870,10 @@ public: CD->overwriteType(ErrorType::get(TC.Context)); CD->setInvalid(); } else { - ArchetypeBuilder builder = createArchetypeBuilder(TC); - checkGenericParamList(builder, gp, TC); + ArchetypeBuilder builder = + createArchetypeBuilder(TC, + CD->getModuleContext()); + checkGenericParamList(builder, gp, TC, CD->getDeclContext()); // Type check the constructor parameters. if (TC.typeCheckPattern(CD->getArgParams(), @@ -2008,7 +2024,8 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) { // Type aliases may not have an underlying type yet. auto typeAlias = cast(D); if (typeAlias->getUnderlyingTypeLoc().getTypeRepr()) - validateType(typeAlias->getUnderlyingTypeLoc()); + validateType(typeAlias->getUnderlyingTypeLoc(), + typeAlias->getDeclContext()); break; } @@ -2066,8 +2083,9 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) { revertGenericParamList(nominal->getGenericParams(), nominal); - ArchetypeBuilder builder = createArchetypeBuilder(*this); - checkGenericParamList(builder, gp, *this); + ArchetypeBuilder builder = + createArchetypeBuilder(*this, nominal->getModuleContext()); + checkGenericParamList(builder, gp, *this, nominal->getDeclContext()); finalizeGenericParamList(builder, gp, nominal, *this); } @@ -2120,7 +2138,8 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) { assert(selfDecl && "no Self decl?"); // Build archetypes for this protocol. - ArchetypeBuilder builder = createArchetypeBuilder(*this); + ArchetypeBuilder builder = createArchetypeBuilder(*this, + D->getModuleContext()); builder.addGenericParameter(selfDecl, 0); builder.addImplicitConformance(selfDecl, proto); builder.assignArchetypes(); @@ -2380,7 +2399,8 @@ void TypeChecker::addImplicitDestructor(ClassDecl *CD) { CD->setMembers(Context.AllocateCopy(Members), CD->getBraces()); } -bool TypeChecker::isDefaultInitializable(Type ty, Expr **initializer, +bool TypeChecker::isDefaultInitializable(Type ty, Expr **initializer, + DeclContext *dc, bool useConstructor) { CanType canTy = ty->getCanonicalType(); switch (canTy->getKind()) { @@ -2443,7 +2463,8 @@ bool TypeChecker::isDefaultInitializable(Type ty, Expr **initializer, // Check whether the element is default-initializable. Expr *eltInit = nullptr; if (!isDefaultInitializable(elt.getType(), - initializer? &eltInit : nullptr)) + initializer? &eltInit : nullptr, + dc)) return false; // If we need to produce an initializer, add this element. @@ -2497,7 +2518,7 @@ bool TypeChecker::isDefaultInitializable(Type ty, Expr **initializer, } // We need to look for a default constructor. - auto ctors = lookupConstructors(ty); + auto ctors = lookupConstructors(ty, dc); if (!ctors) return false; @@ -2578,7 +2599,7 @@ void TypeChecker::defineDefaultConstructor(NominalTypeDecl *decl) { // If this variable is not default-initializable, we're done: we can't // add the default constructor because it will be ill-formed. - if (!isDefaultInitializable(getTypeOfRValue(var), nullptr)) + if (!isDefaultInitializable(getTypeOfRValue(var), nullptr, decl)) return; } } @@ -2587,7 +2608,8 @@ void TypeChecker::defineDefaultConstructor(NominalTypeDecl *decl) { // default-initializable. if (isa(decl)) { if (auto superTy = getSuperClassOf(decl->getDeclaredTypeInContext())) { - if (!isDefaultInitializable(superTy, nullptr, /*useConstructor=*/true)) + if (!isDefaultInitializable(superTy, nullptr, decl, + /*useConstructor=*/true)) return; } } diff --git a/lib/Sema/TypeCheckExpr.cpp b/lib/Sema/TypeCheckExpr.cpp index adc5c6d6953..5a3502144cd 100644 --- a/lib/Sema/TypeCheckExpr.cpp +++ b/lib/Sema/TypeCheckExpr.cpp @@ -137,7 +137,7 @@ Expr *TypeChecker::buildArrayInjectionFnRef(DeclContext *dc, /// getInfixData - If the specified expression is an infix binary /// operator, return its infix operator attributes. -static InfixData getInfixData(TypeChecker &TC, Expr *E) { +static InfixData getInfixData(TypeChecker &TC, DeclContext *DC, Expr *E) { if (auto *ifExpr = dyn_cast(E)) { // Ternary has fixed precedence. assert(!ifExpr->isFolded() && "already folded if expr in sequence?!"); @@ -154,16 +154,20 @@ static InfixData getInfixData(TypeChecker &TC, Expr *E) { (void)as; return InfixData(95, Associativity::None); } else if (DeclRefExpr *DRE = dyn_cast(E)) { - if (Optional maybeOp - = TC.TU.lookupInfixOperator(DRE->getDecl()->getName(), E->getLoc())) { + Module *mod = DC->getParentModule(); + Optional maybeOp + = mod->lookupInfixOperator(DRE->getDecl()->getName(), E->getLoc()); + if (maybeOp) { if (auto *op = *maybeOp) return op->getInfixData(); TC.diagnose(DRE->getLoc(), diag::unknown_binop); } } else if (OverloadedDeclRefExpr *OO = dyn_cast(E)) { + Module *mod = DC->getParentModule(); Identifier name = OO->getDecls()[0]->getName(); - if (Optional maybeOp - = TC.TU.lookupInfixOperator(name, E->getLoc())) { + Optional maybeOp + = mod->lookupInfixOperator(name, E->getLoc()); + if (maybeOp) { if (auto *op = *maybeOp) return op->getInfixData(); TC.diagnose(OO->getLoc(), diag::unknown_binop); @@ -219,7 +223,7 @@ static Expr *makeBinOp(TypeChecker &TC, Expr *Op, Expr *LHS, Expr *RHS) { /// foldSequence - Take a sequence of expressions and fold a prefix of /// it into a tree of BinaryExprs using precedence parsing. -static Expr *foldSequence(TypeChecker &TC, +static Expr *foldSequence(TypeChecker &TC, DeclContext *DC, Expr *LHS, ArrayRef &S, unsigned MinPrecedence) { @@ -240,7 +244,7 @@ static Expr *foldSequence(TypeChecker &TC, Expr *op = S[0]; // If the operator's precedence is lower than the minimum, stop here. - InfixData opInfo = getInfixData(TC, op); + InfixData opInfo = getInfixData(TC, DC, op); if (opInfo.getPrecedence() < MinPrecedence) return {nullptr, {}}; return {op, opInfo}; }; @@ -262,7 +266,7 @@ static Expr *foldSequence(TypeChecker &TC, // Pull out the next binary operator. Expr *Op2 = S[0]; - InfixData Op2Info = getInfixData(TC, Op2); + InfixData Op2Info = getInfixData(TC, DC, Op2); // If the second operator's precedence is lower than the min // precedence, break out of the loop. if (Op2Info.getPrecedence() < MinPrecedence) break; @@ -285,7 +289,7 @@ static Expr *foldSequence(TypeChecker &TC, // higher-precedence operators starting from this point, then // repeat. if (Op1.infixData.getPrecedence() < Op2Info.getPrecedence()) { - RHS = foldSequence(TC, RHS, S, Op1.infixData.getPrecedence() + 1); + RHS = foldSequence(TC, DC, RHS, S, Op1.infixData.getPrecedence() + 1); continue; } @@ -294,14 +298,14 @@ static Expr *foldSequence(TypeChecker &TC, // recursively fold operators starting from this point, then // immediately fold LHS and RHS. if (Op1.infixData == Op2Info && Op1.infixData.isRightAssociative()) { - RHS = foldSequence(TC, RHS, S, Op1.infixData.getPrecedence()); + RHS = foldSequence(TC, DC, RHS, S, Op1.infixData.getPrecedence()); LHS = makeBinOp(TC, Op1.op, LHS, RHS); // If we've drained the entire sequence, we're done. if (S.empty()) return LHS; // Otherwise, start all over with our new LHS. - return foldSequence(TC, LHS, S, MinPrecedence); + return foldSequence(TC, DC, LHS, S, MinPrecedence); } // If we ended up here, it's because we have two operators @@ -321,7 +325,7 @@ static Expr *foldSequence(TypeChecker &TC, // Recover by arbitrarily binding the first two. LHS = makeBinOp(TC, Op1.op, LHS, RHS); - return foldSequence(TC, LHS, S, MinPrecedence); + return foldSequence(TC, DC, LHS, S, MinPrecedence); } // Fold LHS and RHS together and declare completion. @@ -419,8 +423,10 @@ Expr *TypeChecker::buildRefExpr(ArrayRef Decls, SourceLoc NameLoc, return result; } -static Type lookupGlobalType(TypeChecker &TC, StringRef name) { - UnqualifiedLookup lookup(TC.Context.getIdentifier(name), &TC.TU, nullptr); +static Type lookupGlobalType(TypeChecker &TC, DeclContext *dc, StringRef name) { + UnqualifiedLookup lookup(TC.Context.getIdentifier(name), + dc->getParentModule(), + nullptr); TypeDecl *TD = lookup.getSingleTypeResult(); if (!TD) return Type(); @@ -428,7 +434,7 @@ static Type lookupGlobalType(TypeChecker &TC, StringRef name) { } -Type TypeChecker::getDefaultType(ProtocolDecl *protocol) { +Type TypeChecker::getDefaultType(ProtocolDecl *protocol, DeclContext *dc) { Type *type = nullptr; const char *name = nullptr; @@ -481,7 +487,10 @@ Type TypeChecker::getDefaultType(ProtocolDecl *protocol) { // If we haven't found the type yet, look for it now. if (!*type) { - *type = lookupGlobalType(*this, name); + *type = lookupGlobalType(*this, dc, name); + + if (!*type) + *type = lookupGlobalType(*this, getStdlibModule(), name); // Strip off one level of sugar; we don't actually want to print // the name of the typealias itself anywhere. @@ -494,7 +503,7 @@ Type TypeChecker::getDefaultType(ProtocolDecl *protocol) { return *type; } -Expr *TypeChecker::foldSequence(SequenceExpr *expr) { +Expr *TypeChecker::foldSequence(SequenceExpr *expr, DeclContext *dc) { ArrayRef Elts = expr->getElements(); assert(Elts.size() > 1 && "inadequate number of elements in sequence"); assert((Elts.size() & 1) == 1 && "even number of elements in sequence"); @@ -502,7 +511,7 @@ Expr *TypeChecker::foldSequence(SequenceExpr *expr) { Expr *LHS = Elts[0]; Elts = Elts.slice(1); - Expr *Result = ::foldSequence(*this, LHS, Elts, /*min precedence*/ 0); + Expr *Result = ::foldSequence(*this, dc, LHS, Elts, /*min precedence*/ 0); assert(Elts.empty()); return Result; } diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index 8ec69f99bd0..05f579ca3e0 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -27,6 +27,7 @@ Type DependentGenericTypeResolver::resolveGenericTypeParamType( Type DependentGenericTypeResolver::resolveDependentMemberType( Type baseTy, + DeclContext *DC, SourceRange baseRange, Identifier name, SourceLoc nameLoc) { @@ -47,6 +48,7 @@ Type GenericTypeToArchetypeResolver::resolveGenericTypeParamType( Type GenericTypeToArchetypeResolver::resolveDependentMemberType( Type baseTy, + DeclContext *DC, SourceRange baseRange, Identifier name, SourceLoc nameLoc) { @@ -69,6 +71,7 @@ Type PartialGenericTypeToArchetypeResolver::resolveGenericTypeParamType( Type PartialGenericTypeToArchetypeResolver::resolveDependentMemberType( Type baseTy, + DeclContext *DC, SourceRange baseRange, Identifier name, SourceLoc nameLoc) { @@ -92,6 +95,7 @@ Type CompleteGenericTypeResolver::resolveGenericTypeParamType( Type CompleteGenericTypeResolver::resolveDependentMemberType( Type baseTy, + DeclContext *DC, SourceRange baseRange, Identifier name, SourceLoc nameLoc) { @@ -103,8 +107,9 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType( // Find the associated type declaration for this name. for (auto proto : basePA->getConformsTo()) { SmallVector decls; - if (TC.TU.lookupQualified(proto->getDeclaredType(), name, - NL_VisitSupertypes, nullptr, decls)) { + if (Builder.getModule().lookupQualified(proto->getDeclaredType(), name, + NL_VisitSupertypes, nullptr, + decls)) { for (auto decl : decls) { // Note: once we find any associated type, we have our answer, because // the archetype builder is supposed to ensure that all associated @@ -119,7 +124,7 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType( // Check whether the name can be found in the superclass. if (auto superclassTy = basePA->getSuperclass()) { - if (auto lookup = TC.lookupMemberType(superclassTy, name)) { + if (auto lookup = TC.lookupMemberType(superclassTy, name, DC)) { if (lookup.isAmbiguous()) { TC.diagnoseAmbiguousMemberType(baseTy, baseRange, name, nameLoc, lookup); @@ -138,9 +143,9 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType( } /// Create a fresh archetype builder. -static ArchetypeBuilder createArchetypeBuilder(TypeChecker &TC) { +static ArchetypeBuilder createArchetypeBuilder(TypeChecker &TC, Module *mod) { return ArchetypeBuilder( - TC.TU, TC.Diags, + *mod, TC.Diags, [&](ProtocolDecl *protocol) -> ArrayRef { return TC.getDirectConformsTo(protocol); }, @@ -203,7 +208,7 @@ static bool checkGenericParameters(TypeChecker &tc, ArchetypeBuilder *builder, typeParam->setDepth(depth); // Check the inheritance clause of this type parameter. - tc.checkInheritanceClause(typeParam, &resolver); + tc.checkInheritanceClause(typeParam, parentDC, &resolver); if (builder) { // Add the generic parameter to the builder. @@ -230,7 +235,7 @@ static bool checkGenericParameters(TypeChecker &tc, ArchetypeBuilder *builder, switch (req.getKind()) { case RequirementKind::Conformance: { // Validate the types. - if (tc.validateType(req.getSubjectLoc(), + if (tc.validateType(req.getSubjectLoc(), parentDC, /*allowUnboundGenerics=*/false, &resolver)) { invalid = true; @@ -238,7 +243,7 @@ static bool checkGenericParameters(TypeChecker &tc, ArchetypeBuilder *builder, continue; } - if (tc.validateType(req.getConstraintLoc(), + if (tc.validateType(req.getConstraintLoc(), parentDC, /*allowUnboundGenerics=*/false, &resolver)) { invalid = true; @@ -272,7 +277,7 @@ static bool checkGenericParameters(TypeChecker &tc, ArchetypeBuilder *builder, } case RequirementKind::SameType: - if (tc.validateType(req.getFirstTypeLoc(), + if (tc.validateType(req.getFirstTypeLoc(), parentDC, /*allowUnboundGenerics=*/false, &resolver)) { invalid = true; @@ -280,7 +285,7 @@ static bool checkGenericParameters(TypeChecker &tc, ArchetypeBuilder *builder, continue; } - if (tc.validateType(req.getSecondTypeLoc(), + if (tc.validateType(req.getSecondTypeLoc(), parentDC, /*allowUnboundGenerics=*/false, &resolver)) { invalid = true; @@ -368,7 +373,7 @@ namespace { /// potential archetypes to the set of requirements. static void addRequirements( - TranslationUnit &tu, Type type, + Module &mod, Type type, ArchetypeBuilder::PotentialArchetype *pa, llvm::SmallPtrSet &knownPAs, SmallVectorImpl &requirements) { @@ -400,13 +405,13 @@ addRequirements( auto rep = nested.second->getRepresentative(); if (knownPAs.insert(rep)) { // Form the dependent type that refers to this archetype. - auto assocType = pa->getAssociatedType(tu, nested.first); + auto assocType = pa->getAssociatedType(mod, nested.first); if (!assocType) continue; // FIXME: If we do this late enough, there will be no failure. auto nestedType = DependentMemberType::get(type, assocType, - tu.getASTContext()); - addRequirements(tu, nestedType, rep, knownPAs, requirements); + mod.getASTContext()); + addRequirements(mod, nestedType, rep, knownPAs, requirements); } } } @@ -439,7 +444,7 @@ static void collectRequirements(ArchetypeBuilder &builder, // along with the requirements of its nested types. for (auto param : primary) { auto pa = builder.resolveType(param)->getRepresentative(); - addRequirements(builder.getTranslationUnit(), param, pa, knownPAs, + addRequirements(builder.getModule(), param, pa, knownPAs, requirements); } } @@ -477,7 +482,7 @@ static bool checkGenericFuncSignature(TypeChecker &tc, if (auto fn = dyn_cast(func)) { if (!fn->getBodyResultTypeLoc().isNull()) { // Check the result type of the function. - if (tc.validateType(fn->getBodyResultTypeLoc(), + if (tc.validateType(fn->getBodyResultTypeLoc(), fn, /*allowUnboundGenerics=*/false, &resolver)) { badType = true; @@ -533,7 +538,8 @@ static Type computeSelfType(AbstractFunctionDecl *func, bool TypeChecker::validateGenericFuncSignature(AbstractFunctionDecl *func) { // Create the archetype builder. - ArchetypeBuilder builder = createArchetypeBuilder(*this); + ArchetypeBuilder builder = createArchetypeBuilder(*this, + func->getParentModule()); // Type check the function declaration, treating all generic type // parameters as dependent, unresolved. @@ -654,7 +660,8 @@ bool TypeChecker::validateGenericTypeSignature(NominalTypeDecl *nominal) { assert(nominal->getGenericParams() && "Missing generic parameters?"); // Create the archetype builder. - ArchetypeBuilder builder = createArchetypeBuilder(*this); + Module *module = nominal->getModuleContext(); + ArchetypeBuilder builder = createArchetypeBuilder(*this, module); // Type check the generic parameters, treating all generic type // parameters as dependent, unresolved. @@ -761,6 +768,7 @@ void TypeChecker::encodeSubstitutions(const GenericParamList *GenericParams, bool TypeChecker::checkSubstitutions(TypeSubstitutionMap &Substitutions, ConformanceMap &Conformance, + DeclContext *DC, SourceLoc ComplainLoc, TypeSubstitutionMap *RecordSubstitutions) { // FIXME: We want to migrate to a world where we don't need ComplainLoc, and @@ -786,7 +794,7 @@ bool TypeChecker::checkSubstitutions(TypeSubstitutionMap &Substitutions, // Substitute our deductions into the archetype type to produce the // concrete type we need to evaluate. - Type T = substType(archetype, Substitutions); + Type T = substType(DC->getParentModule(), archetype, Substitutions); if (!T) return true; @@ -796,7 +804,7 @@ bool TypeChecker::checkSubstitutions(TypeSubstitutionMap &Substitutions, // If the archetype has a superclass requirement, check that now. if (auto superclass = archetype->getSuperclass()) { - if (!isSubtypeOf(T, superclass)) { + if (!isSubtypeOf(T, superclass, DC)) { if (ComplainLoc.isValid()) { diagnose(ComplainLoc, diag::type_does_not_inherit, T, superclass); // FIXME: Show where the requirement came from? @@ -810,7 +818,7 @@ bool TypeChecker::checkSubstitutions(TypeSubstitutionMap &Substitutions, if (Conformances.empty()) { for (auto Proto : archetype->getConformsTo()) { ProtocolConformance *Conformance = nullptr; - if (conformsToProtocol(T, Proto, &Conformance, ComplainLoc)) { + if (conformsToProtocol(T, Proto, DC, &Conformance, ComplainLoc)) { Conformances.push_back(Conformance); } else { return true; diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index e4a068ed2f6..8ed29b24223 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -30,6 +30,7 @@ void LookupResult::filter(const std::function &pred) { } LookupResult TypeChecker::lookupMember(Type type, Identifier name, + DeclContext *dc, bool allowDynamicLookup) { LookupResult result; unsigned options = NL_QualifiedDefault; @@ -69,13 +70,15 @@ LookupResult TypeChecker::lookupMember(Type type, Identifier name, } // Look for the member. - if (!TU.lookupQualified(type, name, options, this, result.Results)) + if (!dc->getParentModule()->lookupQualified(type, name, options, this, + result.Results)) return result; return result; } -LookupTypeResult TypeChecker::lookupMemberType(Type type, Identifier name) { +LookupTypeResult TypeChecker::lookupMemberType(Type type, Identifier name, + DeclContext *dc) { LookupTypeResult result; // Look through the metatype. @@ -88,7 +91,7 @@ LookupTypeResult TypeChecker::lookupMemberType(Type type, Identifier name) { // Look for members with the given name. SmallVector decls; unsigned options = NL_QualifiedDefault | NL_ProtocolMembers; - if (!TU.lookupQualified(type, name, options, this, decls)) + if (!dc->getParentModule()->lookupQualified(type, name, options, this, decls)) return result; // Look through the declarations, keeping only the unique type declarations. @@ -120,7 +123,8 @@ LookupTypeResult TypeChecker::lookupMemberType(Type type, Identifier name) { // member entirely. // FIXME: This is an error path. Should we try to recover? ProtocolConformance *conformance = nullptr; - if (!conformsToProtocol(type, protocol, &conformance) || !conformance) + if (!conformsToProtocol(type, protocol, dc, &conformance) || + !conformance) continue; // Use the type witness. @@ -134,7 +138,8 @@ LookupTypeResult TypeChecker::lookupMemberType(Type type, Identifier name) { // type of the declaration. if (!memberType) { // Substitute the the base into the member's type. - memberType = substMemberTypeWithBase(typeDecl->getDeclaredType(), + memberType = substMemberTypeWithBase(dc->getParentModule(), + typeDecl->getDeclaredType(), typeDecl, type); } if (!memberType) @@ -148,8 +153,8 @@ LookupTypeResult TypeChecker::lookupMemberType(Type type, Identifier name) { return result; } -LookupResult TypeChecker::lookupConstructors(Type type) { +LookupResult TypeChecker::lookupConstructors(Type type, DeclContext *dc) { // FIXME: Use of string literal here is lame. - return lookupMember(type, Context.getIdentifier("init"), + return lookupMember(type, Context.getIdentifier("init"), dc, /*allowDynamicLookup=*/false); } diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index c6f675e218b..aac23c15856 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -159,10 +159,11 @@ public: return false; // Find a type member by the given name. - lookup = TC.lookupMemberType(td->getDeclaredType(), ude->getName()); + lookup = TC.lookupMemberType(td->getDeclaredType(), ude->getName(), + rootDC); } else if (Module *m = curScope.dyn_cast()) { // Look into the module. - lookup = TC.lookupMemberType(ModuleType::get(m), ude->getName()); + lookup = TC.lookupMemberType(ModuleType::get(m), ude->getName(), rootDC); } else llvm_unreachable("invalid curType"); @@ -190,7 +191,7 @@ public: // constrained extensions would change this), but apply the parameters for // validation and source tracking purposes. - curType = TC.applyGenericArguments(curType, use->getLoc(), + curType = TC.applyGenericArguments(curType, use->getLoc(), rootDC, use->getUnresolvedParams(), nullptr); if (!curType) @@ -220,7 +221,7 @@ lookupEnumMemberElement(TypeChecker &TC, Type ty, Identifier name) { return nullptr; // Look up the case inside the enum. - LookupResult foundElements = TC.lookupMember(ty, name, + LookupResult foundElements = TC.lookupMember(ty, name, oof, /*allowDynamicLookup=*/false); if (!foundElements) return nullptr; @@ -490,14 +491,15 @@ Pattern *TypeChecker::resolvePattern(Pattern *P, DeclContext *DC) { return ResolvePattern(*this, DC).visit(P); } -static bool validateTypedPattern(TypeChecker &TC, TypedPattern *TP, - bool isVararg, GenericTypeResolver *resolver) { +static bool validateTypedPattern(TypeChecker &TC, DeclContext *DC, + TypedPattern *TP, bool isVararg, + GenericTypeResolver *resolver) { if (TP->hasType()) return TP->getType()->is(); bool hadError = false; TypeLoc &TL = TP->getTypeLoc(); - if (TC.validateType(TL, /*allowUnboundGenerics=*/false, resolver)) + if (TC.validateType(TL, DC, /*allowUnboundGenerics=*/false, resolver)) hadError = true; Type Ty = TL.getType(); @@ -547,7 +549,7 @@ bool TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc, // that type. case PatternKind::Typed: { TypedPattern *TP = cast(P); - bool hadError = validateTypedPattern(*this, TP, isVararg, resolver); + bool hadError = validateTypedPattern(*this, dc, TP, isVararg, resolver); hadError |= coerceToType(TP->getSubPattern(), dc, P->getType(), false, resolver); return hadError; @@ -633,7 +635,7 @@ bool TypeChecker::coerceToType(Pattern *P, DeclContext *dc, Type type, // that type. case PatternKind::Typed: { TypedPattern *TP = cast(P); - bool hadError = validateTypedPattern(*this, TP, isVararg, resolver); + bool hadError = validateTypedPattern(*this, dc, TP, isVararg, resolver); if (!hadError) { if (!type->isEqual(TP->getType()) && !type->is()) { // Complain if the types don't match exactly. @@ -732,11 +734,11 @@ bool TypeChecker::coerceToType(Pattern *P, DeclContext *dc, Type type, auto IP = cast(P); // Type-check the type parameter. - if (validateType(IP->getCastTypeLoc())) + if (validateType(IP->getCastTypeLoc(), dc)) return nullptr; CheckedCastKind castKind - = typeCheckCheckedCast(type, IP->getCastTypeLoc().getType(), + = typeCheckCheckedCast(type, IP->getCastTypeLoc().getType(), dc, IP->getLoc(), IP->getLoc(),IP->getCastTypeLoc().getSourceRange(), [](Type) { return false; }); @@ -800,7 +802,7 @@ bool TypeChecker::coerceToType(Pattern *P, DeclContext *dc, Type type, auto NP = cast(P); // Type-check the type. - if (validateType(NP->getCastTypeLoc())) + if (validateType(NP->getCastTypeLoc(), dc)) return nullptr; Type patTy = NP->getCastTypeLoc().getType(); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 32124b79518..f4004e05acc 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -151,7 +151,7 @@ static SmallVector decomposeIntoTupleElements(Type type) { /// /// \returns the result of performing the match. static RequirementMatch -matchWitness(TypeChecker &tc, ProtocolDecl *protocol, +matchWitness(TypeChecker &tc, ProtocolDecl *protocol, DeclContext *dc, ValueDecl *req, Type reqType, Type model, ValueDecl *witness, ArrayRef unresolvedAssocTypes) { @@ -198,7 +198,8 @@ matchWitness(TypeChecker &tc, ProtocolDecl *protocol, // base type and ignore 'self'. if (witness->getDeclContext()->isTypeContext()) { witnessType = witness->getType()->castTo()->getResult(); - witnessType = tc.substMemberTypeWithBase(witnessType, witness, model); + witnessType = tc.substMemberTypeWithBase(dc->getParentModule(), + witnessType, witness, model); assert(witnessType && "Cannot refer to witness?"); } @@ -209,7 +210,8 @@ matchWitness(TypeChecker &tc, ProtocolDecl *protocol, // The witness type is the type of the declaration with the base // substituted. - witnessType = tc.substMemberTypeWithBase(witness->getType(), witness, + witnessType = tc.substMemberTypeWithBase(dc->getParentModule(), + witness->getType(), witness, model); assert(witnessType && "Cannot refer to witness?"); @@ -219,8 +221,7 @@ matchWitness(TypeChecker &tc, ProtocolDecl *protocol, // Construct a constraint system to use to solve the equality between // the required type and the witness type. - // FIXME: Pass the nominal/extension context in as the DeclContext? - constraints::ConstraintSystem cs(tc, &tc.TU); + constraints::ConstraintSystem cs(tc, dc); // Open up the type of the requirement and witness, replacing any unresolved // archetypes with type variables. @@ -343,7 +344,8 @@ matchWitness(TypeChecker &tc, ProtocolDecl *protocol, SmallVector conformances; for (auto archetypeProto : archetype->getConformsTo()) { ProtocolConformance *conformance = nullptr; - bool conformed = tc.conformsToProtocol(sub, archetypeProto, &conformance); + bool conformed = tc.conformsToProtocol(sub, archetypeProto, dc, + &conformance); assert(conformed && "archetype substitution did not conform to requirement?"); (void)conformed; @@ -358,10 +360,11 @@ matchWitness(TypeChecker &tc, ProtocolDecl *protocol, } /// \brief Determine whether one requirement match is better than the other. -static bool isBetterMatch(TypeChecker &tc, const RequirementMatch &match1, +static bool isBetterMatch(TypeChecker &tc, DeclContext *dc, + const RequirementMatch &match1, const RequirementMatch &match2) { // Check whether one declaration is better than the other. - switch (tc.compareDeclarations(match1.Witness, match2.Witness)) { + switch (tc.compareDeclarations(dc, match1.Witness, match2.Witness)) { case Comparison::Better: return true; @@ -461,6 +464,7 @@ diagnoseMatch(TypeChecker &tc, ValueDecl *req, /// Compute the substitution for the given archetype and its replacement /// type. static Substitution getArchetypeSubstitution(TypeChecker &tc, + DeclContext *dc, ArchetypeType *archetype, Type replacement) { Substitution result; @@ -471,7 +475,7 @@ static Substitution getArchetypeSubstitution(TypeChecker &tc, for (auto proto : archetype->getConformsTo()) { ProtocolConformance *conformance = nullptr; - bool conforms = tc.conformsToProtocol(replacement, proto, &conformance); + bool conforms = tc.conformsToProtocol(replacement, proto, dc, &conformance); assert(conforms && "Conformance should already have been verified"); (void)conforms; conformances.push_back(conformance); @@ -485,6 +489,7 @@ static Substitution getArchetypeSubstitution(TypeChecker &tc, /// recording the complete witness table if it does. static ProtocolConformance * checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, + DeclContext *DC, Decl *ExplicitConformance, SourceLoc ComplainLoc) { WitnessMap Mapping; @@ -502,7 +507,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, // Check that T conforms to all inherited protocols. for (auto InheritedProto : Proto->getProtocols()) { ProtocolConformance *InheritedConformance = nullptr; - if (TC.conformsToProtocol(T, InheritedProto, &InheritedConformance, + if (TC.conformsToProtocol(T, InheritedProto, DC, &InheritedConformance, ComplainLoc, ExplicitConformance)) { InheritedMapping[InheritedProto] = InheritedConformance; TypeMapping[InheritedProto->getSelf()->getArchetype()] = T; @@ -549,7 +554,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, continue; } - auto candidates = TC.lookupMemberType(metaT, AssociatedType->getName()); + auto candidates = TC.lookupMemberType(metaT, AssociatedType->getName(), DC); bool didDerive = false; // If we didn't find any matches, try to derive the conformance. @@ -581,7 +586,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, // FIXME: Check superclass requirement as well. bool SatisfiesRequirements = true; for (auto ReqProto : AssociatedType->getProtocols()) { - if (!TC.conformsToProtocol(candidate.second, ReqProto)){ + if (!TC.conformsToProtocol(candidate.second, ReqProto, DC)){ SatisfiesRequirements = false; NonViable.push_back({candidate.first, ReqProto}); @@ -600,7 +605,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, auto archetype = AssociatedType->getArchetype(); TypeMapping[archetype] = Viable.front().second; TypeWitnesses[AssociatedType] - = getArchetypeSubstitution(TC, archetype, Viable.front().second); + = getArchetypeSubstitution(TC, DC, archetype, Viable.front().second); continue; } @@ -703,14 +708,16 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, reqType = reqType->castTo()->getResult(); // Substitute the type mappings we have into the requirement type. - reqType = TC.substType(reqType, TypeMapping, /*IgnoreMissing=*/true); + reqType = TC.substType(DC->getParentModule(), reqType, TypeMapping, + /*IgnoreMissing=*/true); assert(reqType && "We didn't check our type mappings?"); // Gather the witnesses. SmallVector witnesses; if (Requirement->getName().isOperator()) { // Operator lookup is always global. - UnqualifiedLookup Lookup(Requirement->getName(), &TC.TU, &TC); + UnqualifiedLookup Lookup(Requirement->getName(), DC->getParentModule(), + &TC); if (Lookup.isSuccess()) { for (auto Candidate : Lookup.Results) { @@ -720,7 +727,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, } } else { // Variable/function/subscript requirements. - for (auto candidate : TC.lookupMember(metaT, Requirement->getName())) { + for (auto candidate : TC.lookupMember(metaT, Requirement->getName(), DC)){ witnesses.push_back(candidate); } } @@ -744,7 +751,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, if (!witness->hasType()) TC.validateDecl(witness, true); - auto match = matchWitness(TC, Proto, Requirement, reqType, T, witness, + auto match = matchWitness(TC, Proto, DC, Requirement, reqType, T, witness, unresolvedAssocTypes); if (match.isViable()) { ++numViable; @@ -771,7 +778,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, // Find the best match. bestIdx = 0; for (unsigned i = 1, n = matches.size(); i != n; ++i) { - if (isBetterMatch(TC, matches[i], matches[bestIdx])) + if (isBetterMatch(TC, DC, matches[i], matches[bestIdx])) bestIdx = i; } @@ -780,7 +787,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, if (i == bestIdx) continue; - if (!isBetterMatch(TC, matches[bestIdx], matches[i])) { + if (!isBetterMatch(TC, DC, matches[bestIdx], matches[i])) { isReallyBest = false; break; } @@ -808,7 +815,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, // Compute the archetype substitution. TypeWitnesses[assocType] - = getArchetypeSubstitution(TC, archetype, deduction.second); + = getArchetypeSubstitution(TC, DC, archetype, deduction.second); } // Remove the now-resolved associated types from the set of @@ -843,7 +850,7 @@ checkConformsToProtocol(TypeChecker &TC, Type T, ProtocolDecl *Proto, witnesses.push_back(derived); // If the compiler or stdlib is broken, the derived witness may not be // viable. - if (matchWitness(TC, Proto, Requirement, reqType, T, derived, + if (matchWitness(TC, Proto, DC, Requirement, reqType, T, derived, unresolvedAssocTypes).isViable()) { numViable = 1; continue; @@ -1112,7 +1119,8 @@ static void suggestExplicitConformance(TypeChecker &tc, // If the witness owner is not this translation unit, then we don't want // to suggest it as a place to hang the explicit conformance. - if (witnessOwner->getDeclContext()->getParentModule() != &tc.TU) + // FIXME: Distinguish user source files from imported source files. + if (!isa(witnessOwner->getModuleContext())) continue; // We have an owner. @@ -1224,6 +1232,7 @@ static bool existentialConformsToProtocol(TypeChecker &tc, Type type, } bool TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto, + DeclContext *DC, ProtocolConformance **Conformance, SourceLoc ComplainLoc, Decl *ExplicitConformance) { @@ -1298,7 +1307,8 @@ bool TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto, return false; } - auto lookupResult = TU.lookupConformance(T, Proto, this); + Module *M = DC->getParentModule(); + auto lookupResult = M->lookupConformance(T, Proto, this); switch (lookupResult.getInt()) { case ConformanceKind::Conforms: Context.ConformsTo[Key] = ConformanceEntry(lookupResult.getPointer(), @@ -1326,7 +1336,7 @@ bool TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto, Context.ConformsTo[Key] = ConformanceEntry(nullptr, false); // Check whether the type *implicitly* conforms to the protocol. - if (auto *result = checkConformsToProtocol(*this, T, Proto, nullptr, + if (auto *result = checkConformsToProtocol(*this, T, Proto, DC, nullptr, SourceLoc())) { // Success! Record the conformance in the cache. Context.ConformsTo[Key].setPointer(result); @@ -1356,8 +1366,8 @@ bool TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto, // whether it does in fact conform. This eliminates both infinite recursion // (if the protocol hierarchies are circular) as well as tautologies. Context.ConformsTo[Key] = ConformanceEntry(nullptr, false); - auto result = checkConformsToProtocol(*this, T, Proto, ExplicitConformance, - ComplainLoc); + auto result = checkConformsToProtocol(*this, T, Proto, DC, + ExplicitConformance, ComplainLoc); if (!result) return false; @@ -1372,10 +1382,11 @@ bool TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto, ProtocolConformance *TypeChecker::resolveConformance(NominalTypeDecl *type, ProtocolDecl *protocol, ExtensionDecl *ext) { - Decl *explicitConformance = ext? (Decl *)ext : (Decl *)type; + auto explicitConformance = ext ? (Decl *)ext : (Decl *)type; + auto conformanceContext = ext ? (DeclContext *)ext : (DeclContext *)type; ProtocolConformance *conformance = nullptr; bool conforms = conformsToProtocol(type->getDeclaredTypeInContext(), protocol, - &conformance, + conformanceContext, &conformance, explicitConformance->getLoc(), explicitConformance); return conforms? conformance : nullptr; diff --git a/lib/Sema/TypeCheckREPL.cpp b/lib/Sema/TypeCheckREPL.cpp index 3b68506da56..b693ca62628 100644 --- a/lib/Sema/TypeCheckREPL.cpp +++ b/lib/Sema/TypeCheckREPL.cpp @@ -71,7 +71,8 @@ PrintStruct(TypeChecker &TC, VarDecl *Arg, MemberIndexes.push_back(idx); Type SubstType = VD->getType(); - SubstType = TC.substMemberTypeWithBase(SubstType, VD, SugarT); + SubstType = TC.substMemberTypeWithBase(DC->getParentModule(), + SubstType, VD, SugarT); PrintReplExpr(TC, Arg, SubstType, SubstType->getCanonicalType(), Loc, EndLoc, MemberIndexes, @@ -94,7 +95,7 @@ getArgRefExpr(TypeChecker &TC, Expr *ArgRef = TC.buildCheckedRefExpr(Arg, Loc, /*Implicit=*/true); ArgRef = TC.coerceToRValue(ArgRef); for (unsigned i : MemberIndexes) { - bool failed = TC.typeCheckExpression(ArgRef, &TC.TU, Type(), + bool failed = TC.typeCheckExpression(ArgRef, Arg->getDeclContext(), Type(), /*discardedExpr=*/false); assert(!failed); (void)failed; @@ -109,11 +110,11 @@ getArgRefExpr(TypeChecker &TC, } if (BoundGenericStructType *BGST = dyn_cast(CurT)) { VarDecl *VD = cast(BGST->getDecl()->getMembers()[i]); + Module *M = Arg->getDeclContext()->getParentModule(); ArgRef = new (Context) MemberRefExpr( ArgRef, Loc, ConcreteDeclRef(Context, VD, - BGST->getSubstitutions(&TC.TU, - &TC)), + BGST->getSubstitutions(M, &TC)), Loc, /*Implicit=*/true); continue; } @@ -141,7 +142,8 @@ PrintClass(TypeChecker &TC, VarDecl *Arg, bool showedDynamicType = false; Identifier MemberName = Context.getIdentifier("className"); Type MetaT = MetaTypeType::get(SugarT, Context); - if (TC.lookupMember(MetaT,MemberName, /*allowDynamicLookup=*/false)){ + if (TC.lookupMember(MetaT, MemberName, CD, + /*allowDynamicLookup=*/false)){ Expr *ArgRef = getArgRefExpr(TC, Arg, MemberIndexes, Loc); MetatypeExpr *Meta = new (Context) MetatypeExpr(ArgRef, Loc, @@ -218,7 +220,7 @@ PrintCollection(TypeChecker &TC, VarDecl *Arg, Type KeyTy, Type ValueTy, Expr *init = TC.buildCheckedRefExpr(trueDecl, Loc, /*Implicit=*/true); BodyContent.push_back(new (context) PatternBindingDecl(Loc, pattern, init, - &TC.TU)); + DC)); } // Add opening bracket '['. @@ -349,7 +351,8 @@ PrintReplExpr(TypeChecker &TC, VarDecl *Arg, } Identifier MemberName = Context.getIdentifier("replPrint"); - if (TC.lookupMember(T, MemberName, /*allowDynamicLookup=*/false)) { + if (TC.lookupMember(T, MemberName, DC, + /*allowDynamicLookup=*/false)) { Expr *ArgRef = getArgRefExpr(TC, Arg, MemberIndexes, Loc); Expr *Res = new (TC.Context) UnresolvedDotExpr(ArgRef, Loc, MemberName, EndLoc, /*Implicit=*/true); @@ -419,7 +422,7 @@ PrintReplExpr(TypeChecker &TC, VarDecl *Arg, BodyContent); } -Identifier TypeChecker::getNextResponseVariableName() { +Identifier TypeChecker::getNextResponseVariableName(DeclContext *DC) { llvm::SmallString<4> namebuf; llvm::raw_svector_ostream names(namebuf); Identifier ident; @@ -432,7 +435,7 @@ Identifier TypeChecker::getNextResponseVariableName() { names << "r" << NextResponseVariableIndex++; ident = Context.getIdentifier(names.str()); - UnqualifiedLookup lookup(ident, &TU, this); + UnqualifiedLookup lookup(ident, DC, this); nameUsed = lookup.isSuccess(); } while (nameUsed); @@ -501,7 +504,7 @@ struct PatternBindingPrintLHS : public ASTVisitor { /// generatePrintOfExpression - Emit logic to print the specified expression /// value with the given description of the pattern involved. static void generatePrintOfExpression(StringRef NameStr, Expr *E, - TypeChecker *TC) { + TypeChecker *TC, TranslationUnit *TU) { ASTContext &C = TC->Context; // Always print rvalues, not lvalues. @@ -533,7 +536,7 @@ static void generatePrintOfExpression(StringRef NameStr, Expr *E, Arg->getDeclContext(), /*allowUnknownTypes*/false); ClosureExpr *CE = - new (C) ClosureExpr(ParamPat, SourceLoc(), TypeLoc(), &TC->TU); + new (C) ClosureExpr(ParamPat, SourceLoc(), TypeLoc(), TU); Type FuncTy = FunctionType::get(ParamPat->getType(), TupleType::getEmpty(C), C); CE->setType(FuncTy); @@ -573,7 +576,7 @@ static void generatePrintOfExpression(StringRef NameStr, Expr *E, // Inject the call into the top level stream by wrapping it with a TLCD. auto *BS = BraceStmt::create(C, Loc, BraceStmt::ExprStmtOrDecl(TheCall), EndLoc); - TC->TU.Decls.push_back(new (C) TopLevelCodeDecl(&TC->TU, BS)); + TU->Decls.push_back(new (C) TopLevelCodeDecl(TU, BS)); } @@ -581,7 +584,8 @@ static void generatePrintOfExpression(StringRef NameStr, Expr *E, /// processREPLTopLevelExpr - When we see an Expression in a TopLevelCodeDecl /// in the REPL, process it, adding the proper decls back to the top level of /// the TranslationUnit. -static void processREPLTopLevelExpr(Expr *E, TypeChecker *TC) { +static void processREPLTopLevelExpr(Expr *E, TypeChecker *TC, + TranslationUnit *TU) { CanType T = E->getType()->getCanonicalType(); // Don't try to print invalid expressions, module exprs, or void expressions. @@ -594,39 +598,39 @@ static void processREPLTopLevelExpr(Expr *E, TypeChecker *TC) { // in the future. However, if this is a direct reference to a decl (e.g. "x") // then don't create a repl metavariable. if (VarDecl *d = getObviousDECLFromExpr(E)) { - generatePrintOfExpression(d->getName().str(), E, TC); + generatePrintOfExpression(d->getName().str(), E, TC, TU); return; } // Remove the expression from being in the list of decls to execute, we're // going to reparent it. - TC->TU.Decls.pop_back(); + TU->Decls.pop_back(); E = TC->coerceToMaterializable(E); // Create the meta-variable, let the typechecker name it. - VarDecl *vd = new (TC->Context) VarDecl(E->getStartLoc(), - TC->getNextResponseVariableName(), - E->getType(), &TC->TU); - TC->TU.Decls.push_back(vd); - + Identifier name = TC->getNextResponseVariableName(TU); + VarDecl *vd = new (TC->Context) VarDecl(E->getStartLoc(), name, + E->getType(), TU); + TU->Decls.push_back(vd); + // Create a PatternBindingDecl to bind the expression into the decl. Pattern *metavarPat = new (TC->Context) NamedPattern(vd); metavarPat->setType(E->getType()); PatternBindingDecl *metavarBinding - = new (TC->Context) PatternBindingDecl(E->getStartLoc(), metavarPat, E, - &TC->TU); - TC->TU.Decls.push_back(metavarBinding); + = new (TC->Context) PatternBindingDecl(E->getStartLoc(), metavarPat, E, TU); + TU->Decls.push_back(metavarBinding); // Finally, print the variable's value. E = TC->buildCheckedRefExpr(vd, E->getStartLoc(), /*Implicit=*/true); - generatePrintOfExpression(vd->getName().str(), E, TC); + generatePrintOfExpression(vd->getName().str(), E, TC, TU); } /// processREPLTopLevelPatternBinding - When we see a new PatternBinding parsed /// into the REPL, process it by generating code to print it out. static void processREPLTopLevelPatternBinding(PatternBindingDecl *PBD, - TypeChecker *TC) { + TypeChecker *TC, + TranslationUnit *TU) { // If there is no initializer for the new variable, don't auto-print it. // This would just cause a confusing definite initialization error. Some // day we will do some high level analysis of uninitialized variables @@ -645,7 +649,7 @@ static void processREPLTopLevelPatternBinding(PatternBindingDecl *PBD, getSemanticsProvidingPattern())) { Expr *E = TC->buildCheckedRefExpr(NP->getDecl(), PBD->getStartLoc(), /*Implicit=*/true); - generatePrintOfExpression(PatternString, E, TC); + generatePrintOfExpression(PatternString, E, TC, TU); return; } @@ -659,15 +663,14 @@ static void processREPLTopLevelPatternBinding(PatternBindingDecl *PBD, // replPrint(r123) // Remove PBD from the list of Decls so we can insert before it. - TopLevelCodeDecl *PBTLCD = cast(TC->TU.Decls.back()); - - TC->TU.Decls.pop_back(); + TopLevelCodeDecl *PBTLCD = cast(TU->Decls.back()); + TU->Decls.pop_back(); // Create the meta-variable, let the typechecker name it. VarDecl *vd = new (TC->Context) VarDecl(PBD->getStartLoc(), - TC->getNextResponseVariableName(), - PBD->getPattern()->getType(),&TC->TU); - TC->TU.Decls.push_back(vd); + TC->getNextResponseVariableName(TU), + PBD->getPattern()->getType(), TU); + TU->Decls.push_back(vd); // Create a PatternBindingDecl to bind the expression into the decl. @@ -675,25 +678,25 @@ static void processREPLTopLevelPatternBinding(PatternBindingDecl *PBD, metavarPat->setType(vd->getType()); PatternBindingDecl *metavarBinding = new (TC->Context) PatternBindingDecl(PBD->getStartLoc(), metavarPat, - PBD->getInit(), &TC->TU); + PBD->getInit(), TU); auto MVBrace = BraceStmt::create(TC->Context, metavarBinding->getStartLoc(), BraceStmt::ExprStmtOrDecl(metavarBinding), metavarBinding->getEndLoc()); - auto *MVTLCD = new (TC->Context) TopLevelCodeDecl(&TC->TU, MVBrace); - TC->TU.Decls.push_back(MVTLCD); + auto *MVTLCD = new (TC->Context) TopLevelCodeDecl(TU, MVBrace); + TU->Decls.push_back(MVTLCD); // Replace the initializer of PBD with a reference to our repl temporary. Expr *E = TC->buildCheckedRefExpr(vd, vd->getStartLoc(), /*Implicit=*/true); E = TC->coerceToMaterializable(E); PBD->setInit(E); - TC->TU.Decls.push_back(PBTLCD); + TU->Decls.push_back(PBTLCD); // Finally, print out the result, by referring to the repl temp. E = TC->buildCheckedRefExpr(vd, vd->getStartLoc(), /*Implicit=*/true); - generatePrintOfExpression(PatternString, E, TC); + generatePrintOfExpression(PatternString, E, TC, TU); } @@ -701,17 +704,17 @@ static void processREPLTopLevelPatternBinding(PatternBindingDecl *PBD, /// processREPLTopLevel - This is called after we've parsed and typechecked some /// new decls at the top level. We inject code to print out expressions and /// pattern bindings the are evaluated. -void TypeChecker::processREPLTopLevel(unsigned FirstDecl) { +void TypeChecker::processREPLTopLevel(TranslationUnit *TU, unsigned FirstDecl) { // Loop over all of the new decls, moving them out of the Decls list, then // adding them back (with modifications) one at a time. - std::vector NewDecls(TU.Decls.begin()+FirstDecl, TU.Decls.end()); - TU.Decls.resize(FirstDecl); - + std::vector NewDecls(TU->Decls.begin()+FirstDecl, TU->Decls.end()); + TU->Decls.resize(FirstDecl); + // Loop over each of the new decls, processing them, adding them back to // the TU->Decls list. for (Decl *D : NewDecls) { - TU.Decls.push_back(D); - + TU->Decls.push_back(D); + TopLevelCodeDecl *TLCD = dyn_cast(D); if (TLCD == 0) continue; @@ -719,10 +722,10 @@ void TypeChecker::processREPLTopLevel(unsigned FirstDecl) { // Check to see if the TLCD has an expression that we have to transform. if (Expr *E = Entry.dyn_cast()) - processREPLTopLevelExpr(E, this); + processREPLTopLevelExpr(E, this, TU); else if (Decl *D = Entry.dyn_cast()) if (PatternBindingDecl *PBD = dyn_cast(D)) - processREPLTopLevelPatternBinding(PBD, this); + processREPLTopLevelPatternBinding(PBD, this, TU); } } diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 3ce2097bd75..79717e1a401 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -53,17 +53,21 @@ public: /// The level of loop nesting. 'break' and 'continue' are valid only in scopes /// where this is greater than one. - unsigned LoopNestLevel; + unsigned LoopNestLevel = 0; /// The level of 'switch' nesting. 'fallthrough' is valid only in scopes where /// this is greater than one. - unsigned SwitchLevel; + unsigned SwitchLevel = 0; /// The destination block for a 'fallthrough' statement. Null if the switch /// scope depth is zero or if we are checking the final 'case' of the current /// switch. - CaseStmt /*nullable*/ *FallthroughDest; + CaseStmt /*nullable*/ *FallthroughDest = nullptr; SourceLoc EndTypeCheckLoc; + /// Used to check for discarded expression values: in the REPL top-level + /// expressions are not discarded. + bool IsREPL; + struct AddLoopNest { StmtChecker &SC; AddLoopNest(StmtChecker &SC) : SC(SC) { @@ -91,26 +95,17 @@ public: }; StmtChecker(TypeChecker &TC, AbstractFunctionDecl *AFD) - : TC(TC), TheFunc(AFD), - LoopNestLevel(0), SwitchLevel(0), FallthroughDest(nullptr) { - if (auto *CD = dyn_cast(AFD)) { - DC = CD; - return; - } - if (auto *DD = dyn_cast(AFD)) { - DC = DD; - return; - } - DC = cast(AFD); - } + : TC(TC), TheFunc(AFD), DC(AFD), IsREPL(false) { } StmtChecker(TypeChecker &TC, ClosureExpr *TheClosure) - : TC(TC), TheFunc(TheClosure), DC(TheClosure), - LoopNestLevel(0), SwitchLevel(0), FallthroughDest(nullptr) { } + : TC(TC), TheFunc(TheClosure), DC(TheClosure), IsREPL(false) { } StmtChecker(TypeChecker &TC, DeclContext *DC) - : TC(TC), TheFunc(), DC(DC), - LoopNestLevel(0), SwitchLevel(0), FallthroughDest(nullptr) { } + : TC(TC), TheFunc(), DC(DC), IsREPL(false) { + if (auto TU = dyn_cast(DC->getParentModule())) + if (TU->Kind == TranslationUnit::REPL) + IsREPL = true; + } //===--------------------------------------------------------------------===// // Helper Functions. @@ -263,8 +258,8 @@ public: Type ContainerType = Container->getType()->getRValueType(); ProtocolConformance *Conformance = nullptr; - if (!TC.conformsToProtocol(ContainerType, EnumerableProto, &Conformance, - Container->getLoc())) + if (!TC.conformsToProtocol(ContainerType, EnumerableProto, DC, + &Conformance, Container->getLoc())) return nullptr; RangeTy = TC.getWitnessType(ContainerType, EnumerableProto, @@ -324,7 +319,7 @@ public: // FIXME: Would like to customize the diagnostic emitted in // conformsToProtocol(). ProtocolConformance *RangeConformance = nullptr; - if (!TC.conformsToProtocol(RangeTy, EnumeratorProto, &RangeConformance, + if (!TC.conformsToProtocol(RangeTy, EnumeratorProto, DC, &RangeConformance, Container->getLoc())) return nullptr; @@ -366,7 +361,7 @@ public: // FIXME: Would like to customize the diagnostic emitted in // conformsToProtocol(). ProtocolConformance *GenConformance = nullptr; - if (!TC.conformsToProtocol(GeneratorTy, GeneratorProto, &GenConformance, + if (!TC.conformsToProtocol(GeneratorTy, GeneratorProto, DC, &GenConformance, Container->getLoc())) return nullptr; @@ -497,8 +492,7 @@ Stmt *StmtChecker::visitBraceStmt(BraceStmt *BS) { break; // Type check the expression. - bool isDiscarded - = TC.TU.Kind != TranslationUnit::REPL || !isa(DC); + bool isDiscarded = !(IsREPL && isa(DC)); if (TC.typeCheckExpression(SubExpr, DC, Type(), isDiscarded)) { elem = SubExpr; continue; @@ -739,7 +733,7 @@ bool TypeChecker::typeCheckConstructorBodyUntil(ConstructorDecl *ctor, // Look for the member within this type. auto memberDecls = lookupMember(nominalDecl->getDeclaredTypeInContext(), - memberRef->getName(), + memberRef->getName(), ctor, /*allowDynamicLookup=*/false); if (memberDecls.size() == 1) member = dyn_cast(memberDecls[0]); @@ -833,7 +827,7 @@ bool TypeChecker::typeCheckConstructorBodyUntil(ConstructorDecl *ctor, continue; Expr *initializer = nullptr; - if (!isDefaultInitializable(varType, &initializer)) { + if (!isDefaultInitializable(varType, &initializer, ctor)) { diagnose(body->getLBraceLoc(), diag::decl_no_default_init_ivar, var->getName(), varType); diagnose(var->getLoc(), diag::decl_declared_here, var->getName()); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 0b493bb80a0..ca5cdb5717b 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -115,7 +115,8 @@ Type TypeChecker::resolveTypeInContext(TypeDecl *typeDecl, if (isa(typeDecl) && typeDecl->getDeclContext() != fromDC) { if (auto fromProto = dyn_cast(fromDC)) { - return substMemberTypeWithBase(typeDecl->getDeclaredType(), typeDecl, + return substMemberTypeWithBase(fromDC->getParentModule(), + typeDecl->getDeclaredType(), typeDecl, fromProto->getSelf()->getDeclaredType()); } } @@ -140,7 +141,8 @@ Type TypeChecker::resolveTypeInContext(TypeDecl *typeDecl, // the member type declaration. Substitute the type we're coming from as // the base of the member type to produce the projected type result. if (fromType->getAnyNominal() == ownerNominal) { - return substMemberTypeWithBase(typeDecl->getDeclaredType(), typeDecl, + return substMemberTypeWithBase(fromDC->getParentModule(), + typeDecl->getDeclaredType(), typeDecl, fromType); } } @@ -152,6 +154,7 @@ Type TypeChecker::resolveTypeInContext(TypeDecl *typeDecl, /// Apply generic arguments to the given type. Type TypeChecker::applyGenericArguments(Type type, SourceLoc loc, + DeclContext *dc, MutableArrayRef genericArgs, GenericTypeResolver *resolver) { // Make sure we always have a resolver to use. @@ -188,7 +191,7 @@ Type TypeChecker::applyGenericArguments(Type type, SmallVector genericArgTypes; for (auto &genericArg : genericArgs) { // Validate the generic argument. - if (validateType(genericArg, /*allowUnboundGenerics=*/false, + if (validateType(genericArg, dc, /*allowUnboundGenerics=*/false, resolver)) return nullptr; @@ -213,7 +216,7 @@ Type TypeChecker::applyGenericArguments(Type type, Substitutions[Archetype] = Arg; } - if (checkSubstitutions(Substitutions, Conformance, loc)) + if (checkSubstitutions(Substitutions, Conformance, dc, loc)) return nullptr; } @@ -221,12 +224,13 @@ Type TypeChecker::applyGenericArguments(Type type, } static Type applyGenericTypeReprArgs(TypeChecker &TC, Type type, SourceLoc loc, + DeclContext *dc, MutableArrayRef genericArgs, GenericTypeResolver *resolver) { SmallVector args; for (auto tyR : genericArgs) args.push_back(tyR); - Type ty = TC.applyGenericArguments(type, loc, args, resolver); + Type ty = TC.applyGenericArguments(type, loc, dc, args, resolver); if (!ty) return ErrorType::get(TC.Context); return ty; @@ -272,7 +276,7 @@ static Type resolveTypeDecl(TypeChecker &TC, TypeDecl *typeDecl, SourceLoc loc, if (!genericArgs.empty()) { // Apply the generic arguments to the type. - type = applyGenericTypeReprArgs(TC, type, loc, genericArgs, resolver); + type = applyGenericTypeReprArgs(TC, type, loc, dc, genericArgs, resolver); } assert(type); @@ -280,7 +284,7 @@ static Type resolveTypeDecl(TypeChecker &TC, TypeDecl *typeDecl, SourceLoc loc, } static llvm::PointerUnion -resolveIdentTypeComponent(TypeChecker &TC, +resolveIdentTypeComponent(TypeChecker &TC, DeclContext *DC, MutableArrayRef components, bool allowUnboundGenerics, GenericTypeResolver *resolver) { @@ -290,11 +294,7 @@ resolveIdentTypeComponent(TypeChecker &TC, if (parentComps.empty()) { // Resolve the first component, which is the only one that requires // unqualified name lookup. - DeclContext *dc = comp.getUnboundContext(); - assert(dc); - - // Perform an unqualified lookup. - UnqualifiedLookup Globals(comp.getIdentifier(), dc, &TC, comp.getIdLoc(), + UnqualifiedLookup Globals(comp.getIdentifier(), DC, &TC, comp.getIdLoc(), /*TypeLookup*/true); // Process the names we found. @@ -321,7 +321,7 @@ resolveIdentTypeComponent(TypeChecker &TC, continue; Type type = resolveTypeDecl(TC, typeDecl, comp.getIdLoc(), - dc, comp.getGenericArgs(), + DC, comp.getGenericArgs(), allowUnboundGenerics, resolver); if (type->is()) { @@ -378,7 +378,7 @@ resolveIdentTypeComponent(TypeChecker &TC, } else { llvm::PointerUnion - parent = resolveIdentTypeComponent(TC, parentComps, + parent = resolveIdentTypeComponent(TC, DC, parentComps, allowUnboundGenerics, resolver); // If the last resolved component is a type, perform member type lookup. @@ -396,7 +396,7 @@ resolveIdentTypeComponent(TypeChecker &TC, // Try to resolve the dependent member type to a specific associated // type. Type memberType = resolver->resolveDependentMemberType( - parentTy, + parentTy, DC, parentRange, comp.getIdentifier(), comp.getIdLoc()); @@ -415,7 +415,8 @@ resolveIdentTypeComponent(TypeChecker &TC, } // Look for member types with the given name. - auto memberTypes = TC.lookupMemberType(parentTy, comp.getIdentifier()); + auto memberTypes = TC.lookupMemberType(parentTy, comp.getIdentifier(), + DC); // If we didn't find anything, complain. // FIXME: Typo correction! @@ -447,7 +448,7 @@ resolveIdentTypeComponent(TypeChecker &TC, // If there are generic arguments, apply them now. if (!comp.getGenericArgs().empty()) memberType = applyGenericTypeReprArgs(TC, memberType, comp.getIdLoc(), - comp.getGenericArgs(), + DC, comp.getGenericArgs(), resolver); comp.setValue(memberType); @@ -457,7 +458,7 @@ resolveIdentTypeComponent(TypeChecker &TC, // Lookup into a module. auto module = parent.get(); LookupTypeResult foundModuleTypes = - TC.lookupMemberType(ModuleType::get(module), comp.getIdentifier()); + TC.lookupMemberType(ModuleType::get(module), comp.getIdentifier(), DC); // If we didn't find a type, complain. if (!foundModuleTypes) { @@ -491,7 +492,8 @@ resolveIdentTypeComponent(TypeChecker &TC, // If there are generic arguments, apply them now. if (!comp.getGenericArgs().empty()) { foundType = applyGenericTypeReprArgs(TC, foundType, comp.getIdLoc(), - comp.getGenericArgs(), resolver); + DC, comp.getGenericArgs(), + resolver); } comp.setValue(foundType); @@ -522,13 +524,14 @@ resolveIdentTypeComponent(TypeChecker &TC, } /// \brief Returns a valid type or ErrorType in case of an error. -static Type resolveIdentifierType(TypeChecker &TC, IdentTypeRepr* IdType, +static Type resolveIdentifierType(TypeChecker &TC, DeclContext *DC, + IdentTypeRepr *IdType, bool allowUnboundGenerics, GenericTypeResolver *resolver) { assert(resolver && "Missing generic type resolver"); llvm::PointerUnion - result = resolveIdentTypeComponent(TC, IdType->Components, + result = resolveIdentTypeComponent(TC, DC, IdType->Components, allowUnboundGenerics, resolver); if (auto mod = result.dyn_cast()) { @@ -542,7 +545,8 @@ static Type resolveIdentifierType(TypeChecker &TC, IdentTypeRepr* IdType, return result.get(); } -bool TypeChecker::validateType(TypeLoc &Loc, bool allowUnboundGenerics, +bool TypeChecker::validateType(TypeLoc &Loc, DeclContext *DC, + bool allowUnboundGenerics, GenericTypeResolver *resolver) { // FIXME: Verify that these aren't circular and infinite size. @@ -551,7 +555,8 @@ bool TypeChecker::validateType(TypeLoc &Loc, bool allowUnboundGenerics, return Loc.isError(); if (Loc.getType().isNull()) { - Loc.setType(resolveType(Loc.getTypeRepr(), allowUnboundGenerics, resolver), + Loc.setType(resolveType(Loc.getTypeRepr(), DC, allowUnboundGenerics, + resolver), true); return Loc.isError(); } @@ -560,7 +565,8 @@ bool TypeChecker::validateType(TypeLoc &Loc, bool allowUnboundGenerics, return Loc.isError(); } -Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics, +Type TypeChecker::resolveType(TypeRepr *TyR, DeclContext *DC, + bool allowUnboundGenerics, GenericTypeResolver *resolver) { PrettyStackTraceTypeRepr stackTrace(Context, "resolving", TyR); @@ -579,7 +585,7 @@ Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics, auto AttrTyR = cast(TyR); DeclAttributes attrs = AttrTyR->getAttrs(); assert(!attrs.empty()); - Ty = resolveType(AttrTyR->getTypeRepr(), + Ty = resolveType(AttrTyR->getTypeRepr(), DC, /*FIXME:allowUnboundGenerics=*/false, resolver); if (Ty->is()) @@ -653,15 +659,18 @@ Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics, // In SIL translation units *only*, permit [weak] and [unowned] to // apply directly to types. - if (attrs.hasOwnership() && TU.Kind == TranslationUnit::SIL && - Ty->hasReferenceSemantics()) { - Ty = ReferenceStorageType::get(Ty, attrs.getOwnership(), Context); - attrs.clearOwnership(); + if (attrs.hasOwnership() && Ty->hasReferenceSemantics()) { + auto TU = dyn_cast(DC->getParentModule()); + if (TU && TU->Kind == TranslationUnit::SIL) { + Ty = ReferenceStorageType::get(Ty, attrs.getOwnership(), Context); + attrs.clearOwnership(); + } } // Diagnose [local_storage] in nested positions. if (attrs.isLocalStorage()) { - assert(TU.Kind == TranslationUnit::SIL); + assert(cast(DC->getParentModule())->Kind == + TranslationUnit::SIL); diagnose(attrs.AtLoc, diag::sil_local_storage_nested); attrs.LocalStorage = false; } @@ -674,18 +683,18 @@ Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics, } case TypeReprKind::Ident: - return resolveIdentifierType(*this, cast(TyR), + return resolveIdentifierType(*this, DC, cast(TyR), allowUnboundGenerics, resolver); case TypeReprKind::Function: { auto FnTyR = cast(TyR); - Type inputTy = resolveType(FnTyR->getArgsTypeRepr(), + Type inputTy = resolveType(FnTyR->getArgsTypeRepr(), DC, /*FIXME:allowUnboundGenerics=*/false, resolver); if (inputTy->is()) return inputTy; - Type outputTy = resolveType(FnTyR->getResultTypeRepr(), + Type outputTy = resolveType(FnTyR->getResultTypeRepr(), DC, /*FIXME:allowUnboundGenerics=*/false, resolver); if (outputTy->is()) @@ -696,7 +705,7 @@ Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics, case TypeReprKind::Array: { // FIXME: diagnose non-materializability of element type! auto ArrTyR = cast(TyR); - Type baseTy = resolveType(ArrTyR->getBase(), + Type baseTy = resolveType(ArrTyR->getBase(), DC, /*FIXME:allowUnboundGenerics=*/false, resolver); if (baseTy->is()) @@ -720,7 +729,7 @@ Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics, case TypeReprKind::Optional: { // FIXME: diagnose non-materializability of element type! auto optTyR = cast(TyR); - Type baseTy = resolveType(optTyR->getBase(), + Type baseTy = resolveType(optTyR->getBase(), DC, /*FIXME:allowUnboundGenerics=*/false, resolver); if (baseTy->is()) @@ -738,14 +747,14 @@ Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics, SmallVector Elements; for (auto tyR : TupTyR->getElements()) { if (NamedTypeRepr *namedTyR = dyn_cast(tyR)) { - Type ty = resolveType(namedTyR->getTypeRepr(), + Type ty = resolveType(namedTyR->getTypeRepr(), DC, /*FIXME:allowUnboundGenerics=*/false, resolver); if (ty->is()) return ty; Elements.push_back(TupleTypeElt(ty, namedTyR->getName())); } else { - Type ty = resolveType(tyR, + Type ty = resolveType(tyR, DC, /*FIXME:allowUnboundGenerics=*/false, resolver); if (ty->is()) @@ -774,7 +783,7 @@ Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics, auto ProtTyR = cast(TyR); SmallVector ProtocolTypes; for (auto tyR : ProtTyR->getProtocols()) { - Type ty = resolveType(tyR, /*FIXME:allowUnboundGenerics=*/false, + Type ty = resolveType(tyR, DC, /*FIXME:allowUnboundGenerics=*/false, resolver); if (ty->is()) return ty; @@ -801,7 +810,7 @@ Type TypeChecker::resolveType(TypeRepr *TyR, bool allowUnboundGenerics, } case TypeReprKind::MetaType: { - Type ty = resolveType(cast(TyR)->getBase(), + Type ty = resolveType(cast(TyR)->getBase(), DC, /*FIXME:allowUnboundGenerics=*/false, resolver); if (ty->is()) @@ -818,29 +827,30 @@ Type TypeChecker::transformType(Type type, return type.transform(Context, fn); } -Type TypeChecker::substType(Type type, TypeSubstitutionMap &Substitutions, +Type TypeChecker::substType(Module *module, Type type, + TypeSubstitutionMap &Substitutions, bool IgnoreMissing) { - return type.subst(&TU, Substitutions, IgnoreMissing, this); + return type.subst(module, Substitutions, IgnoreMissing, this); } -Type TypeChecker::substMemberTypeWithBase(Type T, ValueDecl *Member, - Type BaseTy) { +Type TypeChecker::substMemberTypeWithBase(Module *module, Type T, + ValueDecl *Member, Type BaseTy) { if (!BaseTy) return T; - return BaseTy->getTypeOfMember(&TU, Member, this, T); + return BaseTy->getTypeOfMember(module, Member, this, T); } Type TypeChecker::getSuperClassOf(Type type) { return type->getSuperclass(this); } -Type TypeChecker::resolveMemberType(Type type, Identifier name) { - LookupTypeResult memberTypes = lookupMemberType(type, name); +Type TypeChecker::resolveMemberType(DeclContext *dc, Type type, + Identifier name) { + LookupTypeResult memberTypes = lookupMemberType(type, name, dc); if (!memberTypes) return Type(); - // FIXME: Detect ambiguities here? return memberTypes.back().second; } diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 3d1aba4ba20..8933d8e2bec 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -36,9 +36,8 @@ using namespace swift; -TypeChecker::TypeChecker(TranslationUnit &TU, DiagnosticEngine &Diags) - : TU(TU), Context(TU.Ctx), - Diags(Diags) +TypeChecker::TypeChecker(ASTContext &Ctx, DiagnosticEngine &Diags) + : Context(Ctx), Diags(Diags) { Context.addMutationListener(*this); @@ -131,8 +130,16 @@ Module *TypeChecker::getStdlibModule() { if (!StdlibModule) StdlibModule = Context.LoadedModules.lookup(Context.StdlibModuleName.str()); - if (!StdlibModule) - StdlibModule = &TU; + if (!StdlibModule) { + // FIXME: Hack. There should just be a pointer on ASTContext to the main + // module. + for (auto &entry : Context.LoadedModules) { + if (auto TU = dyn_cast_or_null(entry.getValue())) + if (TU->getImportBufferID() == -1) + StdlibModule = TU; + } + assert(StdlibModule && "no main module found"); + } Context.recordKnownProtocols(StdlibModule); return StdlibModule; @@ -193,7 +200,8 @@ static Type getBaseMemberDeclType(TypeChecker &TC, ->getClassOrBoundGenericClass(); while (Base->getClassOrBoundGenericClass() != BaseDecl) Base = TC.getSuperClassOf(Base); - return TC.substMemberTypeWithBase(D->getType(), D, Base); + return TC.substMemberTypeWithBase(D->getModuleContext(), + D->getType(), D, Base); } /// \brief Check the given set of members for any members that override a member @@ -238,6 +246,7 @@ static void checkClassOverrides(TypeChecker &TC, ClassDecl *CD, if (FoundDeclResult.second) { for (auto BaseMember : TC.lookupMember(superclassMetaTy, MemberVD->getName(), + CD->getDeclContext(), /*allowDynamicLookup=*/false)) CurDecls.push_back(BaseMember); } @@ -319,12 +328,14 @@ static void checkClassOverrides(TypeChecker &TC, ClassDecl *CD, bool Trivial; isSubtype = TC.isSubtypeOf(MemberFTy->getResult(), OtherFTy->getResult(), + CD->getDeclContext(), Trivial) && Trivial; } } else { bool Trivial; isSubtype = TC.isSubtypeOf(MemberVD->getType(), BaseMemberTy, + CD->getDeclContext(), Trivial) && Trivial; } if (isSubtype) { @@ -369,7 +380,8 @@ static void bindExtensionDecl(ExtensionDecl *ED, TypeChecker &TC) { return; // FIXME: Should allow bound generics here as well. - if (TC.validateType(ED->getExtendedTypeLoc(), /*allowUnboundGenerics=*/true)) { + if (TC.validateType(ED->getExtendedTypeLoc(), ED->getDeclContext(), + /*allowUnboundGenerics=*/true)) { ED->setInvalid(); return; } @@ -457,7 +469,7 @@ void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem) { // checking. performNameBinding(TU, StartElem); - TypeChecker TC(*TU); + TypeChecker TC(TU->Ctx); auto &DefinedFunctions = TC.definedFunctions; // Lookup the swift module. This ensures that we record all known protocols @@ -604,7 +616,7 @@ void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem) { // If we're in REPL mode, inject temporary result variables and other stuff // that the REPL needs to synthesize. if (TU->Kind == TranslationUnit::REPL && !TC.Context.hadError()) - TC.processREPLTopLevel(StartElem); + TC.processREPLTopLevel(TU, StartElem); // Check overloaded vars/funcs. // FIXME: This is quadratic time for TUs with multiple chunks. @@ -697,20 +709,21 @@ void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem) { } bool swift::performTypeLocChecking(TranslationUnit *TU, TypeLoc &T, + DeclContext *DC, bool ProduceDiagnostics) { if (ProduceDiagnostics) { - return TypeChecker(*TU).validateType(T); + return TypeChecker(TU->Ctx).validateType(T, DC); } else { // Set up a diagnostics engine that swallows diagnostics. DiagnosticEngine Diags(TU->Ctx.SourceMgr); - return TypeChecker(*TU, Diags).validateType(T); + return TypeChecker(TU->Ctx, Diags).validateType(T, DC); } } bool swift::typeCheckCompletionDecl(TranslationUnit *TU, Decl *D) { // Set up a diagnostics engine that swallows diagnostics. DiagnosticEngine Diags(TU->Ctx.SourceMgr); - TypeChecker TC(*TU, Diags); + TypeChecker TC(TU->Ctx, Diags); TC.typeCheckDecl(D, true); return true; } @@ -720,7 +733,7 @@ bool swift::typeCheckCompletionContextExpr(TranslationUnit *TU, // Set up a diagnostics engine that swallows diagnostics. DiagnosticEngine diags(TU->Ctx.SourceMgr); - TypeChecker TC(*TU, diags); + TypeChecker TC(TU->Ctx, diags); TC.typeCheckExpression(parsedExpr, TU, Type(), /*discardedExpr=*/true); TU->ASTStage = TranslationUnit::TypeChecked; @@ -738,7 +751,7 @@ bool swift::typeCheckAbstractFunctionBodyUntil(TranslationUnit *TU, // Set up a diagnostics engine that swallows diagnostics. DiagnosticEngine Diags(TU->Ctx.SourceMgr); - TypeChecker TC(*TU, Diags); + TypeChecker TC(TU->Ctx, Diags); return !TC.typeCheckAbstractFunctionBodyUntil(AFD, EndTypeCheckLoc); } @@ -750,7 +763,7 @@ static void deleteTypeCheckerAndDiags(LazyResolver *resolver) { OwnedResolver swift::createLazyResolver(TranslationUnit *TU) { auto diags = new DiagnosticEngine(TU->Ctx.SourceMgr); - return OwnedResolver(new TypeChecker(*TU, *diags), + return OwnedResolver(new TypeChecker(TU->Ctx, *diags), &deleteTypeCheckerAndDiags); } diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 3ac88418d0f..63ca77ac773 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -117,7 +117,6 @@ enum class Comparison { class TypeChecker : public ASTMutationListener, public LazyResolver { public: - TranslationUnit &TU; ASTContext &Context; DiagnosticEngine &Diags; @@ -142,8 +141,8 @@ private: unsigned NextResponseVariableIndex = 0; public: - TypeChecker(TranslationUnit &TU) : TypeChecker(TU, TU.Ctx.Diags) { } - TypeChecker(TranslationUnit &TU, DiagnosticEngine &Diags); + TypeChecker(ASTContext &Ctx) : TypeChecker(Ctx, Ctx.Diags) { } + TypeChecker(ASTContext &Ctx, DiagnosticEngine &Diags); ~TypeChecker(); LangOptions &getLangOpts() const { return Context.LangOpts; } @@ -168,6 +167,8 @@ public: /// \param Loc The type (with source location information) to validate. /// If the type has already been validated, returns immediately. /// + /// \param DC The context that the type appears in. + /// /// \param allowUnboundGenerics Whether the allow unbound generics at the /// top level of the type. Defaults to 'false', and should only be enabled /// in places where the generic arguments will be deduced, e.g., within an @@ -177,7 +178,8 @@ public: /// routine will create a \c PartialGenericTypeToArchetypeResolver to use. /// /// \returns true if type validation failed, or false otherwise. - bool validateType(TypeLoc &Loc, bool allowUnboundGenerics = false, + bool validateType(TypeLoc &Loc, DeclContext *DC, + bool allowUnboundGenerics = false, GenericTypeResolver *resolver = nullptr); /// \brief Resolves a TypeRepr to a type. @@ -187,13 +189,16 @@ public: /// /// \param TyR The type representation to check. /// + /// \param DC The context that the type appears in. + /// /// \param allowUnboundGenerics Whether to allow unbound generic types. /// /// \param resolver A resolver for generic types. If none is supplied, this /// routine will create a \c PartialGenericTypeToArchetypeResolver to use. /// /// \returns a well-formed type or an ErrorType in case of an error. - Type resolveType(TypeRepr *TyR, bool allowUnboundGenerics = false, + Type resolveType(TypeRepr *TyR, DeclContext *DC, + bool allowUnboundGenerics = false, GenericTypeResolver *resolver = nullptr); void validateDecl(ValueDecl *D, bool resolveTypeParams = false); @@ -234,13 +239,14 @@ public: /// FIXME: We probably want to have both silent and loud failure modes. However, /// the only possible failure now is from array slice types, which occur /// simply because we don't have Slice yet. - Type substType(Type T, TypeSubstitutionMap &Substitutions, + Type substType(Module *module, Type T, TypeSubstitutionMap &Substitutions, bool IgnoreMissing = false); /// \brief Apply generic arguments to the given type. /// /// \param type The unbound generic type to which to apply arguments. /// \param loc The source location for diagnostic reporting. + /// \param dc The context where the arguments are applied. /// \param genericArgs The list of generic arguments to apply to the type. /// \param resolver The generic type resolver. /// @@ -248,12 +254,14 @@ public: /// error. Type applyGenericArguments(Type type, SourceLoc loc, + DeclContext *dc, MutableArrayRef genericArgs, GenericTypeResolver *resolver); /// \brief Replace the type \c T of a protocol member \c Member given the /// type of the base of a member access, \c BaseTy. - Type substMemberTypeWithBase(Type T, ValueDecl *Member, Type BaseTy); + Type substMemberTypeWithBase(Module *module, Type T, ValueDecl *Member, + Type BaseTy); /// \brief Retrieve the superclass type of the given type, or a null type if /// the type has no supertype. @@ -263,11 +271,12 @@ public: /// /// \param t1 The potential subtype. /// \param t2 The potential supertype. + /// \param dc The context of the check. /// /// \returns true if \c t1 is a subtype of \c t2. - bool isSubtypeOf(Type t1, Type t2) { + bool isSubtypeOf(Type t1, Type t2, DeclContext *dc) { bool isTrivial; - return isSubtypeOf(t1, t2, isTrivial); + return isSubtypeOf(t1, t2, dc, isTrivial); } /// \brief Determine whether one type is a subtype of another. @@ -276,11 +285,13 @@ public: /// /// \param t2 The potential supertype. /// + /// \param dc The context of the check. + /// /// \param isTrivial Will indicate whether this is a trivial subtyping /// relationship. /// /// \returns true if \c t1 is a subtype of \c t2. - bool isSubtypeOf(Type t1, Type t2, bool &isTrivial); + bool isSubtypeOf(Type t1, Type t2, DeclContext *dc, bool &isTrivial); /// \brief Determine whether one type is implicitly convertible to another. /// @@ -288,8 +299,10 @@ public: /// /// \param t2 The potential destination type of the conversion. /// + /// \param dc The context of the conversion. + /// /// \returns true if \c t1 can be implicitly converted to \c t2. - bool isConvertibleTo(Type t1, Type t2); + bool isConvertibleTo(Type t1, Type t2, DeclContext *dc); /// \brief Determine whether one type would be a valid substitution for an /// archetype. @@ -298,8 +311,10 @@ public: /// /// \param t2 The potential substituted archetype. /// + /// \param dc The context of the check. + /// /// \returns true if \c t1 is a valid substitution for \c t2. - bool isSubstitutableFor(Type t1, ArchetypeType *t2); + bool isSubstitutableFor(Type t1, ArchetypeType *t2, DeclContext *dc); /// If the inputs to an apply expression use a consistent "sugar" type /// (that is, a typealias or shorthand syntax) equivalent to the result type @@ -321,8 +336,8 @@ public: void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD); - void processREPLTopLevel(unsigned StartElem); - Identifier getNextResponseVariableName(); + void processREPLTopLevel(TranslationUnit *TU, unsigned StartElem); + Identifier getNextResponseVariableName(DeclContext *DC); void typeCheckDecl(Decl *D, bool isFirstPass); @@ -355,7 +370,7 @@ public: bool validateGenericTypeSignature(NominalTypeDecl *nominal); /// Check the inheritance clause of the given declaration. - void checkInheritanceClause(Decl *decl, + void checkInheritanceClause(Decl *decl, DeclContext *DC = nullptr, GenericTypeResolver *resolver = nullptr); /// Retrieve the set of protocols to which this nominal type declaration @@ -397,9 +412,11 @@ public: /// \param initializer If non-null, we will assigned an initializer expression /// that performs the default initialization. /// + /// \param dc The context in which default-initialization is needed. + /// /// \param useConstructor Whether we must use a constructor for a class /// (rather than default-initializing to zero). - bool isDefaultInitializable(Type ty, Expr **initializer, + bool isDefaultInitializable(Type ty, Expr **initializer, DeclContext *dc, bool useConstructor = false); /// \brief Define the default constructor for the given struct or class. @@ -410,7 +427,7 @@ public: /// \brief Fold the given sequence expression into an (unchecked) expression /// tree. - Expr *foldSequence(SequenceExpr *expr); + Expr *foldSequence(SequenceExpr *expr, DeclContext *dc); /// Pre-check an expression, validating any types that occur in the /// expression and folding sequence expressions. @@ -457,6 +474,7 @@ public: /// /// \param fromType The source type of the cast. /// \param toType The destination type of the cast. + /// \param dc The context of the cast. /// \param diagLoc The location at which to report diagnostics. /// \param diagFromRange The source range of the input operand of the cast. /// \param diagToRange The source range of the destination type. @@ -468,6 +486,7 @@ public: /// conversion, InvalidCoercible is returned. CheckedCastKind typeCheckCheckedCast(Type fromType, Type toType, + DeclContext *dc, SourceLoc diagLoc, SourceRange diagFromRange, SourceRange diagToRange, @@ -517,7 +536,7 @@ public: /// /// \returns the default type, or null if there is no default type for /// this protocol. - Type getDefaultType(ProtocolDecl *protocol); + Type getDefaultType(ProtocolDecl *protocol, DeclContext *dc); /// \brief Convert the given expression to the given type. /// @@ -580,8 +599,10 @@ public: MutableArrayRef arguments, Diag<> brokenProtocolDiag); - /// conformsToProtocol - Determine whether the given type conforms to the - /// given protocol. + /// \brief Determine whether the given type conforms to the given protocol. + /// + /// \param DC The context in which to check conformance. This affects, for + /// example, extension visibility. /// /// \param Conformance If non-NULL, and the type does conform to the given /// protocol, this will be set to the protocol conformance mapping that @@ -600,7 +621,7 @@ public: /// be checked and diagnosed as a fallback. /// /// \returns true if T conforms to the protocol Proto, false otherwise. - bool conformsToProtocol(Type T, ProtocolDecl *Proto, + bool conformsToProtocol(Type T, ProtocolDecl *Proto, DeclContext *DC, ProtocolConformance **Conformance = 0, SourceLoc ComplainLoc = SourceLoc(), Decl *ExplicitConformance = nullptr); @@ -621,6 +642,7 @@ public: /// the required protocol-conformance relationships. bool checkSubstitutions(TypeSubstitutionMap &Substitutions, ConformanceMap &Conformance, + DeclContext *DC, SourceLoc ComplainLoc, TypeSubstitutionMap *RecordSubstitutions = nullptr); @@ -628,10 +650,11 @@ public: /// /// \param type The type in which we will look for a member. /// \param name The name of the member to look for. + /// \param dc The context that needs the member. /// \param allowDynamicLookup Whether to allow dynamic lookup. /// /// \returns The result of name lookup. - LookupResult lookupMember(Type type, Identifier name, + LookupResult lookupMember(Type type, Identifier name, DeclContext *dc, bool allowDynamicLookup = true); /// \brief Look up a member type within the given type. @@ -640,18 +663,20 @@ public: /// given type. /// /// \param type The type in which we will look for a member type. - /// /// \param name The name of the member to look for. + /// \param dc The context that needs the member. /// /// \returns The result of name lookup. - LookupTypeResult lookupMemberType(Type type, Identifier name); + LookupTypeResult lookupMemberType(Type type, Identifier name, + DeclContext *dc); /// \brief Look up the constructors of the given type. /// /// \param type The type for which we will look for constructors. + /// \param dc The context that needs the constructor. /// /// \returns the constructors found for this type. - LookupResult lookupConstructors(Type type); + LookupResult lookupConstructors(Type type, DeclContext *dc); /// \brief Look up the Bool type in the standard library. Type lookupBoolType(); @@ -675,7 +700,9 @@ public: /// A declaration is more specialized than another declaration if its type /// is a subtype of the other declaration's type (ignoring the 'self' /// parameter of function declarations) and if - Comparison compareDeclarations(ValueDecl *decl1, ValueDecl *decl2); + Comparison compareDeclarations(DeclContext *dc, + ValueDecl *decl1, + ValueDecl *decl2); /// \brief Encode the provided substitutions in the form used by /// SpecializeExpr (and another other AST nodes that require specialization). @@ -777,9 +804,10 @@ public: /// @{ virtual ProtocolConformance *resolveConformance(NominalTypeDecl *type, ProtocolDecl *protocol, - ExtensionDecl *ext); - virtual void resolveExistentialConformsToItself(ProtocolDecl *proto); - virtual Type resolveMemberType(Type type, Identifier name); + ExtensionDecl *ext) override; + virtual void resolveExistentialConformsToItself(ProtocolDecl *proto) override; + virtual Type resolveMemberType(DeclContext *dc, Type type, + Identifier name) override; }; } // end namespace swift