Skip to content

Tracking Issue for Provider API #96024

Open
@yaahc

Description

@yaahc

Feature gate: #![feature(provide_any)]

This is a tracking issue for RFC 3192

This RFC proposes extending the any module of the core library with a generic API for objects to provide type-based access to data. (In contrast to the existing APIs which provides type-driven downcasting, the proposed extension integrates downcasting into data access to provide a safer and more ergonomic API).

The initial motivating use case for this API is to provide the necessary functionality to add generic member access to the Error trait to generalize extracting context like Backtrace and to make it possible to move the Error trait into core while leaving Backtrace in std.

Public API

// core::any
pub trait Provider {
    fn provide<'a>(&'a self, demand: &mut Demand<'a>);
}

pub fn request_value<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<T>
where
    T: 'static;

pub fn request_ref<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<&'a T>
where
    T: 'static + ?Sized;

#[repr(transparent)]
pub struct Demand<'a>(_);

impl<'a> Demand<'a> {
    pub fn provide_value<T>(&mut self, value: T) -> &mut Self
    where
        T: 'static;

    pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
    where
        T: 'static;

    pub fn provide_ref<T: ?Sized + 'static>(&mut self, value: &'a T) -> &mut Self;

    pub fn provide_ref_with<T: ?Sized + 'static>(
        &mut self,
        fulfil: impl FnOnce() -> &'a T,
    ) -> &mut Self;

    pub fn would_be_satisfied_by_value_of<T>(&self) -> bool
    where
        T: 'static;

    pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool
    where
        T: ?Sized + 'static,
}

impl<'a> fmt::Debug for Demand<'a> {}

// core::error
impl<E> Provider for E
where
    E: Error + ?Sized;

Steps / History

  • Implementation: Add the Provider api to core::any #91970
  • Delete the Provider trait and merge its functionality into Error.
  • Pick either demand or request and use that name consistently.
  • LLVM is unable to optimize multiple .provide_* calls into a switch table because each call fetches the type id from Erased::type_id separately each time and the compiler doesn't know that these calls all return the same value. This should be fixed. See Add provide_any module to core rfcs#3192 (comment) for one possible solution (although alternative solutions may be possible).
  • Final comment period (FCP)
  • Stabilization PR

Unresolved Questions

  • Should the APIs be named demand_* or request_*?

Metadata

Metadata

Assignees

Labels

B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.B-RFC-implementedBlocker: Approved by a merged RFC and implemented but not stabilized.B-unstableBlocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions