Skip to content

Commit a9fd623

Browse files
authored
Merge pull request #39189 from slavapestov/misc-rqm-fixes-2
RequirementMachine: More miscellaneous fixes
2 parents 97a1653 + d042cdb commit a9fd623

File tree

11 files changed

+87
-69
lines changed

11 files changed

+87
-69
lines changed

include/swift/AST/DiagnosticsCommon.def

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,6 @@ REMARK(remark_save_cache, none,
209209
// MARK: custom attribute diagnostics
210210
//------------------------------------------------------------------------------
211211

212-
ERROR(ambiguous_custom_attribute_ref,none,
213-
"ambiguous use of attribute %0", (Identifier))
214-
NOTE(ambiguous_custom_attribute_ref_fix,none,
215-
"use '%0.' to reference the attribute %1 in module %2",
216-
(StringRef, Identifier, Identifier))
217-
NOTE(found_attribute_candidate,none,
218-
"found this attribute", ())
219212
ERROR(unknown_attribute,none,
220213
"unknown attribute '%0'", (StringRef))
221214

lib/AST/GenericSignature.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/Module.h"
2424
#include "swift/AST/PrettyStackTrace.h"
2525
#include "swift/AST/Types.h"
26+
#include "swift/Basic/SourceManager.h"
2627
#include "swift/Basic/STLExtras.h"
2728
#include "RequirementMachine/RequirementMachine.h"
2829
#include <functional>
@@ -1492,9 +1493,12 @@ int swift::compareAssociatedTypes(AssociatedTypeDecl *assocType1,
14921493
return compareProtocols;
14931494

14941495
// Error case: if we have two associated types with the same name in the
1495-
// same protocol, just tie-break based on address.
1496-
if (assocType1 != assocType2)
1497-
return assocType1 < assocType2 ? -1 : +1;
1496+
// same protocol, just tie-break based on source location.
1497+
if (assocType1 != assocType2) {
1498+
auto &ctx = assocType1->getASTContext();
1499+
return ctx.SourceMgr.isBeforeInBuffer(assocType1->getLoc(),
1500+
assocType2->getLoc()) ? -1 : +1;
1501+
}
14981502

14991503
return 0;
15001504
}

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4012,7 +4012,7 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
40124012
// Add all of the inherited protocol requirements, recursively.
40134013
auto inheritedReqResult =
40144014
addInheritedRequirements(proto, selfType.getUnresolvedType(), source,
4015-
proto->getModuleContext());
4015+
nullptr);
40164016
if (isErrorResult(inheritedReqResult))
40174017
return inheritedReqResult;
40184018
}

lib/AST/NameLookup.cpp

Lines changed: 11 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,11 +2105,22 @@ directReferencesForUnqualifiedTypeLookup(DeclNameRef name,
21052105
auto descriptor = UnqualifiedLookupDescriptor(name, dc, loc, options);
21062106
auto lookup = evaluateOrDefault(ctx.evaluator,
21072107
UnqualifiedLookupRequest{descriptor}, {});
2108+
2109+
unsigned nominalTypeDeclCount = 0;
21082110
for (const auto &result : lookup.allResults()) {
21092111
auto typeDecl = cast<TypeDecl>(result.getValueDecl());
2112+
2113+
if (isa<NominalTypeDecl>(typeDecl))
2114+
nominalTypeDeclCount++;
2115+
21102116
results.push_back(typeDecl);
21112117
}
21122118

2119+
// If we saw multiple nominal type declarations with the same name,
2120+
// the result of the lookup is definitely ambiguous.
2121+
if (nominalTypeDeclCount > 1)
2122+
results.clear();
2123+
21132124
return results;
21142125
}
21152126

@@ -2607,54 +2618,6 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
26072618
}
26082619
}
26092620

