constant: Handle Self in associated constants.
WebRender used to do this and it's not hard to handle.
This commit is contained in:
parent
60d8234bf3
commit
e14f782743
@ -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),
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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 };
|
||||
|
@ -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 }
|
||||
|
@ -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, };
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user