cc/rust: Alias ffi rlib variant for static_libs

Alias the rlib variant to "link: static". This allows declaring
rust_ffi_rlib modules in static_libs. This effectively removes any
distinction between rust_ffi_static and rust_ffi_rlib. Removing the
functionality for building Rust staticlib modules will be cleaned up in
a follow-on CL.

This should have the effect of changing the default linkage for all rust
modules in static_libs from linking individual staticlibs to building a
single staticlib that includes all rust_ffi rlib dependencies.

This removes the static_rlibs property, as we're now handling
the choice dynamically. This also makes rlibs only propagate through
cc_library_static modules if the rlib is included in
whole_static_lib. This both mirrors the expected behavior of
cc libraries and helps control which version of a crate ends up in the
final link (e.g. libdoh_ffi vs libdoh_ffi_for_test).

Bug: 254469782
Test: m
Test: m blueprint_tests
Change-Id: I2925f67f6dc9329dae3dcccafb8560900ac8a6fc
diff --git a/rust/binary.go b/rust/binary.go
index 9969513..cba29a0 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -134,6 +134,9 @@
 	ret := buildOutput{outputFile: outputFile}
 	crateRootPath := crateRootPath(ctx, binary)
 
+	// Ensure link dirs are not duplicated
+	deps.linkDirs = android.FirstUniqueStrings(deps.linkDirs)
+
 	flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
 	flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
 	flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
diff --git a/rust/builder_test.go b/rust/builder_test.go
index c093ac4..ae5ccde 100644
--- a/rust/builder_test.go
+++ b/rust/builder_test.go
@@ -65,6 +65,11 @@
 			crate_name: "rust_ffi",
 			srcs: ["lib.rs"],
 		}
+		rust_ffi_static {
+			name: "librust_ffi_static",
+			crate_name: "rust_ffi",
+			srcs: ["lib.rs"],
+		}
 	`)
 	testcases := []struct {
 		testName      string
@@ -118,14 +123,14 @@
 			},
 		},
 		{
-			testName:   "rust_ffi static",
-			moduleName: "librust_ffi",
-			variant:    "android_arm64_armv8-a_static",
+			testName:   "rust_ffi_static rlib",
+			moduleName: "librust_ffi_static",
+			variant:    "android_arm64_armv8-a_rlib_rlib-std",
 			expectedFiles: []string{
-				"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/librust_ffi.a",
-				"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/librust_ffi.a.clippy",
-				"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/meta_lic",
-				"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/rustdoc.timestamp",
+				"out/soong/.intermediates/librust_ffi_static/android_arm64_armv8-a_rlib_rlib-std/librust_ffi_static.rlib",
+				"out/soong/.intermediates/librust_ffi_static/android_arm64_armv8-a_rlib_rlib-std/librust_ffi_static.rlib.clippy",
+				"out/soong/.intermediates/librust_ffi_static/android_arm64_armv8-a_rlib_rlib-std/meta_lic",
+				"out/soong/.intermediates/librust_ffi_static/android_arm64_armv8-a_rlib_rlib-std/rustdoc.timestamp",
 			},
 		},
 		{
@@ -148,6 +153,7 @@
 				"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/unstripped/librust_ffi.so",
 				"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/unstripped/librust_ffi.so.toc",
 				"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/meta_lic",
+				"out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/rustdoc.timestamp",
 				"out/soong/target/product/test_device/system/lib64/librust_ffi.so",
 			},
 		},
diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go
index 0d4622a..6cb8b93 100644
--- a/rust/fuzz_test.go
+++ b/rust/fuzz_test.go
@@ -114,17 +114,23 @@
 				srcs: ["foo.rs"],
 				shared_libs: ["libcc_transitive_dep"],
 			}
+			rust_ffi_static {
+				name: "libtest_fuzzing_static",
+				crate_name: "test_fuzzing",
+				srcs: ["foo.rs"],
+				shared_libs: ["libcc_transitive_dep"],
+			}
 			cc_fuzz {
 				name: "fuzz_shared_libtest",
 				shared_libs: ["libtest_fuzzing"],
 			}
 			cc_fuzz {
 				name: "fuzz_static_libtest",
-				static_rlibs: ["libtest_fuzzing"],
+				static_libs: ["libtest_fuzzing"],
 			}
 			cc_fuzz {
 				name: "fuzz_staticffi_libtest",
-				static_libs: ["libtest_fuzzing"],
+				static_libs: ["libtest_fuzzing_static"],
 			}
 	`)
 
