Skip to content

Commit f3708b2

Browse files
committed
Add tests for operator lookup and redeclaration checking
1 parent 11551e1 commit f3708b2

11 files changed

+291
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
// Only declared in module A.
3+
prefix operator >>>
4+
public prefix func >>> (rhs: Int) {}
5+
6+
precedencegroup DeclaredInModuleA {}
7+
8+
// Declared in both modules A and B.
9+
infix operator ???
10+
precedencegroup DeclaredInModulesAB {}
11+
12+
// Declared in both modules A and B, but with a different
13+
// precedence group in each.
14+
infix operator ???? : DeclaredInModuleA
15+
16+
// Declared in both modules A and B, but shadowed by lookup_other.
17+
precedencegroup DeclaredInModulesABShadowed {}
18+
19+
// Declared in both modules A and B.
20+
postfix operator <?
21+
22+
// Declared in both modules A and B, and also the stdlib.
23+
precedencegroup TernaryPrecedence {}
24+
25+
// Also declared in module 'ExportsAC', which shadows this decl.
26+
precedencegroup ShadowsModuleA {}
27+
28+
// Also declared in modules ExportsAC and C.
29+
precedencegroup ShadowsModulesAC {}
30+
31+
// Also declared in modules C and ExportsAC.
32+
infix operator ?????
33+
34+
// Also declared in modules C and ExportsAC, but with a different
35+
// precedencegroup.
36+
infix operator ?????? : DeclaredInModuleA
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
// Both of these decls are also declared in lookup_other, and we should prefer
3+
// those decls.
4+
precedencegroup DeclaredAcrossFiles {}
5+
infix operator &&&
6+
7+
// Also declared in module A.
8+
infix operator ???
9+
precedencegroup DeclaredInModulesAB {}
10+
11+
// Also declared in module A, but with a different precedence group.
12+
infix operator ????
13+
14+
// Declared in both modules A and B, but shadowed by lookup_other.
15+
precedencegroup DeclaredInModulesABShadowed {}
16+
17+
// Also declared in module A.
18+
postfix operator <?
19+
20+
// Declared in both modules A and B, and also the stdlib.
21+
precedencegroup TernaryPrecedence {}
22+
23+
// These are both also declared in module ExportsAC.
24+
infix operator ???!
25+
precedencegroup DeclaredInModulesBExportsAC {}
26+
27+
// Also declared in module ExportsAC, but with a different precedence group.
28+
infix operator ????!
29+
30+
// Also declared in module ExportsAC.
31+
postfix operator <!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
// Also declared in modules ExportsAC and A.
3+
precedencegroup ShadowsModulesAC {}
4+
5+
// Also declared in modules A and ExportsAC.
6+
infix operator ?????
7+
8+
// Also declared in modules A and ExportsAC, with a different precedencegroup.
9+
infix operator ?????? : ShadowsModulesAC
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
precedencegroup DeclaredInModuleD {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
@_exported import A
3+
@_exported import C
4+
5+
// Also declared in module A, but this decl shadows it.
6+
precedencegroup ShadowsModuleA {}
7+
8+
// Also declared in modules A and C, but this decl shadows it.
9+
precedencegroup ShadowsModulesAC {}
10+
11+
// Also declared in modules A and C, but this decl shadows it.
12+
infix operator ?????
13+
14+
// Also declared in modules A and C, but with a different precedencegroup.
15+
// However that shouldn't impact shadowing.
16+
infix operator ??????
17+
18+
// These are both also declared in module B.
19+
infix operator ???!
20+
precedencegroup DeclaredInModulesBExportsAC {}
21+
22+
// Also declared in module B, but with a different precedence group.
23+
infix operator ????! : ShadowsModuleA
24+
25+
// Also declared in module B.
26+
postfix operator <!
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
@_exported import D
3+
4+
// Both of these decls are also declared in module B, but we should prefer
5+
// these decls.
6+
precedencegroup DeclaredAcrossFiles {
7+
higherThan: AssignmentPrecedence
8+
associativity: left
9+
}
10+
infix operator &&& : DeclaredAcrossFiles
11+
12+
// Declared in both modules A and B, but shadowed by this decl.
13+
precedencegroup DeclaredInModulesABShadowed {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
@_exported import D
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
// Also declared in the files being tested.
3+
precedencegroup RedeclaredInModule {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
precedencegroup RedeclaredAcrossFiles {}
2+
3+
infix operator ^^^
4+
prefix operator >>>
5+
postfix operator <<<
6+
7+
precedencegroup P1 {}
8+
infix operator ^^^^ : P1
9+
10+
infix operator &&&
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleD.swift -module-name D -o %t -I %t
4+
// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleC.swift -module-name C -o %t -I %t
5+
// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleB.swift -module-name B -o %t -I %t
6+
// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_moduleA.swift -module-name A -o %t -I %t
7+
// RUN: %target-swift-frontend -emit-module %S/Inputs/lookup_module_exportsAC.swift -module-name ExportsAC -o %t -I %t
8+
9+
// FIXME: Remove -verify-ignore-unknown.
10+
// RUN: %target-swift-frontend -typecheck -verify -verify-ignore-unknown -primary-file %s %S/Inputs/lookup_other.swift %S/Inputs/lookup_other2.swift %S/Inputs/lookup_other_compat.swift -I %t
11+
12+
import ExportsAC
13+
import B
14+
15+
infix operator ^^^ : DeclaredAcrossFiles
16+
func ^^^ (lhs: Int, rhs: Int) -> Int { 0 }
17+
func &&& (lhs: Int, rhs: Int) -> Int { 0 }
18+
19+
// FIXME(SR-12132): The operator decl >>> is declared in module A, which we
20+
// should be able to see through ExportsAC.
21+
prefix func >>> (rhs: Double) {} // expected-error {{operator implementation without matching operator declaration}}
22+
23+
// FIXME(SR-12132): We should also see precedencegroups in module A through
24+
// ExportsAC.
25+
infix operator ^^^^ : DeclaredInModuleA // expected-error {{unknown precedence group 'DeclaredInModuleA'}}
26+
27+
// The operator decl for ??? is declared in both modules A and B, but has the
28+
// same default precedence group in both, so there's no ambiguity.
29+
func ??? (lhs: Int, rhs: Int) {}
30+
31+
// Same for ???!, declared in modules ExportsAC and B, but has the same
32+
// precedence group in both.
33+
func ???! (lhs: Int, rhs: Int) {}
34+
35+
// The operator decl for ???? is declared in both modules A and B, and has a
36+
// different precedence group in each. This should therefore be ambiguous.
37+
// However, for compatibility, we don't look through exports in other modules,
38+
// so we don't see the one in module A.
39+
func ???? (lhs: Int, rhs: Int) {}
40+
41+
// The operator decl for ????! is declared in both modules ExportsAC and B, and
42+
// has a different precedence group in each. Therefore ambiguous.
43+
// FIXME: We shouldn't emit the unknown operator decl error.
44+
func ????! (lhs: Int, rhs: Int) {} // expected-error {{ambiguous operator declarations found for operator}}
45+
// expected-error@-1 {{operator implementation without matching operator declaration}}
46+
47+
// Same as ????, the precedencegroup is declared in both modules A and B, but
48+
// we don't look into module A for compatibility.
49+
infix operator <?> : DeclaredInModulesAB
50+
51+
// The precedencegroup is declared in both modules ExportsAC and B, therefore
52+
// ambiguous.
53+
// FIXME: We shouldn't emit the 'unknown precedence group' error.
54+
infix operator <!> : DeclaredInModulesBExportsAC // expected-error {{multiple precedence groups found}}
55+
// expected-error@-1 {{unknown precedence group 'DeclaredInModulesBExportsAC'}}
56+
57+
// This precedencegroup is declared in this module as well as in both modules A
58+
// and B. The decl in this module should shadow the imported ones, but for
59+
// compatibility we don't see module A's decl and take module B's decl.
60+
infix operator <??> : DeclaredInModulesABShadowed
61+
62+
// The operator decl for <? is declared in both modules A and B, but there's no
63+
// meaningful difference between the declarations, so legal.
64+
postfix func <? (lhs: Int) {}
65+
66+
// Same thing, <! is declared in both modules ExportsAC and B, but there's no
67+
// meaningful difference between the declarations, so legal.
68+
postfix func <! (lhs: Int) {}
69+
70+
// This precedencegroup is declared in both modules A and ExportsAC, but the
71+
// latter shadows the former.
72+
infix operator <???> : ShadowsModuleA
73+
74+
// This precedencegroup is declared in modules A, C, and ExportsAC, but the
75+
// latter shadows both of the former.
76+
infix operator <????> : ShadowsModulesAC
77+
78+
// This operator decl is declared in modules A, C, and ExportsAC, but the
79+
// latter shadows both of the former.
80+
func ????? (lhs: Int, rhs: Int) {}
81+
82+
// This operator decl is declared in modules A, C, and ExportsAC, but the
83+
// latter shadows both of the former, despite them having different
84+
// precedencegroups.
85+
func ?????? (lhs: Int, rhs: Int) {}
86+
87+
// FIXME: Module D is imported through exports in both lookup_other and
88+
// lookup_other2, but we fail to detect the fact that we're visiting the same
89+
// thing twice.
90+
infix operator <> : DeclaredInModuleD // expected-error {{unknown precedence group 'DeclaredInModuleD'}}
91+
92+
// Also declared in lookup_other. To preserve compatibility, we allow an
93+
// unambiguous lookup that will favor this declaration over lookup_other.
94+
precedencegroup RedeclaredInModule {}
95+
infix operator *** : RedeclaredInModule // Okay.
96+
97+
func testOperatorLookup() {
98+
// In lookup_other, DeclaredAcrossFiles is left associative, whereas in
99+
// module B it is non-associative. Make sure we use module B's for
100+
// compatibility.
101+
_ = 5 ^^^ 5 ^^^ 5
102+
// expected-error@-1 {{adjacent operators are in unordered precedence groups 'AssignmentPrecedence' and 'DeclaredAcrossFiles'}}
103+
// expected-error@-2 {{adjacent operators are in non-associative precedence group 'DeclaredAcrossFiles'}}
104+
// expected-error@-3 {{cannot convert value of type '()' to expected argument type 'Int'}}
105+
106+
// Same for &&&, in lookup_other it is declared as left associative.
107+
_ = 5 &&& 5 &&& 5 // expected-error {{adjacent operators are in non-associative precedence group 'DefaultPrecedence'}}
108+
109+
// The operator >>> is declared in module A, which we should be able to see
110+
// through ExportsAC.
111+
>>>1
112+
113+
// We've been evil and overriden TernaryPrecedence in both modules A and B.
114+
// FIXME: We shouldn't emit the 'broken stdlib' error.
115+
true ? () : () // expected-error {{multiple precedence groups found}}
116+
// expected-error@-1 {{broken standard library: missing builtin precedence group 'TernaryPrecedence'}}
117+
}
118+
119+
precedencegroup CastingPrecedence {
120+
lowerThan: AssignmentPrecedence
121+
}
122+
123+
func testBuiltinPrecedenceGroupOverriding() {
124+
// Evil, but allowed.
125+
var x = 0
126+
x = 0 as Int // expected-error {{cannot convert value of type '()' to type 'Int' in coercion}}
127+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-swift-frontend -typecheck -verify -primary-file %s %S/Inputs/redeclaration_other_compat.swift
2+
3+
// We currently allow cross-file redeclarations.
4+
precedencegroup RedeclaredAcrossFiles {}
5+
6+
precedencegroup RedeclaredSameFile {} // expected-note {{previous precedence group declaration here}}
7+
precedencegroup RedeclaredSameFile {} // expected-error {{precedence group redeclared}}
8+
9+
precedencegroup RedeclaredSameFile2 { // expected-note {{previous precedence group declaration here}}
10+
assignment: true
11+
}
12+
precedencegroup RedeclaredSameFile2 {} // expected-error {{precedence group redeclared}}
13+
14+
// These are all declared in the other file, and so are allowed for now.
15+
infix operator ^^^
16+
prefix operator >>>
17+
postfix operator <<<
18+
infix operator ^^^^
19+
20+
// This is declared as an infix operator in the other file, so no problem.
21+
prefix operator &&&
22+
postfix operator &&&
23+
24+
infix operator %%% // expected-note {{previous operator declaration here}}
25+
infix operator %%% // expected-error {{operator redeclared}}
26+
27+
prefix operator %%% // expected-note {{previous operator declaration here}}
28+
prefix operator %%% // expected-error {{operator redeclared}}
29+
30+
precedencegroup P2 {}
31+
infix operator *** : P2 // expected-note {{previous operator declaration here}}
32+
infix operator *** // expected-error {{operator redeclared}}

0 commit comments

Comments
 (0)