Skip to content

Commit

Permalink
ast: make = <expr>; optional in free statics/consts.
Browse files Browse the repository at this point in the history
  • Loading branch information
Centril committed Feb 15, 2020
1 parent 95dc9b9 commit f3e9763
Show file tree
Hide file tree
Showing 19 changed files with 250 additions and 132 deletions.
37 changes: 19 additions & 18 deletions src/librustc_ast_lowering/item.rs
Expand Up @@ -269,26 +269,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs)
}
ItemKind::Static(ref t, m, ref e) => {
let ty = self.lower_ty(
t,
if self.sess.features_untracked().impl_trait_in_bindings {
ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc)
} else {
ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
},
);
hir::ItemKind::Static(ty, m, self.lower_const_body(span, Some(e)))
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
hir::ItemKind::Static(ty, m, body_id)
}
ItemKind::Const(ref t, ref e) => {
let ty = self.lower_ty(
t,
if self.sess.features_untracked().impl_trait_in_bindings {
ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc)
} else {
ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
},
);
hir::ItemKind::Const(ty, self.lower_const_body(span, Some(e)))
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
hir::ItemKind::Const(ty, body_id)
}
ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => {
let fn_def_id = self.resolver.definitions().local_def_id(id);
Expand Down Expand Up @@ -457,6 +443,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
// not cause an assertion failure inside the `lower_defaultness` function.
}

fn lower_const_item(
&mut self,
ty: &Ty,
span: Span,
body: Option<&Expr>,
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
let itctx = if self.sess.features_untracked().impl_trait_in_bindings {
ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc)
} else {
ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
};
let ty = self.lower_ty(ty, itctx);
(ty, self.lower_const_body(span, body))
}

fn lower_use_tree(
&mut self,
tree: &UseTree,
Expand Down
8 changes: 8 additions & 0 deletions src/librustc_ast_passes/ast_validation.rs
Expand Up @@ -948,6 +948,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.err_handler().span_err(item.span, "unions cannot have zero fields");
}
}
ItemKind::Const(.., None) => {
let msg = "free constant item without body";
self.error_item_without_body(item.span, "constant", msg, " = <expr>;");
}
ItemKind::Static(.., None) => {
let msg = "free static item without body";
self.error_item_without_body(item.span, "static", msg, " = <expr>;");
}
_ => {}
}

