The situation is (severely simplified) this (playpen):
mod tokentree {
pub struct TokenTree;
mod serialize {
use std::collections::BTreeMap;
use super::TokenTree;
#[derive(Debug)]
pub struct InternStr;
pub trait InternStrsExt {
fn intern_strs(&self) -> BTreeMap<&str, InternStr>;
}
impl InternStrsExt for [TokenTree] {
fn intern_strs(&self) -> BTreeMap<&str, InternStr> { BTreeMap::new() }
}
}
pub use self::serialize::{InternStrsExt, InternStr};
}
use tokentree::*;
fn main() {
println!("{:?}", [TokenTree].intern_strs());
}
I get the following error (both on nightly and beta):
<anon>:20:22: 20:47 error: source trait is inaccessible
<anon>:20 println!("{:?}", [TokenTree].intern_strs());
^~~~~~~~~~~~~~~~~~~~~~~~~
My problem is that I don't even know what this is supposed to mean.
It needs a pub declaration. Also your declarations are all over the place. Recommended form is to stick your pub mod declarations first, then, use.
Here is the working example.
mod tokentree {
pub struct TokenTree;
pub mod serialize {
use std::collections::BTreeMap;
use super::TokenTree;
#[derive(Debug)]
pub struct InternStr;
pub trait InternStrsExt {
fn intern_strs(&self) -> BTreeMap<&str, InternStr>;
}
impl InternStrsExt for [TokenTree] {
fn intern_strs(&self) -> BTreeMap<&str, InternStr> { BTreeMap::new() }
}
}
pub use self::serialize::{InternStrsExt, InternStr};
}
pub use tokentree::*;
fn main() {
println!("{:?}", [TokenTree].intern_strs());
}
(playpen)
What happened here is that you stumbled upon following glitches:
https://github.com/rust-lang/rust/issues/18241
https://github.com/rust-lang/rust/issues/16264
You can't export your traits from a private module. That's why you need to change mod serialize into pub mod serialize. For example this playpen example demonstrates that exporting struct Export works, but un-commenting the println! will make it stop compiling, because we used a trait.
Tip: One thing that helps me with the visibility rules is to generate doc files and see which doc files are visible.
Related
Is there a way to retrieve public constants from the inner struct in the Newtype pattern?
Say I am using a struct from another crate like this
#[derive(PartialEq)]
pub struct Version(u32);
impl Version {
pub const v0: Self = Self(0);
pub const v1: Self = Self(1);
}
Now, in my code I need to wrap it with a newtype pattern. So far so good.
#[derive(PartialEq)]
pub struct MyVersion(Version);
I want to get the inner constant using the wrapper type along the lines of MyVersion::v0. Is this doable?
Rust Playground link
Thanks to #Sven for suggesting a solution that works with stable Rust.
A way out of this is to implement a trait with an associated type. The end usage is awkward (due to E0223), but at least re-defining constants and associated methods is unnecessary.
// original crate
#[derive(Debug, PartialEq)]
pub struct Version(u32);
impl Version {
pub const V0: Self = Self(0);
pub const V1: Self = Self(1);
}
// another crate
use std::ops::Deref;
#[derive(Debug, PartialEq)]
pub struct MyVersion(Version);
impl Deref for MyVersion {
type Target = Version;
fn deref(&self) -> &Self::Target {
&self.0
}
}
trait Versioning {
type V;
}
impl Versioning for MyVersion {
type V = Version;
}
fn main() {
let myv0 = MyVersion(Version::V0);
assert_eq!(*myv0, <MyVersion as Versioning>::V::V0);
}
The custom trait will probably not be needed when inherent associated type lands in the stable channel.
Say, for purposes of conjecture, that you have three files: main.rs, struct.rs, and impl.rs. Could you define a struct in struct.rs, put an impl there, put another impl in impl.rs, and then use both sets of impls from main.rs? If so, how?
Project structure:
main.rs:
use struct;
use impl;
main() {
let foobar = struct::Struct::new(); // defined in struct.rs
foobar.x(); // defined in impl.rs
}
struct.rs:
Define Struct, first impl
impl.rs:
Second impl
Yes, this is possible. You can provide implementations for your struct throughout the crate. You just can't provide impls for types from foreign crates. And you don't need to do anything special to make this work – just make sure the struct is visible in main. Of course you can't name your modules struct and impl, since these are reserved words.
Here's some example code:
fn main() {
use struct_::A;
A::foo();
A::bar();
}
pub mod struct_ {
pub struct A;
impl A {
pub fn foo() {}
}
}
mod impl_ {
impl crate::struct_::A {
pub fn bar() {}
}
}
(Playground)
Suppose I have the following trait in a library:
pub trait Foo {
fn public_op(&self);
fn internal_op(&self);
}
This trait is then implemented for a bunch of structs in this library:
pub struct One {}
impl Foo for One {
fn public_op(&self) {}
fn internal_op(&self) {}
}
pub struct Two {}
impl Foo for Two {
fn public_op(&self) {}
fn internal_op(&self) {}
}
And there is a public function in this library which receives the trait type:
pub fn process(obj: &dyn Foo) {
obj.public_op();
obj.internal_op();
}
The problem is that, since Foo trait is public in the library, the method internal_op is also public... but in fact it should have pub(crate) visibility, because it must be used inside the library only.
As far as I know, all methods of a trait are public, so how can I redesign this problem?
You can split Foo into two traits, one public and one private.
pub trait Foo: private::Foo {
fn public_op(&self);
}
pub(crate) mod private {
pub trait Foo {
fn internal_op(&self);
}
}
Then implement them both in your library crate as follows:
pub struct One {}
impl Foo for One {
fn public_op(&self) {}
}
impl private::Foo for One {
fn internal_op(&self) {}
}
Then using from outside the library crate would look like:
fn main() {
let one = One {};
one.public_op(); // works
process(&one); // works
//one.internal_op(); // error[E0599]: no method named `internal_op`...
}
This does mean that its impossible for users of your library to implement Foo as Foo is now effectively a 'sealed trait'.
See Jack Wrenn's blog post for a discussion of this and alternative approaches.
Rust playground link
I am trying to use mockiato to mock a function that accepts an Option of my struct A but am receiving the following error.
error: implementation of `std::cmp::PartialEq` is not general enough
--> src\main.rs:45:14
|
45 | .expect_do_feature(|arg| arg.partial_eq(Some(&cfg)))
| ^^^^^^^^^^^^^^^^^ implementation of `std::cmp::PartialEq` is not general enough
|
= note: `std::cmp::PartialEq<std::option::Option<&'1 A>>` would have to be implemented for the type `std::option::Option<&A>`, for any lifetime `'1`...
= note: ...but `std::cmp::PartialEq` is actually implemented for the type `std::option::Option<&'2 A>`, for some specific lifetime `'2`
I would've thought the #[derive(PartialEq)] on the struct A would generate what was needed, but it looks like it doesn't quite do the full job. How do I implement what the compiler is telling me to do?
use std::collections::HashMap;
#[cfg(test)]
use mockiato::mockable;
#[derive(PartialEq)]
pub struct A {
pub data: HashMap<String, i32>,
}
impl A {
pub fn new() -> Self {
A {
data: HashMap::new(),
}
}
}
pub struct B;
#[cfg_attr(test, mockable)]
pub trait ProvidesFeature {
fn do_feature(&self, config: Option<&A>) -> Option<Vec<i32>>;
}
impl B {
pub fn new() -> Self {
B {}
}
pub fn do_feature(&self, config: Option<&A>) -> Option<Vec<i32>> {
Some(vec!())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mocking() {
let mut feature_mock = ProvidesFeatureMock::new();
feature_mock
.expect_do_feature(|arg| arg.partial_eq(None))
.times(1..)
.returns(Some(vec!()));
assert_eq!(vec![0; 0], feature_mock.do_feature(None).unwrap());
}
}
fn main() {
println!("Hello, world!");
}
In order to compile, I used mockiato = "0.9.5" in Cargo.toml. Don't forget to run this with cargo test if you attempt to reproduce.
#![feature(rustc_private)]
extern crate rustc;
use rustc::hir::intravisit as hir_visit;
use rustc::hir;
use std::marker::PhantomData;
// ----------------------------------------------------------------------------
// Why does this compile?
// ----------------------------------------------------------------------------
pub struct Map<'a> {
pub _m: PhantomData<&'a ()>,
}
pub struct SomeVisitor<'a, 'tcx: 'a> {
pub map: &'a Map<'tcx>,
}
pub enum NestedVisitorMap<'this, 'tcx: 'this> {
None,
OnlyBodies(&'this Map<'tcx>),
All(&'this Map<'tcx>),
}
pub trait Visitor<'v>: Sized {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v>;
}
impl<'v, 'tcx> Visitor<'v> for SomeVisitor<'v, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
NestedVisitorMap::All(self.map)
}
}
// ----------------------------------------------------------------------------
// Why does this *not* compile?
// ----------------------------------------------------------------------------
pub struct SomeVisitor2<'a, 'tcx: 'a> {
pub map: &'a hir::map::Map<'tcx>,
}
impl<'v, 'tcx> hir_visit::Visitor<'v> for SomeVisitor2<'v, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'v> {
hir_visit::NestedVisitorMap::All(self.map)
}
}
fn main() {}
playground
NestedVisitorMap and Visitor
I recently ran into a lifetime issue and I decided to recreate it without any dependencies. The odd thing is that I can not recreate the lifetime error. To me both implementations look the same from the outside, but only one compiles successfully. Why is that?
rustc 1.21.0-nightly (e26688824 2017-08-27)
Update:
The problem seems to be the RefCell inside Map.
#[derive(Clone)]
pub struct Map<'hir> {
inlined_bodies: RefCell<rustc::util::nodemap::DefIdMap<&'hir hir::Body>>,
}
If there is a RefCell with a inner lifetime, it will trigger an error.
playground
Update2:
It turns out that I just mixed up lifetime subtyping. playground
I still don't know why only RefCell causes the error.