diff --git a/rust/image_test.go b/rust/image_test.go
index 71e271c..d84eb10 100644
--- a/rust/image_test.go
+++ b/rust/image_test.go
@@ -22,18 +22,20 @@
 	"android/soong/cc"
 )
 
-// Test that cc modules can link against vendor_available rust_ffi_rlib/rust_ffi_static libraries.
+// Test that cc modules can depend on vendor_available rust_ffi_rlib/rust_ffi_static libraries.
 func TestVendorLinkage(t *testing.T) {
 	ctx := testRust(t, `
 			cc_binary {
 				name: "fizz_vendor_available",
-				static_libs: ["libfoo_vendor_static"],
-				static_rlibs: ["libfoo_vendor"],
+				static_libs: [
+					"libfoo_vendor",
+					"libfoo_vendor_static"
+				],
 				vendor_available: true,
 			}
 			cc_binary {
 				name: "fizz_soc_specific",
-				static_rlibs: ["libfoo_vendor"],
+				static_libs: ["libfoo_vendor"],
 				soc_specific: true,
 			}
 			rust_ffi_rlib {
@@ -52,8 +54,8 @@
 
 	vendorBinary := ctx.ModuleForTests("fizz_vendor_available", "android_vendor_arm64_armv8-a").Module().(*cc.Module)
 
-	if !android.InList("libfoo_vendor_static.vendor", vendorBinary.Properties.AndroidMkStaticLibs) {
-		t.Errorf("vendorBinary should have a dependency on libfoo_vendor_static.vendor: %#v", vendorBinary.Properties.AndroidMkStaticLibs)
+	if android.InList("libfoo_vendor_static.vendor", vendorBinary.Properties.AndroidMkStaticLibs) {
+		t.Errorf("vendorBinary should not have a staticlib dependency on libfoo_vendor_static.vendor: %#v", vendorBinary.Properties.AndroidMkStaticLibs)
 	}
 }
 
@@ -110,8 +112,10 @@
 	ctx := testRust(t, `
 			cc_library_shared {
 				name: "libcc_vendor_ramdisk",
-				static_rlibs: ["libfoo_vendor_ramdisk"],
-				static_libs: ["libfoo_static_vendor_ramdisk"],
+				static_libs: [
+					"libfoo_vendor_ramdisk",
+					"libfoo_static_vendor_ramdisk"
+				],
 				system_shared_libs: [],
 				vendor_ramdisk_available: true,
 			}
@@ -131,8 +135,8 @@
 
 	vendorRamdiskLibrary := ctx.ModuleForTests("libcc_vendor_ramdisk", "android_vendor_ramdisk_arm64_armv8-a_shared").Module().(*cc.Module)
 
-	if !android.InList("libfoo_static_vendor_ramdisk.vendor_ramdisk", vendorRamdiskLibrary.Properties.AndroidMkStaticLibs) {
-		t.Errorf("libcc_vendor_ramdisk should have a dependency on libfoo_static_vendor_ramdisk")
+	if android.InList("libfoo_static_vendor_ramdisk.vendor_ramdisk", vendorRamdiskLibrary.Properties.AndroidMkStaticLibs) {
+		t.Errorf("libcc_vendor_ramdisk should not have a dependency on the libfoo_static_vendor_ramdisk static library")
 	}
 }
 
diff --git a/rust/library.go b/rust/library.go
index 2a21263..96c02c8 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -43,9 +43,9 @@
 	android.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory)
 
 	// TODO: Remove when all instances of rust_ffi_static have been switched to rust_ffi_rlib
-	// Alias rust_ffi_static to the combined rust_ffi_rlib factory
-	android.RegisterModuleType("rust_ffi_static", RustFFIStaticRlibFactory)
-	android.RegisterModuleType("rust_ffi_host_static", RustFFIStaticRlibHostFactory)
+	// Alias rust_ffi_static to the rust_ffi_rlib factory
+	android.RegisterModuleType("rust_ffi_static", RustFFIRlibFactory)
+	android.RegisterModuleType("rust_ffi_host_static", RustFFIRlibHostFactory)
 }
 
 type VariantLibraryProperties struct {
@@ -353,7 +353,7 @@
 // type "rlib").
 func RustFFIRlibHostFactory() android.Module {
 	module, library := NewRustLibrary(android.HostSupported)
-	library.BuildOnlyRlibStatic()
+	library.BuildOnlyRlib()
 
 	library.isFFI = true
 	return module.Init()
@@ -368,30 +368,12 @@
 	return module.Init()
 }
 
-// rust_ffi_static produces a staticlib and an rlib variant
-func RustFFIStaticRlibFactory() android.Module {
-	module, library := NewRustLibrary(android.HostAndDeviceSupported)
-	library.BuildOnlyRlibStatic()
-
-	library.isFFI = true
-	return module.Init()
-}
-
-// rust_ffi_static_host produces a staticlib and an rlib variant for the host
-func RustFFIStaticRlibHostFactory() android.Module {
-	module, library := NewRustLibrary(android.HostSupported)
-	library.BuildOnlyRlibStatic()
-
-	library.isFFI = true
-	return module.Init()
-}
-
 func (library *libraryDecorator) BuildOnlyFFI() {
 	library.MutatedProperties.BuildDylib = false
 	// we build rlibs for later static ffi linkage.
 	library.MutatedProperties.BuildRlib = true
 	library.MutatedProperties.BuildShared = true
-	library.MutatedProperties.BuildStatic = true
+	library.MutatedProperties.BuildStatic = false
 
 	library.isFFI = true
 }
@@ -417,14 +399,6 @@
 	library.MutatedProperties.BuildStatic = false
 }
 
