Previously, if a request R evaluated itself N times, we would emit N
"circular reference" diagnostics. These add no value, so instead let's
cache the user-provided default value on the first circular evaluation.
This changes things slightly so that instead of returning an
llvm::Expected<Request::OutputType>, various evaluator methods take
a callback which can produce the default value.
The existing evaluateOrDefault() interface is unchanged, and a new
evaluateOrFatal() entry point replaces
llvm::cantFail(ctx.evaluator(...)).
Direct callers of the evaluator's operator() were updated to pass in
the callback. The benefit of the callback over evaluateOrDefault() is
that if the default value is expensive to constuct, like a dummy
generic signature, we will only construct it in the case where a
cycle actually happened, otherwise we just delete the callback.
(cherry picked from commit b8fcf1c709efa6cd28e1217bd0efe876f7c0d2b7)
This commit changes fixit messages from a question/suggestion to an
imperative message for protocol conformances and switch-case. Addresses
https://github.com/apple/swift/issues/67510.
We can't just ignore unavailable conformances because the
generic signature we're computing might itself be attached
to an unavailable declaration.
Until we get a proper fix, only drop unavailable conformances
to Sendable here.
Fixes rdar://problem/94305457.
When determining whether a superclass conforms to a particular protocol,
skip unavailable conformances. This way, we don't minimize away a
constraint that might only apply to subclasses of the specified
superclass.
Fixes rdar://91853658.
- Don't pass 'verify' since it's now the default
- Update tests where diagnostics changed in a correct way to pass 'on' instead
- Delete compiler_scale/explicit_requirements_perf.swift since it's not testing anything with the requirement machine
Returning a null GenericSignature is not the right way to break a cycle,
because then callers have to be careful to handle the case of a null
GenericSignature together with a non-null GenericParamList, for example
in applyGenericArguments().
An even worse problem can occur when a GenericSignatureRequest for a
nested generic declaration requests the signature of the parent context,
which hits a cycle. In this case, we would build a signature where
the first generic parameter did not have depth 0.
This makes the requirement machine upset, so this patch implements a new
strategy to break such cycles. Instead of returning a null
GenericSignature, we build a signature with the correct generic
parameters, but no requirements. The generic parameters can be computed
just by traversing GenericParamLists, which does not trigger more
GenericSignatureRequests, so this should be safe.
If we don't set this flag, we can end up making an invalid GSB into
the canonical builder for some signature. This was caught by
requirement machine cross-checking on the compiler_crashers suite.
In `ConstraintGenerator::visitDeclRefExpr` instead of using
`getInterfaceType()` for unknown type and later mapping it into
context, let's use `getType()` which does that interally, that
allows to detect presence of error types in resulting type and
abort constraint generation.
Name lookup might find an associated type whose protocol is not in our
conforms-to list, if we have a superclass constraint and the superclass
conforms to the associated type's protocol.
We used to return an unresolved type in this case, which would result in
the constraint getting delayed forever and dropped.
While playing wack-a-mole with regressing crashers, I had to do some
refactoring to get all the tests to pass. Unfortuanately these refactorings
don't lend themselves well to being peeled off into their own commits:
- maybeAddSameTypeRequirementForNestedType() was almost identical to
concretizeNestedTypeFromConcreteParent(), except for superclasses
instead of concrete same-type constraints. I merged them together.
- We used to drop same-type constraints where the subject type was an
ErrorType, because maybeResolveEquivalenceClass() would return an
unresolved type in this case.
This violated some invariants around nested types of ArchetypeTypes,
because now it was possible for a nested type of a concrete type to
be non-concrete, if the type witness in the conformance was missing
due to an error.
Fix this by removing the ErrorType hack, and adjusting a couple of
other places to handle ErrorTypes in order to avoid regressing with
invalid code.
Fixes <rdar://problem/45216921>, <https://bugs.swift.org/browse/SR-8945>,
<https://bugs.swift.org/browse/SR-12744>.
There's no need to instantiate archetypes in the generic environment
of the declaration being opened.
A couple of diagnostics changed. They were already misleading, and the
new diagnostics, while different, are not any more misleading than
before.
Fixes a problem related to presence of InOutType in function parameters
which diagnostics related to generic parameter requirements didn't handle
correctly, and improves diagnostics for unsatisfied generic requirements
in operator applications, which we didn't attempt to diagnose at all.
Resolves: rdar://problem/33477726
Recursive concrete and superclass constraints are detected
per-equivalence-class; record them that way.
Use that information to drop recursive concrete and superclass
constraints from the resulting signature, which frees the canonical
generic signature builder from having to worry about such recursive
constraints. This eliminates the invalid-code crashes introduced in
the prior commit that disabled finalization for the canonical GSBs, as
well as fixing one other random crash-on-invalid.
When a requirement mentions a concrete type, that type might utter
other types (e.g., Set<T>) that infer requirements (here, T:
Hashable). Perform requirement inference for such types.
Part of rdar://problem/31520386.
ArchetypeBuilder::finalize() is needed to tie up any loose ends before
requesting a generic signature or generic environment. Make sure it
gets called consistently.
Previously, validateDecl() would check if the declaration had an
interface type and use that as an indication not to proceed.
However for functions we can only set an interface type after
checking the generic signature, so a recursive call to validateDecl()
on a function would "steal" the outer call and complete validation.
For generic types, this meant we could have a declaration with a
valid interface type but no generic signature.
Both cases were problematic, so narrow workarounds were put in
place with additional new flags. This made the code harder to
reason about.
This patch consolidates the flags and establishes new invariants:
- If validateDecl() returns and the declaration has no interface
type and the isBeingValidated() flag is not set, it means one
of the parent contexts is being validated by an outer recursive
call.
- If validateDecl() returns and the declaration has the
isBeingValidated() flag set, it may or may not have an interface
type. In this case, the declaration itself is being validated
by an outer recursive call.
- If validateDecl() returns and the declaration has an interface
type and the isBeingValidated() flag is not set, it means the
declaration and all of its parent contexts are fully validated
and ready for use.
In general, we still want name lookup to find things that have an
interface type but are not in a valid generic context, so for this
reason nominal types and associated types get an interface type as
early as possible.
Most other code only wants to see fully formed decls, so a new
hasValidSignature() method returns true iff the interface type is
set and the isBeingValidated() flag is not set.
For example, while resolving a type, we can resolve an unqualified
reference to a nominal type without a valid signature. However, when
applying generic parameters, the hasValidSignature() flag is used
to ensure we error out instead of crashing if the generic signature
has not yet been formed.
- In functions called from resolveType(), consistently
use a Type() return value to indicate 'unsatisfied
dependency', and ErrorType to indicate failure.
- Plumb the unsatisfiedDependency callback through the
resolution of the arguments of BoundGenericTypes, and
also pass down the options.
- Before doing a conformance check on the argument of a
BoundGenericType, kick off a TypeCheckSuperclass request
if the type in question is a class. This ensures we don't
recurse through NominalTypeDecl::prepareConformanceTable(),
which wants to see a class with a valid superclass.
- The ResolveTypeOfDecl request was assuming that
the request was satisfied after calling validateDecl().
This is not the case when the ITC is invoked from a
recursive call to validateDecl(), hack this up by returning
*true* from isResolveTypeDeclSatisfied(); otherwise we
assert in satisfy(), and we can't make forward progress
in this case anyway.
- Fix a bug in cycle breaking; it seems if we don't invoke
the cycle break callback on all pending requests, we end
up looping forever in an outer call to satisfy().
- Remove unused TR_GlobalTypeAlias option.
We no longer need a separate "pass" that creates an archetype builder
that inherits context archetypes, because we no longer ever inherit
context archetypes.
This function did three things:
- In debug builds, record an association between the newly-created
context archetypes and the current DeclContext.
- Set the accessibility of the GenericTypeParamDecls as appropriate.
- Re-check the types written in the GenericParamList.
The last step was not needed, because we no longer serialize
GenericParamLists, or care if the RequirementRepr contains valid
types at all. The other two have been moved elsewhere.
First, ensure all ParamDecls that are synthesized from scratch are given
both a contextual type and an interface type.
For ParamDecls written in source, add a new recordParamType() method to
GenericTypeResolver. This calls setType() or setInterfaceType() as
appropriate.
Interestingly enough a handful of diagnostics in the test suite have
improved. I'm not sure why, but I'll take it.
The ParamDecl::createUnboundSelf() method is now only used in the parser,
and no longer sets the type of the self parameter to the unbound generic
type. This was wrong anyway, since the type was always being overwritten.
This allows us to remove DeclContext::getSelfTypeOfContext().
Also, ensure that FuncDecl::getBodyResultTypeLoc() always has an interface
type for synthesized declarations, eliminating a mapTypeOutOfContext()
call when computing the function interface type in configureInterfaceType().
Finally, clean up the logic for resolving the DynamicSelfType. We now
get the interface or contextual type of 'Self' via the resolver, instead
of always getting the contextual type and patching it up inside
configureInterfaceType().
The previous patches regressed a test where we used to diagnose
(poorly) a circular associated type, like so:
associatedtype e: e
With the error "inheritance from non-protocol, non-class type 'e'".
This error went away, because we end up not setting the interface
type of the associated type early enough. Instead, we return an
ErrorType from resolveTypeInContext() and diagnose nothing.
With this patch, emit a diagnostic at the point where the ErrorType
first appears.
Also, remove the isRecursive() bit from AssociatedTypeDecl, and
remove isBeingTypeChecked() which duplicates a bit with the same
name in Decl.
When checking a conformance of a concrete type to a protocol, we
effectively checked the associated types twice -- once when
deriving them, and another time at the end, where we performed
a substitution of the protocol 'Self' type to the concrete type.
The latter checked superclass constraints, while the former did not.
However, this trick no longer works with minimized generic
signatures, because <P : Self> no longer has redundant requirements
for the associated types of 'P'.
Instead, check superclass constraints at the same time as checking
conformances.
and provide a fix-it to move it to the new location as referenced
in SE-0081.
Fix up a few stray places in the standard library that is still using
the old syntax.
Update any ./test files that aren't expecting the new warning/fix-it
in -verify mode.
While investigating what I thought was a new crash due to this new
diagnostic, I discovered two sources of quite a few compiler crashers
related to unterminated generic parameter lists, where the right
angle bracket source location was getting unconditionally set to
the current token, even though it wasn't actually a '>'.
Every call to validateGenericTypeSignature() had the same
boilerplate following; move the common logic into that
function.
As one might expect, each callsite had slight variants on
the same underlying logic -- this makes them consistent.
Also, this slightly widens the scope during which
GenericTypeDecl::isValidatingGenericSignature() returns
true.
Interesting, that change introduces a diagnostic in an
existing testcase where previously there was none:
protocol P {
associatedtype T
}
struct S<A: P where A.T == S<A>> {}
While it looks like this generic signature was built
correctly, in fact I think we weren't computing
conformances for the substitution of 'A' in 'S<A>'.
After trying small variations on the above testcase,
I quickly ran into SILGen crashes, which the diagnostic
now prevents. A few interesting cases still crash.
See test/decl/protocol/req/recursion.swift for the
gory details.
Adds an associatedtype keyword to the parser tokens, and accepts either
typealias or associatedtype to create an AssociatedTypeDecl, warning
that the former is deprecated. The ASTPrinter now emits associatedtype
for AssociatedTypeDecls.
Separated AssociatedType from TypeAlias as two different kinds of
CodeCompletionDeclKinds. This part probably doesn’t turn out to be
absolutely necessary currently, but it is nice cleanup from formerly
specifically glomming the two together.
And then many, many changes to tests. The actual new tests for the fixits
is at the end of Generics/associated_types.swift.
This would just set the NominalTypeDecl's declared type to
ErrorType, which caused problems elsewhere.
Instead, generalize the logic used for AbstractFunctionDecl.
This correctly wires up the GenericTypeParamDecl's archetypes even
if the signature didn't validate, fixing crashes if the generic
parameters of the type are referenced.
Cleans up AST printing somewhat as well as providing slightly better
type-to-declaration mappings for annotated AST printing and indexing.
Swift SVN r32420