Update documentation of visibility

Fixes https://github.com/bazelbuild/bazel/issues/8982
Documents https://github.com/bazelbuild/bazel/issues/7377

RELNOTES: None.
PiperOrigin-RevId: 311376318
diff --git a/site/docs/visibility.md b/site/docs/visibility.md
index bcc5d2c..d16a7b7 100644
--- a/site/docs/visibility.md
+++ b/site/docs/visibility.md
@@ -5,18 +5,22 @@
 distinguish between implementation details and libraries other people can depend
 on.
 
-There are five forms (and one temporary form) a visibility label can take:
+If you need to disable the visibility check (for example when experimenting),
+use `--check_visibility=false`.
+
+## Visibility labels
+
+There are five forms a visibility label can take:
 
 *   `["//visibility:public"]`: Anyone can use this rule.
 *   `["//visibility:private"]`: Only rules in this package can use this rule.
     Rules in `javatests/foo/bar` can always use rules in `java/foo/bar`.
 *   `["//some/package:__pkg__", "//other/package:__pkg__"]`: Only rules in
-    `some/package` and `other/package` (defined in `some/package/BUILD` and
-    `other/package/BUILD`) have access to this rule. Note that sub-packages do
-    not have access to the rule; for example, `//some/package/foo:bar` or
-    `//other/package/testing:bla` wouldn't have access. `__pkg__` is a special
-    target and must be used verbatim. It represents all of the rules in the
-    package.
+    `some/package/BUILD` and `other/package/BUILD` have access to this rule.
+    Note that sub-packages do not have access to the rule; for example,
+    `//some/package/foo:bar` or `//other/package/testing:bla` wouldn't have
+    access. `__pkg__` is a special target and must be used verbatim. It
+    represents all of the rules in the package.
 *   `["//project:__subpackages__", "//other:__subpackages__"]`: Only rules in
     packages `project` or `other` or in one of their sub-packages have access to
     this rule. For example, `//project:rule`, `//project/library:lib` or
@@ -34,19 +38,20 @@
 A visibility specification may contain a combination of package labels (i.e.
 `//foo:__pkg__`) and `package_group`s.
 
+## Visibility of a rule
+
 If a rule does specify the visibility attribute, that specification overrides
 any [`default_visibility`](be/functions.html#package.default_visibility)
 attribute of the [`package`](functions.html#package) statement in the BUILD
 file containing the rule.
 
 Otherwise, if a rule does not specify the visibility attribute, the
-default_visibility of the package is used (except for
-[`exports_files`](be/functions.html#exports_files)).
+default_visibility of the package is used.
 
 Otherwise, if the default_visibility for the package is not specified,
 `//visibility:private` is used.
 
-## Example
+### Example
 
 File `//frobber/bin/BUILD`:
 
@@ -97,3 +102,50 @@
     ],
 )
 ```
+
+## Visibility of a file
+
+By default, files are visible only from the same package. To make a file
+accessible from another package, use
+[`exports_files`](be/functions.html#exports_files).
+
+If the call to `exports_files` rule does specify the visibility attribute, that
+specification applies. Otherwise, the file is public (the `default_visibility`
+is ignored).
+
+### Legacy behavior
+
+If the flag [`--incompatible_no_implicit_file_export`](https://github.com/bazelbuild/bazel/issues/10225)
+is not set, a legacy behavior applies instead.
+
+With the legacy behavior, files used by at least one rule in the file are
+implicitly exported using the `default_visibility` specification. See the
+[design proposal](https://github.com/bazelbuild/proposals/blob/master/designs/2019-10-24-file-visibility.md#example-and-description-of-the-problem)
+for more details.
+
+## Visibility of bzl files
+
+`load` statements are currently not subject to visibility. It is possible to
+load a `bzl` file anywhere in the workspace.
+
+## Visibility of implicit dependencies
+
+Some rules have implicit dependencies. For example, a C++ rule might implicitly
+depend on a C++ compiler.
+
+Currently, implicit dependencies are treated like normal dependencies. They need
+to be visible by all instances of the rule. This behavior can be changed using
+[`--incompatible_visibility_private_attributes_at_definition`](https://github.com/bazelbuild/proposals/blob/master/designs/2019-10-15-tool-visibility.md).
+
+## Best practices
+
+* Avoid setting the default visibility to public. It may be convenient for
+prototyping or in small codebases, but it is discouraged in large codebases: try
+to be explicit about which targets are part of the public interface.
+
+* Use `package_group` to share the visibility specifications among multiple
+  targets. This is especially useful when targets in many BUILD files should be
+  exposed to the same set of packages.
+
+* Use fine-grained visibility specifications when deprecating a target. Restrict
+  the visibility to the current users to avoid new dependencies.