-func (library *libraryDecorator) BuildOnlyRlibStatic() {
-	library.MutatedProperties.BuildDylib = false
-	library.MutatedProperties.BuildRlib = true
-	library.MutatedProperties.BuildShared = false
-	library.MutatedProperties.BuildStatic = true
-	library.isFFI = true
-}
-
 func (library *libraryDecorator) BuildOnlyStatic() {
 	library.MutatedProperties.BuildRlib = false
 	library.MutatedProperties.BuildDylib = false
@@ -766,10 +740,13 @@
 
 	// The order of the variations (modules) matches the variant names provided. Iterate
 	// through the new variation modules and set their mutated properties.
+	var emptyVariant = false
+	var rlibVariant = false
 	for i, v := range modules {
 		switch variants[i] {
 		case rlibVariation:
 			v.(*Module).compiler.(libraryInterface).setRlib()
+			rlibVariant = true
 		case dylibVariation:
 			v.(*Module).compiler.(libraryInterface).setDylib()
 			if v.(*Module).ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation {
@@ -784,11 +761,19 @@
 			// Disable the compilation steps.
 			v.(*Module).compiler.SetDisabled()
 		case "":
-			// if there's an empty variant, alias it so it is the default variant
-			mctx.AliasVariation("")
+			emptyVariant = true
 		}
 	}
 
+	if rlibVariant && library.isFFILibrary() {
+		// If an rlib variant is set and this is an FFI library, make it the
+		// default variant so CC can link against it appropriately.
+		mctx.AliasVariation(rlibVariation)
+	} else if emptyVariant {
+		// If there's an empty variant, alias it so it is the default variant
+		mctx.AliasVariation("")
+	}
+
 	// If a source variant is created, add an inter-variant dependency
 	// between the other variants and the source variant.
 	if sourceVariant {
@@ -817,6 +802,7 @@
 					rlib := modules[0].(*Module)
 					rlib.compiler.(libraryInterface).setRlibStd()
 					rlib.Properties.RustSubName += RlibStdlibSuffix
+					mctx.AliasVariation("rlib-std")
 				} else {
 					variants := []string{"rlib-std", "dylib-std"}
 					modules := mctx.CreateLocalVariations(variants...)
diff --git a/rust/library_test.go b/rust/library_test.go
index 1133c28..35a420c 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -34,10 +34,14 @@
 			name: "libfoo.ffi",
 			srcs: ["foo.rs"],
 			crate_name: "foo"
+		}
+		rust_ffi_host_static {
+			name: "libfoo.ffi_static",
+			srcs: ["foo.rs"],
+			crate_name: "foo"
 		}`)
 
 	// Test all variants are being built.
-	libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static").Rule("rustc")
 	libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
 	libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Rule("rustc")
 	libfooFFIRlib := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
@@ -46,7 +50,6 @@
 	rlibCrateType := "rlib"
 	dylibCrateType := "dylib"
 	sharedCrateType := "cdylib"
-	staticCrateType := "staticlib"
 
 	// Test crate type for rlib is correct.
 	if !strings.Contains(libfooRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) {
@@ -58,11 +61,6 @@
 		t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", dylibCrateType, libfooDylib.Args["rustcFlags"])
 	}
 
-	// Test crate type for C static libraries is correct.
-	if !strings.Contains(libfooStatic.Args["rustcFlags"], "crate-type="+staticCrateType) {
-		t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", staticCrateType, libfooStatic.Args["rustcFlags"])
-	}
-
 	// Test crate type for FFI rlibs is correct
 	if !strings.Contains(libfooFFIRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) {
 		t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", rlibCrateType, libfooFFIRlib.Args["rustcFlags"])
@@ -188,23 +186,18 @@
 
 func TestStaticLibraryLinkage(t *testing.T) {
 	ctx := testRust(t, `
-		rust_ffi {
+		rust_ffi_static {
 			name: "libfoo",
 			srcs: ["foo.rs"],
 			crate_name: "foo",
 		}`)
 
 	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_rlib-std")
-	libfooStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
 
 	if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkRlibs) {
 		t.Errorf("Static libstd rlib expected to be a dependency of Rust rlib libraries. Rlib deps are: %#v",
 			libfoo.Module().(*Module).Properties.AndroidMkDylibs)
 	}
-	if !android.InList("libstd", libfooStatic.Module().(*Module).Properties.AndroidMkRlibs) {
-		t.Errorf("Static libstd rlib expected to be a dependency of Rust static libraries. Rlib deps are: %#v",
-			libfoo.Module().(*Module).Properties.AndroidMkDylibs)
-	}
 }
 
 func TestNativeDependencyOfRlib(t *testing.T) {
@@ -215,39 +208,31 @@
 			rlibs: ["librust_rlib"],
 			srcs: ["foo.rs"],
 		}
-		rust_ffi_static {
-			name: "libffi_static",
-			crate_name: "ffi_static",
-			rlibs: ["librust_rlib"],
-			srcs: ["foo.rs"],
-		}
 		rust_library_rlib {
 			name: "librust_rlib",
 			crate_name: "rust_rlib",
 			srcs: ["foo.rs"],
-			shared_libs: ["shared_cc_dep"],
-			static_libs: ["static_cc_dep"],
+			shared_libs: ["libshared_cc_dep"],
+			static_libs: ["libstatic_cc_dep"],
 		}
 		cc_library_shared {
-			name: "shared_cc_dep",
+			name: "libshared_cc_dep",
 			srcs: ["foo.cpp"],
 		}
 		cc_library_static {
-			name: "static_cc_dep",
+			name: "libstatic_cc_dep",
 			srcs: ["foo.cpp"],
 		}
 		`)
 
 	rustRlibRlibStd := ctx.ModuleForTests("librust_rlib", "android_arm64_armv8-a_rlib_rlib-std")
 	rustRlibDylibStd := ctx.ModuleForTests("librust_rlib", "android_arm64_armv8-a_rlib_dylib-std")
-	ffiStatic := ctx.ModuleForTests("libffi_static", "android_arm64_armv8-a_static")
 	ffiRlib := ctx.ModuleForTests("libffi_rlib", "android_arm64_armv8-a_rlib_rlib-std")
 
 	modules := []android.TestingModule{
 		rustRlibRlibStd,
 		rustRlibDylibStd,
 		ffiRlib,
-		ffiStatic,
 	}
 
 	// librust_rlib specifies -L flag to cc deps output directory on rustc command
@@ -258,17 +243,17 @@
 	// TODO: We could consider removing these flags
 	for _, module := range modules {
 		if !strings.Contains(module.Rule("rustc").Args["libFlags"],
-			"-L out/soong/.intermediates/shared_cc_dep/android_arm64_armv8-a_shared/") {
+			"-L out/soong/.intermediates/libshared_cc_dep/android_arm64_armv8-a_shared/") {
 			t.Errorf(
-				"missing -L flag for shared_cc_dep, rustcFlags: %#v",
-				rustRlibRlibStd.Rule("rustc").Args["libFlags"],
+				"missing -L flag for libshared_cc_dep of %s, rustcFlags: %#v",
+				module.Module().Name(), rustRlibRlibStd.Rule("rustc").Args["libFlags"],
 			)
 		}
 		if !strings.Contains(module.Rule("rustc").Args["libFlags"],
-			"-L out/soong/.intermediates/static_cc_dep/android_arm64_armv8-a_static/") {
+			"-L out/soong/.intermediates/libstatic_cc_dep/android_arm64_armv8-a_static/") {
 			t.Errorf(
-				"missing -L flag for static_cc_dep, rustcFlags: %#v",
-				rustRlibRlibStd.Rule("rustc").Args["libFlags"],
+				"missing -L flag for libstatic_cc_dep of %s, rustcFlags: %#v",
+				module.Module().Name(), rustRlibRlibStd.Rule("rustc").Args["libFlags"],
 			)
 		}
 	}
@@ -305,15 +290,23 @@
 				"libbar",
 				"librlib_only",
 			],
+		}
+		rust_ffi_host_static {
+			name: "libfoo.ffi.static",
+			srcs: ["foo.rs"],
+			crate_name: "foo",
+			rustlibs: [
+				"libbar",
+				"librlib_only",
+			],
 		}`)
 
 	libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std")
 	libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib")
 	libfooFFIRlib := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_rlib_rlib-std")
-	libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static")
 	libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared")
 
-	for _, static := range []android.TestingModule{libfooRlib, libfooStatic, libfooFFIRlib} {
+	for _, static := range []android.TestingModule{libfooRlib, libfooFFIRlib} {
 		if !android.InList("libbar.rlib-std", static.Module().(*Module).Properties.AndroidMkRlibs) {
 			t.Errorf("libbar not present as rlib dependency in static lib: %s", static.Module().Name())
 		}
@@ -381,6 +374,12 @@
 			crate_name: "bar",
 			rustlibs: ["libfoo"],
 		}
+		rust_ffi_static {
+			name: "libbar_static",
+			srcs: ["foo.rs"],
+			crate_name: "bar",
+			rustlibs: ["libfoo"],
+		}
 		rust_ffi {
 			name: "libbar.prefer_rlib",
 			srcs: ["foo.rs"],
@@ -394,7 +393,6 @@
 	libfooRlibDynamic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Module().(*Module)
 
 	libbarShared := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module().(*Module)
-	libbarStatic := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_static").Module().(*Module)
 	libbarFFIRlib := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_rlib_rlib-std").Module().(*Module)
 
 	// prefer_rlib works the same for both rust_library and rust_ffi, so a single check is sufficient here.
@@ -413,12 +411,6 @@
 	if !android.InList("libstd", libbarShared.Properties.AndroidMkDylibs) {
 		t.Errorf("Device rust_ffi_shared does not link libstd as an dylib")
 	}
-	if !android.InList("libstd", libbarStatic.Properties.AndroidMkRlibs) {
-		t.Errorf("Device rust_ffi_static does not link libstd as an rlib")
-	}
-	if !android.InList("libfoo.rlib-std", libbarStatic.Properties.AndroidMkRlibs) {
-		t.Errorf("Device rust_ffi_static does not link dependent rustlib rlib-std variant")
-	}
 	if !android.InList("libstd", libbarFFIRlib.Properties.AndroidMkRlibs) {
 		t.Errorf("Device rust_ffi_rlib does not link libstd as an rlib")
 	}
diff --git a/rust/rust.go b/rust/rust.go
index 3a3ca4d..6b7b2fb 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -420,7 +420,7 @@
 	depFlags     []string
 	depLinkFlags []string
 
-	// linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker.
+	// linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker
 	// Both of these are exported and propagate to dependencies.
 	linkDirs    []string
 	linkObjects []string
@@ -442,9 +442,6 @@
 	// Paths to generated source files
 	SrcDeps          android.Paths
 	srcProviderFiles android.Paths
-
-	// Used by Generated Libraries
-	depExportedRlibs []cc.RustRlibDep
 }
 
 type RustLibraries []RustLibrary
@@ -465,6 +462,7 @@
 
 type flagExporter struct {
 	linkDirs    []string
+	ccLinkDirs  []string
 	linkObjects []string
 }
 
@@ -658,6 +656,24 @@
 	panic(fmt.Errorf("BuildStaticVariant called on non-library module: %q", mod.BaseModuleName()))
 }
 
+func (mod *Module) BuildRlibVariant() bool {
+	if mod.compiler != nil {
+		if library, ok := mod.compiler.(libraryInterface); ok {
+			return library.buildRlib()
+		}
+	}
+	panic(fmt.Errorf("BuildRlibVariant called on non-library module: %q", mod.BaseModuleName()))
+}
+
+func (mod *Module) IsRustFFI() bool {
+	if mod.compiler != nil {
+		if library, ok := mod.compiler.(libraryInterface); ok {
+			return library.isFFILibrary()
+		}
+	}
+	return false
+}
+
 func (mod *Module) BuildSharedVariant() bool {
 	if mod.compiler != nil {
 		if library, ok := mod.compiler.(libraryInterface); ok {
@@ -1237,7 +1253,6 @@
 	ctx.VisitDirectDeps(func(dep android.Module) {
 		depName := ctx.OtherModuleName(dep)
 		depTag := ctx.OtherModuleDependencyTag(dep)
-
 		if _, exists := skipModuleList[depName]; exists {
 			return
 		}
@@ -1250,8 +1265,8 @@
 			//Handle Rust Modules
 			makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName)
 
-			switch depTag {
-			case dylibDepTag:
+			switch {
+			case depTag == dylibDepTag:
 				dylib, ok := rustDep.compiler.(libraryInterface)
 				if !ok || !dylib.dylib() {
 					ctx.ModuleErrorf("mod %q not an dylib library", depName)
@@ -1261,8 +1276,7 @@
 				mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName)
 				mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName))
 
-			case rlibDepTag:
-
+			case depTag == rlibDepTag:
 				rlib, ok := rustDep.compiler.(libraryInterface)
 				if !ok || !rlib.rlib() {
 					ctx.ModuleErrorf("mod %q not an rlib library", makeLibName)
@@ -1277,16 +1291,25 @@
 				depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
 				depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path()))
 
-			case procMacroDepTag:
+			case depTag == procMacroDepTag:
 				directProcMacroDeps = append(directProcMacroDeps, rustDep)
 				mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
 				// proc_macro link dirs need to be exported, so collect those here.
 				depPaths.exportedLinkDirs = append(depPaths.exportedLinkDirs, linkPathFromFilePath(rustDep.OutputFile().Path()))
 
-			case sourceDepTag:
+			case depTag == sourceDepTag:
 				if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
 					collectIncludedProtos(mod, rustDep)
 				}
+			case cc.IsStaticDepTag(depTag):
+				// Rust FFI rlibs should not be declared in a Rust modules
+				// "static_libs" list as we can't handle them properly at the
+				// moment (for example, they only produce an rlib-std variant).
+				// Instead, a normal rust_library variant should be used.
+				ctx.PropertyErrorf("static_libs",
+					"found '%s' in static_libs; use a rust_library module in rustlibs instead of a rust_ffi module in static_libs",
+					depName)
+
 			}
 
 			transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustDep.transitiveAndroidMkSharedLibs)
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 8b96df8..0d005d0 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -447,23 +447,30 @@
 			export_include_dirs: ["foo_includes"]
 		}
 
+		rust_ffi_rlib {
+			name: "libbuzz",
+			crate_name: "buzz",
+			srcs: ["src/lib.rs"],
+			export_include_dirs: ["buzz_includes"]
+		}
+
 		cc_library_shared {
 			name: "libcc_shared",
 			srcs:["foo.c"],
-			static_rlibs: ["libbar"],
+			static_libs: ["libbar"],
 		}
 
 		cc_library_static {
 			name: "libcc_static",
 			srcs:["foo.c"],
-			static_rlibs: ["libfoo"],
+			static_libs: ["libbuzz"],
+			whole_static_libs: ["libfoo"],
 		}
 
 		cc_binary {
 			name: "ccBin",
 			srcs:["foo.c"],
-			static_rlibs: ["libbar"],
-			static_libs: ["libcc_static"],
+			static_libs: ["libcc_static", "libbar"],
 		}
 		`)
 
