@@ -453,7 +453,7 @@ private BoundExpression BindDynamicInvocation(
453453 // Ideally the runtime binder would choose between type and value based on the result of the overload resolution.
454454 // We need to pick one or the other here. Dev11 compiler passes the type only if the value can't be accessed.
455455 bool inStaticContext ;
456- bool useType = IsInstance ( typeOrValue . Data . ValueSymbol ) && ! HasThis ( isExplicit : false , inStaticContext : out inStaticContext ) ;
456+ bool useType = IsInstance ( typeOrValue . ValueSymbol ) && ! HasThis ( isExplicit : false , inStaticContext : out inStaticContext ) ;
457457
458458 BoundExpression finalReceiver = ReplaceTypeOrValueReceiver ( typeOrValue , useType , diagnostics ) ;
459459
@@ -772,7 +772,7 @@ private BoundExpression BindMethodGroupInvocation(
772772 methodGroup . Syntax ,
773773 methodGroup . ResultKind ,
774774 [ methodGroup . LookupSymbolOpt ] ,
775- receiverOpt == null ? [ ] : [ receiverOpt ] ,
775+ receiverOpt == null ? [ ] : [ AdjustBadExpressionChild ( receiverOpt ) ] ,
776776 GetNonMethodMemberType ( methodGroup . LookupSymbolOpt ) ) ;
777777 }
778778 }
@@ -1239,7 +1239,14 @@ private BoundCall BindInvocationExpressionContinued(
12391239 // instance methods. Therefore we must detect this scenario here, rather than in
12401240 // overload resolution.
12411241
1242- var receiver = ReplaceTypeOrValueReceiver ( methodGroup . Receiver , ! method . RequiresInstanceReceiver && ! invokedAsExtensionMethod , diagnostics ) ;
1242+ var receiver = ReplaceTypeOrValueReceiver ( methodGroup . Receiver , useType : ! method . RequiresInstanceReceiver && ! invokedAsExtensionMethod , diagnostics ) ;
1243+
1244+ if ( invokedAsExtensionMethod && ( object ) receiver != methodGroup . Receiver )
1245+ {
1246+ // we will have a different receiver if ReplaceTypeOrValueReceiver has unwrapped TypeOrValue
1247+ Debug . Assert ( analyzedArguments . Arguments [ 0 ] == ( object ) methodGroup . Receiver ) ;
1248+ analyzedArguments . Arguments [ 0 ] = receiver ;
1249+ }
12431250
12441251 ImmutableArray < int > argsToParams ;
12451252 this . CheckAndCoerceArguments ( node , methodResult , analyzedArguments , diagnostics , receiver , invokedAsExtensionMethod : invokedAsExtensionMethod , out argsToParams ) ;
@@ -1261,15 +1268,6 @@ private BoundCall BindInvocationExpressionContinued(
12611268 BoundExpression receiverArgument = analyzedArguments . Argument ( 0 ) ;
12621269 ParameterSymbol receiverParameter = method . Parameters . First ( ) ;
12631270
1264- // we will have a different receiver if ReplaceTypeOrValueReceiver has unwrapped TypeOrValue
1265- if ( ( object ) receiver != methodGroup . Receiver )
1266- {
1267- // Because the receiver didn't pass through CoerceArguments, we need to apply an appropriate conversion here.
1268- Debug . Assert ( argsToParams . IsDefault || argsToParams [ 0 ] == 0 ) ;
1269- receiverArgument = CreateConversion ( receiver , methodResult . Result . ConversionForArg ( 0 ) ,
1270- receiverParameter . Type , diagnostics ) ;
1271- }
1272-
12731271 if ( receiverParameter . RefKind == RefKind . Ref )
12741272 {
12751273 // If this was a ref extension method, receiverArgument must be checked for L-value constraints.
@@ -1955,28 +1953,28 @@ private BoundExpression ReplaceTypeOrValueReceiver(BoundExpression receiver, boo
19551953 {
19561954 case BoundKind . TypeOrValueExpression :
19571955 var typeOrValue = ( BoundTypeOrValueExpression ) receiver ;
1956+ var identifier = ( IdentifierNameSyntax ) typeOrValue . Syntax ;
1957+ Debug . Assert ( typeOrValue . Binder == ( object ) this ) ;
1958+
19581959 if ( useType )
19591960 {
1960- diagnostics . AddRange ( typeOrValue . Data . TypeDiagnostics ) ;
1961-
1962- foreach ( Diagnostic d in typeOrValue . Data . ValueDiagnostics . Diagnostics )
1961+ if ( typeOrValue . Binder . GetShadowedPrimaryConstructorParameter ( identifier , typeOrValue . ValueSymbol , invoked : false , membersOpt : null ) is { } shadowedParameter &&
1962+ ! shadowedParameter . Type . Equals ( typeOrValue . Type , TypeCompareKind . AllIgnoreOptions ) ) // If the type and the name match, we would resolve to the same type rather than a value at the end.
19631963 {
1964- // Avoid forcing resolution of lazy diagnostics to avoid cycles.
1965- var code = d is DiagnosticWithInfo { HasLazyInfo : true , LazyInfo . Code : var lazyCode } ? lazyCode : d . Code ;
1966- if ( code == ( int ) ErrorCode . WRN_PrimaryConstructorParameterIsShadowedAndNotPassedToBase &&
1967- ! ( d . Arguments is [ ParameterSymbol shadowedParameter ] && shadowedParameter . Type . Equals ( typeOrValue . Data . ValueExpression . Type , TypeCompareKind . AllIgnoreOptions ) ) ) // If the type and the name match, we would resolve to the same type rather than a value at the end.
1968- {
1969- Debug . Assert ( d is not DiagnosticWithInfo { HasLazyInfo : true } , "Adjust the Arguments access to handle lazy diagnostics to avoid cycles." ) ;
1970- diagnostics . Add ( d ) ;
1971- }
1964+ diagnostics . Add ( ErrorCode . WRN_PrimaryConstructorParameterIsShadowedAndNotPassedToBase , identifier . Location , shadowedParameter ) ;
19721965 }
19731966
1974- return typeOrValue . Data . TypeExpression ;
1967+ return typeOrValue . Binder . BindNamespaceOrType ( identifier , diagnostics ) ;
19751968 }
19761969 else
19771970 {
1978- diagnostics . AddRange ( typeOrValue . Data . ValueDiagnostics ) ;
1979- return CheckValue ( typeOrValue . Data . ValueExpression , BindValueKind . RValue , diagnostics ) ;
1971+ var boundValue = typeOrValue . Binder . BindIdentifier ( identifier , invoked : false , indexed : false , diagnostics : diagnostics ) ;
1972+
1973+ Debug . Assert ( typeOrValue . Type . Equals ( boundValue . Type , TypeCompareKind . ConsiderEverything ) ) ;
1974+ Debug . Assert ( typeOrValue . ValueSymbol == ( boundValue . ExpressionSymbol ?? ( ( BoundConversion ) boundValue ) . Operand . ExpressionSymbol ) ) ;
1975+
1976+ boundValue = BindToNaturalType ( boundValue , diagnostics ) ;
1977+ return CheckValue ( boundValue , BindValueKind . RValue , diagnostics ) ;
19801978 }
19811979
19821980 case BoundKind . QueryClause :
@@ -1991,7 +1989,7 @@ private BoundExpression ReplaceTypeOrValueReceiver(BoundExpression receiver, boo
19911989 }
19921990 }
19931991
1994- private static BoundExpression GetValueExpressionIfTypeOrValueReceiver ( BoundExpression receiver )
1992+ private static Symbol GetValueSymbolIfTypeOrValueReceiver ( BoundExpression receiver )
19951993 {
19961994 if ( ( object ) receiver == null )
19971995 {
@@ -2001,11 +1999,11 @@ private static BoundExpression GetValueExpressionIfTypeOrValueReceiver(BoundExpr
20011999 switch ( receiver )
20022000 {
20032001 case BoundTypeOrValueExpression typeOrValueExpression :
2004- return typeOrValueExpression . Data . ValueExpression ;
2002+ return typeOrValueExpression . ValueSymbol ;
20052003
20062004 case BoundQueryClause queryClause :
20072005 // a query clause may wrap a TypeOrValueExpression.
2008- return GetValueExpressionIfTypeOrValueReceiver ( queryClause . Value ) ;
2006+ return GetValueSymbolIfTypeOrValueReceiver ( queryClause . Value ) ;
20092007
20102008 default :
20112009 return null ;
@@ -2385,6 +2383,17 @@ private BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax no
23852383 EnsureNameofExpressionSymbols ( methodGroup , diagnostics ) ;
23862384 }
23872385 }
2386+
2387+ boundArgument = methodGroup . Update (
2388+ methodGroup . TypeArgumentsOpt ,
2389+ methodGroup . Name ,
2390+ methodGroup . Methods ,
2391+ methodGroup . LookupSymbolOpt ,
2392+ methodGroup . LookupError ,
2393+ methodGroup . Flags ,
2394+ methodGroup . FunctionType ,
2395+ receiverOpt : ReplaceTypeOrValueReceiver ( methodGroup . ReceiverOpt , useType : false , BindingDiagnosticBag . Discarded ) , //only change
2396+ methodGroup . ResultKind ) ;
23882397 }
23892398 else if ( boundArgument is BoundPropertyAccess propertyAccess )
23902399 {
0 commit comments