mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 03:54:42 +00:00 
			
		
		
		
	Fix a bug in orphan rules calculation
Where a fundamental type applied twice wasn't considered local.
This commit is contained in:
		
							parent
							
								
									5bbf2ce419
								
							
						
					
					
						commit
						246d678d77
					
				
					 2 changed files with 30 additions and 12 deletions
				
			
		|  | @ -874,21 +874,26 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool { | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     let unwrap_fundamental = |ty: Ty| match ty.kind(Interner) { |     let unwrap_fundamental = |mut ty: Ty| { | ||||||
|         TyKind::Ref(_, _, referenced) => referenced.clone(), |         // Unwrap all layers of fundamental types with a loop.
 | ||||||
|  |         loop { | ||||||
|  |             match ty.kind(Interner) { | ||||||
|  |                 TyKind::Ref(_, _, referenced) => ty = referenced.clone(), | ||||||
|                 &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => { |                 &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => { | ||||||
|                     let struct_data = db.struct_data(s); |                     let struct_data = db.struct_data(s); | ||||||
|                     if struct_data.flags.contains(StructFlags::IS_FUNDAMENTAL) { |                     if struct_data.flags.contains(StructFlags::IS_FUNDAMENTAL) { | ||||||
|                         let next = subs.type_parameters(Interner).next(); |                         let next = subs.type_parameters(Interner).next(); | ||||||
|                         match next { |                         match next { | ||||||
|                     Some(ty) => ty, |                             Some(it) => ty = it, | ||||||
|                     None => ty, |                             None => break ty, | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                 ty |                         break ty; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 _ => break ty, | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         _ => ty, |  | ||||||
|     }; |     }; | ||||||
|     //   - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type.
 |     //   - At least one of the types `T0..=Tn`` must be a local type. Let `Ti`` be the first such type.
 | ||||||
|     let is_not_orphan = trait_ref.substitution.type_parameters(Interner).any(|ty| { |     let is_not_orphan = trait_ref.substitution.type_parameters(Interner).any(|ty| { | ||||||
|  |  | ||||||
|  | @ -104,4 +104,17 @@ impl<T> foo::Foo<dyn LocalTrait> for Bar {} | ||||||
| "#,
 | "#,
 | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn twice_fundamental() { | ||||||
|  |         check_diagnostics( | ||||||
|  |             r#" | ||||||
|  | //- /foo.rs crate:foo
 | ||||||
|  | pub trait Trait {} | ||||||
|  | //- /bar.rs crate:bar deps:foo
 | ||||||
|  | struct Foo; | ||||||
|  | impl foo::Trait for &&Foo {} | ||||||
|  |         "#,
 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Chayim Refael Friedman
						Chayim Refael Friedman