@@ -514,10 +521,13 @@
 			"-Ibar_includes", ccbin_cc.Args)
 	}
 
-	// Make sure that direct dependencies and indirect dependencies are
+	// Make sure that direct dependencies and indirect whole static dependencies are
 	// propagating correctly to the generated rlib.
 	if !strings.Contains(ccbin_rustc.Args["libFlags"], "--extern foo=") {
-		t.Errorf("Missing indirect dependency libfoo when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
+		t.Errorf("Missing indirect whole_static_lib dependency libfoo when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
+	}
+	if strings.Contains(ccbin_rustc.Args["libFlags"], "--extern buzz=") {
+		t.Errorf("Indirect static_lib dependency libbuzz found when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
 	}
 	if !strings.Contains(ccbin_rustc.Args["libFlags"], "--extern bar=") {
 		t.Errorf("Missing direct dependency libbar when writing generated Rust staticlib: %#v", ccbin_rustc.Args["libFlags"])
diff --git a/rust/testing.go b/rust/testing.go
index f31c591..6ee49a9 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -189,11 +189,11 @@
 	ctx.RegisterModuleType("rust_ffi", RustFFIFactory)
 	ctx.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory)
 	ctx.RegisterModuleType("rust_ffi_rlib", RustFFIRlibFactory)
-	ctx.RegisterModuleType("rust_ffi_static", RustFFIStaticRlibFactory)
+	ctx.RegisterModuleType("rust_ffi_static", RustFFIRlibFactory)
 	ctx.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
 	ctx.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
 	ctx.RegisterModuleType("rust_ffi_host_rlib", RustFFIRlibHostFactory)
-	ctx.RegisterModuleType("rust_ffi_host_static", RustFFIStaticRlibHostFactory)
+	ctx.RegisterModuleType("rust_ffi_host_static", RustFFIRlibHostFactory)
 	ctx.RegisterModuleType("rust_proc_macro", ProcMacroFactory)
 	ctx.RegisterModuleType("rust_protobuf", RustProtobufFactory)
 	ctx.RegisterModuleType("rust_protobuf_host", RustProtobufHostFactory)