Skip to content

Commit 0595cef

Browse files
committed
[CSDiagnostics] Add diagnostics for two kinds of incorrect initializer reference
- Attempting to construct class object using metatype value via non-required initializer - Referencing initializer of protocol metatype base Both of the diagnostics are used by `AllowInvalidInitRef` fix.
1 parent 1d8cee9 commit 0595cef

File tree

4 files changed

+103
-2
lines changed

4 files changed

+103
-2
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,3 +1506,27 @@ bool PartialApplicationFailure::diagnoseAsError() {
15061506
emitDiagnostic(anchor->getNameLoc(), diagnostic, kind);
15071507
return true;
15081508
}
1509+
1510+
bool InvalidDynamicInitOnMetatypeFailure::diagnoseAsError() {
1511+
auto *anchor = getRawAnchor();
1512+
emitDiagnostic(anchor->getLoc(), diag::dynamic_construct_class,
1513+
BaseType->getMetatypeInstanceType())
1514+
.highlight(BaseRange);
1515+
emitDiagnostic(Init, diag::note_nonrequired_initializer, Init->isImplicit(),
1516+
Init->getFullName());
1517+
return true;
1518+
}
1519+
1520+
bool InitOnProtocolMetatypeFailure::diagnoseAsError() {
1521+
auto *anchor = getRawAnchor();
1522+
if (IsStaticallyDerived) {
1523+
emitDiagnostic(anchor->getLoc(), diag::construct_protocol_by_name,
1524+
BaseType->getMetatypeInstanceType())
1525+
.highlight(BaseRange);
1526+
} else {
1527+
emitDiagnostic(anchor->getLoc(), diag::construct_protocol_value, BaseType)
1528+
.highlight(BaseRange);
1529+
}
1530+
1531+
return true;
1532+
}

lib/Sema/CSDiagnostics.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,70 @@ class PartialApplicationFailure final : public FailureDiagnostic {
707707
bool diagnoseAsError() override;
708708
};
709709

710+
class InvalidInitRefFailure : public FailureDiagnostic {
711+
protected:
712+
Type BaseType;
713+
const ConstructorDecl *Init;
714+
SourceRange BaseRange;
715+
716+
InvalidInitRefFailure(Expr *root, ConstraintSystem &cs, Type baseTy,
717+
const ConstructorDecl *init, SourceRange baseRange,
718+
ConstraintLocator *locator)
719+
: FailureDiagnostic(root, cs, locator), BaseType(baseTy), Init(init),
720+
BaseRange(baseRange) {}
721+
722+
public:
723+
bool diagnoseAsError() override = 0;
724+
};
725+
726+
/// Diagnose an attempt to construct an object of class type with a metatype
727+
/// value without using 'required' initializer:
728+
///
729+
/// ```swift
730+
/// class C {
731+
/// init(value: Int) {}
732+
/// }
733+
///
734+
/// func make<T: C>(type: T.Type) -> T {
735+
/// return T.init(value: 42)
736+
/// }
737+
/// ```
738+
class InvalidDynamicInitOnMetatypeFailure final : public InvalidInitRefFailure {
739+
public:
740+
InvalidDynamicInitOnMetatypeFailure(Expr *root, ConstraintSystem &cs,
741+
Type baseTy, const ConstructorDecl *init,
742+
SourceRange baseRange,
743+
ConstraintLocator *locator)
744+
: InvalidInitRefFailure(root, cs, baseTy, init, baseRange, locator) {}
745+
746+
bool diagnoseAsError() override;
747+
};
748+
749+
/// Diagnose an attempt to call initializer on protocol metatype:
750+
///
751+
/// ```swift
752+
/// protocol P {
753+
/// init(value: Int)
754+
/// }
755+
///
756+
/// func make(type: P.Type) -> P {
757+
/// return type.init(value: 42)
758+
/// }
759+
/// ```
760+
class InitOnProtocolMetatypeFailure final : public InvalidInitRefFailure {
761+
bool IsStaticallyDerived;
762+
763+
public:
764+
InitOnProtocolMetatypeFailure(Expr *root, ConstraintSystem &cs, Type baseTy,
765+
const ConstructorDecl *init,
766+
bool isStaticallyDerived, SourceRange baseRange,
767+
ConstraintLocator *locator)
768+
: InvalidInitRefFailure(root, cs, baseTy, init, baseRange, locator),
769+
IsStaticallyDerived(isStaticallyDerived) {}
770+
771+
bool diagnoseAsError() override;
772+
};
773+
710774
} // end namespace constraints
711775
} // end namespace swift
712776

lib/Sema/CSFix.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,20 @@ AllowInvalidPartialApplication::create(bool isWarning, ConstraintSystem &cs,
277277
}
278278

279279
bool AllowInvalidInitRef::diagnose(Expr *root, bool asNote) const {
280-
return false;
280+
switch (Kind) {
281+
case RefKind::DynamicOnMetatype: {
282+
InvalidDynamicInitOnMetatypeFailure failure(
283+
root, getConstraintSystem(), BaseType, Init, BaseRange, getLocator());
284+
return failure.diagnose(asNote);
285+
}
286+
287+
case RefKind::ProtocolMetatype: {
288+
InitOnProtocolMetatypeFailure failure(root, getConstraintSystem(), BaseType,
289+
Init, IsStaticallyDerived, BaseRange,
290+
getLocator());
291+
return failure.diagnose(asNote);
292+
}
293+
}
281294
}
282295

283296
AllowInvalidInitRef *AllowInvalidInitRef::dynamicOnMetatype(

test/expr/postfix/dot/init_ref_delegation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class Z4 {
113113

114114
convenience init(other: Z4) {
115115
other.init() // expected-error{{'init' is a member of the type; use 'type(of: ...)' to initialize a new object of the same dynamic type}} {{11-11=type(of: }} {{15-15=)}}
116-
type(of: other).init() // expected-error{{must use a 'required' initializer}} expected-warning{{unused}}
116+
type(of: other).init() // expected-error{{must use a 'required' initializer}}
117117
}
118118
}
119119

0 commit comments

Comments
 (0)