While, tracking defaulted constraints based on their type variable
usually works in practice, it can break if the type variable ends up
being equivalent to some other type variable that. Instead, record the
locators associated with Defaultable constraints where we used the
default, which are easier to work with during constraint application.
We had a few places that were performing ad hoc variants of
ConstraintSystem::getFixedTypeRecursive(); simplify it's interface so
we can use it everywhere consistently. Fixes rdar://problem/27261929.
Similar to “isTypeParameter,” this new entry point determines whether the type is a type variable or a nested type of a type thereof. The latter case isn’t actually formed yet, so this is NFC staging the trivial bits of this change.
Var-arg closures are already escaping, so we typically want to issue
an error if @escaping is specified. To not do sure will confuse and
give a false impression on the un-annotated semantics and whether it
is needed. But, 3.0 shipped with a bug where we didn't consistently
apply the no-escape-by-default rule here, and thus it was semantically
meaningful (and needed).
In order to preserve source compatibility, albeit at the expense of
developers on versions 3.0.1 and later in the Swift 3 family, we
suppress the error if we see @escaping. Either way, this is a
relatively uncommon usage, so the confusion won't be too wide spread.
For flags like -debug-time-function-bodies, this
makes it easier to measure the impact of parsing
functions that take a short amount of time to parse
(less than 0.1ms) but are parsed many times and
therefore add up over the course of the full build.
In most places where we were checking "is<ErrorType>()", we now mean
"any error occurred". The few exceptions are in associated type
inference, code completion, and expression diagnostics, where we might
still work with partial errors.
Type::subst()'s "IgnoreMissing" option was fairly unprincipled, dropping
unsubstituted types into the resulting AST without any indication
whatsoever that anything went wrong. Replace this notion with a new
form of ErrorType that explicitly tracks which substituted type caused
the problem. It's still an ErrorType, but it prints like the
substituted type (which is important for code completion) and allows
us to step back to the substituted type if needed (which is used by
associated type inference). Then, allow Type::subst(), when the new
UseErrorTypes flag is passed, to form partially-substituted types that
contain errors, which both code completion and associated type
inference relied on.
Over time, I hope we can use error-types-with-original-types more
often to eliminate "<<error type>>" from diagnostics and teach
Type::subst() never to return a "null" type. Clients can check
"hasError()" to deal with failure cases rather than checking null.
This particular flag should only be used in rare cases where we don't
want to know about failures, but instead want to get some
partially-formed type. Only very specific parts of the type checker
need this (associated type inference), and code completion relies on
it for slightly-better results.
Targeted fix for SR-2673: if a potential protocol witness is
@NSManaged, add accessors the NSManaged way, not the stored property
way.
There's probably more weirdness around here, so I'll clone the bug to
go through maybeAddAccessorsToVariable a lot more often. (Lazy
properties could easily be broken in the same way.)
The idea here is that if a generic signature has invalid requirements,
we would drop all the requirements and build a new set of archetypes
without requirements.
When this logic was added, it fixed 700 compiler_crashers:
<c258f991f6>
Nowadays it appears that all the underlying issues were solved, so
removing this error path actually fixed two crashers and improved
a couple of diagnostics.
When generating constraints for subscript convert InOutType into LValueType,
because base of the subscript should never be marked as inout, but rather as
@lvalue to denote mutability.
Resolves <rdar://problem/25601561>.
This was almost identical to getMemberSubstitutions(), except
protocol and protocol extension members are not properly
supported.
Now that this method is no longer used by the ASTPrinter, there
are only two remaining usages, both trivially refactorable to
use better APIs.
There was a ton of complicated logic here to work around
two problems:
- Same-type constraints were not represented properly in
RequirementReprs, requiring us to store them in strong form
and parse them out when printing type interfaces.
- The TypeBase::getAllGenericArgs() method did not do the
right thing for members of protocols and protocol extensions,
and so instead of simple calls to Type::subst(), we had
an elaborate 'ArchetypeTransformer' abstraction repeated
in two places.
Rewrite this code to use GenericSignatures and
GenericFunctionType instead of old-school GenericParamLists
and PolymorphicFunctionType.
This changes the code completion and AST printer output
slightly. A few of the changes are actually fixes for cases
where the old code didn't handle substitutions properly.
A few others are subjective, for example a generic parameter
list of the form <T : Proto> now prints as <T where T : Proto>.
We can add heuristics to make the output whatever we want
here; the important thing is that now we're using modern
abstractions.
For code completion to use Type::subst() without undoing
previously-added heuristics, we need a form of member lookup
that strips the outermost typealias type. For example, if we
have
protocol P {
associatedtype Fruit
}
struct Apple {}
typealias Pear = Apple
class Bowl : P {
typealias Fruit = Pear
}
With DesugarMemberTypes OFF, the substitution 'T := Bowl'
applied to 'T.Fruit' yields 'Bowl.Fruit'.
With DesugarMemberTypes ON, the same substitution instead
produces 'Pear' (note: not 'Apple'; we only desugar one
level here, to match the current code completion behavior).
Also, add another tweak that will become important shortly;
if a type witness cannot be derived, set the type witness
to an alias type pointing to an error type, instead of
directly storing an error type in there.
We have a special case check for the no-escape-by-default rules for a
computed property setter's newValue argument, which if a closure,
obviously has to be escaping. But, we checked this by checking the
type's overall DeclContext, which unfortunately meant we also made
nested closures escaping implicitly. This fixes that to only tack on
the implicit escaping at the top level for the setter's type.
By moving the is-setter-newValue logic into a TypeCheckOption, we
allow more local reasoning inside of resolve type and can plumb the
special knowledge directly into applyNonEscapingFromContext. This is a
little cleaner, but mainly has the advantage that it will keep future
refactorings of the AST and escapability more localized.
Added test cases for SILGen as well, to make sure we don't crash
(enforces getter/setter escapability parity).
We have a special case check for the no-escape-by-default rules for a
computed property setter's newValue argument, which if a closure,
obviously has to be escaping. But, we checked this by checking the
type's overall DeclContext, which unfortunately meant we also made
nested closures escaping implicitly. This fixes that to only tack on
the implicit escaping at the top level for the setter's type.
This time, propagate the decl marked deprecated or unavailable through
to the fix-it, so we can be sure it's a var.
https://bugs.swift.org/browse/SR-1649