summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BCT/BytecodeTranslator/ExpressionTraverser.cs42
-rw-r--r--BCT/BytecodeTranslator/MetadataTraverser.cs2
-rw-r--r--BCT/BytecodeTranslator/Program.cs2
-rw-r--r--BCT/BytecodeTranslator/Sink.cs124
-rw-r--r--BCT/BytecodeTranslator/StatementTraverser.cs2
-rw-r--r--BCT/BytecodeTranslator/TranslationHelper.cs23
-rw-r--r--BCT/BytecodeTranslator/WholeProgram.cs2
7 files changed, 143 insertions, 54 deletions
diff --git a/BCT/BytecodeTranslator/ExpressionTraverser.cs b/BCT/BytecodeTranslator/ExpressionTraverser.cs
index 8e5170b2..47c68419 100644
--- a/BCT/BytecodeTranslator/ExpressionTraverser.cs
+++ b/BCT/BytecodeTranslator/ExpressionTraverser.cs
@@ -33,6 +33,27 @@ namespace BytecodeTranslator
private bool contractContext;
+ private Bpl.Expr FindOrCreateTypeReferenceInCodeContext(ITypeReference typeReference) {
+ return this.sink.FindOrCreateTypeReference(typeReference, true);
+
+ IGenericTypeParameter gtp = typeReference as IGenericTypeParameter;
+ if (gtp != null) {
+ var selectorName = gtp.Name.Value;
+ selectorName = TranslationHelper.TurnStringIntoValidIdentifier(selectorName);
+ var typeName = TypeHelper.GetTypeName(gtp.DefiningType, NameFormattingOptions.DocumentationId);
+ typeName = TranslationHelper.TurnStringIntoValidIdentifier(typeName);
+ var funcName = String.Format("{0}#{1}", selectorName, typeName);
+ Bpl.IToken tok = Bpl.Token.NoToken;
+ var identExpr = Bpl.Expr.Ident(new Bpl.LocalVariable(tok, new Bpl.TypedIdent(tok, funcName, this.sink.Heap.TypeType)));
+ var funcCall = new Bpl.FunctionCall(identExpr);
+ var thisArg = new Bpl.IdentifierExpr(tok, this.sink.ThisVariable);
+ var dynType = this.sink.Heap.DynamicType(thisArg);
+ var nary = new Bpl.NAryExpr(Bpl.Token.NoToken, funcCall, new Bpl.ExprSeq(dynType));
+ return nary;
+ }
+ return this.sink.FindOrCreateTypeReference(typeReference);
+ }
+
#region Constructors
///// <summary>
@@ -473,7 +494,7 @@ namespace BytecodeTranslator
new Bpl.AssumeCmd(tok,
Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
this.sink.Heap.DynamicType(locExpr),
- this.sink.FindOrCreateTypeReference(typ)
+ this.FindOrCreateTypeReferenceInCodeContext(typ)
)
)
);
@@ -637,7 +658,7 @@ namespace BytecodeTranslator
new Bpl.AssumeCmd(methodCallToken,
Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
this.sink.Heap.DynamicType(thisExpr),
- this.sink.FindOrCreateTypeReference(methodCall.MethodToCall.ResolvedMethod.ContainingTypeDefinition)
+ this.FindOrCreateTypeReferenceInCodeContext(methodCall.MethodToCall.ResolvedMethod.ContainingTypeDefinition)
)
)
);
@@ -701,13 +722,13 @@ namespace BytecodeTranslator
List<ITypeReference> consolidatedTypeArguments = new List<ITypeReference>();
Sink.GetConsolidatedTypeArguments(consolidatedTypeArguments, methodToCall.ContainingType);
foreach (ITypeReference typeReference in consolidatedTypeArguments) {
- inexpr.Add(sink.FindOrCreateTypeReference(typeReference));
+ inexpr.Add(this.FindOrCreateTypeReferenceInCodeContext(typeReference));
}
}
IGenericMethodInstanceReference methodInstanceReference = methodToCall as IGenericMethodInstanceReference;
if (methodInstanceReference != null) {
foreach (ITypeReference typeReference in methodInstanceReference.GenericArguments) {
- inexpr.Add(sink.FindOrCreateTypeReference(typeReference));
+ inexpr.Add(this.FindOrCreateTypeReferenceInCodeContext(typeReference));
}
}
@@ -945,7 +966,7 @@ namespace BytecodeTranslator
new Bpl.AssumeCmd(token,
Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
this.sink.Heap.DynamicType(Bpl.Expr.Ident(a)),
- this.sink.FindOrCreateTypeReference(createObjectInstance.Type)
+ this.FindOrCreateTypeReferenceInCodeContext(createObjectInstance.Type)
)
)
);
@@ -953,6 +974,7 @@ namespace BytecodeTranslator
TranslatedExpressions.Push(Bpl.Expr.Ident(a));
}
+
public override void TraverseChildren(ICreateArray createArrayInstance)
{
Bpl.IToken cloc = createArrayInstance.Token();
@@ -1002,13 +1024,13 @@ namespace BytecodeTranslator
List<ITypeReference> consolidatedTypeArguments = new List<ITypeReference>();
Sink.GetConsolidatedTypeArguments(consolidatedTypeArguments, methodToCall.ContainingType);
foreach (ITypeReference typeReference in consolidatedTypeArguments) {
- typeParameterExprs.Add(sink.FindOrCreateTypeReference(typeReference));
+ typeParameterExprs.Add(this.FindOrCreateTypeReferenceInCodeContext(typeReference));
}
}
IGenericMethodInstanceReference methodInstanceReference = methodToCall as IGenericMethodInstanceReference;
if (methodInstanceReference != null) {
foreach (ITypeReference typeReference in methodInstanceReference.GenericArguments) {
- typeParameterExprs.Add(sink.FindOrCreateTypeReference(typeReference));
+ typeParameterExprs.Add(this.FindOrCreateTypeReferenceInCodeContext(typeReference));
}
}
Bpl.Expr typeParameterExpr =
@@ -1448,7 +1470,7 @@ namespace BytecodeTranslator
public override void TraverseChildren(ICastIfPossible castIfPossible) {
base.Traverse(castIfPossible.ValueToCast);
var exp = TranslatedExpressions.Pop();
- var e = this.sink.FindOrCreateTypeReference(castIfPossible.TargetType);
+ var e = this.FindOrCreateTypeReferenceInCodeContext(castIfPossible.TargetType);
var callAs = new Bpl.NAryExpr(
castIfPossible.Token(),
new Bpl.FunctionCall(this.sink.Heap.AsFunction),
@@ -1458,7 +1480,7 @@ namespace BytecodeTranslator
return;
}
public override void TraverseChildren(ICheckIfInstance checkIfInstance) {
- var e = this.sink.FindOrCreateTypeReference(checkIfInstance.TypeToCheck);
+ var e = this.FindOrCreateTypeReferenceInCodeContext(checkIfInstance.TypeToCheck);
//var callTypeOf = new Bpl.NAryExpr(
// checkIfInstance.Token(),
// new Bpl.FunctionCall(this.sink.Heap.TypeOfFunction),
@@ -1644,7 +1666,7 @@ namespace BytecodeTranslator
}
public override void TraverseChildren(ITypeOf typeOf) {
- var e = this.sink.FindOrCreateTypeReference(typeOf.TypeToGet);
+ var e = this.FindOrCreateTypeReferenceInCodeContext(typeOf.TypeToGet);
var callTypeOf = new Bpl.NAryExpr(
typeOf.Token(),
new Bpl.FunctionCall(this.sink.Heap.TypeOfFunction),
diff --git a/BCT/BytecodeTranslator/MetadataTraverser.cs b/BCT/BytecodeTranslator/MetadataTraverser.cs
index 4f0e3667..f6dc7ecf 100644
--- a/BCT/BytecodeTranslator/MetadataTraverser.cs
+++ b/BCT/BytecodeTranslator/MetadataTraverser.cs
@@ -125,7 +125,7 @@ namespace BytecodeTranslator {
if (typeDefinition.IsClass) {
bool savedSawCctor = this.sawCctor;
this.sawCctor = false;
- sink.FindOrCreateTypeReference(typeDefinition);
+ sink.FindOrDefineType(typeDefinition);
base.TraverseChildren(typeDefinition);
if (!this.sawCctor) {
CreateStaticConstructor(typeDefinition);
diff --git a/BCT/BytecodeTranslator/Program.cs b/BCT/BytecodeTranslator/Program.cs
index 4af8c9ec..4702d5a0 100644
--- a/BCT/BytecodeTranslator/Program.cs
+++ b/BCT/BytecodeTranslator/Program.cs
@@ -211,7 +211,7 @@ namespace BytecodeTranslator {
}
module = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader) as IModule;
// The decompiler does not turn calls to Assert/Assume into Code Model nodes
- module = new Microsoft.Cci.MutableContracts.ContractExtractor.AssertAssumeExtractor(host, pdbReader).Visit(module);
+ module = new Microsoft.Cci.MutableContracts.ContractExtractor.AssertAssumeExtractor(host, pdbReader).Rewrite(module);
host.RegisterAsLatest(module);
modules.Add(module);
diff --git a/BCT/BytecodeTranslator/Sink.cs b/BCT/BytecodeTranslator/Sink.cs
index 50051b0c..957b8c38 100644
--- a/BCT/BytecodeTranslator/Sink.cs
+++ b/BCT/BytecodeTranslator/Sink.cs
@@ -867,14 +867,14 @@ namespace BytecodeTranslator {
/// <paramref name="type"/> in the Bpl program. I.e., its
/// value represents the expression "typeof(type)".
/// </summary>
- public Bpl.Expr FindOrCreateTypeReference(ITypeReference type) {
+ public Bpl.Expr FindOrCreateTypeReference(ITypeReference type, bool codeContext = false) {
var gtir = type as IGenericTypeInstanceReference;
if (gtir != null) {
- var genericType = FindOrDefineType(gtir.GenericType);
+ var genericType = FindOrDefineType(gtir.GenericType.ResolvedType);
var gArgs = new Bpl.ExprSeq();
foreach (var a in gtir.GenericArguments) {
- var a_prime = FindOrCreateTypeReference(a);
+ var a_prime = FindOrCreateTypeReference(a, codeContext);
gArgs.Add(a_prime);
}
var typeExpression = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(genericType), gArgs);
@@ -882,18 +882,24 @@ namespace BytecodeTranslator {
IGenericTypeParameter gtp = type as IGenericTypeParameter;
if (gtp != null) {
- var selectorName = gtp.Name.Value;
- selectorName = TranslationHelper.TurnStringIntoValidIdentifier(selectorName);
- var typeName = TypeHelper.GetTypeName(gtp.DefiningType, NameFormattingOptions.DocumentationId);
- typeName = TranslationHelper.TurnStringIntoValidIdentifier(typeName);
- var funcName = String.Format("{0}#{1}", selectorName, typeName);
- Bpl.IToken tok = Bpl.Token.NoToken;
- var identExpr = Bpl.Expr.Ident(new Bpl.LocalVariable(tok, new Bpl.TypedIdent(tok, funcName, this.Heap.TypeType)));
- var funcCall = new Bpl.FunctionCall(identExpr);
- var thisArg = new Bpl.IdentifierExpr(tok, this.ThisVariable);
- var dynType = this.Heap.DynamicType(thisArg);
- var nary = new Bpl.NAryExpr(Bpl.Token.NoToken, funcCall, new Bpl.ExprSeq(dynType));
- return nary;
+ if (codeContext) {
+ var selectorName = gtp.Name.Value;
+ selectorName = TranslationHelper.TurnStringIntoValidIdentifier(selectorName);
+ var typeName = TypeHelper.GetTypeName(gtp.DefiningType, NameFormattingOptions.DocumentationId);
+ typeName = TranslationHelper.TurnStringIntoValidIdentifier(typeName);
+ var funcName = String.Format("{0}#{1}", selectorName, typeName);
+ Bpl.IToken tok = Bpl.Token.NoToken;
+ var identExpr = Bpl.Expr.Ident(new Bpl.LocalVariable(tok, new Bpl.TypedIdent(tok, funcName, this.Heap.TypeType)));
+ var funcCall = new Bpl.FunctionCall(identExpr);
+ var thisArg = new Bpl.IdentifierExpr(tok, this.ThisVariable);
+ var dynType = this.Heap.DynamicType(thisArg);
+ var nary = new Bpl.NAryExpr(Bpl.Token.NoToken, funcCall, new Bpl.ExprSeq(dynType));
+ return nary;
+
+ } else {
+ var formal = FindOrDefineTypeParameter(gtp);
+ return Bpl.Expr.Ident(formal);
+ }
}
IGenericMethodParameter gmp = type as IGenericMethodParameter;
@@ -903,6 +909,15 @@ namespace BytecodeTranslator {
}
ITypeReference uninstantiatedGenericType = GetUninstantiatedGenericType(type);
+
+ // Corner case: type might be a reference to the uninstantiated generic type.
+ // This happens, e.g., with "typeof(Dictionary<,>)".
+ // In that case, need to create a constant for it (because Boogie doesn't allow
+ // overloading by arity on functions
+ if (type.ResolvedType.IsGeneric && type == uninstantiatedGenericType) {
+ return FindOrDefineTypeConstant(type);
+ }
+
List<ITypeReference> consolidatedTypeArguments = new List<ITypeReference>();
GetConsolidatedTypeArguments(consolidatedTypeArguments, type);
@@ -912,24 +927,58 @@ namespace BytecodeTranslator {
var f2 = this.declaredTypeFunctions[k];
Bpl.ExprSeq args = new Bpl.ExprSeq();
foreach (ITypeReference p in consolidatedTypeArguments) {
- args.Add(FindOrCreateTypeReference(p));
+ args.Add(FindOrCreateTypeReference(p, codeContext));
}
Bpl.Expr naryExpr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(f2), args);
return naryExpr;
}
- var f = FindOrDefineType(type);
- // BUGBUG: Generics!
+ var f = FindOrDefineType(type.ResolvedType);
var fCall = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(f), new Bpl.ExprSeq());
return fCall;
}
+ /// <summary>
+ /// Constants of type "Type" that represent the uninstantiated type of a generic type.
+ /// E.g. "Dictionary&lt;,&gt;".
+ /// </summary>
+ private Dictionary<uint, Bpl.Constant> declaredTypeConstants = new Dictionary<uint, Bpl.Constant>();
+ private Bpl.Expr FindOrDefineTypeConstant(ITypeReference type) {
+ Bpl.Constant c;
+ var k = type.InternedKey;
+ if (!this.declaredTypeConstants.TryGetValue(k, out c)) {
+ var typeName = TypeHelper.GetTypeName(type);
+ var i = typeName.IndexOf('`');
+ // assume there is just one occurrence
+ if (i != -1) {
+ typeName = typeName.Substring(0, i);
+ }
+ typeName = TranslationHelper.TurnStringIntoValidIdentifier(typeName);
+ var typedIdent = new Bpl.TypedIdent(Bpl.Token.NoToken, typeName, this.Heap.TypeType);
+ c = new Bpl.Constant(Bpl.Token.NoToken, typedIdent, true);
+ this.declaredTypeConstants.Add(k, c);
+ this.TranslatedProgram.TopLevelDeclarations.Add(c);
+ }
+ return Bpl.Expr.Ident(c);
+ }
+
+ private Dictionary<IGenericParameter, Bpl.Formal> declaredTypeParameters = new Dictionary<IGenericParameter, Bpl.Formal>();
+ public Bpl.Formal FindOrDefineTypeParameter(IGenericParameter genericParameter) {
+ Bpl.Formal formal;
+ if (!this.declaredTypeParameters.TryGetValue(genericParameter, out formal)) {
+ var n = genericParameter.Name.Value;
+ var n2 = TranslationHelper.TurnStringIntoValidIdentifier(n);
+ formal = new Bpl.Formal(Bpl.Token.NoToken, new Bpl.TypedIdent(Bpl.Token.NoToken, n2, this.Heap.TypeType), true);
+ }
+ return formal;
+ }
/// <summary>
- /// The Heap has to decide how to represent the type.
- /// All the Sink cares about is adding a declaration for it.
+ /// Every type is represented as a function.
+ /// Non-generic types are nullary functions.
+ /// Generic types are n-ary functions, where n is the number of generic parameters.
/// </summary>
- public Bpl.Function FindOrDefineType(ITypeReference type) {
+ public Bpl.Function FindOrDefineType(ITypeDefinition type) {
Bpl.Function f;
@@ -939,19 +988,30 @@ namespace BytecodeTranslator {
var numParameters = ConsolidatedGenericParameterCount(type);
- f = this.Heap.CreateTypeFunction(type, numParameters);
+ //f = this.Heap.CreateTypeFunction(type, numParameters);
+
+ string typename = TypeHelper.GetTypeName(type, NameFormattingOptions.DocumentationId);
+ typename = TranslationHelper.TurnStringIntoValidIdentifier(typename);
+ var tok = type.Token();
+ var inputs = new Bpl.VariableSeq();
+ foreach (var t in TranslationHelper.ConsolidatedGenericParameters(type)) {
+ var formal = FindOrDefineTypeParameter(t);
+ inputs.Add(formal);
+ }
+ Bpl.Variable output = new Bpl.Formal(tok, new Bpl.TypedIdent(tok, "result", this.Heap.TypeType), false);
+ Bpl.Function func = new Bpl.Function(tok, typename, inputs, output);
+ func.Attributes = new Bpl.QKeyValue(Bpl.Token.NoToken, "constructor", new List<object>(1), null);
+ f = func;
+
this.declaredTypeFunctions.Add(key, f);
this.TranslatedProgram.TopLevelDeclarations.Add(f);
- DeclareParents(type.ResolvedType, f);
+ DeclareParents(type, f);
bool isExtern = this.assemblyBeingTranslated != null &&
!TypeHelper.GetDefiningUnitReference(type).UnitIdentity.Equals(this.assemblyBeingTranslated.UnitIdentity);
if (isExtern) {
var attrib = new Bpl.QKeyValue(Bpl.Token.NoToken, "extern", new List<object>(1), null);
- if (f.Attributes == null)
- f.Attributes = attrib;
- else
- f.Attributes.AddLast(attrib);
+ f.Attributes.AddLast(attrib);
}
return f;
}
@@ -966,31 +1026,27 @@ namespace BytecodeTranslator {
return;
}
private void DeclareSuperType(Bpl.Function typeDefinitionAsBplFunction, ITypeReference superType) {
- var superTypeFunction = FindOrDefineType(superType);
+ var superTypeExpr = FindOrCreateTypeReference(superType);
var numberOfGenericParameters = typeDefinitionAsBplFunction.InParams.Length;
var qvars = new Bpl.VariableSeq();
var exprs = new Bpl.ExprSeq();
- var superTypeArgs = new Bpl.ExprSeq();
for (int i = 0; i < numberOfGenericParameters; i++) {
var t = typeDefinitionAsBplFunction.InParams[i];
qvars.Add(t);
var identForT = Bpl.Expr.Ident(t);
exprs.Add(identForT);
- if (i < superTypeFunction.InParams.Length)
- superTypeArgs.Add(identForT);
}
// G(t,u)
var callToG = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(typeDefinitionAsBplFunction), exprs);
- var callToSuperType = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(superTypeFunction), superTypeArgs);
// Subtype(G(t,u), super)
- Bpl.Expr subtype = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.Heap.Subtype), new Bpl.ExprSeq(callToG, callToSuperType));
+ Bpl.Expr subtype = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.Heap.Subtype), new Bpl.ExprSeq(callToG, superTypeExpr));
Bpl.Expr disjointSubtree = null;
var isDisjoint = !superType.ResolvedType.IsInterface;
if (isDisjoint) {
// DisjointSubtree(G(t,u), super)
- disjointSubtree = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.Heap.DisjointSubtree), new Bpl.ExprSeq(callToG, callToSuperType));
+ disjointSubtree = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.Heap.DisjointSubtree), new Bpl.ExprSeq(callToG, superTypeExpr));
}
if (0 < numberOfGenericParameters) {
diff --git a/BCT/BytecodeTranslator/StatementTraverser.cs b/BCT/BytecodeTranslator/StatementTraverser.cs
index 7a9340db..424064ff 100644
--- a/BCT/BytecodeTranslator/StatementTraverser.cs
+++ b/BCT/BytecodeTranslator/StatementTraverser.cs
@@ -512,7 +512,7 @@ namespace BytecodeTranslator
List<Bpl.Expr> typeReferences = new List<Bpl.Expr>();
this.sink.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InCatch));
foreach (ICatchClause catchClause in tryCatchFinallyStatement.CatchClauses) {
- typeReferences.Insert(0, this.sink.FindOrCreateTypeReference(catchClause.ExceptionType));
+ typeReferences.Insert(0, this.sink.FindOrCreateTypeReference(catchClause.ExceptionType, true));
StatementTraverser catchTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
if (catchClause.ExceptionContainer != Dummy.LocalVariable) {
Bpl.Variable catchClauseVariable = this.sink.FindOrCreateLocalVariable(catchClause.ExceptionContainer);
diff --git a/BCT/BytecodeTranslator/TranslationHelper.cs b/BCT/BytecodeTranslator/TranslationHelper.cs
index 98610297..2862a520 100644
--- a/BCT/BytecodeTranslator/TranslationHelper.cs
+++ b/BCT/BytecodeTranslator/TranslationHelper.cs
@@ -126,14 +126,25 @@ namespace BytecodeTranslator {
Contract.Requires(typeReference != null);
var typeDefinition = typeReference.ResolvedType;
- var totalParameters = new List<IGenericTypeParameter>(typeDefinition.GenericParameters);
+ var totalParameters = new List<IGenericTypeParameter>();
+ ConsolidatedGenericParameters(typeDefinition, totalParameters);
+ return totalParameters;
+
+ //var nestedTypeDefinition = typeDefinition as INestedTypeDefinition;
+ //while (nestedTypeDefinition != null) {
+ // var containingType = nestedTypeDefinition.ContainingType.ResolvedType;
+ // totalParameters.AddRange(containingType.GenericParameters);
+ // nestedTypeDefinition = containingType as INestedTypeDefinition;
+ //}
+ //totalParameters.AddRange(typeDefinition.GenericParameters);
+ //return totalParameters;
+ }
+ private static void ConsolidatedGenericParameters(ITypeDefinition typeDefinition, List<IGenericTypeParameter> consolidatedParameters){
var nestedTypeDefinition = typeDefinition as INestedTypeDefinition;
- while (nestedTypeDefinition != null) {
- var containingType = nestedTypeDefinition.ContainingType.ResolvedType;
- totalParameters.AddRange(containingType.GenericParameters);
- nestedTypeDefinition = containingType as INestedTypeDefinition;
+ if (nestedTypeDefinition != null){
+ ConsolidatedGenericParameters(nestedTypeDefinition.ContainingTypeDefinition, consolidatedParameters);
}
- return totalParameters;
+ consolidatedParameters.AddRange(typeDefinition.GenericParameters);
}
public static string CreateUniqueMethodName(IMethodReference method) {
diff --git a/BCT/BytecodeTranslator/WholeProgram.cs b/BCT/BytecodeTranslator/WholeProgram.cs
index e1d2d73a..d9366708 100644
--- a/BCT/BytecodeTranslator/WholeProgram.cs
+++ b/BCT/BytecodeTranslator/WholeProgram.cs
@@ -165,7 +165,7 @@ namespace BytecodeTranslator {
var m = typeMethodPair.Item2;
// guard: is#T($DynamicType(local_variable))
- var typeFunction = this.sink.FindOrDefineType(t);
+ var typeFunction = this.sink.FindOrDefineType(t.ResolvedType);
if (typeFunction == null) {
// BUGBUG!! This just silently skips the branch that would dispatch to t's implementation of the method!
continue;