Skip to content

Commit a899872

Browse files
committed
Reapply r31105, with some fixes to invalid unconstrained generics. These fixes correct
the regressions that r31105 introduced in the validation tests, as well as fixing a number of other validation tests as well. Introduce a new UnresolvedType to the type system, and have CSDiags start to use it as a way to get more type information out of incorrect subexpressions. UnresolvedType generally just propagates around the type system like a type variable: - it magically conforms to all protocols - it CSGens as an unconstrained type variable. - it ASTPrints as _, just like a type variable. The major difference is that UnresolvedType can be used outside the context of a ConstraintSystem, which is useful for CSGen since it sets up several of them to diagnose subexpressions w.r.t. their types. For now, our use of this is extremely limited: when a closureexpr has no contextual type available and its parameters are invalid, we wipe them out with UnresolvedType (instead of the previous nulltype dance) to get ambiguities later on. We also introduce a new FreeTypeVariableBinding::UnresolvedType approach for constraint solving (and use this only in one place in CSDiags so far, to resolve the callee of a CallExpr) which solves a system and rewrites any leftover type variables as UnresolvedTypes. This allows us to get more precise information out, for example, diagnosing: func r22162441(lines: [String]) { lines.map { line in line.fooBar() } } with: value of type 'String' has no member 'fooBar' instead of: type of expression is ambiguous without more context This improves a number of other diagnostics as well, but is just the infrastructural stepping stone for greater things. Swift SVN r31130
1 parent 66c8598 commit a899872

File tree

55 files changed

+219
-102
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+219
-102
lines changed

