Avoid some duplicated typechecking work
There was a FIXME noting that ty::enum_variants and typeck::check:: check_enum_variants both call eval_const_expr. I tried refactoring the code so that check_enum_variants does all the work and enum_variants just looks up cached results, but this turned out not to be easy because several ty functions call enum_variants and it might get invoked on an enum before that enum item has been typechecked. Instead, I just made check_enum_variants update the enum_var_cache so that enum_variants will never call eval_const_expr twice on the same const.
This commit is contained in:
parent
aeb9a2b72c
commit
97bcb20244
@ -2693,9 +2693,11 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] {
|
||||
let result = if ast::local_crate != id.crate {
|
||||
@csearch::get_enum_variants(cx, id)
|
||||
} else {
|
||||
// FIXME: Now that the variants are run through the type checker (to
|
||||
// check the disr_expr if it exists), this code should likely be
|
||||
// moved there to avoid having to call eval_const_expr twice.
|
||||
/*
|
||||
Although both this code and check_enum_variants in typeck/check
|
||||
call eval_const_expr, it should never get called twice for the same
|
||||
expr, since check_enum_variants also updates the enum_var_cache
|
||||
*/
|
||||
alt cx.items.get(id.node) {
|
||||
ast_map::node_item(@{node: ast::item_enum(variants, _, _), _}, _) {
|
||||
let mut disr_val = -1;
|
||||
|
@ -1200,14 +1200,14 @@ fn check_expr_fn(fcx: @fn_ctxt,
|
||||
none {
|
||||
alt sty {
|
||||
ty::ty_enum(*) {
|
||||
tcx.sess.span_fatal(
|
||||
tcx.sess.span_err(
|
||||
expr.span,
|
||||
"can only dereference enums \
|
||||
with a single variant which has a \
|
||||
single argument");
|
||||
}
|
||||
_ {
|
||||
tcx.sess.span_fatal(
|
||||
tcx.sess.span_err(
|
||||
expr.span,
|
||||
#fmt["type %s cannot be dereferenced",
|
||||
fcx.infcx.ty_to_str(oper_t)]);
|
||||
@ -1892,6 +1892,7 @@ fn check_enum_variants(ccx: @crate_ctxt,
|
||||
let fcx = blank_fn_ctxt(ccx, rty);
|
||||
let mut disr_vals: [int] = [];
|
||||
let mut disr_val = 0;
|
||||
let mut variants = [];
|
||||
for vs.each {|v|
|
||||
alt v.node.disr_expr {
|
||||
some(e) {
|
||||
@ -1920,9 +1921,19 @@ fn check_enum_variants(ccx: @crate_ctxt,
|
||||
"discriminator value already exists.");
|
||||
}
|
||||
disr_vals += [disr_val];
|
||||
let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
|
||||
let arg_tys = if v.node.args.len() > 0u {
|
||||
ty::ty_fn_args(ctor_ty).map {|a| a.ty }
|
||||
} else { [] };
|
||||
variants += [@{args: arg_tys, ctor_ty: ctor_ty,
|
||||
name: v.node.name, id: local_def(v.node.id),
|
||||
disr_val: disr_val}];
|
||||
disr_val += 1;
|
||||
}
|
||||
|
||||
// cache so that ty::enum_variants won't repeat this work
|
||||
ccx.tcx.enum_var_cache.insert(local_def(id), @variants);
|
||||
|
||||
// Check that it is possible to represent this enum:
|
||||
let mut outer = true, did = local_def(id);
|
||||
if ty::type_structurally_contains(ccx.tcx, rty, {|sty|
|
||||
|
Loading…
Reference in New Issue
Block a user