@@ -638,17 +638,9 @@ private TypeParameterType AddTypeParameterToSymbolTable(
638638 #region LoadTypeChain
639639 /////////////////////////////////////////////////////////////////////////////////
640640
641- private CType LoadSymbolsFromType ( Type originalType )
641+ private CType LoadSymbolsFromType ( Type type )
642642 {
643- List < object > declarationChain = BuildDeclarationChain ( originalType ) ;
644-
645- Type type = originalType ;
646- CType ret = null ;
647- bool bIsByRef = type . IsByRef ;
648- if ( bIsByRef )
649- {
650- type = type . GetElementType ( ) ;
651- }
643+ List < object > declarationChain = BuildDeclarationChain ( type ) ;
652644
653645 NamespaceOrAggregateSymbol current = NamespaceSymbol . Root ;
654646
@@ -657,106 +649,55 @@ private CType LoadSymbolsFromType(Type originalType)
657649 for ( int i = 0 ; i < declarationChain . Count ; i ++ )
658650 {
659651 object o = declarationChain [ i ] ;
660- NamespaceOrAggregateSymbol next ;
661- if ( o is Type )
652+ if ( o is Type t )
662653 {
663- Type t = o as Type ;
664- next = _symbolTable . LookupSym ( GetName ( t ) , current , symbmask_t . MASK_AggregateSymbol ) as AggregateSymbol ;
665-
666- // Make sure we match arity as well when we find an aggregate.
667- if ( next != null )
654+ if ( t . IsNullableType ( ) )
668655 {
669- next = FindSymWithMatchingArity ( next as AggregateSymbol , t ) ;
656+ return _typeManager . GetNullable ( GetCTypeFromType ( t . GetGenericArguments ( ) [ 0 ] ) ) ;
670657 }
671658
672- // In the event that two different types exist that have the same name, they
673- // cannot both have entries in the symbol table with our current architecture.
674- // This can happen in dynamic, since the runtime binder lives across all
675- // call sites in an appdomain, and assemblies can have been loaded at runtime
676- // that have different types with the same name.
677-
678- // In the real compiler, this would have been an error and name lookup would
679- // be ambiguous, but here we never have to lookup names of types for real (only
680- // names of members).
681-
682- // The tactical fix is this: if we encounter this situation, where we have
683- // identically named types that are not the same, then we are going to clear
684- // the entire symbol table and restart this binding. This solution is not
685- // without its own problems, since it is possible to conceive of a single
686- // dynamic binding that needs to simultaneously know about both of the
687- // similarly named types, but we are not going to try to solve that
688- // scenario here.
689-
690- if ( next != null )
691- {
692- Type existingType = ( next as AggregateSymbol ) . AssociatedSystemType ;
693- Type newType = t . IsGenericType ? t . GetGenericTypeDefinition ( ) : t ;
694-
695- // We use "IsEquivalentTo" so that unified local types for NoPIA do
696- // not trigger a reset. There are other mechanisms to make those sorts
697- // of types work in some scenarios.
698- if ( ! existingType . IsEquivalentTo ( newType ) )
699- {
700- throw new ResetBindException ( ) ;
701- }
702- }
659+ AggregateSymbol next = FindSymForType (
660+ _symbolTable . LookupSym ( GetName ( t ) , current , symbmask_t . MASK_AggregateSymbol ) , t ) ;
703661
704662 // If we haven't found this type yet, then add it to our symbol table.
705- if ( next == null || t . IsNullableType ( ) )
663+ if ( next == null )
706664 {
707665 // Note that if we have anything other than an AggregateSymbol,
708666 // we must be at the end of the line - that is, nothing else can
709667 // have children.
710-
711668 CType ctype = ProcessSpecialTypeInChain ( current , t ) ;
712669 if ( ctype != null )
713670 {
714- // If we had an aggregate type, its possible we're not at the end.
715- // This will happen for nullable<T> for instance.
716- if ( ctype is AggregateType cat )
717- {
718- next = cat . GetOwningAggregate ( ) ;
719- }
720- else
721- {
722- ret = ctype ;
723- break ;
724- }
725- }
726- else
727- {
728- // This is a regular class.
729- next = AddAggregateToSymbolTable ( current , t ) ;
671+ Debug . Assert ( ! ( ctype is AggregateType ) ) ;
672+ return ctype ;
730673 }
674+
675+ // This is a regular class.
676+ next = AddAggregateToSymbolTable ( current , t ) ;
731677 }
732678
733679 if ( t == type )
734680 {
735- ret = GetConstructedType ( type , next as AggregateSymbol ) ;
736- break ;
681+ return GetConstructedType ( type , next ) ;
737682 }
683+
684+ current = next ;
738685 }
739- else if ( o is MethodInfo )
686+ else if ( o is MethodInfo m )
740687 {
741688 // We cant be at the end.
742689 Debug . Assert ( i + 1 < declarationChain . Count ) ;
743- ret = ProcessMethodTypeParameter ( o as MethodInfo , declarationChain [ ++ i ] as Type , current as AggregateSymbol ) ;
744- break ;
690+ return ProcessMethodTypeParameter ( m , declarationChain [ ++ i ] as Type , current as AggregateSymbol ) ;
745691 }
746692 else
747693 {
748694 Debug . Assert ( o is string ) ;
749- next = AddNamespaceToSymbolTable ( current , o as string ) ;
695+ current = AddNamespaceToSymbolTable ( current , o as string ) ;
750696 }
751- current = next ;
752697 }
753698
754- Debug . Assert ( ret != null ) ;
755- if ( bIsByRef )
756- {
757- ret = _typeManager . GetParameterModifier ( ret , false ) ;
758- }
759- return ret ;
699+ Debug . Fail ( "Should be unreachable" ) ;
700+ return null ;
760701 }
761702
762703 /////////////////////////////////////////////////////////////////////////////////
@@ -804,18 +745,17 @@ private CType GetConstructedType(Type type, AggregateSymbol agg)
804745
805746 private CType ProcessSpecialTypeInChain ( NamespaceOrAggregateSymbol parent , Type t )
806747 {
807- CType ctype ;
808748 if ( t . IsGenericParameter )
809749 {
810750 AggregateSymbol agg = parent as AggregateSymbol ;
811751 Debug . Assert ( agg != null ) ;
812- ctype = LoadClassTypeParameter ( agg , t ) ;
813- return ctype ;
752+ return LoadClassTypeParameter ( agg , t ) ;
814753 }
815- else if ( t . IsArray )
754+
755+ if ( t . IsArray )
816756 {
817757 // Now we return an array of nesting level corresponding to the rank.
818- ctype = _typeManager . GetArray (
758+ return _typeManager . GetArray (
819759 GetCTypeFromType ( t . GetElementType ( ) ) ,
820760 t . GetArrayRank ( ) ,
821761#if netcoreapp
@@ -824,37 +764,14 @@ private CType ProcessSpecialTypeInChain(NamespaceOrAggregateSymbol parent, Type
824764 t . GetElementType ( ) . MakeArrayType ( ) == t
825765#endif
826766 ) ;
827- return ctype ;
828767 }
829- else if ( t . IsPointer )
768+
769+ if ( t . IsPointer )
830770 {
831771 // Now we return the pointer type that we want.
832- ctype = _typeManager . GetPointer ( GetCTypeFromType ( t . GetElementType ( ) ) ) ;
833- return ctype ;
834- }
835- else if ( t . IsNullableType ( ) )
836- {
837- // Get a nullable type of the underlying type.
838- if ( t . GetGenericArguments ( ) [ 0 ] . DeclaringType == t )
839- {
840- // If the generic argument for nullable is our child, then we're
841- // declaring the initial Nullable<T>.
842- AggregateSymbol agg = _symbolTable . LookupSym (
843- GetName ( t ) , parent , symbmask_t . MASK_AggregateSymbol ) as AggregateSymbol ;
844- if ( agg != null )
845- {
846- agg = FindSymWithMatchingArity ( agg , t ) ;
847- if ( agg != null )
848- {
849- Debug . Assert ( agg . getThisType ( ) . AssociatedSystemType == t ) ;
850- return agg . getThisType ( ) ;
851- }
852- }
853- return AddAggregateToSymbolTable ( parent , t ) . getThisType ( ) ;
854- }
855- ctype = _typeManager . GetNullable ( GetCTypeFromType ( t . GetGenericArguments ( ) [ 0 ] ) ) ;
856- return ctype ;
772+ return _typeManager . GetPointer ( GetCTypeFromType ( t . GetElementType ( ) ) ) ;
857773 }
774+
858775 return null ;
859776 }
860777
@@ -906,40 +823,41 @@ private static List<object> BuildDeclarationChain(Type callingType)
906823 Debug . Assert ( bAdded ) ;
907824 }
908825 }
826+
909827 callChain . Reverse ( ) ;
910828
911829 // Now take out the namespaces and add them to the end of the chain.
912-
913830 if ( callingType . Namespace != null )
914831 {
915- string [ ] namespaces = callingType . Namespace . Split ( '.' ) ;
916- int index = 0 ;
917- foreach ( string s in namespaces )
918- {
919- callChain . Insert ( index ++ , s ) ;
920- }
832+ callChain . InsertRange ( 0 , callingType . Namespace . Split ( '.' ) ) ;
921833 }
922834 return callChain ;
923835 }
924836
925- /////////////////////////////////////////////////////////////////////////////////
837+ // We have an aggregate symbol of the correct parent and full name, but it may have the wrong arity, or, due to
838+ // dynamic loading or creation, two different types can exist that have the same name.
839+
840+ // In the static compiler, this would have been an error and name lookup would be ambiguous, but here we never have
841+ // to lookup names of types for real (only names of members).
926842
927- private AggregateSymbol FindSymWithMatchingArity ( AggregateSymbol aggregateSymbol , Type type )
843+ // For either case, move onto the next symbol in the chain, and check again for appropriate type.
844+ private AggregateSymbol FindSymForType ( Symbol sym , Type t )
928845 {
929- for ( AggregateSymbol agg = aggregateSymbol ;
930- agg != null ;
931- agg = BSYMMGR . LookupNextSym ( agg , agg . Parent , symbmask_t . MASK_AggregateSymbol ) as AggregateSymbol )
846+ while ( sym != null )
932847 {
933- if ( agg . GetTypeVarsAll ( ) . Count == type . GetGenericArguments ( ) . Length )
848+ // We use "IsEquivalentTo" so that unified local types match.
849+ if ( sym is AggregateSymbol agg )
850+ if ( agg . AssociatedSystemType . IsEquivalentTo ( t . IsGenericType ? t . GetGenericTypeDefinition ( ) : t ) )
934851 {
935852 return agg ;
936853 }
854+
855+ sym = sym . nextSameName ;
937856 }
857+
938858 return null ;
939859 }
940860
941- /////////////////////////////////////////////////////////////////////////////////
942-
943861 private NamespaceSymbol AddNamespaceToSymbolTable ( NamespaceOrAggregateSymbol parent , string sz )
944862 {
945863 Name name = GetName ( sz ) ;
@@ -974,10 +892,10 @@ internal CType[] GetCTypeArrayFromTypes(Type[] types)
974892
975893 /////////////////////////////////////////////////////////////////////////////////
976894
977- internal CType GetCTypeFromType ( Type t )
978- {
979- return LoadSymbolsFromType ( t ) ;
980- }
895+ internal CType GetCTypeFromType ( Type type ) => type . IsByRef
896+ ? _typeManager . GetParameterModifier ( LoadSymbolsFromType ( type . GetElementType ( ) ) , false )
897+ : LoadSymbolsFromType ( type ) ;
898+
981899 #endregion
982900
983901 #region Aggregates
0 commit comments