Expand Down
14 changes: 8 additions & 6 deletions src/librustc_ast_pretty/pprust.rs
Expand Up @@ -1124,9 +1124,10 @@ impl<'a> State<'a> {
self.print_type(ty);
self.s.space();
self.end(); // end the head-ibox

self.word_space("=");
self.print_expr(expr);
if let Some(expr) = expr {
self.word_space("=");
self.print_expr(expr);
}
self.s.word(";");
self.end(); // end the outer cbox
}
Expand All @@ -1137,9 +1138,10 @@ impl<'a> State<'a> {
self.print_type(ty);
self.s.space();
self.end(); // end the head-ibox

self.word_space("=");
self.print_expr(expr);
if let Some(expr) = expr {
self.word_space("=");
self.print_expr(expr);
}
self.s.word(";");
self.end(); // end the outer cbox
}
Expand Down
148 changes: 76 additions & 72 deletions src/librustc_builtin_macros/test.rs
Expand Up @@ -186,81 +186,85 @@ pub fn expand_test_or_bench(
ast::ItemKind::Const(
cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
// test::TestDescAndFn {
cx.expr_struct(
sp,
test_path("TestDescAndFn"),
vec![
// desc: test::TestDesc {
field(
"desc",
cx.expr_struct(
sp,
test_path("TestDesc"),
vec![
// name: "path::to::test"
field(
"name",
cx.expr_call(
sp,
cx.expr_path(test_path("StaticTestName")),
vec![cx.expr_str(
sp,
Symbol::intern(&item_path(
// skip the name of the root module
&cx.current_expansion.module.mod_path[1..],
&item.ident,
)),
)],
),
),
// ignore: true | false
field("ignore", cx.expr_bool(sp, should_ignore(&item))),
// allow_fail: true | false
field("allow_fail", cx.expr_bool(sp, should_fail(&item))),
// should_panic: ...
field(
"should_panic",
match should_panic(cx, &item) {
// test::ShouldPanic::No
ShouldPanic::No => cx.expr_path(should_panic_path("No")),
// test::ShouldPanic::Yes
ShouldPanic::Yes(None) => {
cx.expr_path(should_panic_path("Yes"))
}
// test::ShouldPanic::YesWithMessage("...")
ShouldPanic::Yes(Some(sym)) => cx.expr_call(
Some(
cx.expr_struct(
sp,
test_path("TestDescAndFn"),
vec![
// desc: test::TestDesc {
field(
"desc",
cx.expr_struct(
sp,
test_path("TestDesc"),
vec![
// name: "path::to::test"
field(
"name",
cx.expr_call(
sp,
cx.expr_path(should_panic_path("YesWithMessage")),
vec![cx.expr_str(sp, sym)],
cx.expr_path(test_path("StaticTestName")),
vec![cx.expr_str(
sp,
Symbol::intern(&item_path(
// skip the name of the root module
&cx.current_expansion.module.mod_path[1..],
&item.ident,
)),
)],
),
},
),
// test_type: ...
field(
"test_type",
match test_type(cx) {
// test::TestType::UnitTest
TestType::UnitTest => {
cx.expr_path(test_type_path("UnitTest"))
}
// test::TestType::IntegrationTest
TestType::IntegrationTest => {
cx.expr_path(test_type_path("IntegrationTest"))
}
// test::TestPath::Unknown
TestType::Unknown => {
cx.expr_path(test_type_path("Unknown"))
}
},
),
// },
],
),
// ignore: true | false
field("ignore", cx.expr_bool(sp, should_ignore(&item))),
// allow_fail: true | false
field("allow_fail", cx.expr_bool(sp, should_fail(&item))),
// should_panic: ...
field(
"should_panic",
match should_panic(cx, &item) {
// test::ShouldPanic::No
ShouldPanic::No => {
cx.expr_path(should_panic_path("No"))
}
// test::ShouldPanic::Yes
ShouldPanic::Yes(None) => {
cx.expr_path(should_panic_path("Yes"))
}
// test::ShouldPanic::YesWithMessage("...")
ShouldPanic::Yes(Some(sym)) => cx.expr_call(
sp,
cx.expr_path(should_panic_path("YesWithMessage")),
vec![cx.expr_str(sp, sym)],
),
},
),
// test_type: ...
field(
"test_type",
match test_type(cx) {
// test::TestType::UnitTest
TestType::UnitTest => {
cx.expr_path(test_type_path("UnitTest"))
}
// test::TestType::IntegrationTest
TestType::IntegrationTest => {
cx.expr_path(test_type_path("IntegrationTest"))
}
// test::TestPath::Unknown
TestType::Unknown => {
cx.expr_path(test_type_path("Unknown"))
}
},
),
// },
],
),
),
),
// testfn: test::StaticTestFn(...) | test::StaticBenchFn(...)
field("testfn", test_fn), // }
],
), // }
// testfn: test::StaticTestFn(...) | test::StaticBenchFn(...)
field("testfn", test_fn), // }
],
), // }
),
),
);
test_const = test_const.map(|mut tc| {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_expand/build.rs
Expand Up @@ -634,7 +634,7 @@ impl<'a> ExtCtxt<'a> {
mutbl: ast::Mutability,
expr: P<ast::Expr>,
) -> P<ast::Item> {
self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, expr))
self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr)))
}

pub fn item_const(
Expand All @@ -644,7 +644,7 @@ impl<'a> ExtCtxt<'a> {
ty: P<ast::Ty>,
expr: P<ast::Expr>,
) -> P<ast::Item> {
self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, expr))
self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, Some(expr)))
}

pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_lint/unused.rs
Expand Up @@ -603,7 +603,7 @@ impl EarlyLintPass for UnusedParens {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
use ast::ItemKind::*;

if let Const(.., ref expr) | Static(.., ref expr) = item.kind {
if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind {
self.check_unused_parens_expr(cx, expr, "assigned value", false, None, None);
}
}
Expand Down
19 changes: 8 additions & 11 deletions src/librustc_parse/parser/item.rs
Expand Up @@ -966,7 +966,7 @@ impl<'a> Parser<'a> {
}
}

