Rust语言-接口设计的建议之受约束(Constrained)RustAPI指南GitHub:https://github.com/rust-lang/api-guidelinesRustAPI指南中文:https://rust-chinese-translation.gith
例子一:
pub mod outer_mod {
  pub mod inner_mod {
    // This function is visible within `outer_mod`
    pub(in crate::outer_mod) fn outer_mod_visible_fn() {}
    // This function is visible to the entire crate
    pub(crate) fn crate_visible_fn() {}
    // This function is visible within `outer_mod`
    pub(super) fn super_mod_visible_fn() {
      // This function is visible since we're in the same `mod`
      inner_mod_visible_fn();
    }
    // This function is visible only within `inner_mod`,
    // which is the same as leaving it private.
    pub(self) fn inner_mod_visible_fn() {}
  }
  pub fn foo() {
    inner_mod::outer_mod_visible_fn();
    inner_mod::crate_visible_fn();
    inner_mod::super_mod_visible_fn();
    // This function is no longer visible since we're outside of `inner_mod`
    // Error! `inner_mod_visible_fn` is private
    // inner_mod::inner_mod_visible_fn();
  }
}
fn bar() {
  // This function is still visible since we're in the same crate
  outer_mod::inner_mod::crate_visible_fn();
  // This function is no longer visible since we're outside of `outer_mod`
  // Error! `super_mod_visible_fn` is private
  outer_mod::inner_mod::super_mod_visible_fn();
  // This function is no longer visible since we're outside of `outer_mod`
  // Error! `outer_mod_visible_fn` is private
  outer_mod::inner_mod::outer_mod_visible_fn();
  outer_mod::foo();
}
fn main() {
  bar()
}
例子二:
lib.rs
pub struct Unit;
main.rs
fn main() {
  let u = constrained::Unit; // v0 库是 constrained
}
修改一
lib.rs
pub struct Unit {
  pub field: bool,
}
main.rs
fn is_true(u: constrained::Unit) -> bool {
  matches!(u, constrained::Unit { field: true })
}
fn main() {
  let u = constrained::Unit; // v0  报错,因为添加字段之后 Unit struct 原有的构造方式不可用
}
修改二
lib.rs
pub struct Unit {
  local: i32, // 增加私有字段
}
main.rs
fn main() {
  let u = constrained::Unit; // v0  报错,虽然字段看不见,但是编译器可以看到
}
#[non_exhaustive] 来缓解这些问题
non_exhaustive  表示类型或枚举在将来可能会添加更多字段或变体non_exhaustive 定义的类型,编译器会禁止:lib::Unit { field1: true }例子三:
lib.rs
#[non_exhaustive]
pub struct Config {
  pub window_width: u16,
  pub window_height: u16,
}
fn SomeFunction() {
  let config = Config {
    window_width: 640,
    window_height: 480,
  };
  // Non-exhaustive structs can be matched on exhaustively within the defining crate.
  if let Config {
    window_width,
    window_height,
  } = config
  {
    // ...
  }
}
main.rs
use constrained::Config;
fn main() {
  // Not allowed.
  let config =  Config {  // 报错
    window_width: 640,
    window_height: 480,
  };
  if let Config {
    window_width,
    window_height,
    .. // This is the only difference. 必须加 .. 否则报错
  } = config
  {
    // ...
  }
}
impl <T> Foo for T)例子四:
lib.rs
pub struct Unit;
pub trait Fool {
  fn foo(&self);
}
main.rs
use constrained::{Foo1, Unit};
trait Foo2 {
  fn foo(&self);
}
impl Foo2 for Unit {
  fn foo(&self) {
    println!("foo2");
  }
}
fn main() {
  Unit.foo()
}
修改一
lib.rs
pub struct Unit;
pub trait Fool {
  fn foo(&self);
}
// case 1: Add impl Foo1 for Unit in this crate
impl Foo1 for Unit {
  fn foo(&self) {
    println!("foo1");
  }
}
main.rs
use constrained::{Foo1, Unit};
trait Foo2 {
  fn foo(&self);
}
impl Foo2 for Unit {
  fn foo(&self) {
    println!("foo2");
  }
}
fn main() {
  Unit.foo() // 报错
}
修改二
lib.rs
pub struct Unit;
pub trait Fool {
  fn foo(&self);
}
// case 2: Add a new public Trait
pub trait Bar1 {
  fn foo(&self); // with the same name
}
impl Bar1 for Unit {
  fn foo(&self) {
    println!("bar1");
  }
}
main.rs
use constrained::{Foo1, Unit};
trait Foo2 {
  fn foo(&self);
}
impl Foo2 for Unit {
  fn foo(&self) {
    println!("foo2");
  }
}
fn main() {
  Unit.foo()  // 因为没有引入lib.rs中的Bar1,所以暂时没有报错
}
main.rs
use constrained::*;
trait Foo2 {
  fn foo(&self);
}
impl Foo2 for Unit {
  fn foo(&self) {
    println!("foo2");
  }
}
fn main() {
  Unit.foo()  // 报错
}
例子五:
lib.rs
use std::fmt::{Debug, Display};
mod sealed {
  use std::fmt::{Debug, Display};
  pug trait Sealed {}
  impl<T> Sealed for T where T: Debug + Display {}
}
pub trait CanUseCannotImplement: sealed::Sealed {
  // ..
}
impl<T> CanUseCannotImplement for T where T: Debug + Display {}
main.rs
use std::fmt::{Debug, Display};
use constrained::CanUseCannotImplement;
pub struct Bar {}
impl Debug for Bar {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    Ok(())
  }
}
impl Display for Bar {
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    Ok(())
  }
}
// impl CanUseCannotImplement for Bar {}  // 报错 因为在 lib.rs 中已经实现好了,不能再实现
// Conflicting implementation,
// The trait `CanUseCannotImplement` has been already implemented
// for the types that satisfy the bounds specified by the sealed trait which are `Debug + Display`
pub struct Foo {}
impl CanUseCannotImplement for Foo {} // 报错 没有实现 Debug 和 Display
fn main() {}
例子六:
lib.rs
// 你的 crate,叫 bestiter
pub fn iter<T>() -> itercrate::Empty<T> { .. }
// 依赖的外部 crate,叫 itercrate (v1.0),提供了 Empty<T> 类型
// 用户的 crate 中
struct EmptyIterator { it: itercrate::Empty<()> }
EmptyIterator { it: bestiter::iter() }
// ---------------------------------------------------------------
// 你的 crate, 叫 bestiter
pub fn iter<T>() -> itercrate::Empty<T> { .. }
// 依赖的外部crate,叫 itercrate,提供了 Empty<T> 类型
// 依赖的版本改为 v2.0,别处没有更改
// 编译器认为:itercrate1.0::Empty 和 itercrate2.0::Empty 是不同的类型
// 导致破坏性变更
// 用户的 crate 中
struct EmptyIterator { it: itercrate::Empty<()> }
例子七:
fn is_normal<T: Sized + Send + Sync + Unpin>() {}
#[test]
fn normal_types() {
  is_normal::<MyType>();
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!