Refactor cc/rust to prep for Rust stubs

This CL largely handles this refactoring in preparation for Rust stubs
support.

Rust modules need to be able to communicate stubs information to cc, and
certain bits of cc needs to be exported so rust can reuse them.

A new VersionedLinkableInterface is added to capture most of the
stubs-related interface definitions.

Bug: 203478530
Test: m blueprint_tests
Change-Id: I380225402fa85a3c39e7b18deb657054b3a52fbe
diff --git a/rust/library.go b/rust/library.go
index 2d62dcf..9912c94 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -277,6 +277,71 @@
 var _ compiler = (*libraryDecorator)(nil)
 var _ libraryInterface = (*libraryDecorator)(nil)
 var _ exportedFlagsProducer = (*libraryDecorator)(nil)
+var _ cc.VersionedInterface = (*libraryDecorator)(nil)
+
+func (library *libraryDecorator) HasLLNDKStubs() bool {
+	// Rust does not support LLNDK yet.
+	return false
+}
+
+func (library *libraryDecorator) HasVendorPublicLibrary() bool {
+	// Rust does not support vendor public library.
+	return false
+}
+
+func (library *libraryDecorator) HasLLNDKHeaders() bool {
+	// Rust does not support LLNDK yet.
+	return false
+}
+
+func (library *libraryDecorator) HasStubsVariants() bool {
+	return false
+}
+
+func (library *libraryDecorator) IsStubsImplementationRequired() bool {
+	return false
+}
+
+func (library *libraryDecorator) GetAPIListCoverageXMLPath() android.ModuleOutPath {
+	panic(fmt.Errorf("GetAPIListCoverageXMLPath called on unsupported Rust module"))
+}
+
+func (library *libraryDecorator) AllStubsVersions() []string {
+	panic(fmt.Errorf("AllStubsVersions called on unsupported Rust module"))
+}
+
+func (library *libraryDecorator) SetAllStubsVersions(versions []string) {
+	panic(fmt.Errorf("ApexSdkVersion called on unsupported Rust module"))
+}
+
+func (library *libraryDecorator) SetStubsVersion(version string) {
+	panic(fmt.Errorf("SetStubsVersion called on unsupported Rust module"))
+}
+
+func (library *libraryDecorator) SetBuildStubs(isLatest bool) {
+	panic(fmt.Errorf("SetBuildStubs called on unsupported Rust module"))
+}
+
+func (library *libraryDecorator) BuildStubs() bool {
+	return false
+}
+
+func (library *libraryDecorator) ImplementationModuleName(name string) string {
+	panic(fmt.Errorf("ImplementationModuleName called on unsupported Rust module"))
+}
+
+func (library *libraryDecorator) IsLLNDKMovedToApex() bool {
+	// Rust does not support LLNDK.
+	return false
+}
+
+func (library *libraryDecorator) StubsVersions(ctx android.BaseModuleContext) []string {
+	panic(fmt.Errorf("StubsVersions called on unsupported Rust module"))
+}
+
+func (library *libraryDecorator) StubsVersion() string {
+	panic(fmt.Errorf("StubsVersions called on unsupported Rust module"))
+}
 
 // rust_library produces all Rust variants (rust_library_dylib and
 // rust_library_rlib).
diff --git a/rust/rust.go b/rust/rust.go
index ba6e293..a4c1afd 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -406,10 +406,6 @@
 	return false
 }
 
-func (mod *Module) StubsVersion() string {
-	panic(fmt.Errorf("StubsVersion called on non-versioned module: %q", mod.BaseModuleName()))
-}
-
 func (mod *Module) SdkVersion() string {
 	return ""
 }
@@ -561,6 +557,9 @@
 func (mod *Module) PreventInstall() bool {
 	return mod.Properties.PreventInstall
 }
+func (c *Module) ForceDisableSanitizers() {
+	c.sanitize.Properties.ForceDisable = true
+}
 
 func (mod *Module) MarkAsCoverageVariant(coverage bool) {
 	mod.coverage.Properties.IsCoverageVariant = coverage
@@ -743,11 +742,28 @@
 	return false
 }
 
+func (mod *Module) IsStubs() bool {
+	return false
+}
+
 func (mod *Module) HasStubsVariants() bool {
 	return false
 }
 
-func (mod *Module) IsStubs() bool {
+func (mod *Module) ApexSdkVersion() android.ApiLevel {
+	panic(fmt.Errorf("ApexSdkVersion called on unsupported Rust module: %q", mod.BaseModuleName()))
+}
+
+func (mod *Module) ImplementationModuleNameForMake(ctx android.BaseModuleContext) string {
+	return mod.Name()
+}
+
+func (mod *Module) Multilib() string {
+	return mod.Arch().ArchType.Multilib
+}
+
+func (mod *Module) IsCrt() bool {
+	// Rust does not currently provide any crt modules.
 	return false
 }
 
@@ -771,6 +787,7 @@
 }
 
 var _ cc.LinkableInterface = (*Module)(nil)
+var _ cc.VersionedLinkableInterface = (*Module)(nil)
 
 func (mod *Module) Init() android.Module {
 	mod.AddProperties(&mod.Properties)
@@ -881,6 +898,25 @@
 	return mod.compiler != nil && mod.compiler.nativeCoverage()
 }
 
+func (mod *Module) SetStl(s string) {
+	// STL is a CC concept; do nothing for Rust
+}
+
+func (mod *Module) SetSdkVersion(s string) {
+	panic(fmt.Errorf("SetSdkVersion called on unsupported Rust module: %q", mod.BaseModuleName()))
+}
+
+func (mod *Module) SetMinSdkVersion(s string) {
+	mod.Properties.Min_sdk_version = StringPtr(s)
+}
+
+func (mod *Module) VersionedInterface() cc.VersionedInterface {
+	if _, ok := mod.compiler.(cc.VersionedInterface); ok {
+		return mod.compiler.(cc.VersionedInterface)
+	}
+	return nil
+}
+
 func (mod *Module) EverInstallable() bool {
 	return mod.compiler != nil &&
 		// Check to see whether the module is actually ever installable.
@@ -1064,6 +1100,12 @@
 	}
 	android.SetProvider(ctx, RustInfoProvider, rustInfo)
 
+	ccInfo := &cc.CcInfo{
+		IsPrebuilt: mod.IsPrebuilt(),
+	}
+
+	android.SetProvider(ctx, cc.CcInfoProvider, ccInfo)
+
 	mod.setOutputFiles(ctx)
 
 	buildComplianceMetadataInfo(ctx, mod, deps)
diff --git a/rust/sanitize.go b/rust/sanitize.go
index b8f922f..50f55ce 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -53,6 +53,9 @@
 
 	// Used when we need to place libraries in their own directory, such as ASAN.
 	InSanitizerDir bool `blueprint:"mutated"`
+
+	// ForceDisable is set by the version mutator to disable sanitization of stubs variants
+	ForceDisable bool `blueprint:"mutated"`
 }
 
 var fuzzerFlags = []string{
@@ -103,6 +106,10 @@
 func (sanitize *sanitize) begin(ctx BaseModuleContext) {
 	s := &sanitize.Properties.Sanitize
 
+	if sanitize.Properties.ForceDisable {
+		return
+	}
+
 	// Disable sanitizers for musl x86 modules, rustc does not support any sanitizers.
 	if ctx.Os() == android.LinuxMusl && ctx.Arch().ArchType == android.X86 {
 		s.Never = proptools.BoolPtr(true)
@@ -221,6 +228,10 @@
 }
 
 func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
+	if sanitize.Properties.ForceDisable {
+		return flags, deps
+	}
+
 	if !sanitize.Properties.SanitizerEnabled {
 		return flags, deps
 	}
@@ -253,6 +264,9 @@
 		if !mod.Enabled(mctx) {
 			return
 		}
+		if mod.sanitize.Properties.ForceDisable {
+			return
+		}
 
 		if Bool(mod.sanitize.Properties.Sanitize.Memtag_heap) && mod.Binary() {
 			noteDep := "note_memtag_heap_async"
@@ -364,7 +378,7 @@
 // distinguish between the cases. It isn't needed though - both cases can be
 // treated identically.
 func (sanitize *sanitize) isSanitizerEnabled(t cc.SanitizerType) bool {
-	if sanitize == nil || !sanitize.Properties.SanitizerEnabled {
+	if sanitize == nil || !sanitize.Properties.SanitizerEnabled || sanitize.Properties.ForceDisable {
 		return false
 	}
 
@@ -453,7 +467,7 @@
 }
 
 func (mod *Module) SanitizeNever() bool {
-	return Bool(mod.sanitize.Properties.Sanitize.Never)
+	return Bool(mod.sanitize.Properties.Sanitize.Never) || mod.sanitize.Properties.ForceDisable
 }
 
 var _ cc.PlatformSanitizeable = (*Module)(nil)