Skip to content

Commit 56a5ef0

Browse files
committed
Add a fixit for attempting member lookup on Any.
Suggest casting to AnyObject or a more specific type. rdar://problem/27639935
1 parent fdedd5a commit 56a5ef0

File tree

4 files changed

+20
-0
lines changed

4 files changed

+20
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ ERROR(could_not_find_type_member,none,
7575
NOTE(did_you_mean_raw_type,none,
7676
"did you mean to specify a raw type on the enum declaration?", ())
7777

78+
NOTE(any_as_anyobject_fixit, none,
79+
"cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members", ())
80+
7881
ERROR(expected_argument_in_contextual_member,none,
7982
"contextual member %0 expects argument of type %1", (DeclName, Type))
8083

lib/Sema/CSDiag.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2490,6 +2490,14 @@ diagnoseUnviableLookupResults(MemberLookupResult &result, Type baseObjTy,
24902490
diagnose(loc, diag::did_you_mean_raw_type);
24912491
return; // Always prefer this over typo corrections.
24922492
}
2493+
} else if (baseObjTy->isAny()) {
2494+
if (auto DRE = dyn_cast<DeclRefExpr>(baseExpr)) {
2495+
auto name = DRE->getDecl()->getName().str().str();
2496+
std::string replacement = "(" + name + " as AnyObject)";
2497+
diagnose(loc, diag::any_as_anyobject_fixit)
2498+
.fixItReplace(baseExpr->getSourceRange(), replacement);
2499+
return;
2500+
}
24932501
}
24942502
}
24952503

test/Constraints/dynamic_lookup.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,9 @@ uopt.wibble!()
219219
// Should not be able to see private or internal @objc methods.
220220
uopt.privateFoo!() // expected-error{{'privateFoo' is inaccessible due to 'private' protection level}}
221221
uopt.internalFoo!() // expected-error{{'internalFoo' is inaccessible due to 'internal' protection level}}
222+
223+
let anyValue: Any = X()
224+
_ = anyValue.bar() // expected-error {{value of type 'Any' has no member 'bar'}}
225+
// expected-note@-1 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}{{5-13=(anyValue as AnyObject)}}
226+
_ = (anyValue as AnyObject).bar()
227+
_ = (anyValue as! X).bar()

test/Constraints/tuple.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ any = (label: 4)
6161
// Scalars don't have .0/.1/etc
6262
i = j.0 // expected-error{{value of type 'Int' has no member '0'}}
6363
any.1 // expected-error{{value of type 'Any' has no member '1'}}
64+
// expected-note@-1{{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}
65+
any = (5.0, 6.0) as (Float, Float)
66+
_ = (any as! (Float, Float)).1
6467

6568
// Fun with tuples
6669
protocol PosixErrorReturn {

0 commit comments

Comments
 (0)