@@ -1021,6 +1021,19 @@ impl<'a> JavaTypeLowering<'a> {
10211021 let signature = declaration. signature . as_ref ( ) ;
10221022 let annotations = self . method_annotations ( declaration) ?;
10231023 let mut name_scope = crate :: language:: java:: JavaNameScope :: default ( ) ;
1024+ let reserved_type_qualifiers = method
1025+ . body
1026+ . as_ref ( )
1027+ . into_iter ( )
1028+ . flat_map ( super :: java_model:: method:: JavaMethodBody :: static_owner_types)
1029+ . map ( |owner| self . names . resolve_type ( & owner) )
1030+ . collect :: < Result < Vec < _ > , _ > > ( ) ?
1031+ . iter ( )
1032+ . filter_map ( source_type_qualifier)
1033+ . collect :: < std:: collections:: BTreeSet < _ > > ( ) ;
1034+ for qualifier in & reserved_type_qualifiers {
1035+ name_scope. reserve ( qualifier. clone ( ) ) ;
1036+ }
10241037 let parameter_naming = super :: semantic_naming:: ParameterNameRecovery :: new ( self . names ) ;
10251038 let mut visible_parameter = 0usize ;
10261039 let parameter_names = declaration
@@ -1166,12 +1179,17 @@ impl<'a> JavaTypeLowering<'a> {
11661179 source_type_bounds. clone( ) ,
11671180 generic_throw_types. clone( ) ,
11681181 outer_instances,
1169- declaration
1170- . kind
1171- . is_class_initializer( )
1172- . then( || owner. map( |owner| self . members. field_names( owner) ) )
1173- . flatten( )
1174- . unwrap_or_default( ) ,
1182+ {
1183+ let mut reserved = reserved_type_qualifiers. clone( ) ;
1184+ if declaration. kind. is_class_initializer( ) {
1185+ reserved. extend(
1186+ owner
1187+ . map( |owner| self . members. field_names( owner) )
1188+ . unwrap_or_default( ) ,
1189+ ) ;
1190+ }
1191+ reserved
1192+ } ,
11751193 declaration. kind. is_class_initializer( ) ,
11761194 self . observer. clone( ) ,
11771195 )
@@ -1692,6 +1710,16 @@ fn type_kind(kind: JavaClassKind) -> JavaTypeDeclarationKind {
16921710 }
16931711}
16941712
1713+ /// The first source component is the expression qualifier that a static
1714+ /// member access must keep visible. Reserving it prevents a local binding from
1715+ /// turning `Owner.field` into an access through an unrelated local variable.
1716+ fn source_type_qualifier ( ty : & JavaType ) -> Option < JavaIdentifier > {
1717+ let JavaType :: Class ( class) = ty else {
1718+ return None ;
1719+ } ;
1720+ class. segments . first ( ) . map ( |segment| segment. name . clone ( ) )
1721+ }
1722+
16951723fn method_kind ( kind : MethodModelKind ) -> JavaMethodDeclarationKind {
16961724 match kind {
16971725 MethodModelKind :: Method => JavaMethodDeclarationKind :: Method ,
@@ -1706,6 +1734,19 @@ mod tests {
17061734 use crate :: ir:: generic_types:: GenericSignatures ;
17071735 use crate :: language:: java:: GenericTypeProjection ;
17081736
1737+ #[ test]
1738+ fn static_type_qualifier_is_reserved_from_local_names ( ) {
1739+ let owner = JavaType :: source_class ( "a" ) ;
1740+ let owner = source_type_qualifier ( & owner) . expect ( "owner qualifier" ) ;
1741+ let mut names = crate :: language:: java:: JavaNameScope :: default ( ) ;
1742+ names. reserve ( owner) ;
1743+
1744+ assert_eq ! (
1745+ names. claim( JavaIdentifier :: from_dex( "a" ) ) ,
1746+ JavaIdentifier :: from_dex( "a2" )
1747+ ) ;
1748+ }
1749+
17091750 #[ test]
17101751 fn merged_throwable_rethrow_uses_generic_cast_but_catch_parameter_does_not ( ) {
17111752 let throwable = JavaType :: source_class ( "Throwable" ) ;
0 commit comments