Rollup merge of #92164 - WaffleLapkin:rustc_must_implement_one_of_attr, r=Aaron1011
Implement `#[rustc_must_implement_one_of]` attribute This PR adds a new attribute — `#[rustc_must_implement_one_of]` that allows changing the "minimal complete definition" of a trait. It's similar to GHC's minimal `{-# MINIMAL #-}` pragma, though `#[rustc_must_implement_one_of]` is weaker atm. Such attribute was long wanted. It can be, for example, used in `Read` trait to make transitions to recently added `read_buf` easier: ```rust #[rustc_must_implement_one_of(read, read_buf)] pub trait Read { fn read(&mut self, buf: &mut [u8]) -> Result<usize> { let mut buf = ReadBuf::new(buf); self.read_buf(&mut buf)?; Ok(buf.filled_len()) } fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { default_read_buf(|b| self.read(b), buf) } } impl Read for Ty0 {} //^ This will fail to compile even though all `Read` methods have default implementations // Both of these will compile just fine impl Read for Ty1 { fn read(&mut self, buf: &mut [u8]) -> Result<usize> { /* ... */ } } impl Read for Ty2 { fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { /* ... */ } } ``` For now, this is implemented as an internal attribute to start experimenting on the design of this feature. In the future we may want to extend it: - Allow arbitrary requirements like `a | (b & c)` - Allow multiple requirements like - ```rust #[rustc_must_implement_one_of(a, b)] #[rustc_must_implement_one_of(c, d)] ``` - Make it appear in rustdoc documentation - Change the syntax? - Etc Eventually, we should make an RFC and make this (or rather similar) attribute public. --- I'm fairly new to compiler development and not at all sure if the implementation makes sense, but at least it passes tests :)
This commit is contained in:
commit
32d85c0b5a
17 changed files with 431 additions and 4 deletions
|
@ -820,6 +820,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
data.skip_array_during_method_dispatch,
|
||||
data.specialization_kind,
|
||||
self.def_path_hash(item_id),
|
||||
data.must_implement_one_of,
|
||||
)
|
||||
}
|
||||
EntryKind::TraitAlias => ty::TraitDef::new(
|
||||
|
@ -831,6 +832,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
false,
|
||||
ty::trait_def::TraitSpecializationKind::None,
|
||||
self.def_path_hash(item_id),
|
||||
None,
|
||||
),
|
||||
_ => bug!("def-index does not refer to trait or trait alias"),
|
||||
}
|
||||
|
|
|
@ -1513,6 +1513,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
is_marker: trait_def.is_marker,
|
||||
skip_array_during_method_dispatch: trait_def.skip_array_during_method_dispatch,
|
||||
specialization_kind: trait_def.specialization_kind,
|
||||
must_implement_one_of: trait_def.must_implement_one_of.clone(),
|
||||
};
|
||||
|
||||
EntryKind::Trait(self.lazy(data))
|
||||
|
|
|
@ -378,6 +378,7 @@ struct TraitData {
|
|||
is_marker: bool,
|
||||
skip_array_during_method_dispatch: bool,
|
||||
specialization_kind: ty::trait_def::TraitSpecializationKind,
|
||||
must_implement_one_of: Option<Box<[Ident]>>,
|
||||
}
|
||||
|
||||
#[derive(TyEncodable, TyDecodable)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue