@@ -2498,4 +2498,76 @@ public void AssigningListToArrayTypeIsIllegal()
24982498 Assert . Equal ( 2 , diags . Length ) ;
24992499 AssertDiagnostics ( diags , TypeCheckingErrors . InferenceIncomplete , TypeCheckingErrors . TypeMismatch ) ;
25002500 }
2501+
2502+ [ Fact ]
2503+ public void OrderIndependenceInTypeInference ( )
2504+ {
2505+ // Bug https://github.com/Draco-lang/Compiler/issues/515
2506+
2507+ // Working code:
2508+ // import System;
2509+ // import System.Collections.Generic;
2510+ //
2511+ // func main() {
2512+ // val l = List();
2513+ // l.Add(ArgumentException());
2514+ // l.Add(Exception());
2515+ // l.Add(InvalidOperationException());
2516+ // }
2517+ var workingSyntax = SyntaxTree . Create ( CompilationUnit (
2518+ ImportDeclaration ( "System" ) ,
2519+ ImportDeclaration ( "System" , "Collections" , "Generic" ) ,
2520+ FunctionDeclaration (
2521+ "main" ,
2522+ ParameterList ( ) ,
2523+ null ,
2524+ BlockFunctionBody (
2525+ DeclarationStatement ( ValDeclaration ( "l" , null , CallExpression ( NameExpression ( "List" ) ) ) ) ,
2526+ ExpressionStatement ( CallExpression ( MemberExpression ( NameExpression ( "l" ) , "Add" ) , CallExpression ( NameExpression ( "ArgumentException" ) ) ) ) ,
2527+ ExpressionStatement ( CallExpression ( MemberExpression ( NameExpression ( "l" ) , "Add" ) , CallExpression ( NameExpression ( "Exception" ) ) ) ) ,
2528+ ExpressionStatement ( CallExpression ( MemberExpression ( NameExpression ( "l" ) , "Add" ) , CallExpression ( NameExpression ( "InvalidOperationException" ) ) ) ) ) ) ) ) ;
2529+
2530+ // Flipped code:
2531+ // import System;
2532+ // import System.Collections.Generic;
2533+ //
2534+ // func main() {
2535+ // val l = List();
2536+ // l.Add(ArgumentException());
2537+ // l.Add(InvalidOperationException());
2538+ // l.Add(Exception());
2539+ // }
2540+ var flippedSyntax = SyntaxTree . Create ( CompilationUnit (
2541+ ImportDeclaration ( "System" ) ,
2542+ ImportDeclaration ( "System" , "Collections" , "Generic" ) ,
2543+ FunctionDeclaration (
2544+ "main" ,
2545+ ParameterList ( ) ,
2546+ null ,
2547+ BlockFunctionBody (
2548+ DeclarationStatement ( ValDeclaration ( "l" , null , CallExpression ( NameExpression ( "List" ) ) ) ) ,
2549+ ExpressionStatement ( CallExpression ( MemberExpression ( NameExpression ( "l" ) , "Add" ) , CallExpression ( NameExpression ( "ArgumentException" ) ) ) ) ,
2550+ ExpressionStatement ( CallExpression ( MemberExpression ( NameExpression ( "l" ) , "Add" ) , CallExpression ( NameExpression ( "InvalidOperationException" ) ) ) ) ,
2551+ ExpressionStatement ( CallExpression ( MemberExpression ( NameExpression ( "l" ) , "Add" ) , CallExpression ( NameExpression ( "Exception" ) ) ) ) ) ) ) ) ;
2552+
2553+ // Act
2554+ var workingCompilation = CreateCompilation ( workingSyntax ) ;
2555+ var workingSemanticModel = workingCompilation . GetSemanticModel ( workingSyntax ) ;
2556+ var workingDiags = workingSemanticModel . Diagnostics ;
2557+ var workingListVariable = GetInternalSymbol < LocalSymbol > ( workingSemanticModel . GetDeclaredSymbol ( workingSyntax . GetNode < VariableDeclarationSyntax > ( ) ) ) ;
2558+
2559+ var flippedCompilation = CreateCompilation ( flippedSyntax ) ;
2560+ var flippedSemanticModel = flippedCompilation . GetSemanticModel ( flippedSyntax ) ;
2561+ var flippedDiags = flippedSemanticModel . Diagnostics ;
2562+ var flippedListVariable = GetInternalSymbol < LocalSymbol > ( flippedSemanticModel . GetDeclaredSymbol ( flippedSyntax . GetNode < VariableDeclarationSyntax > ( ) ) ) ;
2563+
2564+ // Assert
2565+ Assert . Empty ( workingDiags ) ;
2566+ Assert . Empty ( flippedDiags ) ;
2567+
2568+ // NOTE: This is a janky way to compare the types, but currently SymbolEqualityComparer
2569+ // can't compare types between different compilation instances
2570+ Assert . Equal ( "List<Exception>" , workingListVariable . Type . ToString ( ) ) ;
2571+ Assert . Equal ( "List<Exception>" , flippedListVariable . Type . ToString ( ) ) ;
2572+ }
25012573}
0 commit comments