@@ -491,17 +491,47 @@ Type const* FunctionDefinition::type() const
491491 return TypeProvider::function (*this , FunctionType::Kind::Internal);
492492}
493493
494- Type const * FunctionDefinition::typeViaContractName () const
494+ Type const * FunctionDefinition::typeViaContractName (ContractNameAccessKind _accessKind ) const
495495{
496- if ( libraryFunction () )
496+ switch (_accessKind )
497497 {
498- if (isPublic ())
499- return FunctionType (*this ).asExternallyCallableFunction (true );
500- else
501- return TypeProvider::function (*this , FunctionType::Kind::Internal);
498+ case ContractNameAccessKind::Local:
499+ {
500+ solAssert (!libraryFunction (), " Library member cannot be accessed from local/deriving scope" );
501+ solAssert (visibility () > Visibility::Private, " Private non-library member is not visible via contract type name" );
502+
503+ if (!Declaration::isVisibleInContract () || !isImplemented ())
504+ // If is external or has no implementation, it cannot be called using contract type name. In case of accessing
505+ // via contract type name, only declaration is available, to be used in non calling context. I.e. to access
506+ // function selector `C.foo.selector` where foo has external visibility.
507+ return TypeProvider::function (*this , FunctionType::Kind::Declaration);
508+ else
509+ // If call is in local (or deriving) scope, function is visible in contract (non-external) and it has an
510+ // implementation, internal call is used.
511+ return type ();
512+ }
513+ case ContractNameAccessKind::Foreign:
514+ {
515+ solAssert (!libraryFunction (), " Library members can only be accessed via library name." );
516+ solAssert (isVisibleViaContractInstance (), " Externally invisible member accessed via contract name." );
517+ // Foreign contract member function being accessed via contract type name, cannot be called.
518+ return TypeProvider::function (*this , FunctionType::Kind::Declaration);
519+ }
520+ case ContractNameAccessKind::Library:
521+ {
522+ // Private library members can be accessed in context of `using` statement.
523+ solAssert (libraryFunction (), " Non-library members cannot be accessed via library name." );
524+ // In case of library contract, member call kind depends on its visibility.
525+ if (isPublic ())
526+ // When Lib.foo is public or external, an external call (delegate call) is used.
527+ return FunctionType (*this ).asExternallyCallableFunction (true );
528+ else
529+ // For private or internal visibility, internal call is used.
530+ return type ();
531+ }
532+ default :
533+ solAssert (false , " Unimplemented contract member access kind." );
502534 }
503- else
504- return TypeProvider::function (*this , FunctionType::Kind::Declaration);
505535}
506536
507537std::string FunctionDefinition::externalSignature () const
@@ -952,7 +982,7 @@ FunctionType const* UnaryOperation::userDefinedFunctionType() const
952982 FunctionDefinition const * userDefinedFunction = *annotation ().userDefinedFunction ;
953983 return dynamic_cast <FunctionType const *>(
954984 userDefinedFunction->libraryFunction () ?
955- userDefinedFunction->typeViaContractName () :
985+ userDefinedFunction->typeViaContractName (Declaration::ContractNameAccessKind::Library ) :
956986 userDefinedFunction->type ()
957987 );
958988}
@@ -965,7 +995,7 @@ FunctionType const* BinaryOperation::userDefinedFunctionType() const
965995 FunctionDefinition const * userDefinedFunction = *annotation ().userDefinedFunction ;
966996 return dynamic_cast <FunctionType const *>(
967997 userDefinedFunction->libraryFunction () ?
968- userDefinedFunction->typeViaContractName () :
998+ userDefinedFunction->typeViaContractName (Declaration::ContractNameAccessKind::Library ) :
969999 userDefinedFunction->type ()
9701000 );
9711001}
0 commit comments