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:
@@ -1,7 +1,7 @@
|
||||
use crate::traits::specialization_graph;
|
||||
use crate::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences};
|
||||
use crate::ty::fold::TypeFoldable;
|
||||
use crate::ty::{Ty, TyCtxt};
|
||||
use crate::ty::{Ident, Ty, TyCtxt};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::definitions::DefPathHash;
|
||||
@@ -44,6 +44,10 @@ pub struct TraitDef {
|
||||
/// The ICH of this trait's DefPath, cached here so it doesn't have to be
|
||||
/// recomputed all the time.
|
||||
pub def_path_hash: DefPathHash,
|
||||
|
||||
/// List of functions from `#[rustc_must_implement_one_of]` attribute one of which
|
||||
/// must be implemented.
|
||||
pub must_implement_one_of: Option<Box<[Ident]>>,
|
||||
}
|
||||
|
||||
/// Whether this trait is treated specially by the standard library
|
||||
@@ -87,6 +91,7 @@ impl<'tcx> TraitDef {
|
||||
skip_array_during_method_dispatch: bool,
|
||||
specialization_kind: TraitSpecializationKind,
|
||||
def_path_hash: DefPathHash,
|
||||
must_implement_one_of: Option<Box<[Ident]>>,
|
||||
) -> TraitDef {
|
||||
TraitDef {
|
||||
def_id,
|
||||
@@ -97,6 +102,7 @@ impl<'tcx> TraitDef {
|
||||
skip_array_during_method_dispatch,
|
||||
specialization_kind,
|
||||
def_path_hash,
|
||||
must_implement_one_of,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user