2610-
// If we have more than one attribute declaration, we have an ambiguity.
2611-
// So, emit an ambiguity diagnostic.
2612-
if (auto typeRepr = attr->getTypeRepr()) {
2613-
if (nominals.size() > 1) {
2614-
SmallVector<NominalTypeDecl *, 4> ambiguousCandidates;
2615-
// Filter out declarations that cannot be attributes.
2616-
for (auto decl : nominals) {
2617-
if (isa<ProtocolDecl>(decl)) {
2618-
continue;
2619-
}
2620-
ambiguousCandidates.push_back(decl);
2621-
}
2622-
if (ambiguousCandidates.size() > 1) {
2623-
auto attrName = nominals.front()->getName();
2624-
ctx.Diags.diagnose(typeRepr->getLoc(),
2625-
diag::ambiguous_custom_attribute_ref, attrName);
2626-
for (auto candidate : ambiguousCandidates) {
2627-
ctx.Diags.diagnose(candidate->getLoc(),
2628-
diag::found_attribute_candidate);
2629-
// If the candidate is a top-level attribute, let's suggest
2630-
// adding module name to resolve the ambiguity.
2631-
if (candidate->getDeclContext()->isModuleScopeContext()) {
2632-
auto moduleName = candidate->getParentModule()->getName();
2633-
ctx.Diags
2634-
.diagnose(typeRepr->getLoc(),
2635-
diag::ambiguous_custom_attribute_ref_fix,
2636-
moduleName.str(), attrName, moduleName)
2637-
.fixItInsert(typeRepr->getLoc(), moduleName.str().str() + ".");
2638-
}
2639-
}
2640-
return nullptr;
2641-
}
2642-
}
2643-
}
2644-
2645-
// There is no nominal type with this name, so complain about this being
2646-
// an unknown attribute.
2647-
std::string typeName;
2648-
if (auto typeRepr = attr->getTypeRepr()) {
2649-
llvm::raw_string_ostream out(typeName);
2650-
typeRepr->print(out);
2651-
} else {
2652-
typeName = attr->getType().getString();
2653-
}
2654-
2655-
ctx.Diags.diagnose(attr->getLocation(), diag::unknown_attribute, typeName);
2656-
attr->setInvalid();
2657-
26582621
return nullptr;
26592622
}
26602623

lib/Sema/TypeCheckAttr.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2955,7 +2955,30 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
29552955
auto nominal = evaluateOrDefault(
29562956
Ctx.evaluator, CustomAttrNominalRequest{attr, dc}, nullptr);
29572957

2958+
// Diagnose errors.
29582959
if (!nominal) {
2960+
auto typeRepr = attr->getTypeRepr();
2961+
2962+
auto type = TypeResolution::forInterface(dc, TypeResolverContext::CustomAttr,
2963+
// Unbound generics and placeholders
2964+
// are not allowed within this
2965+
// attribute.
2966+
/*unboundTyOpener*/ nullptr,
2967+
/*placeholderHandler*/ nullptr)
2968+
.resolveType(typeRepr);
2969+
2970+
if (type->is<ErrorType>()) {
2971+
// Type resolution has failed, and we should have diagnosed something already.
2972+
assert(Ctx.hadError());
2973+
} else {
2974+
// Otherwise, something odd happened.
2975+
std::string typeName;
2976+
llvm::raw_string_ostream out(typeName);
2977+
typeRepr->print(out);
2978+
2979+
Ctx.Diags.diagnose(attr->getLocation(), diag::unknown_attribute, typeName);
2980+
}
2981+
29592982
attr->setInvalid();
29602983
return;
29612984
}

lib/Sema/TypeCheckType.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,14 @@ static Type diagnoseUnknownType(TypeResolution resolution,
10801080

10811081
// Unqualified lookup case.
10821082
if (parentType.isNull()) {
1083+
// Tailored diagnostic for custom attributes.
1084+
if (resolution.getOptions().is(TypeResolverContext::CustomAttr)) {
1085+
diags.diagnose(comp->getNameLoc(), diag::unknown_attribute,
1086+
comp->getNameRef().getBaseIdentifier().str());
1087+
1088+
return ErrorType::get(ctx);
1089+
}
1090+
10831091
if (comp->getNameRef().isSimpleName(ctx.Id_Self) &&
10841092
!isa<GenericIdentTypeRepr>(comp)) {
10851093
DeclContext *nominalDC = nullptr;
@@ -1642,6 +1650,15 @@ resolveIdentTypeComponent(TypeResolution resolution,
16421650
!options.is(TypeResolverContext::TypeAliasDecl)) {
16431651

16441652
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
1653+
// Tailored diagnostic for custom attributes.
1654+
if (options.is(TypeResolverContext::CustomAttr)) {
1655+
auto &ctx = resolution.getASTContext();
1656+
ctx.Diags.diagnose(lastComp->getNameLoc(), diag::unknown_attribute,
1657+
lastComp->getNameRef().getBaseIdentifier().str());
1658+
1659+
return ErrorType::get(ctx);
1660+
}
1661+
16451662
diagnoseUnboundGenericType(result,
16461663
lastComp->getNameLoc().getBaseNameLoc());
16471664
}
@@ -3605,6 +3622,7 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType(
36053622
case TypeResolverContext::AbstractFunctionDecl:
36063623
case TypeResolverContext::ClosureExpr:
36073624
case TypeResolverContext::Inherited:
3625+
case TypeResolverContext::CustomAttr:
36083626
doDiag = true;
36093627
break;
36103628
}

lib/Sema/TypeCheckType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ enum class TypeResolverContext : uint8_t {
133133

134134
/// Whether this is an "inherited" type.
135135
Inherited,
136+
137+
/// Whether this is a custom attribute.
138+
CustomAttr
136139
};
137140

138141
/// Options that determine how type resolution should work.
@@ -215,6 +218,7 @@ class TypeResolutionOptions {
215218
case Context::ImmediateOptionalTypeArgument:
216219
case Context::AbstractFunctionDecl:
217220
case Context::Inherited:
221+
case Context::CustomAttr:
218222
return false;
219223
}
220224
llvm_unreachable("unhandled kind");
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-typecheck-verify-swift -requirement-machine=verify
2+
3+
protocol Base { // expected-note {{'Base' previously declared here}}
4+
// expected-note@-1 {{found this candidate}}
5+
associatedtype E
6+
}
7+
8+
struct Base<T> {} // expected-error {{invalid redeclaration of 'Base'}}
9+
// expected-note@-1 {{found this candidate}}
10+
11+
protocol Derived : Base { // expected-error {{'Base' is ambiguous for type lookup in this context}}
12+
associatedtype E
13+
}
14+
15+
func foo<T : Derived>(_: T.E, _: T) {}

test/Generics/requirement_inference.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,13 +508,15 @@ extension X1WithP2MoreArgs {
508508
}
509509
}
510510

511-
// Inference from protocol inheritance clauses.
511+
// Inference from protocol inheritance clauses is not allowed.
512512
typealias ExistentialP4WithP2Assoc<T: P4> = P4 where T.P4Assoc : P2
513513

514514
protocol P37 : ExistentialP4WithP2Assoc<Self> { }
515+
// expected-error@-1 {{type 'Self.P4Assoc' does not conform to protocol 'P2'}}
515516

516517
extension P37 {
517518
func f() {
518-
_ = X5<P4Assoc>() // requires P2
519+
_ = X5<P4Assoc>()
520+
// expected-error@-1 {{type 'Self.P4Assoc' does not conform to protocol 'P2'}}
519521
}
520522
}

test/NameLookup/custom_attrs_ambiguous.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@ import custom_attrs_B
99

1010
struct Test {
1111
@Wrapper var x: Int = 17
12-
// expected-error@-1 {{ambiguous use of attribute 'Wrapper'}}
13-
// expected-note@-2 {{use 'custom_attrs_A.' to reference the attribute 'Wrapper' in module 'custom_attrs_A'}} {{4-4=custom_attrs_A.}}
14-
// expected-note@-3 {{use 'custom_attrs_B.' to reference the attribute 'Wrapper' in module 'custom_attrs_B'}} {{4-4=custom_attrs_B.}}
12+
// expected-error@-1 {{'Wrapper' is ambiguous for type lookup in this context}}
1513

1614
init(@Builder closure: () -> Int) {}
17-
// expected-error@-1 {{ambiguous use of attribute 'Builder'}}
18-
// expected-note@-2 {{use 'custom_attrs_A.' to reference the attribute 'Builder' in module 'custom_attrs_A'}} {{9-9=custom_attrs_A.}}
19-
// expected-note@-3 {{use 'custom_attrs_B.' to reference the attribute 'Builder' in module 'custom_attrs_B'}} {{9-9=custom_attrs_B.}}
15+
// expected-error@-1 {{'Builder' is ambiguous for type lookup in this context}}
2016
}
2117

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// RUN: %target-swift-frontend %s -emit-ir -o /dev/null
1+
// RUN: %target-typecheck-verify-swift
22

33
protocol P {
44
associatedtype A
55
}
66
struct Straint<C: P> where C.A : P {
77
typealias X = Any
88
}
9-
protocol Q : Straint<Self>.X {}
9+
protocol Q : Straint<Self>.X {} // expected-error {{type 'Self' does not conform to protocol 'P'}}

0 commit comments

Comments
 (0)