Skip to content

Commit a434126

Browse files
committed
Disallow referencing a value generic outside of certain contexts
1 parent f4f60f4 commit a434126

File tree

5 files changed

+82
-10
lines changed

5 files changed

+82
-10
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8012,8 +8012,6 @@ ERROR(cannot_pass_type_for_value_generic,none,
80128012
"cannot pass type %0 as a value for generic value %1", (Type, Type))
80138013
ERROR(value_type_used_in_type_parameter,none,
80148014
"cannot use value type %0 for generic argument %1", (Type, Type))
8015-
ERROR(cannot_self_value_generic,none,
8016-
"cannot reference '.self' on value generic parameter %0", (Type))
80178015
ERROR(invalid_value_type_value_generic,none,
80188016
"%0 is not a supported value type for %1", (Type, Type))
80198017
ERROR(invalid_value_generic_conformance,none,
@@ -8022,6 +8020,8 @@ ERROR(invalid_value_generic_same_type,none,
80228020
"cannot constrain value parameter %0 to be type %1", (Type, Type))
80238021
ERROR(integer_type_not_accepted,none,
80248022
"integer unexpectedly used in a type position", ())
8023+
ERROR(value_generic_unexpected,none,
8024+
"using value generic %0 here is not allowed", (Type))
80258025

80268026
#define UNDEFINE_DIAGNOSTIC_MACROS
80278027
#include "DefineDiagnosticMacros.h"

lib/AST/LifetimeDependence.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,10 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
441441
return std::nullopt;
442442
}
443443

444+
if (getResultOrYield(afd)->hasError()) {
445+
return std::nullopt;
446+
}
447+
444448
// Setters infer 'self' dependence on 'newValue'.
445449
if (auto accessor = dyn_cast<AccessorDecl>(afd)) {
446450
if (accessor->getAccessorKind() == AccessorKind::Set) {

lib/Sema/TypeCheckType.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -721,13 +721,9 @@ void swift::diagnoseInvalidGenericArguments(SourceLoc loc,
721721
}
722722

723723
namespace {
724-
/// Visits a requirement type to match it to a potential witness for
725-
/// the purpose of deducing associated types.
726-
///
727-
/// The visitor argument is the witness type. If there are any
728-
/// obvious conflicts between the structure of the two types,
729-
/// returns true. The conflict checking is fairly conservative, only
730-
/// considering rough structure.
724+
/// Visits a generic parameter and the type attempting to substitute for it
725+
/// to see if it's a valid parameter for integer arguments or other value
726+
/// generic parameters.
731727
class ValueMatchVisitor : public TypeMatcher<ValueMatchVisitor> {
732728
public:
733729
ValueMatchVisitor() {}
@@ -4945,6 +4941,19 @@ TypeResolver::resolveDeclRefTypeRepr(DeclRefTypeRepr *repr,
49454941
if (result->is<FunctionType>())
49464942
result = applyNonEscapingIfNecessary(result, options);
49474943

4944+
// Referencing a value generic by name, e.g. 'let N' and referencing 'N', is
4945+
// only valid as a generic argument, in generic requirements, and when being
4946+
// used as an expression.
4947+
if (result->isValueParameter() &&
4948+
!(options.isGenericArgument() ||
4949+
options.isGenericRequirement() ||
4950+
options.isAnyExpr())) {
4951+
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
4952+
diagnose(repr->getNameLoc(), diag::value_generic_unexpected, result);
4953+
}
4954+
return ErrorType::get(getASTContext());
4955+
}
4956+
49484957
return result;
49494958
}
49504959

lib/Sema/TypeCheckType.h

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ enum class TypeResolverContext : uint8_t {
106106
/// arguments.
107107
VariadicGenericArgument,
108108

109+
/// Whether we are checking generic arguments of a bound generic type with
110+
/// value parameters. We use the ValueMatchVisitor to ensure that all value
111+
/// parameters line up with integer types or other value parameters.
109112
ValueGenericArgument,
110113

111114
/// Whether we are checking a tuple element type.
@@ -272,7 +275,6 @@ class TypeResolutionOptions {
272275
case Context::InExpression:
273276
case Context::ExplicitCastExpr:
274277
case Context::ForEachStmt:
275-
case Context::PatternBindingDecl:
276278
case Context::EditorPlaceholderExpr:
277279
case Context::ClosureExpr:
278280
return true;
@@ -305,6 +307,7 @@ class TypeResolutionOptions {
305307
case Context::CustomAttr:
306308
case Context::Inverted:
307309
case Context::ValueGenericArgument:
310+
case Context::PatternBindingDecl:
308311
return false;
309312
}
310313
llvm_unreachable("unhandled kind");
@@ -397,6 +400,50 @@ class TypeResolutionOptions {
397400
}
398401
}
399402

403+
/// Whether we are resolving a type in a generic argument list.
404+
bool isGenericArgument() const {
405+
switch (context) {
406+
case Context::ScalarGenericArgument:
407+
case Context::VariadicGenericArgument:
408+
case Context::ValueGenericArgument:
409+
return true;
410+
411+
case Context::None:
412+
case Context::Inherited:
413+
case Context::FunctionInput:
414+
case Context::PackElement:
415+
case Context::TupleElement:
416+
case Context::GenericRequirement:
417+
case Context::SameTypeRequirement:
418+
case Context::ExtensionBinding:
419+
case Context::TypeAliasDecl:
420+
case Context::GenericTypeAliasDecl:
421+
case Context::ExistentialConstraint:
422+
case Context::MetatypeBase:
423+
case Context::InExpression:
424+
case Context::ExplicitCastExpr:
425+
case Context::ForEachStmt:
426+
case Context::PatternBindingDecl:
427+
case Context::EditorPlaceholderExpr:
428+
case Context::ClosureExpr:
429+
case Context::VariadicFunctionInput:
430+
case Context::InoutFunctionInput:
431+
case Context::FunctionResult:
432+
case Context::SubscriptDecl:
433+
case Context::EnumElementDecl:
434+
case Context::MacroDecl:
435+
case Context::EnumPatternPayload:
436+
case Context::ProtocolMetatypeBase:
437+
case Context::ImmediateOptionalTypeArgument:
438+
case Context::AbstractFunctionDecl:
439+
case Context::CustomAttr:
440+
case Context::Inverted:
441+
case Context::GenericParameterInherited:
442+
case Context::AssociatedTypeInherited:
443+
return false;
444+
}
445+
}
446+
400447
/// Whether we are resolving a type in a `where` clause, generic parameter
401448
/// declaration inheritance clause, or associated type inheritance clause.
402449
bool isGenericRequirement() const {

test/Sema/value_generics.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ struct A<let N: Int> {
1818
var intSelf: Int {
1919
N.self // OK
2020
}
21+
22+
var n: N { // expected-error {{using value generic 'let N' here is not allowed}}
23+
fatalError()
24+
}
25+
26+
var nType: N.Type { // expected-error {{using value generic 'let N' here is not allowed}}
27+
fatalError()
28+
}
29+
30+
var a: A<N> { // OK
31+
fatalError()
32+
}
2133
}
2234

2335
extension A where N: P {} // expected-error {{value generic type 'let N' cannot conform to protocol 'P'}}

0 commit comments

Comments
 (0)