Skip to content

Commit 6c12a3d

Browse files
committed
Merge pull request #20295 from eddyb/poly-const
Allow paths in constants to refer to polymorphic items. Reviewed-by: nikomatsakis
2 parents c6c7866 + c37e7ae commit 6c12a3d

File tree

14 files changed

+322
-272
lines changed

14 files changed

+322
-272
lines changed

src/librustc/middle/check_const.rs

Lines changed: 40 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ use middle::ty;
1414
use util::ppaux;
1515

1616
use syntax::ast;
17-
use syntax::ast_util;
18-
use syntax::visit::Visitor;
19-
use syntax::visit;
17+
use syntax::visit::{mod, Visitor};
2018

2119
struct CheckCrateVisitor<'a, 'tcx: 'a> {
2220
tcx: &'a ty::ctxt<'tcx>,
@@ -37,24 +35,39 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
3735
{
3836
self.with_const(true, f);
3937
}
40-
fn outside_const<F>(&mut self, f: F) where
41-
F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
42-
{
43-
self.with_const(false, f);
44-
}
4538
}
4639

4740
impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
4841
fn visit_item(&mut self, i: &ast::Item) {
49-
check_item(self, i);
42+
match i.node {
43+
ast::ItemStatic(_, _, ref ex) |
44+
ast::ItemConst(_, ref ex) => {
45+
self.inside_const(|v| v.visit_expr(&**ex));
46+
}
47+
ast::ItemEnum(ref enum_definition, _) => {
48+
self.inside_const(|v| {
49+
for var in enum_definition.variants.iter() {
50+
if let Some(ref ex) = var.node.disr_expr {
51+
v.visit_expr(&**ex);
52+
}
53+
}
54+
});
55+
}
56+
_ => self.with_const(false, |v| visit::walk_item(v, i))
57+
}
5058
}
5159
fn visit_pat(&mut self, p: &ast::Pat) {
52-
check_pat(self, p);
60+
let is_const = match p.node {
61+
ast::PatLit(_) | ast::PatRange(..) => true,
62+
_ => false
63+
};
64+
self.with_const(is_const, |v| visit::walk_pat(v, p))
5365
}
5466
fn visit_expr(&mut self, ex: &ast::Expr) {
55-
if check_expr(self, ex) {
56-
visit::walk_expr(self, ex);
67+
if self.in_const {
68+
check_expr(self, ex);
5769
}
70+
visit::walk_expr(self, ex);
5871
}
5972
}
6073

@@ -64,57 +77,13 @@ pub fn check_crate(tcx: &ty::ctxt) {
6477
tcx.sess.abort_if_errors();
6578
}
6679

