GenericEnvironment: Replace 'substDependentTypesWithErrorTypes' with an assertion

This commit is contained in:
Anthony Latsis
2021-10-25 05:11:34 +03:00
parent 127f2f5cd0
commit 1cf9622f32
6 changed files with 28 additions and 13 deletions

View File

@@ -317,9 +317,6 @@ public:
LookupConformanceFn conformances, LookupConformanceFn conformances,
SubstOptions options=None) const; SubstOptions options=None) const;
/// Replace references to substitutable types with error types.
Type substDependentTypesWithErrorTypes() const;
bool isPrivateStdlibType(bool treatNonBuiltinProtocolsAsPublic = true) const; bool isPrivateStdlibType(bool treatNonBuiltinProtocolsAsPublic = true) const;
SWIFT_DEBUG_DUMP; SWIFT_DEBUG_DUMP;

View File

@@ -87,9 +87,12 @@ Optional<Type> GenericEnvironment::getMappingIfPresent(
Type GenericEnvironment::mapTypeIntoContext(GenericEnvironment *env, Type GenericEnvironment::mapTypeIntoContext(GenericEnvironment *env,
Type type) { Type type) {
assert(!type->hasArchetype() && "already have a contextual type"); assert(!type->hasArchetype() && "already have a contextual type");
assert((env || !type->hasTypeParameter()) &&
"no generic environment provided for type with type parameters");
if (!env) if (!env) {
return type.substDependentTypesWithErrorTypes(); return type;
}
return env->mapTypeIntoContext(type); return env->mapTypeIntoContext(type);
} }

View File

@@ -4151,13 +4151,6 @@ Type Type::subst(TypeSubstitutionFn substitutions,
return substType(*this, substitutions, conformances, options); return substType(*this, substitutions, conformances, options);
} }
Type Type::substDependentTypesWithErrorTypes() const {
return substType(*this,
[](SubstitutableType *t) -> Type { return Type(); },
MakeAbstractConformanceForGenericType(),
SubstFlags::AllowLoweredTypes);
}
const DependentMemberType *TypeBase::findUnresolvedDependentMemberType() { const DependentMemberType *TypeBase::findUnresolvedDependentMemberType() {
if (!hasTypeParameter()) return nullptr; if (!hasTypeParameter()) return nullptr;

View File

@@ -1011,7 +1011,7 @@ ValueDecl *DerivedConformance::deriveHashable(ValueDecl *requirement) {
// Hashable because DerivedConformance::canDeriveHashable returns true // Hashable because DerivedConformance::canDeriveHashable returns true
// even if the conformance can't be derived. See the note there for // even if the conformance can't be derived. See the note there for
// details. // details.
auto *dc = ConformanceDecl->getDeclContext(); auto *dc = cast<DeclContext>(ConformanceDecl);
tryDiagnoseFailedHashableDerivation(dc, Nominal); tryDiagnoseFailedHashableDerivation(dc, Nominal);
return nullptr; return nullptr;
} }

View File

@@ -1199,7 +1199,23 @@ AssociatedTypeDecl *AssociatedTypeInference::completeSolution(
// If the substitution produced an error, we're done. // If the substitution produced an error, we're done.
if (type->hasError()) if (type->hasError())
return witness.getAssocType(); return witness.getAssocType();
// FIXME: If we still have a type parameter and it isn't a generic
// parameter of the conforming nominal, it's either a cycle or a
// solution that is beyond the current algorithm, i.e.
//
// protocol P {
// associatedtype A = B
// associatedtype B = C
// associatedtype C = Int
// }
// struct Conformer: P {}
if (type->hasTypeParameter() &&
!adoptee->getAnyNominal()->isGeneric()) {
return witness.getAssocType();
} }
}
type = dc->mapTypeIntoContext(type); type = dc->mapTypeIntoContext(type);
} }

View File

@@ -173,6 +173,12 @@ func genericNotHashable() {
GenericNotHashable<String>.A("a").hash(into: &hasher) // expected-error {{value of type 'GenericNotHashable<String>' has no member 'hash'}} GenericNotHashable<String>.A("a").hash(into: &hasher) // expected-error {{value of type 'GenericNotHashable<String>' has no member 'hash'}}
} }
enum GenericNotHashable2<T: Equatable, U: Hashable>: Hashable {
// expected-error@-1 {{type 'GenericNotHashable2' does not conform to protocol 'Hashable'}}
case A(U, T) // expected-note {{associated value type 'T' does not conform to protocol 'Hashable', preventing synthesized conformance of 'GenericNotHashable2<T, U>' to 'Hashable'}}
case B
}
// An enum with no cases should also derive conformance. // An enum with no cases should also derive conformance.
enum NoCases: Hashable {} enum NoCases: Hashable {}