Make BaseComponent Sealed. (#2359)

This commit is contained in:
Kaede Hoshikawa 2022-01-12 00:00:41 +09:00 committed by GitHub
parent e1a9619fba
commit 5dd8b7635c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 106 additions and 3 deletions

View File

@ -65,6 +65,8 @@ features = [
easybench-wasm = "0.2"
wasm-bindgen-test = "0.3"
gloo = { version = "0.6", features = ["futures"] }
rustversion = "1"
trybuild = "1"
[features]
doc_test = []

View File

@ -1,4 +1,10 @@
[tasks.native-test]
command = "cargo"
toolchain = "1.56"
args = ["test", "native_"]
[tasks.test]
dependencies = ["native-test"]
extend = "core::wasm-pack-base"
command = "wasm-pack"
args = [

View File

@ -24,6 +24,9 @@ mod hooks;
pub use hooks::*;
use crate::html::Context;
use crate::html::SealedBaseComponent;
/// This attribute creates a function component from a normal Rust function.
///
/// Functions with this attribute **must** return `Html` and can optionally take an argument for props.
@ -100,9 +103,9 @@ where
}
}
impl<T: 'static> BaseComponent for FunctionComponent<T>
impl<T> BaseComponent for FunctionComponent<T>
where
T: FunctionProvider,
T: FunctionProvider + 'static,
{
type Message = Box<dyn FnOnce() -> bool>;
type Properties = T::TProps;
@ -167,6 +170,8 @@ pub(crate) fn get_current_scope() -> Option<AnyScope> {
}
}
impl<T> SealedBaseComponent for FunctionComponent<T> where T: FunctionProvider + 'static {}
#[derive(Clone, Default)]
struct MsgQueue(Rc<RefCell<Vec<Msg>>>);

View File

@ -34,13 +34,17 @@ impl<COMP: BaseComponent> Context<COMP> {
}
}
/// A Sealed trait that prevents direct implementation of
/// [BaseComponent].
pub trait SealedBaseComponent {}
/// The common base of both function components and struct components.
///
/// If you are taken here by doc links, you might be looking for [`Component`] or
/// [`#[function_component]`](crate::functional::function_component).
///
/// We provide a blanket implementation of this trait for every member that implements [`Component`].
pub trait BaseComponent: Sized + 'static {
pub trait BaseComponent: SealedBaseComponent + Sized + 'static {
/// The Component's Message.
type Message: 'static;
@ -160,3 +164,5 @@ where
Component::destroy(self, ctx)
}
}
impl<T> SealedBaseComponent for T where T: Sized + Component + 'static {}

View File

@ -0,0 +1,26 @@
use yew::html::BaseComponent;
use yew::prelude::*;
pub struct Comp;
impl BaseComponent for Comp {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn update(&mut self, _ctx: &Context<Self>, _msg: Self::Message) -> bool {
false
}
fn changed(&mut self, _ctx: &Context<Self>) -> bool {
false
}
fn view(&self, _ctx: &Context<Self>) -> HtmlResult {
todo!()
}
fn rendered(&mut self, _ctx: &Context<Self>, _first_render: bool) {}
fn destroy(&mut self, _ctx: &Context<Self>) {}
}
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0277]: the trait bound `Comp: yew::Component` is not satisfied
--> tests/failed_tests/base_component_impl-fail.rs:6:6
|
6 | impl BaseComponent for Comp {
| ^^^^^^^^^^^^^ the trait `yew::Component` is not implemented for `Comp`
|
= note: required because of the requirements on the impl of `SealedBaseComponent` for `Comp`
note: required by a bound in `BaseComponent`
--> src/html/component/mod.rs
|
| pub trait BaseComponent: SealedBaseComponent + Sized + 'static {
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `BaseComponent`

View File

@ -0,0 +1,28 @@
use yew::html::BaseComponent;
use yew::prelude::*;
pub struct Comp;
impl BaseComponent for Comp {
type Message = ();
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn update(&mut self, _ctx: &Context<Self>, _msg: Self::Message) -> bool {
false
}
fn changed(&mut self, _ctx: &Context<Self>) -> bool {
false
}
fn view(&self, _ctx: &Context<Self>) -> HtmlResult {
todo!()
}
fn rendered(&mut self, _ctx: &Context<Self>, _first_render: bool) {}
fn destroy(&mut self, _ctx: &Context<Self>) {}
}
impl yew::html::component::SealedBaseComponent for Comp {}
fn main() {}

View File

@ -0,0 +1,11 @@
error[E0603]: module `component` is private
--> tests/failed_tests/sealed_base_component_impl-fail.rs:26:17
|
26 | impl yew::html::component::SealedBaseComponent for Comp {}
| ^^^^^^^^^ private module
|
note: the module `component` is defined here
--> src/html/mod.rs
|
| mod component;
| ^^^^^^^^^^^^^^

View File

@ -0,0 +1,7 @@
#[allow(dead_code)]
#[cfg(not(target_arch = "wasm32"))]
#[rustversion::attr(stable(1.56), test)]
fn native_failed_tests() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/failed_tests/*-fail.rs");
}