Skip to content

Commit

Permalink
Merge pull request #429 from ratmice/unstable_api
Browse files Browse the repository at this point in the history
RFC: codify unstable api
  • Loading branch information
ltratt committed Dec 18, 2023
2 parents e2a1f38 + 9f4c40a commit 0f30331
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 2 deletions.
4 changes: 4 additions & 0 deletions lrlex/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ name = "lrlex"
name = "lrlex"
path = "src/lib/mod.rs"

[features]
_unstable_api = []
_unsealed_unstable_traits = ["_unstable_api"]

[build-dependencies]
vergen = { version = "8", default-features = false, features = ["build"] }

Expand Down
2 changes: 1 addition & 1 deletion lrlex/src/lib/ctbuilder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ pub fn lexerdef() -> {lexerdef_type} {{
write!(
outs,
"
Rule::new({}, {}, {}, {}.to_string(), {}.to_vec(), {}, &regex_options).unwrap(),",
Rule::new(::lrlex::unstable_api::InternalPublicApi, {}, {}, {}, {}.to_string(), {}.to_vec(), {}, &regex_options).unwrap(),",
tok_id,
n,
n_span,
Expand Down
3 changes: 3 additions & 0 deletions lrlex/src/lib/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ impl<StorageT> Rule<StorageT> {
/// Create a new `Rule`. This interface is unstable and should only be used by code generated
/// by lrlex itself.
#[doc(hidden)]
#[allow(private_interfaces)]
#[allow(clippy::too_many_arguments)]
pub fn new(
_: crate::unstable_api::InternalPublicApi,
tok_id: Option<StorageT>,
name: Option<String>,
name_span: Span,
Expand Down
67 changes: 67 additions & 0 deletions lrlex/src/lib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,70 @@ macro_rules! lrlex_mod {
include!(concat!(env!("OUT_DIR"), "/", $path, ".rs"));
};
}

/// This private module with pub items which is directly related to
/// the "Sealed trait" pattern. These items are used within the current
/// crate. See `unstable_api` module for enabling usage outside the crate.
mod unstable {
#![allow(unused)]
#![allow(unreachable_pub)]
pub struct UnstableApi;
pub trait UnstableTrait {}
}

/// A module for lifting restrictions on visibility by enabling unstable features.
///
/// See the sources for a complete list of features, and members.
pub mod unstable_api {
/// Unstable functions that take a value `UnstableApi` require
/// the "_unstable_api" feature. This feature controls
/// whether the value has `pub` visibility outside the crate.
#[cfg(feature = "_unstable_api")]
pub use unstable::UnstableApi;

/// This is a a supertrait for traits that are considered to be Unstable.
/// Unstable traits do not provide any semver guarantees.
///
/// Enabling the `_unsealed_unstable traits` makes this supertrait publicly
/// Visible.
///
///
/// Declaring an unstable Api within the crate:
/// ```
/// // Within the crate use `crate::unstable::` .
/// pub trait Foo: crate::unstable::UnstableTrait {
/// fn foo(key: crate::unstable::UnstableApi);
/// }
/// ```
///
/// Deriving the trait outside the crate (requires feature `_unsealed_unstable_traits`)
/// ```
/// struct Bar;
/// impl unstable_api::UnstableTrait for Bar{}
/// impl Foo for Bar {
/// fn foo(key: unstable_api::UnstableApi) {
/// ...
/// }
/// }
/// ```
///
///
/// Calling an implementation of the trait outside the crate (requires feature `_unstable_api`:
/// ```
/// let x: &dyn Foo = ...;
/// x.foo(unstable_api::UnstableApi);
/// ```
#[cfg(feature = "_unsealed_unstable_traits")]
pub use unstable::UnstableTrait;

/// An value that acts as a key to inform callers that they are
/// calling an unstable internal api. This value is public by default.
/// Access to it does not require any features to be enabled.
///
/// Q. When this should be used?
///
/// A. When generated code needs to call internal api within it,
/// where you do not want the caller to have to enable any features
/// to use the generated code.
pub struct InternalPublicApi;
}
1 change: 1 addition & 0 deletions lrlex/src/lib/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ where
.unwrap_or_else(|_| panic!("StorageT::try_from \
failed on {} (if StorageT is an unsigned integer type, this probably means that {} exceeds the type's maximum value)", rules_len, rules_len));
let rule = Rule::new(
crate::unstable_api::InternalPublicApi,
Some(tok_id),
name,
name_span,
Expand Down
2 changes: 2 additions & 0 deletions lrpar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ path = "src/lib/mod.rs"

[features]
serde = []
_unstable_api = []
_unsealed_unstable_traits = ["_unstable_api"]

[build-dependencies]
vergen = { version = "8", default-features = false, features = ["build"] }
Expand Down
4 changes: 3 additions & 1 deletion lrpar/src/lib/ctbuilder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1332,8 +1332,10 @@ where
/// always return `None`, even if the grammar actually has conflicts.
///
/// **Note: The conflicts feature is currently unstable and may change in the future.**
#[allow(private_interfaces)]
pub fn conflicts(
&self,
_: crate::unstable::UnstableApi,
) -> Option<(
&YaccGrammar<StorageT>,
&StateGraph<StorageT>,
Expand Down Expand Up @@ -1378,7 +1380,7 @@ C : 'a';"
.output_path(file_path.with_extension("ignored"))
.build()
.unwrap()
.conflicts()
.conflicts(crate::unstable::UnstableApi)
{
Some((_, _, _, conflicts)) => {
assert_eq!(conflicts.sr_len(), 1);
Expand Down
67 changes: 67 additions & 0 deletions lrpar/src/lib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,70 @@ macro_rules! lrpar_mod {
note = "Please import this as `cfgrammar::Span` instead"
)]
pub use cfgrammar::Span;

/// This private module with pub items which is directly related to
/// the "Sealed trait" pattern. These items are used within the current
/// crate. See `unstable_api` module for enabling usage outside the crate.
mod unstable {
#![allow(unused)]
#![allow(unreachable_pub)]
pub struct UnstableApi;
pub trait UnstableTrait {}
}

/// A module for lifting restrictions on visibility by enabling unstable features.
///
/// See the sources for a complete list of features, and members.
pub mod unstable_api {
/// Unstable functions that take a value `UnstableApi` require
/// the "_unstable_api" feature. This feature controls
/// whether the value has `pub` visibility outside the crate.
#[cfg(feature = "_unstable_api")]
pub use unstable::UnstableApi;

/// This is a a supertrait for traits that are considered to be Unstable.
/// Unstable traits do not provide any semver guarantees.
///
/// Enabling the `_unsealed_unstable traits` makes this supertrait publicly
/// Visible.
///
///
/// Declaring an unstable Api within the crate:
/// ```
/// // Within the crate use `crate::unstable::` .
/// pub trait Foo: crate::unstable::UnstableTrait {
/// fn foo(key: crate::unstable::UnstableApi);
/// }
/// ```
///
/// Deriving the trait outside the crate (requires feature `_unsealed_unstable_traits`)
/// ```
/// struct Bar;
/// impl unstable_api::UnstableTrait for Bar{}
/// impl Foo for Bar {
/// fn foo(key: unstable_api::UnstableApi) {
/// ...
/// }
/// }
/// ```
///
///
/// Calling an implementation of the trait outside the crate (requires feature `_unstable_api`:
/// ```
/// let x: &dyn Foo = ...;
/// x.foo(unstable_api::UnstableApi);
/// ```
#[cfg(feature = "_unsealed_unstable_traits")]
pub use unstable::UnstableTrait;

/// An value that acts as a key to inform callers that they are
/// calling an unstable internal api. This value is public by default.
/// Access to it does not require any features to be enabled.
///
/// Q. When this should be used?
///
/// A. When generated code needs to call internal api within it,
/// where you do not want the caller to have to enable any features
/// to use the generated code.
pub struct InternalPublicApi;
}

0 comments on commit 0f30331

Please sign in to comment.