Skip to content

Commit ef8e576

Browse files
authored
Merge pull request #82741 from hamishknight/err-val-6.2
[6.2] [AST] Use ErrorType for invalid value generic parameter
2 parents f8c1df8 + 4c6e06f commit ef8e576

File tree

9 files changed

+44
-24
lines changed

9 files changed

+44
-24
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5261,15 +5261,15 @@ SourceLoc extractNearestSourceLoc(RegexLiteralPatternFeatureKind kind);
52615261

52625262
class GenericTypeParamDeclGetValueTypeRequest
52635263
: public SimpleRequest<GenericTypeParamDeclGetValueTypeRequest,
5264-
Type(GenericTypeParamDecl *decl),
5264+
Type(const GenericTypeParamDecl *decl),
52655265
RequestFlags::Cached> {
52665266
public:
52675267
using SimpleRequest::SimpleRequest;
52685268

52695269
private:
52705270
friend SimpleRequest;
52715271

5272-
Type evaluate(Evaluator &evaluator, GenericTypeParamDecl *decl) const;
5272+
Type evaluate(Evaluator &evaluator, const GenericTypeParamDecl *decl) const;
52735273

52745274
public:
52755275
bool isCached() const { return true; }

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ SWIFT_REQUEST(TypeChecker, CustomDerivativesRequest,
620620
Cached, NoLocationInfo)
621621

622622
SWIFT_REQUEST(TypeChecker, GenericTypeParamDeclGetValueTypeRequest,
623-
Type(GenericTypeParamDecl *), Cached, NoLocationInfo)
623+
Type(const GenericTypeParamDecl *), Cached, NoLocationInfo)
624624

625625
SWIFT_REQUEST(TypeChecker, SemanticAvailableAttrRequest,
626626
std::optional<SemanticAvailableAttr>

lib/AST/Decl.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6102,9 +6102,13 @@ GenericTypeParamDecl *GenericTypeParamDecl::createImplicit(
61026102
}
61036103

61046104
Type GenericTypeParamDecl::getValueType() const {
6105-
return evaluateOrDefault(getASTContext().evaluator,
6106-
GenericTypeParamDeclGetValueTypeRequest{const_cast<GenericTypeParamDecl *>(this)},
6107-
Type());
6105+
if (!isValue())
6106+
return Type();
6107+
6108+
auto &ctx = getASTContext();
6109+
GenericTypeParamDeclGetValueTypeRequest req(this);
6110+
auto ty = evaluateOrDefault(ctx.evaluator, req, Type());
6111+
return ty ? ty : ErrorType::get(ctx);
61086112
}
61096113

61106114
SourceRange GenericTypeParamDecl::getSourceRange() const {

lib/Sema/CSGen.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1723,7 +1723,10 @@ namespace {
17231723
}
17241724

17251725
Type visitTypeValueExpr(TypeValueExpr *E) {
1726-
return E->getParamDecl()->getValueType();
1726+
auto ty = E->getParamDecl()->getValueType();
1727+
if (!ty || ty->hasError())
1728+
return recordInvalidNode(E);
1729+
return ty;
17271730
}
17281731

17291732
Type visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *expr) {

lib/Sema/TypeCheckRequestFunctions.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -487,12 +487,12 @@ Type ResultBuilderTypeRequest::evaluate(Evaluator &evaluator,
487487
return type->mapTypeOutOfContext();
488488
}
489489

490-
Type GenericTypeParamDeclGetValueTypeRequest::evaluate(Evaluator &evaluator,
491-
GenericTypeParamDecl *decl) const {
492-
if (!decl->isValue())
493-
return Type();
490+
Type GenericTypeParamDeclGetValueTypeRequest::evaluate(
491+
Evaluator &evaluator, const GenericTypeParamDecl *decl) const {
492+
ASSERT(decl->isValue());
494493

495-
if (decl->getInherited().size() == 0) {
494+
auto inherited = decl->getInherited();
495+
if (inherited.empty()) {
496496
decl->diagnose(diag::missing_value_generic_type, decl->getName());
497497
return Type();
498498
}
@@ -503,12 +503,11 @@ Type GenericTypeParamDeclGetValueTypeRequest::evaluate(Evaluator &evaluator,
503503
//
504504
// We should have 1 inherited type for 'N', 'Int', and have a 2nd generic
505505
// parameter called 'Bool'.
506-
ASSERT(decl->getInherited().size() == 1);
506+
ASSERT(inherited.size() == 1);
507507

508508
// The value type of a generic parameter should never rely on the generic
509509
// signature of the generic parameter itself or any of the outside context.
510-
return decl->getInherited().getResolvedType(0,
511-
TypeResolutionStage::Structural);
510+
return inherited.getResolvedType(0, TypeResolutionStage::Structural);
512511
}
513512

514513
// Define request evaluation functions for each of the type checker requests.

lib/Sema/TypeCheckType.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -809,16 +809,16 @@ namespace {
809809
if (!paramType->isValue())
810810
return true;
811811

812-
// Both of these generic type parameters are values, but they may not have
813-
// underlying value types associated with them. This can occur when a
814-
// parameter doesn't declare a value type and we're going to diagnose it
815-
// later.
816-
if (!paramType->getValueType() || !secondType->getValueType())
812+
// If either value type has an error, we've already diagnosed the issue.
813+
auto paramValueTy = paramType->getValueType();
814+
auto secondValueTy = secondType->getValueType();
815+
if (!paramValueTy || paramValueTy->hasError() ||
816+
!secondValueTy || secondValueTy->hasError()) {
817817
return true;
818-
818+
}
819819
// Otherwise, these are both value parameters and check that both their
820820
// value types are the same.
821-
return paramType->getValueType()->isEqual(secondType->getValueType());
821+
return paramValueTy->isEqual(secondValueTy);
822822
}
823823

824824
bool alwaysMismatchTypeParameters() const { return true; }

test/Sema/value_generics.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
protocol P {}
44

5-
func invalid<let N>() {} // expected-error {{value generic 'N' must have an explicit value type declared}}
6-
// expected-error@-1 {{generic parameter 'N' is not used in function signature}}
5+
func invalid<let N>() { // expected-error {{value generic 'N' must have an explicit value type declared}}
6+
// expected-error@-1 {{generic parameter 'N' is not used in function signature}}
7+
let x: String = N // Fine, we bind to a hole.
8+
}
79
func invalid<let N>(_: A<N>) {} // expected-error {{value generic 'N' must have an explicit value type declared}}
810

911
struct A<let N: Int> {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// {"kind":"complete","signature":"swift::Mangle::ASTMangler::appendType(swift::Type, swift::GenericSignature, swift::ValueDecl const*)"}
2+
// RUN: %target-swift-ide-test -code-completion --code-completion-token=COMPLETE -source-filename %s
3+
func a<let b
4+
#^COMPLETE^#
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// {"signature":"swift::constraints::ConstraintSystem::getTypeOfMemberReference(swift::Type, swift::ValueDecl*, swift::DeclContext*, bool, swift::FunctionRefInfo, swift::constraints::ConstraintLocator*, llvm::SmallVectorImpl<std::__1::pair<swift::GenericTypeParamType*, swift::TypeVariableType*>>*)"}
2+
// RUN: not %target-swift-frontend -typecheck %s
3+
struct a < let b > {
4+
func
5+
< (c : Self) {
6+
c.b
7+
}
8+
}

0 commit comments

Comments
 (0)