mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-29 19:17:12 +00:00 
			
		
		
		
	Merge pull request #19963 from ChayimFriedman2/unsized-impl-items
fix: Do not error at impls for unsized types that do not include `where Self: Sized` items
This commit is contained in:
		
						commit
						f15267aaf4
					
				
					 4 changed files with 64 additions and 3 deletions
				
			
		|  | @ -122,7 +122,7 @@ pub fn dyn_compatibility_of_trait_query( | ||||||
|     res |     res | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool { | pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool { | ||||||
|     let krate = def.module(db).krate(); |     let krate = def.module(db).krate(); | ||||||
|     let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else { |     let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else { | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|  | @ -229,7 +229,7 @@ impl Generics { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
 |     /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
 | ||||||
|     pub(crate) fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution { |     pub fn placeholder_subst(&self, db: &dyn HirDatabase) -> Substitution { | ||||||
|         Substitution::from_iter( |         Substitution::from_iter( | ||||||
|             Interner, |             Interner, | ||||||
|             self.iter_id().map(|id| match id { |             self.iter_id().map(|id| match id { | ||||||
|  |  | ||||||
|  | @ -846,7 +846,7 @@ impl Module { | ||||||
|                     ) |                     ) | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let missing: Vec<_> = required_items |                 let mut missing: Vec<_> = required_items | ||||||
|                     .filter(|(name, id)| { |                     .filter(|(name, id)| { | ||||||
|                         !impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| { |                         !impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| { | ||||||
|                             discriminant(impl_item) == discriminant(id) && impl_name == name |                             discriminant(impl_item) == discriminant(id) && impl_name == name | ||||||
|  | @ -854,6 +854,38 @@ impl Module { | ||||||
|                     }) |                     }) | ||||||
|                     .map(|(name, item)| (name.clone(), AssocItem::from(*item))) |                     .map(|(name, item)| (name.clone(), AssocItem::from(*item))) | ||||||
|                     .collect(); |                     .collect(); | ||||||
|  | 
 | ||||||
|  |                 if !missing.is_empty() { | ||||||
|  |                     let self_ty = db.impl_self_ty(impl_def.id).substitute( | ||||||
|  |                         Interner, | ||||||
|  |                         &hir_ty::generics::generics(db, impl_def.id.into()).placeholder_subst(db), | ||||||
|  |                     ); | ||||||
|  |                     let self_ty = if let TyKind::Alias(AliasTy::Projection(projection)) = | ||||||
|  |                         self_ty.kind(Interner) | ||||||
|  |                     { | ||||||
|  |                         db.normalize_projection( | ||||||
|  |                             projection.clone(), | ||||||
|  |                             db.trait_environment(impl_def.id.into()), | ||||||
|  |                         ) | ||||||
|  |                     } else { | ||||||
|  |                         self_ty | ||||||
|  |                     }; | ||||||
|  |                     let self_ty_is_guaranteed_unsized = matches!( | ||||||
|  |                         self_ty.kind(Interner), | ||||||
|  |                         TyKind::Dyn(..) | TyKind::Slice(..) | TyKind::Str | ||||||
|  |                     ); | ||||||
|  |                     if self_ty_is_guaranteed_unsized { | ||||||
|  |                         missing.retain(|(_, assoc_item)| { | ||||||
|  |                             let assoc_item = match *assoc_item { | ||||||
|  |                                 AssocItem::Function(it) => it.id.into(), | ||||||
|  |                                 AssocItem::Const(it) => it.id.into(), | ||||||
|  |                                 AssocItem::TypeAlias(it) => it.id.into(), | ||||||
|  |                             }; | ||||||
|  |                             !hir_ty::dyn_compatibility::generics_require_sized_self(db, assoc_item) | ||||||
|  |                         }); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 if !missing.is_empty() { |                 if !missing.is_empty() { | ||||||
|                     acc.push( |                     acc.push( | ||||||
|                         TraitImplMissingAssocItems { |                         TraitImplMissingAssocItems { | ||||||
|  |  | ||||||
|  | @ -127,4 +127,33 @@ impl !Trait for () {} | ||||||
| "#,
 | "#,
 | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn impl_sized_for_unsized() { | ||||||
|  |         check_diagnostics( | ||||||
|  |             r#" | ||||||
|  | //- minicore: sized
 | ||||||
|  | trait Trait { | ||||||
|  |     type Item | ||||||
|  |     where | ||||||
|  |         Self: Sized; | ||||||
|  | 
 | ||||||
|  |     fn item() | ||||||
|  |     where | ||||||
|  |         Self: Sized; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | trait OtherTrait {} | ||||||
|  | 
 | ||||||
|  | impl Trait for () { | ||||||
|  |     type Item = (); | ||||||
|  |     fn item() {} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Items with Self: Sized bound not required to be implemented for unsized types.
 | ||||||
|  | impl Trait for str {} | ||||||
|  | impl Trait for dyn OtherTrait {} | ||||||
|  |  "#,
 | ||||||
|  |         ) | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth