diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 5880774e710..aa5806c9b71 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -2109,25 +2109,6 @@ static bool isConversionConstraint(const Constraint *C) { return C->getClassification() == ConstraintClassification::Relational; } -/// Return true if this member constraint is a low priority for diagnostics, so -/// low that we would only like to issue an error message about it if there is -/// nothing else interesting we can scrape out of the constraint system. -static bool isLowPriorityConstraint(Constraint *C) { - // If the member constraint is a ".Iterator" lookup to find the iterator - // type in a foreach loop, or a ".Element" lookup to find its element type, - // then it is very low priority: We will get a better and more useful - // diagnostic from the failed conversion to Sequence that will fail as well. - if (C->getKind() == ConstraintKind::TypeMember) { - if (auto *loc = C->getLocator()) - for (auto Elt : loc->getPath()) - if (Elt.getKind() == ConstraintLocator::GeneratorElementType || - Elt.getKind() == ConstraintLocator::SequenceIteratorProtocol) - return true; - } - - return false; -} - /// Attempt to diagnose a failure without taking into account the specific /// kind of expression that could not be type checked. bool FailureDiagnosis::diagnoseConstraintFailure() { @@ -2148,9 +2129,6 @@ bool FailureDiagnosis::diagnoseConstraintFailure() { // This is a predicate that classifies constraints according to our // priorities. std::function classifyConstraint = [&](Constraint *C) { - if (isLowPriorityConstraint(C)) - return rankedConstraints.push_back({C, CR_OtherConstraint}); - if (isMemberConstraint(C)) return rankedConstraints.push_back({C, CR_MemberConstraint}); diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 4fa935f4384..1eadd569dc7 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -686,7 +686,6 @@ matchCallArguments(ConstraintSystem &cs, ConstraintKind kind, case ConstraintKind::LiteralConformsTo: case ConstraintKind::OptionalObject: case ConstraintKind::SelfObjectOfProtocol: - case ConstraintKind::TypeMember: case ConstraintKind::UnresolvedValueMember: case ConstraintKind::ValueMember: llvm_unreachable("Not a call argument constraint"); @@ -813,7 +812,6 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2, case ConstraintKind::LiteralConformsTo: case ConstraintKind::OptionalObject: case ConstraintKind::SelfObjectOfProtocol: - case ConstraintKind::TypeMember: case ConstraintKind::UnresolvedValueMember: case ConstraintKind::ValueMember: llvm_unreachable("Not a conversion"); @@ -940,7 +938,6 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1, case ConstraintKind::LiteralConformsTo: case ConstraintKind::OptionalObject: case ConstraintKind::SelfObjectOfProtocol: - case ConstraintKind::TypeMember: case ConstraintKind::UnresolvedValueMember: case ConstraintKind::ValueMember: return false; @@ -1006,7 +1003,6 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, case ConstraintKind::LiteralConformsTo: case ConstraintKind::OptionalObject: case ConstraintKind::SelfObjectOfProtocol: - case ConstraintKind::TypeMember: case ConstraintKind::UnresolvedValueMember: case ConstraintKind::ValueMember: llvm_unreachable("Not a relational constraint"); @@ -1431,7 +1427,6 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, case ConstraintKind::LiteralConformsTo: case ConstraintKind::OptionalObject: case ConstraintKind::SelfObjectOfProtocol: - case ConstraintKind::TypeMember: case ConstraintKind::UnresolvedValueMember: case ConstraintKind::ValueMember: llvm_unreachable("Not a relational constraint"); @@ -2969,40 +2964,6 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName, return result; } - // If we want member types only, use member type lookup. - if (constraintKind == ConstraintKind::TypeMember) { - // Types don't have compound names. - // FIXME: Customize diagnostic to mention types and compound names. - if (!memberName.isSimpleName()) - return result; // No result. - - NameLookupOptions lookupOptions = defaultMemberTypeLookupOptions; - if (isa(DC)) - lookupOptions |= NameLookupFlags::KnownPrivate; - - // If we're doing a lookup for diagnostics, include inaccessible members, - // the diagnostics machinery will sort it out. - if (includeInaccessibleMembers) - lookupOptions |= NameLookupFlags::IgnoreAccessibility; - - auto lookup = TC.lookupMemberType(DC, baseObjTy, memberName.getBaseName(), - lookupOptions); - // Form the overload set. - for (auto candidate : lookup) { - // If the result is invalid, don't cascade errors. - TC.validateDecl(candidate.first, true); - if (candidate.first->isInvalid()) - return result.markErrorAlreadyDiagnosed(); - - result.addViable(OverloadChoice(baseTy, candidate.first, - /*isSpecialized=*/false, - functionRefKind)); - } - - return result; - } - - // Look for members within the base. LookupResult &lookup = lookupMember(baseObjTy, memberName); @@ -3303,32 +3264,6 @@ ConstraintSystem::simplifyMemberConstraint(ConstraintKind kind, // If the lookup found no hits at all (either viable or unviable), diagnose it // as such and try to recover in various ways. - if (kind == ConstraintKind::TypeMember) { - // If the base type was an optional, try to look through it. - if (shouldAttemptFixes() && baseObjTy->getOptionalObjectType()) { - // Determine whether or not we want to provide an optional chaining fixit or - // a force unwrap fixit. - bool optionalChain; - if (!getContextualType()) - optionalChain = !(Options & ConstraintSystemFlags::PreferForceUnwrapToOptional); - else - optionalChain = !getContextualType()->getOptionalObjectType().isNull(); - auto fixKind = optionalChain ? FixKind::OptionalChaining : FixKind::ForceOptional; - - // Note the fix. - if (recordFix(fixKind, locator)) - return SolutionKind::Error; - - // Look through one level of optional. - addTypeMemberConstraint(baseObjTy->getOptionalObjectType(), - member, memberTy, locator); - return SolutionKind::Solved; - } - - return SolutionKind::Error; - } - - auto instanceTy = baseObjTy; if (auto MTT = instanceTy->getAs()) instanceTy = MTT->getInstanceType(); @@ -4207,7 +4142,6 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first, case ConstraintKind::ValueMember: case ConstraintKind::UnresolvedValueMember: - case ConstraintKind::TypeMember: case ConstraintKind::BindOverload: case ConstraintKind::Disjunction: llvm_unreachable("Use the correct addConstraint()"); @@ -4328,7 +4262,6 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { case ConstraintKind::ValueMember: case ConstraintKind::UnresolvedValueMember: - case ConstraintKind::TypeMember: return simplifyMemberConstraint(constraint.getKind(), constraint.getFirstType(), constraint.getMember(), diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index c57f1fa102f..c9e09f714e1 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -720,7 +720,6 @@ static bool shouldBindToValueType(Constraint *constraint) case ConstraintKind::DynamicTypeOf: case ConstraintKind::ValueMember: case ConstraintKind::UnresolvedValueMember: - case ConstraintKind::TypeMember: case ConstraintKind::Defaultable: case ConstraintKind::Disjunction: llvm_unreachable("shouldBindToValueType() may only be called on " @@ -950,7 +949,6 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs, case ConstraintKind::ValueMember: case ConstraintKind::UnresolvedValueMember: - case ConstraintKind::TypeMember: // If our type variable shows up in the base type, there's // nothing to do. // FIXME: Can we avoid simplification here? diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp index eb97ddd17c4..ea6e6d39a62 100644 --- a/lib/Sema/Constraint.cpp +++ b/lib/Sema/Constraint.cpp @@ -77,7 +77,6 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, assert(!Member && "Relational constraint cannot have a member"); break; - case ConstraintKind::TypeMember: case ConstraintKind::ValueMember: case ConstraintKind::UnresolvedValueMember: assert(Member && "Member constraint has no member"); @@ -175,7 +174,6 @@ Constraint *Constraint::clone(ConstraintSystem &cs) const { case ConstraintKind::ValueMember: case ConstraintKind::UnresolvedValueMember: - case ConstraintKind::TypeMember: return create(cs, getKind(), getFirstType(), getSecondType(), getMember(), getFunctionRefKind(), getLocator()); @@ -291,9 +289,6 @@ void Constraint::print(llvm::raw_ostream &Out, SourceManager *sm) const { case ConstraintKind::UnresolvedValueMember: Out << "[(implicit) ." << Types.Member << ": value] == "; break; - case ConstraintKind::TypeMember: - Out << "[." << Types.Member << ": type] == "; - break; case ConstraintKind::Defaultable: Out << " can default to "; break; @@ -462,7 +457,6 @@ gatherReferencedTypeVars(Constraint *constraint, case ConstraintKind::CheckedCast: case ConstraintKind::Equal: case ConstraintKind::Subtype: - case ConstraintKind::TypeMember: case ConstraintKind::UnresolvedValueMember: case ConstraintKind::ValueMember: case ConstraintKind::DynamicTypeOf: diff --git a/lib/Sema/Constraint.h b/lib/Sema/Constraint.h index d08203699ed..29cc0246271 100644 --- a/lib/Sema/Constraint.h +++ b/lib/Sema/Constraint.h @@ -114,9 +114,6 @@ enum class ConstraintKind : char { /// name, and the type of that member, when referenced as a value, is the /// second type. UnresolvedValueMember, - /// \brief The first type has a type member with the given name, and the - /// type of that member, when referenced as a type, is the second type. - TypeMember, /// \brief The first type can be defaulted to the second (which currently /// cannot be dependent). This is more like a type property than a /// relational constraint. @@ -485,7 +482,6 @@ public: case ConstraintKind::ValueMember: case ConstraintKind::UnresolvedValueMember: - case ConstraintKind::TypeMember: return ConstraintClassification::Member; case ConstraintKind::DynamicTypeOf: @@ -519,16 +515,14 @@ public: /// \brief Retrieve the name of the member for a member constraint. DeclName getMember() const { assert(Kind == ConstraintKind::ValueMember || - Kind == ConstraintKind::UnresolvedValueMember || - Kind == ConstraintKind::TypeMember); + Kind == ConstraintKind::UnresolvedValueMember); return Types.Member; } /// \brief Determine whether this constraint kind has a second type. static bool hasMember(ConstraintKind kind) { return kind == ConstraintKind::ValueMember - || kind == ConstraintKind::UnresolvedValueMember - || kind == ConstraintKind::TypeMember; + || kind == ConstraintKind::UnresolvedValueMember; } /// Determine the kind of function reference we have for a member reference. diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index c10260fcef9..a0e171ee0d3 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -1336,32 +1336,6 @@ public: resolveOverload(locator, boundTy, choice); } - /// \brief Add a value member constraint to the constraint system. - void addTypeMemberConstraint(Type baseTy, DeclName name, Type memberTy, - ConstraintLocatorBuilder locator) { - assert(baseTy); - assert(memberTy); - assert(name); - switch (simplifyMemberConstraint(ConstraintKind::TypeMember, baseTy, name, - memberTy, FunctionRefKind::Compound, - TMF_GenerateConstraints, locator)) { - case SolutionKind::Unsolved: - llvm_unreachable("Unsolved result when generating constraints!"); - - case SolutionKind::Solved: - break; - - case SolutionKind::Error: - if (shouldAddNewFailingConstraint()) { - addNewFailingConstraint( - Constraint::create(*this, ConstraintKind::TypeMember, baseTy, - memberTy, name, FunctionRefKind::Compound, - getConstraintLocator(locator))); - } - break; - } - } - /// \brief Add a value member constraint to the constraint system. void addValueMemberConstraint(Type baseTy, DeclName name, Type memberTy, FunctionRefKind functionRefKind, diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 7d491134985..0b72b88fbe4 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -2017,6 +2017,11 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) { auto sequenceType = expr->getType()->getRValueType(); + // Look through one level of optional; this improves recovery but doesn't + // change the result. + if (auto sequenceObjectType = sequenceType->getAnyOptionalObjectType()) + sequenceType = sequenceObjectType; + // If the sequence type is an existential, we should not attempt to // look up the member type at all, since we cannot represent associated // types of existentials. @@ -2053,27 +2058,16 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) { } } - // If the type lookup failed, just add some constraints we can - // try to solve later. if (elementType.isNull()) { - // Determine the iterator type of the sequence. - iteratorType = cs.createTypeVariable(Locator, /*options=*/0); - cs.addTypeMemberConstraint(SequenceType, tc.Context.Id_Iterator, - iteratorType, iteratorLocator); - - // Determine the element type of the iterator. - // FIXME: Should look up the type witness. - elementType = cs.createTypeVariable(Locator, /*options=*/0); - cs.addTypeMemberConstraint(iteratorType, tc.Context.Id_Element, - elementType, elementLocator); + elementType = cs.createTypeVariable(elementLocator, + TVO_MustBeMaterializable); } - // Add a conversion constraint between the element type of the sequence // and the type of the element pattern. cs.addConstraint(ConstraintKind::Conversion, elementType, InitType, elementLocator); - + Stmt->setSequence(expr); return false; }