Skip to content

Commit e42afd3

Browse files
committed
Let const_deref "dereference" newtypes.
1 parent 5ca1d35 commit e42afd3

File tree

1 file changed

+47
-10
lines changed

1 file changed

+47
-10
lines changed

src/librustc/middle/trans/consts.rs

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,46 @@ fn const_addr_of(cx: @CrateContext, cv: ValueRef) -> ValueRef {
106106
}
107107
}
108108

109-
pub fn const_deref(cx: @CrateContext, v: ValueRef) -> ValueRef {
109+
fn const_deref_ptr(cx: @CrateContext, v: ValueRef) -> ValueRef {
110+
let v = match cx.const_globals.find(&(v as int)) {
111+
Some(v) => v,
112+
None => v
113+
};
110114
unsafe {
111-
let v = match cx.const_globals.find(&(v as int)) {
112-
Some(v) => v,
113-
None => v
114-
};
115115
fail_unless!(llvm::LLVMIsGlobalConstant(v) == True);
116-
let v = llvm::LLVMGetInitializer(v);
117-
v
116+
llvm::LLVMGetInitializer(v)
117+
}
118+
}
119+
120+
fn const_deref_newtype(cx: @CrateContext, v: ValueRef, t: ty::t)
121+
-> ValueRef {
122+
let repr = adt::represent_type(cx, t);
123+
adt::const_get_field(cx, repr, v, 0, 0)
124+
}
125+
126+
fn const_deref(cx: @CrateContext, v: ValueRef, t: ty::t, explicit: bool)
127+
-> (ValueRef, ty::t) {
128+
match ty::deref(cx.tcx, t, explicit) {
129+
Some(ref mt) => {
130+
fail_unless!(mt.mutbl != ast::m_mutbl);
131+
let dv = match ty::get(t).sty {
132+
ty::ty_ptr(*) | ty::ty_rptr(*) => {
133+
const_deref_ptr(cx, v)
134+
}
135+
ty::ty_enum(*) | ty::ty_struct(*) => {
136+
const_deref_newtype(cx, v, t)
137+
}
138+
_ => {
139+
cx.sess.bug(fmt!("Unexpected dereferenceable type %s",
140+
ty_to_str(cx.tcx, t)))
141+
}
142+
};
143+
(dv, mt.ty)
144+
}
145+
None => {
146+
cx.sess.bug(fmt!("Can't dereference const of type %s",
147+
ty_to_str(cx.tcx, t)))
148+
}
118149
}
119150
}
120151

@@ -150,8 +181,11 @@ pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef {
150181
region %? sigil %?", *r, *s))
151182
}
152183
Some(@ty::AutoDerefRef(ref adj)) => {
184+
let mut ty = ety;
153185
for adj.autoderefs.times {
154-
llconst = const_deref(cx, llconst)
186+
let (dv, dt) = const_deref(cx, llconst, ty, false);
187+
llconst = dv;
188+
ty = dt;
155189
}
156190

157191
match adj.autoref {
@@ -263,7 +297,10 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
263297
return match u {
264298
ast::box(_) |
265299
ast::uniq(_) |
266-
ast::deref => const_deref(cx, te),
300+
ast::deref => {
301+
let (dv, _dt) = const_deref(cx, te, ty, true);
302+
dv
303+
}
267304
ast::not => {
268305
match ty::get(ty).sty {
269306
ty::ty_bool => {
@@ -313,7 +350,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef {
313350
let llunitty = type_of::type_of(cx, unit_ty);
314351
let unit_sz = machine::llsize_of(cx, llunitty);
315352

316-
(const_deref(cx, const_get_elt(cx, bv, [0])),
353+
(const_deref_ptr(cx, const_get_elt(cx, bv, [0])),
317354
llvm::LLVMConstUDiv(const_get_elt(cx, bv, [1]),
318355
unit_sz))
319356
},

0 commit comments

Comments
 (0)