mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Stop creating ImplicitlyUnwrappedOptional<T> so that we can remove it
from the type system.
Enable the code that generates disjunctions for Optional<T> and
rewrites expressions based on the original declared type being 'T!'.
Most of the changes supporting this were previously merged to master,
but some things were difficult to merge to master without actually
removing IUOs from the type system:
- Dynamic member lookup and dynamic subscripting
- Changes to ensure the bridging peephole still works
Past commits have attempted to retain as much fidelity with how we
were printing things as possible. There are some cases where we still
are not printing things the same way:
- In diagnostics we will print '?' rather than '!'
- Some SourceKit and Code Completion output where we print a Type
rather than Decl.
Things like module printing via swift-ide-test attempt to print '!'
any place that we now have Optional types that were declared as IUOs.
There are some diagnostics regressions related to the fact that we can
no longer "look through" IUOs. For the same reason some output and
functionality changes in Code Completion. I have an idea of how we can
restore these, and have opened a bug to investigate doing so.
There are some small source compatibility breaks that result from
this change:
- Results of dynamic lookup that are themselves declared IUO can in
rare circumstances be inferred differently. This shows up in
test/ClangImporter/objc_parse.swift, where we have
var optStr = obj.nsstringProperty
Rather than inferring optStr to be 'String!?', we now infer this to
be 'String??', which is in line with the expectations of SE-0054.
The fact that we were only inferring the outermost IUO to be an
Optional in Swift 4 was a result of the incomplete implementation of
SE-0054 as opposed to a particular design. This should rarely cause
problems since in the common-case of actually using the property rather
than just assigning it to a value with inferred type, we will behave
the same way.
- Overloading functions with inout parameters strictly by a difference
in optionality (i.e. Optional<T> vs. ImplicitlyUnwrappedOptional<T>)
will result in an error rather than the diagnostic that was added
in Swift 4.1.
- Any place where '!' was being used where it wasn't supposed to be
allowed by SE-0054 will now treat the '!' as if it were '?'.
Swift 4.1 generates warnings for these saying that putting '!'
in that location is deprecated. These locations include for example
typealiases or any place where '!' is nested in another type like
`Int!?` or `[Int!]`.
This commit effectively means ImplicitlyUnwrappedOptional<T> is no
longer part of the type system, although I haven't actually removed
all of the code dealing with it yet.
ImplicitlyUnwrappedOptional<T> is is dead, long live implicitly
unwrapped Optional<T>!
Resolves rdar://problem/33272674.
266 lines
6.3 KiB
C++
266 lines
6.3 KiB
C++
//===--- ConstraintLocator.cpp - Constraint Locator -----------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the \c ConstraintLocator class and its related types,
|
|
// which is used by the constraint-based type checker to describe how
|
|
// a particular constraint was derived.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "ConstraintLocator.h"
|
|
#include "ConstraintSystem.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/Expr.h"
|
|
#include "swift/AST/Types.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace swift;
|
|
using namespace constraints;
|
|
|
|
void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, Expr *anchor,
|
|
ArrayRef<PathElement> path) {
|
|
id.AddPointer(anchor);
|
|
id.AddInteger(path.size());
|
|
for (auto elt : path) {
|
|
id.AddInteger(elt.getKind());
|
|
switch (elt.getKind()) {
|
|
case Archetype:
|
|
id.AddPointer(elt.getArchetype()->getCanonicalType().getPointer());
|
|
break;
|
|
|
|
case Requirement:
|
|
id.AddPointer(elt.getRequirement());
|
|
break;
|
|
|
|
case Witness:
|
|
id.AddPointer(elt.getWitness());
|
|
break;
|
|
|
|
case AssociatedType:
|
|
id.AddPointer(elt.getAssociatedType());
|
|
break;
|
|
|
|
case ApplyArgument:
|
|
case ApplyFunction:
|
|
case FunctionArgument:
|
|
case FunctionResult:
|
|
case OptionalPayload:
|
|
case Member:
|
|
case MemberRefBase:
|
|
case UnresolvedMember:
|
|
case SubscriptIndex:
|
|
case SubscriptMember:
|
|
case SubscriptResult:
|
|
case ConstructorMember:
|
|
case RvalueAdjustment:
|
|
case ClosureResult:
|
|
case ParentType:
|
|
case InstanceType:
|
|
case SequenceIteratorProtocol:
|
|
case GeneratorElementType:
|
|
case ArrayElementType:
|
|
case ScalarToTuple:
|
|
case Load:
|
|
case GenericArgument:
|
|
case NamedTupleElement:
|
|
case TupleElement:
|
|
case ApplyArgToParam:
|
|
case OpenedGeneric:
|
|
case KeyPathComponent:
|
|
case ConditionalRequirement:
|
|
case TypeParameterRequirement:
|
|
case ImplicitlyUnwrappedDisjunctionChoice:
|
|
case DynamicLookupResult:
|
|
if (unsigned numValues = numNumericValuesInPathElement(elt.getKind())) {
|
|
id.AddInteger(elt.getValue());
|
|
if (numValues > 1)
|
|
id.AddInteger(elt.getValue2());
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ConstraintLocator::dump(SourceManager *sm) {
|
|
dump(sm, llvm::errs());
|
|
llvm::errs() << "\n";
|
|
}
|
|
|
|
void ConstraintLocator::dump(ConstraintSystem *CS) {
|
|
dump(&CS->TC.Context.SourceMgr, llvm::errs());
|
|
llvm::errs() << "\n";
|
|
}
|
|
|
|
|
|
void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) {
|
|
out << "locator@" << (void*) this << " [";
|
|
|
|
if (anchor) {
|
|
out << Expr::getKindName(anchor->getKind());
|
|
if (sm) {
|
|
out << '@';
|
|
anchor->getLoc().print(out, *sm);
|
|
}
|
|
}
|
|
|
|
for (auto elt : getPath()) {
|
|
out << " -> ";
|
|
switch (elt.getKind()) {
|
|
case ArrayElementType:
|
|
out << "array element";
|
|
break;
|
|
|
|
case Archetype:
|
|
out << "archetype '" << elt.getArchetype()->getString() << "'";
|
|
break;
|
|
|
|
case AssociatedType:
|
|
out << "associated type '"
|
|
<< elt.getAssociatedType()->getNameStr() << "'";
|
|
break;
|
|
|
|
case ApplyArgument:
|
|
out << "apply argument";
|
|
break;
|
|
|
|
case ApplyFunction:
|
|
out << "apply function";
|
|
break;
|
|
|
|
case OptionalPayload:
|
|
out << "optional payload";
|
|
break;
|
|
|
|
case ApplyArgToParam:
|
|
out << "comparing call argument #" << llvm::utostr(elt.getValue())
|
|
<< " to parameter #" << llvm::utostr(elt.getValue2());
|
|
break;
|
|
|
|
case ClosureResult:
|
|
out << "closure result";
|
|
break;
|
|
|
|
case ConstructorMember:
|
|
out << "constructor member";
|
|
break;
|
|
|
|
case FunctionArgument:
|
|
out << "function argument";
|
|
break;
|
|
|
|
case FunctionResult:
|
|
out << "function result";
|
|
break;
|
|
|
|
case GeneratorElementType:
|
|
out << "generator element type";
|
|
break;
|
|
|
|
case GenericArgument:
|
|
out << "generic argument #" << llvm::utostr(elt.getValue());
|
|
break;
|
|
|
|
case InstanceType:
|
|
out << "instance type";
|
|
break;
|
|
|
|
case Load:
|
|
out << "load";
|
|
break;
|
|
|
|
case Member:
|
|
out << "member";
|
|
break;
|
|
|
|
case MemberRefBase:
|
|
out << "member reference base";
|
|
break;
|
|
|
|
case NamedTupleElement:
|
|
out << "named tuple element #" << llvm::utostr(elt.getValue());
|
|
break;
|
|
|
|
case UnresolvedMember:
|
|
out << "unresolved member";
|
|
break;
|
|
|
|
case ParentType:
|
|
out << "parent type";
|
|
break;
|
|
|
|
case RvalueAdjustment:
|
|
out << "rvalue adjustment";
|
|
break;
|
|
|
|
case ScalarToTuple:
|
|
out << "scalar to tuple";
|
|
break;
|
|
|
|
case SequenceIteratorProtocol:
|
|
out << "sequence iterator type";
|
|
break;
|
|
|
|
case SubscriptIndex:
|
|
out << "subscript index";
|
|
break;
|
|
|
|
case SubscriptMember:
|
|
out << "subscript member";
|
|
break;
|
|
|
|
case SubscriptResult:
|
|
out << "subscript result";
|
|
break;
|
|
|
|
case TupleElement:
|
|
out << "tuple element #" << llvm::utostr(elt.getValue());
|
|
break;
|
|
|
|
case KeyPathComponent:
|
|
out << "key path component #" << llvm::utostr(elt.getValue());
|
|
break;
|
|
|
|
case Requirement:
|
|
out << "requirement ";
|
|
elt.getRequirement()->dumpRef(out);
|
|
break;
|
|
|
|
case Witness:
|
|
out << "witness ";
|
|
elt.getWitness()->dumpRef(out);
|
|
break;
|
|
|
|
case OpenedGeneric:
|
|
out << "opened generic";
|
|
break;
|
|
|
|
case ConditionalRequirement:
|
|
out << "conditional requirement #" << llvm::utostr(elt.getValue());
|
|
break;
|
|
|
|
case TypeParameterRequirement:
|
|
out << "type parameter requirement #" << llvm::utostr(elt.getValue());
|
|
break;
|
|
|
|
case ImplicitlyUnwrappedDisjunctionChoice:
|
|
out << "implictly unwrapped disjunction choice";
|
|
break;
|
|
|
|
case DynamicLookupResult:
|
|
out << "dynamic lookup result";
|
|
break;
|
|
}
|
|
}
|
|
|
|
out << ']';
|
|
}
|