Auto merge of #40272 - jseyfried:fix_const_macro_invocations, r=petrochenkov
macros: fix const expression invocations Fixes #40136. r? @nrc
This commit is contained in:
commit
b04ebef432
4 changed files with 45 additions and 21 deletions
|
@ -26,7 +26,7 @@ pub struct DefCollector<'a> {
|
|||
pub struct MacroInvocationData {
|
||||
pub mark: Mark,
|
||||
pub def_index: DefIndex,
|
||||
pub const_integer: bool,
|
||||
pub const_expr: bool,
|
||||
}
|
||||
|
||||
impl<'a> DefCollector<'a> {
|
||||
|
@ -65,10 +65,10 @@ impl<'a> DefCollector<'a> {
|
|||
self.parent_def = parent;
|
||||
}
|
||||
|
||||
pub fn visit_ast_const_integer(&mut self, expr: &Expr) {
|
||||
pub fn visit_const_expr(&mut self, expr: &Expr) {
|
||||
match expr.node {
|
||||
// Find the node which will be used after lowering.
|
||||
ExprKind::Paren(ref inner) => return self.visit_ast_const_integer(inner),
|
||||
ExprKind::Paren(ref inner) => return self.visit_const_expr(inner),
|
||||
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, true),
|
||||
// FIXME(eddyb) Closures should have separate
|
||||
// function definition IDs and expression IDs.
|
||||
|
@ -79,11 +79,11 @@ impl<'a> DefCollector<'a> {
|
|||
self.create_def(expr.id, DefPathData::Initializer);
|
||||
}
|
||||
|
||||
fn visit_macro_invoc(&mut self, id: NodeId, const_integer: bool) {
|
||||
fn visit_macro_invoc(&mut self, id: NodeId, const_expr: bool) {
|
||||
if let Some(ref mut visit) = self.visit_macro_invoc {
|
||||
visit(MacroInvocationData {
|
||||
mark: Mark::from_placeholder_id(id),
|
||||
const_integer: const_integer,
|
||||
const_expr: const_expr,
|
||||
def_index: self.parent_def.unwrap(),
|
||||
})
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
}
|
||||
|
||||
if let Some(ref expr) = v.node.disr_expr {
|
||||
this.visit_ast_const_integer(expr);
|
||||
this.visit_const_expr(expr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
let def = self.create_def(ti.id, def_data);
|
||||
self.with_parent(def, |this| {
|
||||
if let TraitItemKind::Const(_, Some(ref expr)) = ti.node {
|
||||
this.create_def(expr.id, DefPathData::Initializer);
|
||||
this.visit_const_expr(expr);
|
||||
}
|
||||
|
||||
visit::walk_trait_item(this, ti);
|
||||
|
@ -212,7 +212,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
let def = self.create_def(ii.id, def_data);
|
||||
self.with_parent(def, |this| {
|
||||
if let ImplItemKind::Const(_, ref expr) = ii.node {
|
||||
this.create_def(expr.id, DefPathData::Initializer);
|
||||
this.visit_const_expr(expr);
|
||||
}
|
||||
|
||||
visit::walk_impl_item(this, ii);
|
||||
|
@ -240,7 +240,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
|
||||
match expr.node {
|
||||
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false),
|
||||
ExprKind::Repeat(_, ref count) => self.visit_ast_const_integer(count),
|
||||
ExprKind::Repeat(_, ref count) => self.visit_const_expr(count),
|
||||
ExprKind::Closure(..) => {
|
||||
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
|
||||
self.parent_def = Some(def);
|
||||
|
@ -255,11 +255,11 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
fn visit_ty(&mut self, ty: &'a Ty) {
|
||||
match ty.node {
|
||||
TyKind::Mac(..) => return self.visit_macro_invoc(ty.id, false),
|
||||
TyKind::Array(_, ref length) => self.visit_ast_const_integer(length),
|
||||
TyKind::Array(_, ref length) => self.visit_const_expr(length),
|
||||
TyKind::ImplTrait(..) => {
|
||||
self.create_def(ty.id, DefPathData::ImplTrait);
|
||||
}
|
||||
TyKind::Typeof(ref expr) => self.visit_ast_const_integer(expr),
|
||||
TyKind::Typeof(ref expr) => self.visit_const_expr(expr),
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_ty(self, ty);
|
||||
|
|
|
@ -511,7 +511,7 @@ impl<'a> Resolver<'a> {
|
|||
let invocation = self.arenas.alloc_invocation_data(InvocationData {
|
||||
module: Cell::new(self.get_extern_crate_root(def_id.krate)),
|
||||
def_index: CRATE_DEF_INDEX,
|
||||
const_integer: false,
|
||||
const_expr: false,
|
||||
legacy_scope: Cell::new(LegacyScope::Empty),
|
||||
expansion: Cell::new(LegacyScope::Empty),
|
||||
});
|
||||
|
|
|
@ -40,9 +40,9 @@ use syntax_pos::{Span, DUMMY_SP};
|
|||
pub struct InvocationData<'a> {
|
||||
pub module: Cell<Module<'a>>,
|
||||
pub def_index: DefIndex,
|
||||
// True if this expansion is in a `const_integer` position, for example `[u32; m!()]`.
|
||||
// c.f. `DefCollector::visit_ast_const_integer`.
|
||||
pub const_integer: bool,
|
||||
// True if this expansion is in a `const_expr` position, for example `[u32; m!()]`.
|
||||
// c.f. `DefCollector::visit_const_expr`.
|
||||
pub const_expr: bool,
|
||||
// The scope in which the invocation path is resolved.
|
||||
pub legacy_scope: Cell<LegacyScope<'a>>,
|
||||
// The smallest scope that includes this invocation's expansion,
|
||||
|
@ -55,7 +55,7 @@ impl<'a> InvocationData<'a> {
|
|||
InvocationData {
|
||||
module: Cell::new(graph_root),
|
||||
def_index: CRATE_DEF_INDEX,
|
||||
const_integer: false,
|
||||
const_expr: false,
|
||||
legacy_scope: Cell::new(LegacyScope::Empty),
|
||||
expansion: Cell::new(LegacyScope::Empty),
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
|
||||
module: Cell::new(module),
|
||||
def_index: module.def_id().unwrap().index,
|
||||
const_integer: false,
|
||||
const_expr: false,
|
||||
legacy_scope: Cell::new(LegacyScope::Empty),
|
||||
expansion: Cell::new(LegacyScope::Empty),
|
||||
}));
|
||||
|
@ -517,13 +517,13 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
fn collect_def_ids(&mut self, invocation: &'a InvocationData<'a>, expansion: &Expansion) {
|
||||
let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
|
||||
let InvocationData { def_index, const_integer, .. } = *invocation;
|
||||
let InvocationData { def_index, const_expr, .. } = *invocation;
|
||||
|
||||
let visit_macro_invoc = &mut |invoc: map::MacroInvocationData| {
|
||||
invocations.entry(invoc.mark).or_insert_with(|| {
|
||||
arenas.alloc_invocation_data(InvocationData {
|
||||
def_index: invoc.def_index,
|
||||
const_integer: invoc.const_integer,
|
||||
const_expr: invoc.const_expr,
|
||||
module: Cell::new(graph_root),
|
||||
expansion: Cell::new(LegacyScope::Empty),
|
||||
legacy_scope: Cell::new(LegacyScope::Empty),
|
||||
|
@ -534,9 +534,9 @@ impl<'a> Resolver<'a> {
|
|||
let mut def_collector = DefCollector::new(&mut self.definitions);
|
||||
def_collector.visit_macro_invoc = Some(visit_macro_invoc);
|
||||
def_collector.with_parent(def_index, |def_collector| {
|
||||
if const_integer {
|
||||
if const_expr {
|
||||
if let Expansion::Expr(ref expr) = *expansion {
|
||||
def_collector.visit_ast_const_integer(expr);
|
||||
def_collector.visit_const_expr(expr);
|
||||
}
|
||||
}
|
||||
expansion.visit_with(def_collector)
|
||||
|
|
24
src/test/run-pass/issue-40136.rs
Normal file
24
src/test/run-pass/issue-40136.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_consts)]
|
||||
|
||||
macro_rules! m { () => { 0 } }
|
||||
|
||||
trait T {
|
||||
const C: i32 = m!();
|
||||
}
|
||||
|
||||
struct S;
|
||||
impl S {
|
||||
const C: i32 = m!();
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Add table
Reference in a new issue