67-
fn check_item(v: &mut CheckCrateVisitor, it: &ast::Item) {
68-
match it.node {
69-
ast::ItemStatic(_, _, ref ex) |
70-
ast::ItemConst(_, ref ex) => {
71-
v.inside_const(|v| v.visit_expr(&**ex));
72-
}
73-
ast::ItemEnum(ref enum_definition, _) => {
74-
for var in (*enum_definition).variants.iter() {
75-
for ex in var.node.disr_expr.iter() {
76-
v.inside_const(|v| v.visit_expr(&**ex));
77-
}
78-
}
79-
}
80-
_ => v.outside_const(|v| visit::walk_item(v, it))
81-
}
82-
}
83-
84-
fn check_pat(v: &mut CheckCrateVisitor, p: &ast::Pat) {
85-
fn is_str(e: &ast::Expr) -> bool {
86-
match e.node {
87-
ast::ExprBox(_, ref expr) => {
88-
match expr.node {
89-
ast::ExprLit(ref lit) => ast_util::lit_is_str(&**lit),
90-
_ => false,
91-
}
92-
}
93-
_ => false,
94-
}
95-
}
96-
match p.node {
97-
// Let through plain ~-string literals here
98-
ast::PatLit(ref a) => if !is_str(&**a) { v.inside_const(|v| v.visit_expr(&**a)); },
99-
ast::PatRange(ref a, ref b) => {
100-
if !is_str(&**a) { v.inside_const(|v| v.visit_expr(&**a)); }
101-
if !is_str(&**b) { v.inside_const(|v| v.visit_expr(&**b)); }
102-
}
103-
_ => v.outside_const(|v| visit::walk_pat(v, p))
104-
}
105-
}
106-
107-
fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
108-
if !v.in_const { return true }
109-
80+
fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
11081
match e.node {
11182
ast::ExprUnary(ast::UnDeref, _) => {}
11283
ast::ExprUnary(ast::UnUniq, _) => {
11384
span_err!(v.tcx.sess, e.span, E0010,
11485
"cannot do allocations in constant expressions");
115-
return false;
11686
}
117-
ast::ExprLit(ref lit) if ast_util::lit_is_str(&**lit) => {}
11887
ast::ExprBinary(..) | ast::ExprUnary(..) => {
11988
let method_call = ty::MethodCall::expr(e.id);
12089
if v.tcx.method_map.borrow().contains_key(&method_call) {
@@ -123,7 +92,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
12392
expressions");
12493
}
12594
}
126-
ast::ExprLit(_) => (),
95+
ast::ExprLit(_) => {}
12796
ast::ExprCast(ref from, _) => {
12897
let toty = ty::expr_ty(v.tcx, e);
12998
let fromty = ty::expr_ty(v.tcx, &**from);
@@ -142,39 +111,23 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
142111
expression");
143112
}
144113
}
145-
ast::ExprPath(ref pth) => {
146-
// NB: In the future you might wish to relax this slightly
147-
// to handle on-demand instantiation of functions via
148-
// foo::<bar> in a const. Currently that is only done on
149-
// a path in trans::callee that only works in block contexts.
150-
if !pth.segments.iter().all(|segment| segment.parameters.is_empty()) {
151-
span_err!(v.tcx.sess, e.span, E0013,
152-
"paths in constants may only refer to items without \
153-
type parameters");
154-
}
155-
match v.tcx.def_map.borrow().get(&e.id) {
156-
Some(&DefStatic(..)) |
157-
Some(&DefConst(..)) |
158-
Some(&DefFn(..)) |
159-
Some(&DefVariant(_, _, _)) |
160-
Some(&DefStruct(_)) => { }
114+
ast::ExprPath(_) => {
115+
match v.tcx.def_map.borrow()[e.id] {
116+
DefStatic(..) | DefConst(..) |
117+
DefFn(..) | DefStaticMethod(..) | DefMethod(..) |
118+
DefStruct(_) | DefVariant(_, _, _) => {}
161119

162-
Some(&def) => {
120+
def => {
163121
debug!("(checking const) found bad def: {}", def);
164122
span_err!(v.tcx.sess, e.span, E0014,
165123
"paths in constants may only refer to constants \
166124
or functions");
167125
}
168-
None => {
169-
v.tcx.sess.span_bug(e.span, "unbound path in const?!");
170-
}
171126
}
172127
}
173128
ast::ExprCall(ref callee, _) => {
174-
match v.tcx.def_map.borrow().get(&callee.id) {
175-
Some(&DefStruct(..)) |
176-
Some(&DefVariant(..)) => {} // OK.
177-
129+
match v.tcx.def_map.borrow()[callee.id] {
130+
DefStruct(..) | DefVariant(..) => {} // OK.
178131
_ => {
179132
span_err!(v.tcx.sess, e.span, E0015,
180133
"function calls in constants are limited to \
@@ -190,9 +143,9 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
190143
"blocks in constants are limited to items and \
191144
tail expressions");
192145
match stmt.node {
193-
ast::StmtDecl(ref span, _) => {
194-
match span.node {
195-
ast::DeclLocal(_) => block_span_err(span.span),
146+
ast::StmtDecl(ref decl, _) => {
147+
match decl.node {
148+
ast::DeclLocal(_) => block_span_err(decl.span),
196149

197150
// Item statements are allowed
198151
ast::DeclItem(_) => {}
@@ -206,10 +159,6 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
206159
}
207160
}
208161
}
209-
match block.expr {
210-
Some(ref expr) => { check_expr(v, &**expr); }
211-
None => {}
212-
}
213162
}
214163
ast::ExprVec(_) |
215164
ast::ExprAddrOf(ast::MutImmutable, _) |
@@ -232,11 +181,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
232181
}
233182
}
234183

235-
_ => {
236-
span_err!(v.tcx.sess, e.span, E0019,
237-
"constant contains unimplemented expression type");
238-
return false;
239-
}
184+
_ => span_err!(v.tcx.sess, e.span, E0019,
185+
"constant contains unimplemented expression type")
240186
}
241-
true
242187
}

src/librustc/middle/mem_categorization.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -559,14 +559,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
559559
id, expr_ty.repr(self.tcx()), def);
560560

561561
match def {
562-
def::DefStruct(..) | def::DefVariant(..) | def::DefFn(..) |
563-
def::DefStaticMethod(..) | def::DefConst(..) => {
562+
def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
563+
def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
564564
Ok(self.cat_rvalue_node(id, span, expr_ty))
565565
}
566566
def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
567567
def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
568568
def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
569-
def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) |
569+
def::DefLabel(_) | def::DefSelfTy(..) |
570570
def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
571571
Ok(Rc::new(cmt_ {
572572
id:id,

src/librustc_trans/trans/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
511511
// Since we're in trans we don't care for any region parameters
512512
let substs = subst::Substs::erased(substs.types.clone());
513513

514-
let (val, _) = monomorphize::monomorphic_fn(ccx, did, &substs, None);
514+
let (val, _, _) = monomorphize::monomorphic_fn(ccx, did, &substs, None);
515515

516516
val
517517
} else if did.krate == ast::LOCAL_CRATE {

0 commit comments

Comments
 (0)