edit: $/Dev10/feature/vs_langs01/Merlin/External.LCA_RESTRICTED/Languages/IronRuby/yaml/IronRuby.Libraries.Yaml/RubyRepresenter.cs;C840659
File: RubyRepresenter.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/External.LCA_RESTRICTED/Languages/IronRuby/yaml/IronRuby.Libraries.Yaml/RubyRepresenter.cs;C840659  (server)    7/21/2009 6:03 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/External.LCA_RESTRICTED/Languages/IronRuby/yaml/IronRuby.Libraries.Yaml/RubyRepresenter.cs;InteropVisibility
@@ -43,7 +43,7 @@
         public RubyRepresenter(RubyContext/*!*/ context, Serializer/*!*/ serializer, YamlOptions/*!*/ opts)
             : base(serializer, opts) {
             _context = context;
-            _objectToYamlMethod = context.GetClass(typeof(object)).ResolveMethod("to_yaml", RubyClass.IgnoreVisibility).Info;
+            _objectToYamlMethod = context.GetClass(typeof(object)).ResolveMethod("to_yaml", VisibilityContext.AllVisible).Info;
 
              _TagUri =
                 CallSite<Func<CallSite, object, object>>.Create(
@@ -88,7 +88,7 @@
         #endregion
 
         protected override Node CreateNode(object data) {
-            RubyMemberInfo method = _context.GetImmediateClassOf(data).ResolveMethodForSite("to_yaml", RubyClass.IgnoreVisibility).Info;
+            RubyMemberInfo method = _context.GetImmediateClassOf(data).ResolveMethodForSite("to_yaml", VisibilityContext.AllVisible).Info;
 
             if (method == _objectToYamlMethod) {
                 return (Node)_ToYamlNode.Target(_ToYamlNode, data, this);
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C1009004
File: RubyTests.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C1009004  (server)    7/21/2009 6:22 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;InteropVisibility
@@ -621,6 +621,7 @@
                 Dlr_Comparable,
                 Dlr_RubyObjects,
                 Dlr_Methods,
+                Dlr_Visibility,
                 Dlr_Languages,
             };
         }
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/DlrInteropTests.cs;C949767
File: DlrInteropTests.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/DlrInteropTests.cs;C949767  (server)    7/21/2009 4:59 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/DlrInteropTests.cs;InteropVisibility
@@ -787,6 +787,42 @@
             //assert_equal Methods.with_block {|x| x + 1000}, 1100
         }
 
+        public void Dlr_Visibility() {
+            Engine.Execute(@"
+class C
+  def public_m
+    0
+  end
+
+  private
+  def private_m
+    1
+  end
+
+  protected
+  def protected_m
+    2
+  end
+end
+");
+            var classC = Runtime.Globals.GetVariable("C");
+            var c = Engine.Operations.CreateInstance(classC);
+
+            AssertExceptionThrown<MissingMethodException>(() => MyInvokeMemberBinder.Invoke(c, "private_m"));
+            AssertExceptionThrown<MissingMethodException>(() => MyInvokeMemberBinder.Invoke(c, "protected_m"));
+            var r1 = MyInvokeMemberBinder.Invoke(c, "public_m");
+            Assert(r1 is int && (int)r1 == 0);
+
+            Engine.Execute(@"
+class C
+  def method_missing name
+    3
+  end
+end");
+            var r2 = MyInvokeMemberBinder.Invoke(c, "private_m");
+            Assert(r2 is int && (int)r2 == 3);
+        }
+
         public void Dlr_Languages() {
             //# Pass in ref/out params
             //# Named arguments
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs;C1009004
File: KernelOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs;C1009004  (server)    7/21/2009 5:44 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/KernelOps.cs;InteropVisibility
@@ -1535,7 +1535,7 @@
         // thread-safe:
         [RubyMethod("method")]
         public static RubyMethod/*!*/ GetMethod(RubyContext/*!*/ context, object self, [DefaultProtocol, NotNull]string/*!*/ name) {
-            RubyMemberInfo info = context.ResolveMethod(self, name, RubyClass.IgnoreVisibility).Info;
+            RubyMemberInfo info = context.ResolveMethod(self, name, VisibilityContext.AllVisible).Info;
             if (info == null) {
                 throw RubyExceptions.CreateUndefinedMethodError(context.GetClassOf(self), name);
             }
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/Marshal.cs;C977140
File: Marshal.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/Marshal.cs;C977140  (server)    7/21/2009 5:43 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/Marshal.cs;InteropVisibility
@@ -25,6 +25,7 @@
 using Microsoft.Scripting.Runtime;
 using Microsoft.Scripting.Utils;
 using Microsoft.Scripting.Generation;
+using IronRuby.Runtime.Calls;
 
 namespace IronRuby.Builtins {
 
@@ -384,8 +385,8 @@
 
                         // TODO: replace with a table-driven implementation
                         // TODO: visibility?
-                        bool implementsDump = _context.ResolveMethod(obj, "_dump", RubyClass.IgnoreVisibility).Found;
-                        bool implementsMarshalDump = _context.ResolveMethod(obj, "marshal_dump", RubyClass.IgnoreVisibility).Found;
+                        bool implementsDump = _context.ResolveMethod(obj, "_dump", VisibilityContext.AllVisible).Found;
+                        bool implementsMarshalDump = _context.ResolveMethod(obj, "marshal_dump", VisibilityContext.AllVisible).Found;
 
                         bool writeInstanceData = false;
                         string[] instanceNames = null;
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ModuleOps.cs;C1009004
File: ModuleOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ModuleOps.cs;C1009004  (server)    7/21/2009 5:42 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/ModuleOps.cs;InteropVisibility
@@ -266,7 +266,7 @@
                         options |= MethodLookup.ReturnForwarder;
                     }
 
-                    method = module.ResolveMethodNoLock(methodName, RubyClass.IgnoreVisibility, options).Info;
+                    method = module.ResolveMethodNoLock(methodName, VisibilityContext.AllVisible, options).Info;
                     if (method == null) {
                         throw RubyExceptions.CreateNameError(RubyExceptions.FormatMethodMissingMessage(context, module, methodName));
                     }
@@ -536,7 +536,7 @@
         // thread-safe:
         [RubyMethod("undef_method", RubyMethodAttributes.PrivateInstance)]
         public static RubyModule/*!*/ UndefineMethod(RubyModule/*!*/ self, [DefaultProtocol, NotNull]string/*!*/ methodName) {
-            if (!self.ResolveMethod(methodName, RubyClass.IgnoreVisibility).Found) {
+            if (!self.ResolveMethod(methodName, VisibilityContext.AllVisible).Found) {
                 throw RubyExceptions.CreateUndefinedMethodError(self, methodName);
             }
             self.UndefineMethod(methodName);
@@ -890,28 +890,28 @@
         // thread-safe:
         [RubyMethod("method_defined?")]
         public static bool MethodDefined(RubyModule/*!*/ self, [DefaultProtocol, NotNull]string/*!*/ methodName) {
-            RubyMemberInfo method = self.ResolveMethod(methodName, RubyClass.IgnoreVisibility).Info;
+            RubyMemberInfo method = self.ResolveMethod(methodName, VisibilityContext.AllVisible).Info;
             return method != null && method.Visibility != RubyMethodVisibility.Private;
         }
 
         // thread-safe:
         [RubyMethod("private_method_defined?")]
         public static bool PrivateMethodDefined(RubyModule/*!*/ self, [DefaultProtocol, NotNull]string/*!*/ methodName) {
-            RubyMemberInfo method = self.ResolveMethod(methodName, RubyClass.IgnoreVisibility).Info;
+            RubyMemberInfo method = self.ResolveMethod(methodName, VisibilityContext.AllVisible).Info;
             return method != null && method.Visibility == RubyMethodVisibility.Private;
         }
 
         // thread-safe:
         [RubyMethod("protected_method_defined?")]
         public static bool ProtectedMethodDefined(RubyModule/*!*/ self, [DefaultProtocol, NotNull]string/*!*/ methodName) {
-            RubyMemberInfo method = self.ResolveMethod(methodName, RubyClass.IgnoreVisibility).Info;
+            RubyMemberInfo method = self.ResolveMethod(methodName, VisibilityContext.AllVisible).Info;
             return method != null && method.Visibility == RubyMethodVisibility.Protected;
         }
 
         // thread-safe:
         [RubyMethod("public_method_defined?")]
         public static bool PublicMethodDefined(RubyModule/*!*/ self, [DefaultProtocol, NotNull]string/*!*/ methodName) {
-            RubyMemberInfo method = self.ResolveMethod(methodName, RubyClass.IgnoreVisibility).Info;
+            RubyMemberInfo method = self.ResolveMethod(methodName, VisibilityContext.AllVisible).Info;
             return method != null && method.Visibility == RubyMethodVisibility.Public;
         }
 
@@ -922,7 +922,7 @@
         // thread-safe:
         [RubyMethod("instance_method")]
         public static UnboundMethod/*!*/ GetInstanceMethod(RubyModule/*!*/ self, [DefaultProtocol, NotNull]string/*!*/ methodName) {
-            RubyMemberInfo method = self.ResolveMethod(methodName, RubyClass.IgnoreVisibility).Info;
+            RubyMemberInfo method = self.ResolveMethod(methodName, VisibilityContext.AllVisible).Info;
             if (method == null) {
                 throw RubyExceptions.CreateUndefinedMethodError(self, methodName);
             }
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Ruby.csproj;C1005406
File: Ruby.csproj
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Ruby.csproj;C1005406  (server)    7/21/2009 5:22 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Ruby.csproj;InteropVisibility
@@ -2,7 +2,7 @@
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>9.0.21022</ProductVersion>
+    <ProductVersion>9.0.30729</ProductVersion>
     <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{7F6984B4-EE6D-4E6F-ABB1-E210D7DC4FDD}</ProjectGuid>
     <OutputType>Library</OutputType>
@@ -192,6 +192,7 @@
     <Compile Include="Runtime\Calls\RubyOverloadResolver.cs" />
     <Compile Include="Runtime\Calls\SuperForwarderInfo.cs" />
     <Compile Include="Runtime\Calls\VersionHandle.cs" />
+    <Compile Include="Runtime\Calls\VisibilityContext.cs" />
     <Compile Include="Runtime\CheckedMonitor.cs" />
     <Compile Include="Runtime\ClrName.cs" />
     <Compile Include="Runtime\CustomTypeDescHelpers.cs" />
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Ruby.csproj.vspscc;C390406
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyClass.cs;C955994
File: RubyClass.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyClass.cs;C955994  (server)    7/21/2009 5:28 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyClass.cs;InteropVisibility
@@ -35,11 +35,6 @@
 
 namespace IronRuby.Builtins {
     public sealed partial class RubyClass : RubyModule, IDuplicable {
-        /// <summary>
-        /// Visibility context within which all methods are visible.
-        /// </summary>
-        public const RubyClass IgnoreVisibility = null;
-
         public const string/*!*/ ClassSingletonName = "__ClassSingleton";
         public const string/*!*/ ClassSingletonSingletonName = "__ClassSingletonSingleton";
         public const string/*!*/ MainSingletonName = "__MainSingleton";
@@ -641,7 +636,7 @@
 
         internal RubyMemberInfo ResolveMethodMissingForSite(string/*!*/ name, RubyMethodVisibility incompatibleVisibility) {
             Context.RequiresClassHierarchyLock();
-            var methodMissing = ResolveMethodForSiteNoLock(Symbols.MethodMissing, null);
+            var methodMissing = ResolveMethodForSiteNoLock(Symbols.MethodMissing, VisibilityContext.AllVisible);
             if (incompatibleVisibility == RubyMethodVisibility.None) {
                 methodMissing.InvalidateSitesOnMissingMethodAddition(name, Context);
             }
@@ -1208,7 +1203,7 @@
                 // check version of the class so that we invalidate the rule whenever the initializer changes:
                 metaBuilder.AddVersionTest(this);
 
-                initializer = ResolveMethodForSiteNoLock(Symbols.Initialize, IgnoreVisibility).Info;
+                initializer = ResolveMethodForSiteNoLock(Symbols.Initialize, VisibilityContext.AllVisible).Info;
 
                 // Initializer resolves to Object#initializer unless overridden in a derived class.
                 // We ensure that this method cannot be removed.
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyModule.cs;C1009004
File: RubyModule.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyModule.cs;C1009004  (server)    7/21/2009 5:26 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyModule.cs;InteropVisibility
@@ -1215,7 +1215,7 @@
             RubyMemberInfo method;
             using (Context.ClassHierarchyLocker()) {
                 // MRI: aliases a super-forwarder not the real method.
-                method = ResolveMethodNoLock(oldName, RubyClass.IgnoreVisibility, MethodLookup.FallbackToObject | MethodLookup.ReturnForwarder).Info;
+                method = ResolveMethodNoLock(oldName, VisibilityContext.AllVisible, MethodLookup.FallbackToObject | MethodLookup.ReturnForwarder).Info;
                 if (method == null) {
                     throw RubyExceptions.CreateUndefinedMethodError(this, oldName);
                 }
@@ -1496,32 +1496,32 @@
         }
 
         // thread-safe:
-        public MethodResolutionResult ResolveMethodForSite(string/*!*/ name, RubyClass visibilityContext) {
+        public MethodResolutionResult ResolveMethodForSite(string/*!*/ name, VisibilityContext visibility) {
             using (Context.ClassHierarchyLocker()) {
-                return ResolveMethodForSiteNoLock(name, visibilityContext);
+                return ResolveMethodForSiteNoLock(name, visibility);
             }
         }
 
         // thread-safe:
-        public MethodResolutionResult ResolveMethod(string/*!*/ name, RubyClass visibilityContext) {
+        public MethodResolutionResult ResolveMethod(string/*!*/ name, VisibilityContext visibility) {
             using (Context.ClassHierarchyLocker()) {
-                return ResolveMethodNoLock(name, visibilityContext);
+                return ResolveMethodNoLock(name, visibility);
             }
         }
 
-        public MethodResolutionResult ResolveMethodForSiteNoLock(string/*!*/ name, RubyClass visibilityContext) {
-            return ResolveMethodForSiteNoLock(name, visibilityContext, MethodLookup.Default);
+        public MethodResolutionResult ResolveMethodForSiteNoLock(string/*!*/ name, VisibilityContext visibility) {
+            return ResolveMethodForSiteNoLock(name, visibility, MethodLookup.Default);
         }
 
-        internal MethodResolutionResult ResolveMethodForSiteNoLock(string/*!*/ name, RubyClass visibilityContext, MethodLookup options) {
-            return ResolveMethodNoLock(name, visibilityContext, options).InvalidateSitesOnOverride();
+        internal MethodResolutionResult ResolveMethodForSiteNoLock(string/*!*/ name, VisibilityContext visibility, MethodLookup options) {
+            return ResolveMethodNoLock(name, visibility, options).InvalidateSitesOnOverride();
         }
 
-        public MethodResolutionResult ResolveMethodNoLock(string/*!*/ name, RubyClass visibilityContext) {
-            return ResolveMethodNoLock(name, visibilityContext, MethodLookup.Default);
+        public MethodResolutionResult ResolveMethodNoLock(string/*!*/ name, VisibilityContext visibility) {
+            return ResolveMethodNoLock(name, visibility, MethodLookup.Default);
         }
 
-        public MethodResolutionResult ResolveMethodNoLock(string/*!*/ name, RubyClass visibilityContext, MethodLookup options) {
+        public MethodResolutionResult ResolveMethodNoLock(string/*!*/ name, VisibilityContext visibility, MethodLookup options) {
             Context.RequiresClassHierarchyLock();
             Assert.NotNull(name);
 
@@ -1534,12 +1534,12 @@
 
             if (ForEachAncestor((module) => {
                 owner = module;
-                foundCallerSelf |= module == visibilityContext;
+                foundCallerSelf |= module == visibility.Class;
                 return module.TryGetMethod(name, ref skipHidden, (options & MethodLookup.Virtual) != 0, out info);
             })) {
                 if (info == null || info.IsUndefined) {
                     result = MethodResolutionResult.NotFound;
-                } else if (!IsMethodVisible(info, owner, visibilityContext, foundCallerSelf)) {
+                } else if (!IsMethodVisible(info, owner, visibility, foundCallerSelf)) {
                     result = new MethodResolutionResult(info, owner, false);
                 } else if (info.IsSuperForwarder) {
                     if ((options & MethodLookup.ReturnForwarder) != 0) {
@@ -1557,16 +1557,18 @@
 
             // Note: all classes include Object in ancestors, so we don't need to search it again:
             if (!result.Found && (options & MethodLookup.FallbackToObject) != 0 && !IsClass) {
-                return _context.ObjectClass.ResolveMethodNoLock(name, visibilityContext, options & ~MethodLookup.FallbackToObject);
+                return _context.ObjectClass.ResolveMethodNoLock(name, visibility, options & ~MethodLookup.FallbackToObject);
             }
 
             return result;
         }
 
-        private bool IsMethodVisible(RubyMemberInfo/*!*/ method, RubyModule/*!*/ owner, RubyClass visibilityContext, bool foundCallerSelf) {
-            // call with implicit self => all methods are visible
-            if (visibilityContext == RubyClass.IgnoreVisibility) {
-                return true;
+        private bool IsMethodVisible(RubyMemberInfo/*!*/ method, RubyModule/*!*/ owner, VisibilityContext visibility, bool foundCallerSelf) {
+            // Visibility not constrained by a class:
+            // - call with implicit self => all methods are visible.
+            // - interop call => only public methods are visible.
+            if (visibility.Class == null) {
+                return visibility.IsVisible(method.Visibility);
             } 
             
             if (method.Visibility == RubyMethodVisibility.Protected) {
@@ -1576,7 +1578,7 @@
                 }
                 // walk ancestors from caller's self class (visibilityContext)
                 // until the method owner is found or this module is found (this module is a descendant of the owner):
-                return visibilityContext.ForEachAncestor((module) => module == owner || module == this);
+                return visibility.Class.ForEachAncestor((module) => module == owner || module == this);
             } 
 
             return method.Visibility == RubyMethodVisibility.Public;
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyContext.cs;C1006896
File: RubyContext.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyContext.cs;C1006896  (server)    7/21/2009 5:19 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyContext.cs;InteropVisibility
@@ -1237,12 +1237,12 @@
         // thread-safe:
         public MethodResolutionResult ResolveMethod(object target, string/*!*/ name, bool includePrivate) {
             var owner = GetImmediateClassOf(target);
-            return owner.ResolveMethod(name, includePrivate ? RubyClass.IgnoreVisibility : owner);
+            return owner.ResolveMethod(name, includePrivate ? VisibilityContext.AllVisible : new VisibilityContext(owner));
         }
 
         // thread-safe:
-        public MethodResolutionResult ResolveMethod(object target, string/*!*/ name, RubyClass visibilityContext) {
-            return GetImmediateClassOf(target).ResolveMethod(name, visibilityContext);
+        public MethodResolutionResult ResolveMethod(object target, string/*!*/ name, VisibilityContext visibility) {
+            return GetImmediateClassOf(target).ResolveMethod(name, visibility);
         }
 
         // thread-safe:
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;C999418
File: RubyOps.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;C999418  (server)    7/21/2009 5:31 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/RubyOps.cs;InteropVisibility
@@ -553,7 +553,7 @@
         public static void UndefineMethod(RubyScope/*!*/ scope, string/*!*/ name) {
             RubyModule owner = scope.GetInnerMostModuleForMethodLookup();
 
-            if (!owner.ResolveMethod(name, RubyClass.IgnoreVisibility).Found) {
+            if (!owner.ResolveMethod(name, VisibilityContext.AllVisible).Found) {
                 throw RubyExceptions.CreateUndefinedMethodError(owner, name);
             }
             owner.UndefineMethod(name);
@@ -563,7 +563,7 @@
         public static bool IsDefinedMethod(object self, RubyScope/*!*/ scope, string/*!*/ name) {
             // MRI: this is different from UndefineMethod, it behaves like Kernel#method (i.e. doesn't use lexical scope):
             // TODO: visibility
-            return scope.RubyContext.ResolveMethod(self, name, RubyClass.IgnoreVisibility).Found;
+            return scope.RubyContext.ResolveMethod(self, name, VisibilityContext.AllVisible).Found;
         }
 
         #endregion
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/ConvertToSAction.cs;C940713
File: ConvertToSAction.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/ConvertToSAction.cs;C940713  (server)    7/21/2009 5:29 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/ConvertToSAction.cs;InteropVisibility
@@ -78,7 +78,7 @@
                     new[] { ToS, Symbols.MethodMissing }
                 );
 
-                conversionMethod = targetClass.ResolveMethodForSiteNoLock(ToS, RubyClass.IgnoreVisibility).Info;
+                conversionMethod = targetClass.ResolveMethodForSiteNoLock(ToS, VisibilityContext.AllVisible).Info;
 
                 // find method_missing - we need to add "to_xxx" methods to the missing methods table:
                 if (conversionMethod == null) {
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/InteropBinder.cs;C942557
File: InteropBinder.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/InteropBinder.cs;C942557  (server)    7/21/2009 5:57 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/InteropBinder.cs;InteropVisibility
@@ -248,7 +248,7 @@
                 Func<DynamicMetaObject, DynamicMetaObject[], DynamicMetaObject>/*!*/ fallback) {
                 Debug.Assert(fallback != null);
 
-                var callArgs = new CallArguments(context, target, args, RubyCallSignature.WithImplicitSelf(callInfo.ArgumentCount));
+                var callArgs = new CallArguments(context, target, args, RubyCallSignature.Interop(callInfo.ArgumentCount));
                 var metaBuilder = new MetaObjectBuilder(target, args);
 
                 if (!RubyCallAction.BuildCall(metaBuilder, methodName, callArgs, false, false)) {
@@ -301,7 +301,7 @@
                 Func<DynamicMetaObject, DynamicMetaObject>/*!*/ fallback) {
                 Debug.Assert(fallback != null);
 
-                var callArgs = new CallArguments(context, target, DynamicMetaObject.EmptyMetaObjects, RubyCallSignature.WithImplicitSelf(0));
+                var callArgs = new CallArguments(context, target, DynamicMetaObject.EmptyMetaObjects, RubyCallSignature.Interop(0));
                 var metaBuilder = new MetaObjectBuilder(target);
 
                 if (!RubyCallAction.BuildAccess(metaBuilder, binder.Name, callArgs, false, false)) {
@@ -357,7 +357,7 @@
                 Debug.Assert(fallback != null);
 
                 var args = new[] { value };
-                var callArgs = new CallArguments(context, target, args, RubyCallSignature.WithImplicitSelf(1));
+                var callArgs = new CallArguments(context, target, args, RubyCallSignature.Interop(1));
                 var metaBuilder = new MetaObjectBuilder(target, args);
 
                 if (!RubyCallAction.BuildCall(metaBuilder, binder.Name + "=", callArgs, false, false)) {
@@ -414,7 +414,7 @@
                 Func<DynamicMetaObject, DynamicMetaObject[], DynamicMetaObject>/*!*/ fallback) {
                 Debug.Assert(fallback != null);
                 
-                var callArgs = new CallArguments(context, target, indexes, RubyCallSignature.WithImplicitSelf(indexes.Length));
+                var callArgs = new CallArguments(context, target, indexes, RubyCallSignature.Interop(indexes.Length));
                 var metaBuilder = new MetaObjectBuilder(target, indexes);
 
                 if (!RubyCallAction.BuildCall(metaBuilder, "[]", callArgs, false, false)) {
@@ -472,7 +472,7 @@
 
                 var args = ArrayUtils.Append(indexes, value);
                 var callArgs = new CallArguments(context, target, args,
-                    new RubyCallSignature(indexes.Length, RubyCallFlags.HasImplicitSelf | RubyCallFlags.HasRhsArgument)
+                    new RubyCallSignature(indexes.Length, RubyCallFlags.IsInteropCall | RubyCallFlags.HasRhsArgument)
                 );
 
                 var metaBuilder = new MetaObjectBuilder(target, args);
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/ProtocolConversionAction.cs;C953692
File: ProtocolConversionAction.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/ProtocolConversionAction.cs;C953692  (server)    7/21/2009 5:29 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/ProtocolConversionAction.cs;InteropVisibility
@@ -193,20 +193,20 @@
                 );
 
                 // we can optimize if Kernel#respond_to? method is not overridden:
-                respondToMethod = targetClass.ResolveMethodForSiteNoLock(Symbols.RespondTo, RubyClass.IgnoreVisibility);
+                respondToMethod = targetClass.ResolveMethodForSiteNoLock(Symbols.RespondTo, VisibilityContext.AllVisible);
                 if (respondToMethod.Found && respondToMethod.Info.DeclaringModule == targetClass.Context.KernelModule && respondToMethod.Info is RubyLibraryMethodInfo) { // TODO: better override detection
                     respondToMethod = MethodResolutionResult.NotFound;
 
                     // get the first applicable conversion:
                     foreach (var conversion in conversions) {
                         selectedConversion = conversion;
-                        conversionMethod = targetClass.ResolveMethodForSiteNoLock(conversion.ToMethodName, RubyClass.IgnoreVisibility).Info;
+                        conversionMethod = targetClass.ResolveMethodForSiteNoLock(conversion.ToMethodName, VisibilityContext.AllVisible).Info;
                         if (conversionMethod != null) {
                             break;
                         } else {
                             // find method_missing - we need to add "to_xxx" methods to the missing methods table:
                             if (!methodMissing.Found) {
-                                methodMissing = targetClass.ResolveMethodNoLock(Symbols.MethodMissing, RubyClass.IgnoreVisibility);
+                                methodMissing = targetClass.ResolveMethodNoLock(Symbols.MethodMissing, VisibilityContext.AllVisible);
                             }
                             methodMissing.InvalidateSitesOnMissingMethodAddition(conversion.ToMethodName, targetClass.Context);
                         }
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyCallAction.cs;C953692
File: RubyCallAction.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyCallAction.cs;C953692  (server)    7/21/2009 5:13 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyCallAction.cs;InteropVisibility
@@ -187,23 +187,25 @@
             }
         }
 
-        private static RubyClass GetVisibilityContext(RubyCallSignature callSignature, RubyScope scope) {
-            // TODO: All sites should have either implicit-self or has-scope flag set?
-            return callSignature.HasImplicitSelf || !callSignature.HasScope ? RubyClass.IgnoreVisibility : scope.SelfImmediateClass;
+        private static VisibilityContext GetVisibilityContext(RubyCallSignature callSignature, RubyScope scope) {
+            return callSignature.HasImplicitSelf || !callSignature.HasScope ? 
+                new VisibilityContext(callSignature.IsInteropCall ? RubyMethodAttributes.Public : RubyMethodAttributes.VisibilityMask) :
+                new VisibilityContext(scope.SelfImmediateClass);
         }
 
         internal static MethodResolutionResult Resolve(MetaObjectBuilder/*!*/ metaBuilder, string/*!*/ methodName, CallArguments/*!*/ args,
             out RubyMemberInfo methodMissing) {
 
             MethodResolutionResult method;
-            RubyClass targetClass = args.TargetClass;
+            var targetClass = args.TargetClass;
+            var visibilityContext = GetVisibilityContext(args.Signature, args.Scope);
             using (targetClass.Context.ClassHierarchyLocker()) {
                 metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext, 
                     new[] { methodName, Symbols.MethodMissing }
                 );
 
                 var options = args.Signature.IsVirtualCall ? MethodLookup.Virtual : MethodLookup.Default;
-                method = targetClass.ResolveMethodForSiteNoLock(methodName, GetVisibilityContext(args.Signature, args.Scope), options);
+                method = targetClass.ResolveMethodForSiteNoLock(methodName, visibilityContext, options);
                 if (!method.Found) {
                     methodMissing = targetClass.ResolveMethodMissingForSite(methodName, method.IncompatibleVisibility);
                 } else {
@@ -212,12 +214,12 @@
             }
 
             // Whenever the current self's class changes we need to invalidate the rule, if a protected method is being called.
-            if (method.Info != null && method.Info.IsProtected && !args.Signature.HasImplicitSelf) {
+            if (method.Info != null && method.Info.IsProtected && visibilityContext.Class != null) {
                 // We don't need to compare versions, just the class objects (super-class relationship cannot be changed).
                 // Since we don't want to hold on a class object (to make it collectible) we compare references to the version handlers.
                 metaBuilder.AddCondition(Ast.Equal(
                     Methods.GetSelfClassVersionHandle.OpCall(AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope))),
-                    Ast.Constant(args.Scope.SelfImmediateClass.Version)
+                    Ast.Constant(visibilityContext.Class.Version)
                 ));
             }
 
===================================================================
edit: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyCallSignature.cs;C922537
File: RubyCallSignature.cs
===================================================================
--- $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyCallSignature.cs;C922537  (server)    7/21/2009 5:46 PM
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/RubyCallSignature.cs;InteropVisibility
@@ -35,16 +35,19 @@
         // Used for private visibility check. By default method call sites have explicit self, so private methods are not visible.
         HasImplicitSelf = 16,
 
+        // Interop calls can only see Ruby-public members.
+        IsInteropCall = 32,
+
         // If the resolved method is a Ruby method call it otherwise invoke #base# method on target's type.
         // Used in method overrides defined in types emitted for Ruby classes that derive from CLR type.
-        IsVirtualCall = 32,
+        IsVirtualCall = 64,
     }
         
     /// <summary>
     /// RubyScope/RubyContext, (self), (argument){ArgumentCount}, (splatted-argument)?, (block)?
     /// </summary>
     public struct RubyCallSignature : IEquatable<RubyCallSignature> {
-        private const int FlagsCount = 6;
+        private const int FlagsCount = 7;
         private const int MaxArgumentCount = (int)(UInt32.MaxValue >> FlagsCount);
         private const RubyCallFlags FlagsMask = (RubyCallFlags)(1 << FlagsCount) - 1;
 
@@ -55,6 +58,7 @@
         public bool HasBlock { get { return ((RubyCallFlags)_countAndFlags & RubyCallFlags.HasBlock) != 0; } }
         public bool HasSplattedArgument { get { return ((RubyCallFlags)_countAndFlags & RubyCallFlags.HasSplattedArgument) != 0; } }
         public bool HasRhsArgument { get { return ((RubyCallFlags)_countAndFlags & RubyCallFlags.HasRhsArgument) != 0; } }
+        public bool IsInteropCall { get { return ((RubyCallFlags)_countAndFlags & RubyCallFlags.IsInteropCall) != 0; } }
         public bool IsVirtualCall { get { return ((RubyCallFlags)_countAndFlags & RubyCallFlags.IsVirtualCall) != 0; } }
 
         public int ArgumentCount { get { return (int)_countAndFlags >> FlagsCount; } }
@@ -97,7 +101,7 @@
         }
 
         internal static bool TryCreate(CallInfo callInfo, out RubyCallSignature callSignature) {
-            callSignature = Simple(callInfo.ArgumentCount);
+            callSignature = RubyCallSignature.Interop(callInfo.ArgumentCount);
             return callInfo.ArgumentNames.Count != 0;
         }
 
@@ -109,6 +113,10 @@
             return new RubyCallSignature(argumentCount, RubyCallFlags.None);
         }
 
+        public static RubyCallSignature Interop(int argumentCount) {
+            return new RubyCallSignature(argumentCount, RubyCallFlags.IsInteropCall);
+        }
+
         public static RubyCallSignature WithBlock(int argumentCount) {
             return new RubyCallSignature(argumentCount, RubyCallFlags.HasBlock);
         }
===================================================================
add: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/VisibilityContext.cs
File: VisibilityContext.cs
===================================================================
--- [no source file]
+++ Shelved Change: $/Dev10/feature/vs_langs01/Merlin/Main/Languages/Ruby/Ruby/Runtime/Calls/VisibilityContext.cs;InteropVisibility
@@ -1,0 +1,39 @@
+?/* ****************************************************************************
+ *
+ * Copyright (c) Microsoft Corporation. 
+ *
+ * This source code is subject to terms and conditions of the Microsoft Public License. A 
+ * copy of the license can be found in the License.html file at the root of this distribution. If 
+ * you cannot locate the  Microsoft Public License, please send an email to 
+ * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
+ * by the terms of the Microsoft Public License.
+ *
+ * You must not remove this notice, or any other, from this software.
+ *
+ *
+ * ***************************************************************************/
+
+using IronRuby.Builtins;
+
+namespace IronRuby.Runtime.Calls {
+    public struct VisibilityContext {
+        public static readonly VisibilityContext AllVisible = new VisibilityContext(RubyMethodAttributes.VisibilityMask);
+
+        public readonly RubyClass Class;
+        public readonly RubyMethodAttributes Visible;
+
+        public VisibilityContext(RubyMethodAttributes mask) {
+            Class = null;
+            Visible = mask;
+        }
+
+        public VisibilityContext(RubyClass cls) {
+            Class = cls;
+            Visible = RubyMethodAttributes.VisibilityMask;
+        }
+
+        public bool IsVisible(RubyMethodVisibility visibility) {
+            return ((int)visibility & (int)Visible) != 0;
+        }
+    }
+}
===================================================================
