diff --git a/.all-contributorsrc b/.all-contributorsrc
index fc2817df60..511fce6f28 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -1272,7 +1272,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/66279577?v=4",
"profile": "https://github.com/comcalvi",
"contributions": [
- "code"
+ "code",
+ "review"
]
},
{
@@ -1428,6 +1429,34 @@
"contributions": [
"bug"
]
+ },
+ {
+ "login": "DanielMSchmidt",
+ "name": "Daniel Schmidt",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1337046?v=4",
+ "profile": "http://danielmschmidt.de/",
+ "contributions": [
+ "bug",
+ "code"
+ ]
+ },
+ {
+ "login": "kaizencc",
+ "name": "Kaizen Conroy",
+ "avatar_url": "https://avatars.githubusercontent.com/u/36202692?v=4",
+ "profile": "https://github.com/kaizencc",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Naumel",
+ "name": "Naumel",
+ "avatar_url": "https://avatars.githubusercontent.com/u/104374999?v=4",
+ "profile": "https://github.com/Naumel",
+ "contributions": [
+ "review"
+ ]
}
],
"repoType": "github",
diff --git a/README.md b/README.md
index ddde39ead0..2c8dd27f8e 100644
--- a/README.md
+++ b/README.md
@@ -54,193 +54,200 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
diff --git a/packages/jsii-calc/lib/index.ts b/packages/jsii-calc/lib/index.ts
index 5e6f39c2ca..9c487d7c6c 100644
--- a/packages/jsii-calc/lib/index.ts
+++ b/packages/jsii-calc/lib/index.ts
@@ -25,3 +25,4 @@ export * as cdk16625 from './cdk16625';
export * as jsii3656 from './jsii3656';
export * as anonymous from './anonymous';
+export * as union from './union';
diff --git a/packages/jsii-calc/lib/union.ts b/packages/jsii-calc/lib/union.ts
new file mode 100644
index 0000000000..ef4bf22b8f
--- /dev/null
+++ b/packages/jsii-calc/lib/union.ts
@@ -0,0 +1,21 @@
+import { IFriendly } from '@scope/jsii-calc-lib';
+
+export interface IResolvable {
+ resolve(): any;
+}
+
+export class Resolvable implements IResolvable {
+ private constructor() {}
+
+ public resolve(): any {
+ return false;
+ }
+}
+
+export class ConsumesUnion {
+ public static unionType(param: IResolvable | Resolvable | IFriendly) {
+ void param;
+ }
+
+ private constructor() {}
+}
diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii
index 469a62babe..d392689d96 100644
--- a/packages/jsii-calc/test/assembly.jsii
+++ b/packages/jsii-calc/test/assembly.jsii
@@ -421,6 +421,13 @@
"line": 4
},
"symbolId": "lib/submodule/returns-param/index:"
+ },
+ "jsii-calc.union": {
+ "locationInModule": {
+ "filename": "lib/index.ts",
+ "line": 28
+ },
+ "symbolId": "lib/union:"
}
},
"targets": {
@@ -18199,8 +18206,125 @@
"name": "ReturnsSpecialParameter",
"namespace": "submodule.returnsparam",
"symbolId": "lib/submodule/returns-param/index:ReturnsSpecialParameter"
+ },
+ "jsii-calc.union.ConsumesUnion": {
+ "assembly": "jsii-calc",
+ "docs": {
+ "stability": "stable"
+ },
+ "fqn": "jsii-calc.union.ConsumesUnion",
+ "kind": "class",
+ "locationInModule": {
+ "filename": "lib/union.ts",
+ "line": 15
+ },
+ "methods": [
+ {
+ "docs": {
+ "stability": "stable"
+ },
+ "locationInModule": {
+ "filename": "lib/union.ts",
+ "line": 16
+ },
+ "name": "unionType",
+ "parameters": [
+ {
+ "name": "param",
+ "type": {
+ "union": {
+ "types": [
+ {
+ "fqn": "jsii-calc.union.IResolvable"
+ },
+ {
+ "fqn": "jsii-calc.union.Resolvable"
+ },
+ {
+ "fqn": "@scope/jsii-calc-lib.IFriendly"
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "static": true
+ }
+ ],
+ "name": "ConsumesUnion",
+ "namespace": "union",
+ "symbolId": "lib/union:ConsumesUnion"
+ },
+ "jsii-calc.union.IResolvable": {
+ "assembly": "jsii-calc",
+ "docs": {
+ "stability": "stable"
+ },
+ "fqn": "jsii-calc.union.IResolvable",
+ "kind": "interface",
+ "locationInModule": {
+ "filename": "lib/union.ts",
+ "line": 3
+ },
+ "methods": [
+ {
+ "abstract": true,
+ "docs": {
+ "stability": "stable"
+ },
+ "locationInModule": {
+ "filename": "lib/union.ts",
+ "line": 4
+ },
+ "name": "resolve",
+ "returns": {
+ "type": {
+ "primitive": "any"
+ }
+ }
+ }
+ ],
+ "name": "IResolvable",
+ "namespace": "union",
+ "symbolId": "lib/union:IResolvable"
+ },
+ "jsii-calc.union.Resolvable": {
+ "assembly": "jsii-calc",
+ "docs": {
+ "stability": "stable"
+ },
+ "fqn": "jsii-calc.union.Resolvable",
+ "interfaces": [
+ "jsii-calc.union.IResolvable"
+ ],
+ "kind": "class",
+ "locationInModule": {
+ "filename": "lib/union.ts",
+ "line": 7
+ },
+ "methods": [
+ {
+ "docs": {
+ "stability": "stable"
+ },
+ "locationInModule": {
+ "filename": "lib/union.ts",
+ "line": 10
+ },
+ "name": "resolve",
+ "overrides": "jsii-calc.union.IResolvable",
+ "returns": {
+ "type": {
+ "primitive": "any"
+ }
+ }
+ }
+ ],
+ "name": "Resolvable",
+ "namespace": "union",
+ "symbolId": "lib/union:Resolvable"
}
},
"version": "3.20.120",
- "fingerprint": "Ze43eowG9ImRufT3MQ8yO+bW8JzOQlZIYtFsjpc960E="
+ "fingerprint": "OaHwYmdPa8tbAJnlREahLGpRaNNBor2aoG04vsA/SvM="
}
\ No newline at end of file
diff --git a/packages/jsii-pacmak/lib/targets/dotnet/runtime-type-checking.ts b/packages/jsii-pacmak/lib/targets/dotnet/runtime-type-checking.ts
index c59e6d3703..8014a86638 100644
--- a/packages/jsii-pacmak/lib/targets/dotnet/runtime-type-checking.ts
+++ b/packages/jsii-pacmak/lib/targets/dotnet/runtime-type-checking.ts
@@ -172,6 +172,31 @@ abstract class Validation {
code.openBlock(`switch (${expression})`);
for (const type of types) {
validTypes.push(resolver.toDotNetTypeName(type.spec!));
+
+ /**
+ * Filter to remove classes and interfaces from a set of type references that
+ * are implied by another entry in the set. Practically this is meant to remove
+ * types from a set if a parent type of it is also present in the set, keeping
+ * only the most generic declaration.
+ *
+ * This is useful because the TypeScript compiler and jsii do not guarantee that
+ * all entries in a type union are unrelated, but the C# compiler treats dead
+ * code as an error, and will refuse to compile (error CS8120) a pattern-matching
+ * switch case if it cannot be matched (for example, if it matches on a child of
+ * a type that was previously matched on already).
+ */
+ if (
+ (type.type?.isClassType() || type.type?.isInterfaceType()) &&
+ types.some(
+ (other) =>
+ other !== type &&
+ other.type != null &&
+ type.type!.extends(other.type),
+ )
+ ) {
+ continue;
+ }
+
const typeNames = [resolver.toDotNetType(type.spec!)];
if (typeNames[0] === 'double') {
// For doubles, we accept any numeric value, really...
diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.js.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.js.snap
index 4af83084d1..ee78fe8a21 100644
--- a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.js.snap
+++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.js.snap
@@ -3167,6 +3167,10 @@ exports[`Generated code for "jsii-calc": / 1`] = `
β β£β π TwoMethodsWithSimilarCapitalization.cs
β β£β π UmaskCheck.cs
β β£β π UnaryOperation.cs
+ β β£β π Union
+ β β β£β π ConsumesUnion.cs
+ β β β£β π IResolvable.cs
+ β β ββ π Resolvable.cs
β β£β π UnionProperties.cs
β β£β π UpcasingReflectable.cs
β β£β π UseBundledDependency.cs
@@ -19762,6 +19766,105 @@ namespace Amazon.JSII.Tests.CalculatorNamespace
`;
+exports[`Generated code for "jsii-calc": /dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/Union/ConsumesUnion.cs 1`] = `
+using Amazon.JSII.Runtime.Deputy;
+
+#pragma warning disable CS0672,CS0809,CS1591
+
+namespace Amazon.JSII.Tests.CalculatorNamespace.Union
+{
+ [JsiiClass(nativeType: typeof(Amazon.JSII.Tests.CalculatorNamespace.Union.ConsumesUnion), fullyQualifiedName: "jsii-calc.union.ConsumesUnion")]
+ public class ConsumesUnion : DeputyBase
+ {
+ /// Used by jsii to construct an instance of this class from a Javascript-owned object reference
+ /// The Javascript-owned object reference
+ [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
+ protected ConsumesUnion(ByRefValue reference): base(reference)
+ {
+ }
+
+ /// Used by jsii to construct an instance of this class from DeputyProps
+ /// The deputy props
+ [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
+ protected ConsumesUnion(DeputyProps props): base(props)
+ {
+ }
+
+ [JsiiMethod(name: "unionType", parametersJson: "[{\\"name\\":\\"param\\",\\"type\\":{\\"union\\":{\\"types\\":[{\\"fqn\\":\\"jsii-calc.union.IResolvable\\"},{\\"fqn\\":\\"jsii-calc.union.Resolvable\\"},{\\"fqn\\":\\"@scope/jsii-calc-lib.IFriendly\\"}]}}}]")]
+ public static void UnionType(object param)
+ {
+ InvokeStaticVoidMethod(typeof(Amazon.JSII.Tests.CalculatorNamespace.Union.ConsumesUnion), new System.Type[]{typeof(object)}, new object[]{param});
+ }
+ }
+}
+
+`;
+
+exports[`Generated code for "jsii-calc": /dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/Union/IResolvable.cs 1`] = `
+using Amazon.JSII.Runtime.Deputy;
+
+#pragma warning disable CS0672,CS0809,CS1591
+
+namespace Amazon.JSII.Tests.CalculatorNamespace.Union
+{
+ [JsiiInterface(nativeType: typeof(IResolvable), fullyQualifiedName: "jsii-calc.union.IResolvable")]
+ public interface IResolvable
+ {
+ [JsiiMethod(name: "resolve", returnsJson: "{\\"type\\":{\\"primitive\\":\\"any\\"}}")]
+ object Resolve();
+
+ [JsiiTypeProxy(nativeType: typeof(IResolvable), fullyQualifiedName: "jsii-calc.union.IResolvable")]
+ internal sealed class _Proxy : DeputyBase, Amazon.JSII.Tests.CalculatorNamespace.Union.IResolvable
+ {
+ private _Proxy(ByRefValue reference): base(reference)
+ {
+ }
+
+ [JsiiMethod(name: "resolve", returnsJson: "{\\"type\\":{\\"primitive\\":\\"any\\"}}")]
+ public object Resolve()
+ {
+ return InvokeInstanceMethod