/// Parse `["const" | ("static" "mut"?)] $ident ":" $ty = $expr` with
/// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with
/// `["const" | ("static" "mut"?)]` already parsed and stored in `m`.
///
/// When `m` is `"const"`, `$ident` may also be `"_"`.
Expand All @@ -975,25 +975,22 @@ impl<'a> Parser<'a> {

// Parse the type of a `const` or `static mut?` item.
// That is, the `":" $ty` fragment.
let ty = if self.token == token::Eq {
self.recover_missing_const_type(id, m)
} else {
// Not `=` so expect `":"" $ty` as usual.
self.expect(&token::Colon)?;
let ty = if self.eat(&token::Colon) {
self.parse_ty()?
} else {
self.recover_missing_const_type(id, m)
};

self.expect(&token::Eq)?;
let e = self.parse_expr()?;
let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
self.expect_semi()?;
let item = match m {
Some(m) => ItemKind::Static(ty, m, e),
None => ItemKind::Const(ty, e),
Some(m) => ItemKind::Static(ty, m, expr),
None => ItemKind::Const(ty, expr),
};
Ok((id, item))
}

/// We were supposed to parse `:` but instead, we're already at `=`.
/// We were supposed to parse `:` but the `:` was missing.
/// This means that the type is missing.
fn recover_missing_const_type(&mut self, id: Ident, m: Option<Mutability>) -> P<Ty> {
// Construct the error and stash it away with the hope
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_resolve/late.rs
Expand Up @@ -881,9 +881,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
debug!("resolve_item ItemKind::Const");
self.with_item_rib(HasGenericParams::No, |this| {
this.visit_ty(ty);
this.with_constant_rib(|this| {
this.visit_expr(expr);
});
if let Some(expr) = expr {
this.with_constant_rib(|this| this.visit_expr(expr));
}
});
}

Expand Down
8 changes: 4 additions & 4 deletions src/librustc_save_analysis/dump_visitor.rs
Expand Up @@ -400,7 +400,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
&mut self,
item: &'l ast::Item,
typ: &'l ast::Ty,
expr: &'l ast::Expr,
expr: Option<&'l ast::Expr>,
) {
let hir_id = self.tcx.hir().node_to_hir_id(item.id);
self.nest_tables(item.id, |v| {
Expand All @@ -409,7 +409,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), var_data);
}
v.visit_ty(&typ);
v.visit_expr(expr);
walk_list!(v, visit_expr, expr);
});
}

Expand Down Expand Up @@ -1293,8 +1293,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
Fn(ref sig, ref ty_params, ref body) => {
self.process_fn(item, &sig.decl, &sig.header, ty_params, body.as_deref())
}
Static(ref typ, _, ref expr) => self.process_static_or_const_item(item, typ, expr),
Const(ref typ, ref expr) => self.process_static_or_const_item(item, &typ, &expr),
Static(ref typ, _, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()),
Const(ref typ, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()),
Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => {
self.process_struct(item, def, ty_params)
}
Expand Down
18 changes: 12 additions & 6 deletions src/librustc_save_analysis/sig.rs
Expand Up @@ -334,10 +334,13 @@ impl Sig for ast::Item {

let ty = ty.make(offset + text.len(), id, scx)?;
text.push_str(&ty.text);
text.push_str(" = ");

let expr = pprust::expr_to_string(expr).replace('\n', " ");
text.push_str(&expr);
if let Some(expr) = expr {
text.push_str(" = ");
let expr = pprust::expr_to_string(expr).replace('\n', " ");
text.push_str(&expr);
}

text.push(';');

Ok(extend_sig(ty, text, defs, vec![]))
Expand All @@ -355,10 +358,13 @@ impl Sig for ast::Item {

let ty = ty.make(offset + text.len(), id, scx)?;
text.push_str(&ty.text);
text.push_str(" = ");

let expr = pprust::expr_to_string(expr).replace('\n', " ");
text.push_str(&expr);
if let Some(expr) = expr {
text.push_str(" = ");
let expr = pprust::expr_to_string(expr).replace('\n', " ");
text.push_str(&expr);
}

text.push(';');

Ok(extend_sig(ty, text, defs, vec![]))
Expand Down

0 comments on commit f3e9763

Please sign in to comment.