include/swift/AST/ASTContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ class ASTContext {
527527

528528
// Builtin type and simple types that are used frequently.
529529
const CanType TheErrorType; /// This is the ErrorType singleton.
530+
const CanType TheUnresolvedType; /// This is the UnresolvedType singleton.
530531
const CanType TheEmptyTupleType; /// This is "()", aka Void
531532
const CanType TheNativeObjectType; /// Builtin.NativeObject
532533
const CanType TheBridgeObjectType; /// Builtin.BridgeObject

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
#endif
8585

8686
UNCHECKED_TYPE(Error, Type)
87+
UNCHECKED_TYPE(Unresolved, Type)
8788
ABSTRACT_TYPE(Builtin, Type)
8889
BUILTIN_TYPE(BuiltinInteger, BuiltinType)
8990
BUILTIN_TYPE(BuiltinFloat, BuiltinType)

include/swift/AST/Types.h

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,26 @@ class RecursiveTypeProperties {
9292
/// This type expression contains a GenericTypeParamType.
9393
HasTypeParameter = 0x04,
9494

95+
/// This type expression contains an UnresolvedType.
96+
HasUnresolvedType = 0x08,
97+
98+
9599
/// This type expression contains an LValueType or InOutType,
96100
/// other than as a function input.
97-
IsNotMaterializable = 0x08,
101+
IsNotMaterializable = 0x10,
98102

99103
/// This type expression contains an LValueType and can be loaded to convert
100104
/// to an rvalue.
101-
IsLValue = 0x10,
105+
IsLValue = 0x20,
102106

103107
/// This type expression contains an opened existential ArchetypeType.
104-
HasOpenedExistential = 0x20,
108+
HasOpenedExistential = 0x40,
105109

106110
/// This type expression contains a DynamicSelf type.
107-
HasDynamicSelf = 0x40,
111+
HasDynamicSelf = 0x80,
108112

109113
/// Whether this type expression contains an unbound generic type.
110-
HasUnboundGeneric = 0x80,
114+
HasUnboundGeneric = 0x100,
111115
};
112116

113117
private:
@@ -132,6 +136,9 @@ class RecursiveTypeProperties {
132136
/// Does a type with these properties have a type parameter somewhere in it?
133137
bool hasTypeParameter() const { return Bits & HasTypeParameter; }
134138

139+
/// Does a type with these properties have an unresolved type somewhere in it?
140+
bool hasUnresolvedType() const { return Bits & HasUnresolvedType; }
141+
135142
/// Is a type with these properties materializable: that is, is it a
136143
/// first-class value type?
137144
bool isMaterializable() const { return !(Bits & IsNotMaterializable); }
@@ -379,6 +386,11 @@ class alignas(1 << TypeAlignInBits) TypeBase {
379386
return getRecursiveProperties().hasTypeVariable();
380387
}
381388

389+
/// \brief Determine whether this type involves a UnresolvedType.
390+
bool hasUnresolvedType() const {
391+
return getRecursiveProperties().hasUnresolvedType();
392+
}
393+
382394
/// Determine whether the type involves an archetype.
383395
bool hasArchetype() const {
384396
return getRecursiveProperties().hasArchetype();
@@ -818,6 +830,27 @@ class ErrorType : public TypeBase {
818830
};
819831
DEFINE_EMPTY_CAN_TYPE_WRAPPER(ErrorType, Type)
820832

833+
/// UnresolvedType - This represents a type variable that cannot be resolved to
834+
/// a concrete type because the expression is ambiguous. This is produced when
835+
/// parsing expressions and producing diagnostics. Any instance of this should
836+
/// cause the entire expression to be ambiguously typed.
837+
class UnresolvedType : public TypeBase {
838+
friend class ASTContext;
839+
// The Unresolved type is always canonical.
840+
UnresolvedType(ASTContext &C)
841+
: TypeBase(TypeKind::Unresolved, &C,
842+
RecursiveTypeProperties(RecursiveTypeProperties::HasUnresolvedType)) { }
843+
public:
844+
static Type get(const ASTContext &C);
845+
846+
// Implement isa/cast/dyncast/etc.
847+
static bool classof(const TypeBase *T) {
848+
return T->getKind() == TypeKind::Unresolved;
849+
}
850+
};
851+
DEFINE_EMPTY_CAN_TYPE_WRAPPER(UnresolvedType, Type)
852+
853+
821854
/// BuiltinType - An abstract class for all the builtin types.
822855
class BuiltinType : public TypeBase {
823856
protected:

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,8 @@ ASTContext::ASTContext(LangOptions &langOpts, SearchPathOptions &SearchPathOpts,
383383
SwiftShimsModuleName(getIdentifier(SWIFT_SHIMS_NAME)),
384384
TypeCheckerDebug(new StderrTypeCheckerDebugConsumer()),
385385
TheErrorType(new (*this, AllocationArena::Permanent) ErrorType(*this)),
386+
TheUnresolvedType(new (*this, AllocationArena::Permanent)
387+
UnresolvedType(*this)),
386388
TheEmptyTupleType(TupleType::get(ArrayRef<TupleTypeElt>(), *this)),
387389
TheNativeObjectType(new (*this, AllocationArena::Permanent)
388390
BuiltinNativeObjectType(*this)),
@@ -405,7 +407,7 @@ ASTContext::ASTContext(LangOptions &langOpts, SearchPathOptions &SearchPathOpts,
405407
TheIEEE128Type(new (*this, AllocationArena::Permanent)
406408
BuiltinFloatType(BuiltinFloatType::IEEE128, *this)),
407409
ThePPC128Type(new (*this, AllocationArena::Permanent)
408-
BuiltinFloatType(BuiltinFloatType::PPC128,*this)) {
410+
BuiltinFloatType(BuiltinFloatType::PPC128, *this)) {
409411

410412
// Initialize all of the known identifiers.
411413
#define IDENTIFIER_WITH_NAME(Name, IdStr) Id_##Name = getIdentifier(IdStr);

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2343,6 +2343,7 @@ namespace {
23432343
}
23442344

23452345
TRIVIAL_TYPE_PRINTER(Error, error)
2346+
TRIVIAL_TYPE_PRINTER(Unresolved, unresolved)
23462347

23472348
void visitBuiltinIntegerType(BuiltinIntegerType *T, StringRef label) {
23482349
printCommon(T, label, "builtin_integer_type");

lib/AST/ASTPrinter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2305,6 +2305,13 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
23052305
Printer << "<<error type>>";
23062306
}
23072307

2308+
void visitUnresolvedType(UnresolvedType *T) {
2309+
if (T->getASTContext().LangOpts.DebugConstraintSolver)
2310+
Printer << "<<unresolvedtype>>";
2311+
else
2312+
Printer << "_";
2313+
}
2314+
23082315
void visitBuiltinRawPointerType(BuiltinRawPointerType *T) {
23092316
Printer << "Builtin.RawPointer";
23102317
}

lib/AST/Mangle.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ void Mangler::mangleType(Type type, ResilienceExpansion explosion,
761761
llvm_unreachable("Cannot mangle module type yet");
762762

763763
case TypeKind::Error:
764+
case TypeKind::Unresolved:
764765
Buffer << "ERR";
765766
return;
766767

lib/AST/Module.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,18 @@ LookupConformanceResult Module::lookupConformance(Type type,
830830
}
831831
}
832832

833+
// UnresolvedType is a placeholder for an unknown type used when generating
834+
// diagnostics. We consider it to conform to all protocols, since the
835+
// intended type might have.
836+
if (type->is<UnresolvedType>()) {
837+
return {
838+
ctx.getConformance(type, protocol, protocol->getLoc(), this,
839+
ProtocolConformanceState::Complete),
840+
ConformanceKind::Conforms
841+
};
842+
}
843+
844+
833845
auto nominal = type->getAnyNominal();
834846

835847
// If we don't have a nominal type, there are no conformances.

lib/AST/Type.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ bool CanType::isReferenceTypeImpl(CanType type, bool functionsCount) {
117117
// Nothing else is statically just a class reference.
118118
case TypeKind::SILBlockStorage:
119119
case TypeKind::Error:
120+
case TypeKind::Unresolved:
120121
case TypeKind::BuiltinInteger:
121122
case TypeKind::BuiltinFloat:
122123
case TypeKind::BuiltinRawPointer:
@@ -369,6 +370,7 @@ bool TypeBase::isUnspecializedGeneric() {
369370
return false;
370371

371372
case TypeKind::Error:
373+
case TypeKind::Unresolved:
372374
case TypeKind::TypeVariable:
373375
llvm_unreachable("querying invalid type");
374376

@@ -1251,6 +1253,7 @@ CanType TypeBase::getCanonicalType() {
12511253
#define TYPE(id, parent)
12521254
#include "swift/AST/TypeNodes.def"
12531255
case TypeKind::Error:
1256+
case TypeKind::Unresolved:
12541257
case TypeKind::TypeVariable:
12551258
llvm_unreachable("these types are always canonical");
12561259

@@ -2527,8 +2530,8 @@ static Type getMemberForBaseType(Module *module,
25272530
// conformances we're supposed to skip this conformance's unsatisfied type
25282531
// witnesses, and we have an unsatisfied type witness, return
25292532
// "missing".
2530-
if (conformance.getPointer() &&
2531-
conformance.getPointer()->getRootNormalConformance()->getState()
2533+
assert(conformance.getPointer());
2534+
if (conformance.getPointer()->getRootNormalConformance()->getState()
25322535
== ProtocolConformanceState::CheckingTypeWitnesses &&
25332536
!conformance.getPointer()->hasTypeWitness(assocType, nullptr))
25342537
return Type();
@@ -2777,6 +2780,7 @@ case TypeKind::Id:
27772780
#define TYPE(Id, Parent)
27782781
#include "swift/AST/TypeNodes.def"
27792782
case TypeKind::Error:
2783+
case TypeKind::Unresolved:
27802784
case TypeKind::TypeVariable:
27812785
case TypeKind::AssociatedType:
27822786
case TypeKind::GenericTypeParam:

lib/AST/TypeWalker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class Traversal : public TypeVisitor<Traversal, bool>
3333
TypeWalker &Walker;
3434

3535
bool visitErrorType(ErrorType *ty) { return false; }
36+
bool visitUnresolvedType(UnresolvedType *ty) { return false; }
3637
bool visitBuiltinType(BuiltinType *ty) { return false; }
3738
bool visitNameAliasType(NameAliasType *ty) { return false; }
3839

0 commit comments

Comments
 (0)