Skip to content

[Constraint solver] Remove 'type member' constraint. #5663

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions lib/Sema/CSDiag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -2148,9 +2129,6 @@ bool FailureDiagnosis::diagnoseConstraintFailure() {
// This is a predicate that classifies constraints according to our
// priorities.
std::function<void (Constraint*)> classifyConstraint = [&](Constraint *C) {
if (isLowPriorityConstraint(C))
return rankedConstraints.push_back({C, CR_OtherConstraint});

if (isMemberConstraint(C))
return rankedConstraints.push_back({C, CR_MemberConstraint});

Expand Down
67 changes: 0 additions & 67 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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<AbstractFunctionDecl>(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);

Expand Down Expand Up @@ -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<MetatypeType>())
instanceTy = MTT->getInstanceType();
Expand Down Expand Up @@ -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()");
Expand Down Expand Up @@ -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(),
Expand Down
2 changes: 0 additions & 2 deletions lib/Sema/CSSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand Down Expand Up @@ -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?
Expand Down
6 changes: 0 additions & 6 deletions lib/Sema/Constraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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());

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
10 changes: 2 additions & 8 deletions lib/Sema/Constraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -485,7 +482,6 @@ class Constraint final : public llvm::ilist_node<Constraint>,

case ConstraintKind::ValueMember:
case ConstraintKind::UnresolvedValueMember:
case ConstraintKind::TypeMember:
return ConstraintClassification::Member;

case ConstraintKind::DynamicTypeOf:
Expand Down Expand Up @@ -519,16 +515,14 @@ class Constraint final : public llvm::ilist_node<Constraint>,
/// \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.
Expand Down
26 changes: 0 additions & 26 deletions lib/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -1336,32 +1336,6 @@ class ConstraintSystem {
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,
Expand Down
22 changes: 8 additions & 14 deletions lib/Sema/TypeCheckConstraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}
Expand Down