constant: Handle Self in associated constants.

WebRender used to do this and it's not hard to handle.
This commit is contained in:
Emilio Cobos Álvarez 2019-03-07 16:48:49 +01:00 committed by Ryan Hunt
parent 60d8234bf3
commit e14f782743
9 changed files with 83 additions and 11 deletions

View File

@ -36,6 +36,24 @@ pub enum Literal {
}
impl Literal {
fn replace_self_with(&mut self, self_ty: &Path) {
match *self {
Literal::BinOp { .. } | Literal::Expr(..) => {}
Literal::Struct {
ref mut path,
ref mut export_name,
ref mut fields,
} => {
if path.replace_self_with(self_ty) {
*export_name = self_ty.name().to_owned();
}
for &mut (ref _name, ref mut expr) in fields {
expr.replace_self_with(self_ty);
}
}
}
}
fn is_valid(&self, bindings: &Bindings) -> bool {
match *self {
Literal::Expr(..) => true,
@ -225,7 +243,7 @@ impl Constant {
associated_to: Option<Path>,
) -> Result<Constant, String> {
let ty = Type::load(ty)?;
let ty = match ty {
let mut ty = match ty {
Some(ty) => ty,
None => {
return Err("Cannot have a zero sized const definition.".to_owned());
@ -236,10 +254,17 @@ impl Constant {
return Err("Unhanded const definition".to_owned());
}
let mut lit = Literal::load(&expr)?;
if let Some(ref associated_to) = associated_to {
ty.replace_self_with(associated_to);
lit.replace_self_with(associated_to);
}
Ok(Constant::new(
path,
ty,
Literal::load(&expr)?,
lit,
Cfg::append(mod_cfg, Cfg::load(attrs)),
AnnotationSet::load(attrs)?,
Documentation::load(attrs),

View File

@ -74,6 +74,15 @@ impl GenericPath {
}
}
pub fn replace_self_with(&mut self, self_ty: &Path) {
if self.path.replace_self_with(self_ty) {
self.export_name = self_ty.name().to_owned();
}
for ty in &mut self.generics {
ty.replace_self_with(self_ty);
}
}
pub fn path(&self) -> &Path {
&self.path
}

View File

@ -21,6 +21,14 @@ impl Path {
pub fn name(&self) -> &str {
&self.name
}
pub fn replace_self_with(&mut self, path: &Self) -> bool {
if self.name() != "Self" {
return false;
}
*self = path.clone();
true
}
}
impl PartialOrd for Path {

View File

@ -393,24 +393,44 @@ impl Type {
}
}
pub fn replace_self_with(&mut self, self_ty: &Path) {
match *self {
Type::Array(ref mut ty, ..)
| Type::MutRef(ref mut ty)
| Type::Ref(ref mut ty)
| Type::Ptr(ref mut ty)
| Type::ConstPtr(ref mut ty) => ty.replace_self_with(self_ty),
Type::Path(ref mut generic_path) => {
generic_path.replace_self_with(self_ty);
}
Type::Primitive(..) => {}
Type::FuncPtr(ref mut ret, ref mut args) => {
ret.replace_self_with(self_ty);
for arg in args {
arg.1.replace_self_with(self_ty);
}
}
}
}
pub fn get_root_path(&self) -> Option<Path> {
let mut current = self;
loop {
match current {
&Type::ConstPtr(ref ty) => current = ty,
&Type::Ptr(ref ty) => current = ty,
&Type::Ref(ref ty) => current = ty,
&Type::MutRef(ref ty) => current = ty,
&Type::Path(ref generic) => {
match *current {
Type::ConstPtr(ref ty) => current = ty,
Type::Ptr(ref ty) => current = ty,
Type::Ref(ref ty) => current = ty,
Type::MutRef(ref ty) => current = ty,
Type::Path(ref generic) => {
return Some(generic.path().clone());
}
&Type::Primitive(..) => {
Type::Primitive(..) => {
return None;
}
&Type::Array(..) => {
Type::Array(..) => {
return None;
}
&Type::FuncPtr(..) => {
Type::FuncPtr(..) => {
return None;
}
};

View File

@ -10,6 +10,8 @@ typedef struct Foo {
uint32_t b;
} Foo;
#define Foo_FOO (Foo){ .a = 42, .b = 47 }
#define Foo_FOO2 (Foo){ .a = 42, .b = 47 }
#define Foo_FOO3 (Foo){ .a = 42, .b = 47 }
#define BAR (Foo){ .a = 42, .b = 1337 }

View File

@ -10,6 +10,8 @@ typedef struct {
uint32_t b;
} Foo;
#define Foo_FOO (Foo){ .a = 42, .b = 47 }
#define Foo_FOO2 (Foo){ .a = 42, .b = 47 }
#define Foo_FOO3 (Foo){ .a = 42, .b = 47 }
#define BAR (Foo){ .a = 42, .b = 1337 }

View File

@ -9,6 +9,8 @@ struct Foo {
uint32_t b;
};
static const Foo Foo_FOO = (Foo){ .a = 42, .b = 47 };
static const Foo Foo_FOO2 = (Foo){ .a = 42, .b = 47 };
static const Foo Foo_FOO3 = (Foo){ .a = 42, .b = 47 };
static const Foo BAR = (Foo){ .a = 42, .b = 1337 };

View File

@ -10,6 +10,8 @@ struct Foo {
uint32_t b;
};
#define Foo_FOO (Foo){ .a = 42, .b = 47 }
#define Foo_FOO2 (Foo){ .a = 42, .b = 47 }
#define Foo_FOO3 (Foo){ .a = 42, .b = 47 }
#define BAR (Foo){ .a = 42, .b = 1337 }

View File

@ -11,6 +11,8 @@ struct Bar {
impl Foo {
const FOO: Foo = Foo { a: 42, b: 47, };
const FOO2: Self = Foo { a: 42, b: 47, };
const FOO3: Self = Self { a: 42, b: 47, };
const BAZ: Bar = Bar { a: 42, b: 47, };
}