From d87e049cde308582bb27cdaebd81d835985b89f9 Mon Sep 17 00:00:00 2001 From: Greg Titus Date: Sun, 21 Jul 2024 06:21:21 -0700 Subject: [PATCH] Improve diagnoses of generic specializations Always add constraints, find fixes during simplify. New separate fix for allow generic function specialization. Improve parse heuristic for isGenericTypeDisambiguatingToken. Degrade concrete type specialization fix to warning for macros. --- include/swift/AST/DiagnosticsSema.def | 4 +- include/swift/AST/Types.h | 2 +- include/swift/Sema/CSFix.h | 44 +++++++++-- include/swift/Sema/ConstraintLocator.h | 6 +- lib/AST/ASTDumper.cpp | 4 +- lib/AST/ASTPrinter.cpp | 4 +- lib/Parse/ParseType.cpp | 4 +- lib/Sema/CSDiagnostics.cpp | 11 ++- lib/Sema/CSDiagnostics.h | 19 ++++- lib/Sema/CSFix.cpp | 23 ++++-- lib/Sema/CSGen.cpp | 79 ++++++------------- lib/Sema/CSSimplify.cpp | 25 +++--- lib/Sema/ConstraintSystem.cpp | 22 +++--- lib/Sema/TypeCheckDeclPrimary.cpp | 3 +- ...biguous_specialized_name_diagnostics.swift | 3 +- test/Macros/attached_macros_diags.swift | 4 + test/Parse/enum_element_pattern_swift4.swift | 14 +++- test/Parse/generic_disambiguation.swift | 16 ++-- test/Sema/generic-arg-list.swift | 41 ++++++++++ 19 files changed, 218 insertions(+), 110 deletions(-) create mode 100644 test/Sema/generic-arg-list.swift diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index f8c89e56b84f2..772a3ad7b8af3 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -4605,10 +4605,10 @@ NOTE(duplicated_key_declared_here, none, // Generic specializations ERROR(cannot_explicitly_specialize_generic_function,none, "cannot explicitly specialize a generic function", ()) -ERROR(not_a_generic_definition,none, - "cannot specialize a non-generic definition", ()) ERROR(not_a_generic_type,none, "cannot specialize non-generic type %0", (Type)) +ERROR(not_a_generic_macro,none, + "cannot specialize a non-generic external macro %0", (const ValueDecl *)) ERROR(protocol_declares_unknown_primary_assoc_type,none, "an associated type named %0 must be declared in the protocol %1 or a protocol it inherits", (Identifier, Type)) diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index d5fcf0a4154d7..4677bdf6f239f 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -7327,7 +7327,7 @@ class PlaceholderType : public TypeBase { // recursive property logic in PlaceholderType::get. using Originator = llvm::PointerUnion; + ErrorExpr *, TypeRepr *>; Originator O; diff --git a/include/swift/Sema/CSFix.h b/include/swift/Sema/CSFix.h index 61f050bb8b82b..8a113aeddba08 100644 --- a/include/swift/Sema/CSFix.h +++ b/include/swift/Sema/CSFix.h @@ -462,9 +462,12 @@ enum class FixKind : uint8_t { /// because its name doesn't appear in 'initializes' or 'accesses' attributes. AllowInvalidMemberReferenceInInitAccessor, - /// Ignore an attempt to specialize non-generic type. + /// Ignore an attempt to specialize a non-generic type. AllowConcreteTypeSpecialization, + /// Ignore an attempt to specialize a generic function. + AllowGenericFunctionSpecialization, + /// Ignore an out-of-place \c then statement. IgnoreOutOfPlaceThenStmt, @@ -3718,11 +3721,14 @@ class AllowInvalidMemberReferenceInInitAccessor final : public ConstraintFix { class AllowConcreteTypeSpecialization final : public ConstraintFix { Type ConcreteType; + ValueDecl *Decl; AllowConcreteTypeSpecialization(ConstraintSystem &cs, Type concreteTy, - ConstraintLocator *locator) - : ConstraintFix(cs, FixKind::AllowConcreteTypeSpecialization, locator), - ConcreteType(concreteTy) {} + ValueDecl *decl, ConstraintLocator *locator, + FixBehavior fixBehavior) + : ConstraintFix(cs, FixKind::AllowConcreteTypeSpecialization, locator, + fixBehavior), + ConcreteType(concreteTy), Decl(decl) {} public: std::string getName() const override { @@ -3736,13 +3742,41 @@ class AllowConcreteTypeSpecialization final : public ConstraintFix { } static AllowConcreteTypeSpecialization * - create(ConstraintSystem &cs, Type concreteTy, ConstraintLocator *locator); + create(ConstraintSystem &cs, Type concreteTy, ValueDecl *decl, + ConstraintLocator *locator, FixBehavior fixBehavior); static bool classof(const ConstraintFix *fix) { return fix->getKind() == FixKind::AllowConcreteTypeSpecialization; } }; +class AllowGenericFunctionSpecialization final : public ConstraintFix { + ValueDecl *Decl; + + AllowGenericFunctionSpecialization(ConstraintSystem &cs, ValueDecl *decl, + ConstraintLocator *locator) + : ConstraintFix(cs, FixKind::AllowGenericFunctionSpecialization, locator), + Decl(decl) {} + +public: + std::string getName() const override { + return "allow generic function specialization"; + } + + bool diagnose(const Solution &solution, bool asNote = false) const override; + + bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override { + return diagnose(*commonFixes.front().first); + } + + static AllowGenericFunctionSpecialization * + create(ConstraintSystem &cs, ValueDecl *decl, ConstraintLocator *locator); + + static bool classof(const ConstraintFix *fix) { + return fix->getKind() == FixKind::AllowGenericFunctionSpecialization; + } +}; + class IgnoreOutOfPlaceThenStmt final : public ConstraintFix { IgnoreOutOfPlaceThenStmt(ConstraintSystem &cs, ConstraintLocator *locator) : ConstraintFix(cs, FixKind::IgnoreOutOfPlaceThenStmt, locator) {} diff --git a/include/swift/Sema/ConstraintLocator.h b/include/swift/Sema/ConstraintLocator.h index 198a87887947a..631e84cdcc24d 100644 --- a/include/swift/Sema/ConstraintLocator.h +++ b/include/swift/Sema/ConstraintLocator.h @@ -985,13 +985,13 @@ class LocatorPathElt::ConformanceRequirement final }; class LocatorPathElt::PlaceholderType final - : public StoredPointerElement { + : public StoredPointerElement { public: - PlaceholderType(PlaceholderTypeRepr *placeholderRepr) + PlaceholderType(TypeRepr *placeholderRepr) : StoredPointerElement(PathElementKind::PlaceholderType, placeholderRepr) {} - PlaceholderTypeRepr *getPlaceholderRepr() const { return getStoredPointer(); } + TypeRepr *getPlaceholderRepr() const { return getStoredPointer(); } static bool classof(const LocatorPathElt *elt) { return elt->getKind() == ConstraintLocator::PlaceholderType; diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 4dde6b4631e4a..b473100c39d7d 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -3987,8 +3987,8 @@ namespace { printFlag("error_expr"); } else if (auto *DMT = originator.dyn_cast()) { printRec(DMT, "dependent_member_type"); - } else if (originator.is()) { - printFlag("placeholder_type_repr"); + } else if (originator.is()) { + printFlag("type_repr"); } else { assert(false && "unknown originator"); } diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 133c15b2bf7ff..c60663619e18f 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -5870,8 +5870,8 @@ class TypePrinter : public TypeVisitor { Printer << "error_expr"; } else if (auto *DMT = originator.dyn_cast()) { visit(DMT); - } else if (originator.is()) { - Printer << "placeholder_type_repr"; + } else if (originator.is()) { + Printer << "type_repr"; } else { assert(false && "unknown originator"); } diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index 632e3e3e27420..038170d0ae459 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -1476,7 +1476,9 @@ static bool isGenericTypeDisambiguatingToken(Parser &P) { auto &tok = P.Tok; switch (tok.getKind()) { default: - return false; + // If this is the end of the expr (wouldn't match parseExprSequenceElement), + // prefer generic type list over an illegal unary postfix '>' operator. + return P.isStartOfSwiftDecl() || P.isStartOfStmt(/*prefer expr=*/true); case tok::r_paren: case tok::r_square: case tok::l_brace: diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 5b5a326c5a5a4..7c69eccc3dcf9 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -9360,7 +9360,16 @@ bool InvalidMemberReferenceWithinInitAccessor::diagnoseAsError() { } bool ConcreteTypeSpecialization::diagnoseAsError() { - emitDiagnostic(diag::not_a_generic_type, ConcreteType); + if (isa(Decl)) { + emitDiagnostic(diag::not_a_generic_macro, Decl); + } else { + emitDiagnostic(diag::not_a_generic_type, ConcreteType); + } + return true; +} + +bool GenericFunctionSpecialization::diagnoseAsError() { + emitDiagnostic(diag::cannot_explicitly_specialize_generic_function); return true; } diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 4d4c81ce2b0fa..06cddcd77fdec 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -3127,12 +3127,25 @@ class InvalidMemberReferenceWithinInitAccessor final /// \endcode class ConcreteTypeSpecialization final : public FailureDiagnostic { Type ConcreteType; + ValueDecl *Decl; public: ConcreteTypeSpecialization(const Solution &solution, Type concreteTy, - ConstraintLocator *locator) - : FailureDiagnostic(solution, locator), - ConcreteType(resolveType(concreteTy)) {} + ValueDecl *decl, ConstraintLocator *locator, + FixBehavior fixBehavior) + : FailureDiagnostic(solution, locator, fixBehavior), + ConcreteType(resolveType(concreteTy)), Decl(decl) {} + + bool diagnoseAsError() override; +}; + +class GenericFunctionSpecialization final : public FailureDiagnostic { + ValueDecl *Decl; + +public: + GenericFunctionSpecialization(const Solution &solution, ValueDecl *decl, + ConstraintLocator *locator) + : FailureDiagnostic(solution, locator), Decl(decl) {} bool diagnoseAsError() override; }; diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index 7bda044857a54..d35f843f2aa30 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -2605,15 +2605,28 @@ AllowInvalidMemberReferenceInInitAccessor::create(ConstraintSystem &cs, bool AllowConcreteTypeSpecialization::diagnose(const Solution &solution, bool asNote) const { - ConcreteTypeSpecialization failure(solution, ConcreteType, getLocator()); + ConcreteTypeSpecialization failure(solution, ConcreteType, Decl, getLocator(), + fixBehavior); return failure.diagnose(asNote); } -AllowConcreteTypeSpecialization * -AllowConcreteTypeSpecialization::create(ConstraintSystem &cs, Type concreteTy, - ConstraintLocator *locator) { +AllowConcreteTypeSpecialization *AllowConcreteTypeSpecialization::create( + ConstraintSystem &cs, Type concreteTy, ValueDecl *decl, + ConstraintLocator *locator, FixBehavior fixBehavior) { + return new (cs.getAllocator()) AllowConcreteTypeSpecialization( + cs, concreteTy, decl, locator, fixBehavior); +} + +bool AllowGenericFunctionSpecialization::diagnose(const Solution &solution, + bool asNote) const { + GenericFunctionSpecialization failure(solution, Decl, getLocator()); + return failure.diagnose(asNote); +} + +AllowGenericFunctionSpecialization *AllowGenericFunctionSpecialization::create( + ConstraintSystem &cs, ValueDecl *decl, ConstraintLocator *locator) { return new (cs.getAllocator()) - AllowConcreteTypeSpecialization(cs, concreteTy, locator); + AllowGenericFunctionSpecialization(cs, decl, locator); } bool IgnoreOutOfPlaceThenStmt::diagnose(const Solution &solution, diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 4397d9b7139d0..4b972a62bb2b8 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1903,9 +1903,9 @@ namespace { /// introduce them as an explicit generic arguments constraint. /// /// \returns true if resolving any of the specialization types failed. - bool addSpecializationConstraint( - ConstraintLocator *locator, Type boundType, - ArrayRef specializationArgs) { + void addSpecializationConstraint(ConstraintLocator *locator, Type boundType, + SourceLoc lAngleLoc, + ArrayRef specializationArgs) { // Resolve each type. SmallVector specializationArgTypes; auto options = @@ -1916,61 +1916,35 @@ namespace { options |= TypeResolutionFlags::AllowPackReferences; elementEnv = OuterExpansions.back(); } - const auto result = TypeResolution::resolveContextualType( + auto result = TypeResolution::resolveContextualType( specializationArg, CurDC, options, // Introduce type variables for unbound generics. OpenUnboundGenericType(CS, locator), HandlePlaceholderType(CS, locator), OpenPackElementType(CS, locator, elementEnv)); - if (result->hasError()) - return true; - + if (result->hasError()) { + auto &ctxt = CS.getASTContext(); + result = PlaceholderType::get(ctxt, specializationArg); + ctxt.Diags.diagnose(lAngleLoc, + diag::while_parsing_as_left_angle_bracket); + } specializationArgTypes.push_back(result); } - CS.addConstraint( - ConstraintKind::ExplicitGenericArguments, boundType, - PackType::get(CS.getASTContext(), specializationArgTypes), - locator); - return false; + auto constraint = Constraint::create( + CS, ConstraintKind::ExplicitGenericArguments, boundType, + PackType::get(CS.getASTContext(), specializationArgTypes), locator); + CS.addUnsolvedConstraint(constraint); + CS.activateConstraint(constraint); } Type visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *expr) { auto baseTy = CS.getType(expr->getSubExpr()); - - if (baseTy->isTypeVariableOrMember()) { - return baseTy; - } - - // We currently only support explicit specialization of generic types. - // FIXME: We could support explicit function specialization. - auto &de = CS.getASTContext().Diags; - if (baseTy->is()) { - de.diagnose(expr->getSubExpr()->getLoc(), - diag::cannot_explicitly_specialize_generic_function); - de.diagnose(expr->getLAngleLoc(), - diag::while_parsing_as_left_angle_bracket); - return Type(); - } - - if (AnyMetatypeType *meta = baseTy->getAs()) { - auto *overloadLocator = CS.getConstraintLocator(expr->getSubExpr()); - if (addSpecializationConstraint(overloadLocator, - meta->getInstanceType(), - expr->getUnresolvedParams())) { - return Type(); - } - - return baseTy; - } - - // FIXME: If the base type is a type variable, constrain it to a metatype - // of a bound generic type. - de.diagnose(expr->getSubExpr()->getLoc(), - diag::not_a_generic_definition); - de.diagnose(expr->getLAngleLoc(), - diag::while_parsing_as_left_angle_bracket); - return Type(); + auto *overloadLocator = CS.getConstraintLocator(expr->getSubExpr()); + addSpecializationConstraint( + overloadLocator, baseTy->getMetatypeInstanceType(), + expr->getLAngleLoc(), expr->getUnresolvedParams()); + return baseTy; } Type visitSequenceExpr(SequenceExpr *expr) { @@ -4080,10 +4054,9 @@ namespace { // Add explicit generic arguments, if there were any. if (expr->getGenericArgsRange().isValid()) { - if (addSpecializationConstraint( - CS.getConstraintLocator(expr), macroRefType, - expr->getGenericArgs())) - return Type(); + addSpecializationConstraint(CS.getConstraintLocator(expr), macroRefType, + expr->getGenericArgsRange().Start, + expr->getGenericArgs()); } // Form the applicable-function constraint. The result type @@ -4828,11 +4801,11 @@ bool ConstraintSystem::generateConstraints( // If we have a placeholder originating from a PlaceholderTypeRepr, // tack that on to the locator. if (auto *placeholderTy = ty->getAs()) - if (auto *placeholderRepr = placeholderTy->getOriginator() - .dyn_cast()) + if (auto *typeRepr = placeholderTy->getOriginator() + .dyn_cast()) return getConstraintLocator( convertTypeLocator, - LocatorPathElt::PlaceholderType(placeholderRepr)); + LocatorPathElt::PlaceholderType(typeRepr)); return convertTypeLocator; }; diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 8592aa2b491b4..318bf82a9d5bd 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -13950,6 +13950,8 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint( // Bail out if we haven't selected an overload yet. auto simplifiedBoundType = simplifyType(type1, flags); + if (simplifiedBoundType->isPlaceholder()) + return SolutionKind::Solved; if (simplifiedBoundType->isTypeVariableOrMember()) return formUnsolved(); @@ -14042,13 +14044,15 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint( } } - if (!decl->getAsGenericContext()) - return SolutionKind::Error; - auto genericParams = getGenericParams(decl); - if (!genericParams) { - // FIXME: Record an error here that we're ignoring the parameters. - return SolutionKind::Solved; + if (!decl->getAsGenericContext() || !genericParams) { + // Allow concrete macros to have specializations with just a warning. + return recordFix(AllowConcreteTypeSpecialization::create( + *this, type1, decl, getConstraintLocator(locator), + isa(decl) ? FixBehavior::DowngradeToWarning + : FixBehavior::Error)) + ? SolutionKind::Error + : SolutionKind::Solved; } // Map the generic parameters we have over to their opened types. @@ -14081,12 +14085,14 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint( } } - if (openedGenericParams.empty()) { + // FIXME: We could support explicit function specialization. + if (openedGenericParams.empty() || + (isa(decl) && !hasParameterPack)) { if (!shouldAttemptFixes()) return SolutionKind::Error; - return recordFix(AllowConcreteTypeSpecialization::create( - *this, type1, getConstraintLocator(locator))) + return recordFix(AllowGenericFunctionSpecialization::create( + *this, decl, getConstraintLocator(locator))) ? SolutionKind::Error : SolutionKind::Solved; } @@ -15217,6 +15223,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( case FixKind::AllowAssociatedValueMismatch: case FixKind::GenericArgumentsMismatch: case FixKind::AllowConcreteTypeSpecialization: + case FixKind::AllowGenericFunctionSpecialization: case FixKind::IgnoreGenericSpecializationArityMismatch: case FixKind::IgnoreKeyPathSubscriptIndexMismatch: case FixKind::AllowMemberRefOnExistential: { diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index da599475a36a4..b422268624c69 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -1077,17 +1077,17 @@ Type ConstraintSystem::replaceInferableTypesWithTypeVars( return openUnboundGenericType(unbound->getDecl(), unbound->getParent(), locator, /*isTypeResolution=*/false); } else if (auto *placeholderTy = type->getAs()) { - if (auto *placeholderRepr = placeholderTy->getOriginator() - .dyn_cast()) { - - return createTypeVariable( - getConstraintLocator( - locator, LocatorPathElt::PlaceholderType(placeholderRepr)), - TVO_CanBindToNoEscape | TVO_PrefersSubtypeBinding | - TVO_CanBindToHole); - } - - if (auto *var = placeholderTy->getOriginator().dyn_cast()) { + if (auto *typeRepr = + placeholderTy->getOriginator().dyn_cast()) { + if (isa(typeRepr)) { + return createTypeVariable( + getConstraintLocator(locator, + LocatorPathElt::PlaceholderType(typeRepr)), + TVO_CanBindToNoEscape | TVO_PrefersSubtypeBinding | + TVO_CanBindToHole); + } + } else if (auto *var = + placeholderTy->getOriginator().dyn_cast()) { if (var->getName().hasDollarPrefix()) { auto *repr = new (type->getASTContext()) PlaceholderTypeRepr(var->getLoc()); diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 4573e0cb4d2cb..c86ccd039a944 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -1171,7 +1171,8 @@ void TypeChecker::notePlaceholderReplacementTypes(Type writtenType, } if (auto *origRepr = - placeholder->getOriginator().dyn_cast()) { + placeholder->getOriginator().dyn_cast()) { + assert(isa(origRepr)); t1->getASTContext() .Diags .diagnose(origRepr->getLoc(), diff --git a/test/Constraints/ambiguous_specialized_name_diagnostics.swift b/test/Constraints/ambiguous_specialized_name_diagnostics.swift index 322d004ed308c..90d363b8f1e88 100644 --- a/test/Constraints/ambiguous_specialized_name_diagnostics.swift +++ b/test/Constraints/ambiguous_specialized_name_diagnostics.swift @@ -42,7 +42,6 @@ func test() { S(t: 42).test() // expected-error {{ambiguous use of 'init(t:)'}} - // FIXME(diagnostics): This should produce ambiguity diagnostic too S.staticFn() - // expected-error@-1 {{generic parameter 'T' could not be inferred}} + // expected-error@-1 {{ambiguous use of 'staticFn()'}} } diff --git a/test/Macros/attached_macros_diags.swift b/test/Macros/attached_macros_diags.swift index f084d47a201c3..85749424190ae 100644 --- a/test/Macros/attached_macros_diags.swift +++ b/test/Macros/attached_macros_diags.swift @@ -69,4 +69,8 @@ struct TestMacroArgs { // expected-error@-1{{missing argument for parameter #1 in macro expansion}} @m3(message: #stringify(Nested.x).1) struct Args8 {} + + // Allow macros to have arbitrary generic specialization lists, but warn + // https://github.com/swiftlang/swift/issues/75500 + @m1 struct Args9 {} // expected-warning {{cannot specialize a non-generic external macro 'm1()'}} } diff --git a/test/Parse/enum_element_pattern_swift4.swift b/test/Parse/enum_element_pattern_swift4.swift index 942f10420be94..4cdbea06d6f45 100644 --- a/test/Parse/enum_element_pattern_swift4.swift +++ b/test/Parse/enum_element_pattern_swift4.swift @@ -9,10 +9,13 @@ enum E { static func testE(e: E) { switch e { - case A(): // expected-error {{cannot specialize a non-generic definition}} + case A(): // expected-error {{cannot find type 'UndefinedTy' in scope}} // expected-note@-1 {{while parsing this '<' as a type parameter bracket}} + // expected-error@-2 {{cannot specialize non-generic type 'E'}} + // expected-error@-3 {{cannot call value of non-function type 'E'}} break - case B(): // expected-error {{cannot specialize a non-generic definition}} expected-note {{while parsing this '<' as a type parameter bracket}} + case B(): // expected-error {{cannot specialize non-generic type 'E'}} + // expected-error@-1 {{cannot call value of non-function type 'E'}} break default: break; @@ -22,10 +25,13 @@ enum E { func testE(e: E) { switch e { - case E.A(): // expected-error {{cannot specialize a non-generic definition}} + case E.A(): // expected-error {{cannot find type 'UndefinedTy' in scope}} // expected-note@-1 {{while parsing this '<' as a type parameter bracket}} + // expected-error@-2 {{cannot specialize non-generic type 'E'}} + // expected-error@-3 {{cannot call value of non-function type 'E'}} break - case E.B(): // expected-error {{cannot specialize a non-generic definition}} expected-note {{while parsing this '<' as a type parameter bracket}} + case E.B(): // expected-error {{cannot specialize non-generic type 'E'}} + // expected-error@-1 {{cannot call value of non-function type 'E'}} break case .C(): // expected-error {{pattern with associated values does not match enum case 'C'}} // expected-note@-1 {{remove associated values to make the pattern match}} {{10-12=}} diff --git a/test/Parse/generic_disambiguation.swift b/test/Parse/generic_disambiguation.swift index ebb900e3e8c47..e93d26f4a4efe 100644 --- a/test/Parse/generic_disambiguation.swift +++ b/test/Parse/generic_disambiguation.swift @@ -26,15 +26,21 @@ var a, b, c, d : Int _ = a < b _ = (a < b, c > d) // Parses as generic because of lparen after '>' -(a < b, c > (d)) // expected-error{{cannot specialize a non-generic definition}} -// expected-note@-1 {{while parsing this '<' as a type parameter bracket}} +(a < b, c > (d)) // expected-error{{cannot find type 'b' in scope}} +// expected-note@-1 2 {{while parsing this '<' as a type parameter bracket}} +// expected-error@-2 {{cannot specialize non-generic type 'Int'}} +// expected-error@-3 {{cannot call value of non-function type 'Int'}} +// expected-error@-4 {{cannot find type 'c' in scope}} // Parses as generic because of lparen after '>' -(a(d)) // expected-error{{cannot specialize a non-generic definition}} -// expected-note@-1 {{while parsing this '<' as a type parameter bracket}} +(a(d)) // expected-error{{cannot find type 'b' in scope}} +// expected-note@-1 2 {{while parsing this '<' as a type parameter bracket}} +// expected-error@-2 {{cannot specialize non-generic type 'Int'}} +// expected-error@-3 {{cannot call value of non-function type 'Int'}} +// expected-error@-4 {{cannot find type 'c' in scope}} _ = a>(b) _ = a > (b) -generic(0) // expected-error{{cannot explicitly specialize a generic function}} expected-note{{while parsing this '<' as a type parameter bracket}} +generic(0) // expected-error{{cannot explicitly specialize a generic function}} A.c() A>.c() diff --git a/test/Sema/generic-arg-list.swift b/test/Sema/generic-arg-list.swift new file mode 100644 index 0000000000000..04e7c1c24cf75 --- /dev/null +++ b/test/Sema/generic-arg-list.swift @@ -0,0 +1,41 @@ +// RUN: %target-typecheck-verify-swift + +extension Int { + func foo() -> Int {} + var bar: Int { + get {} + } + + func baz() -> Int {} + func baz(_ x: Int = 0) -> Int {} + + func gen() -> T {} // expected-note 2 {{in call to function 'gen()'}} +} + +// https://github.com/swiftlang/swift/issues/74857 +func test(i: Int) { + let _ = i.foo() // expected-error {{cannot specialize non-generic type '() -> Int'}} + + let _ = i.gen() // expected-error {{cannot explicitly specialize a generic function}} + // expected-error@-1 {{generic parameter 'T' could not be inferred}} + + let _ = 0.foo() // expected-error {{cannot specialize non-generic type '() -> Int'}} + + let _ = i.gen // expected-error {{cannot explicitly specialize a generic function}} + // expected-error@-1 {{generic parameter 'T' could not be inferred}} + let _ = i.bar // expected-error {{cannot specialize non-generic type 'Int'}} + let _ = 0.bar // expected-error {{cannot specialize non-generic type 'Int'}} +} + +extension Bool { + func foo() -> T {} +} + +let _: () -> Bool = false.foo // expected-error {{cannot explicitly specialize a generic function}} + +func foo(_ x: Int) { + _ = { + _ = x // expected-error {{cannot specialize non-generic type 'Int'}} + } +} +