rustc: introduce {ast,hir}::AnonConst to consolidate so-called "embedded constants".

This commit is contained in:
Eduard-Mihai Burtescu 2018-05-17 21:28:50 +03:00
parent 072b0f617f
commit 26aad25487
35 changed files with 334 additions and 306 deletions

View File

@ -272,6 +272,9 @@ pub trait Visitor<'v> : Sized {
fn visit_decl(&mut self, d: &'v Decl) {
walk_decl(self, d)
}
fn visit_anon_const(&mut self, c: &'v AnonConst) {
walk_anon_const(self, c)
}
fn visit_expr(&mut self, ex: &'v Expr) {
walk_expr(self, ex)
}
@ -547,7 +550,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
generics,
parent_item_id,
variant.span);
walk_list!(visitor, visit_nested_body, variant.node.disr_expr);
walk_list!(visitor, visit_anon_const, &variant.node.disr_expr);
walk_list!(visitor, visit_attribute, &variant.node.attrs);
}
@ -576,9 +579,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
TyPath(ref qpath) => {
visitor.visit_qpath(qpath, typ.id, typ.span);
}
TyArray(ref ty, length) => {
TyArray(ref ty, ref length) => {
visitor.visit_ty(ty);
visitor.visit_nested_body(length)
visitor.visit_anon_const(length)
}
TyTraitObject(ref bounds, ref lifetime) => {
for bound in bounds {
@ -592,8 +595,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
walk_list!(visitor, visit_ty_param_bound, bounds);
walk_list!(visitor, visit_lifetime, lifetimes);
}
TyTypeof(expression) => {
visitor.visit_nested_body(expression)
TyTypeof(ref expression) => {
visitor.visit_anon_const(expression)
}
TyInfer | TyErr => {}
}
@ -944,6 +947,11 @@ pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
}
}
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
visitor.visit_id(constant.id);
visitor.visit_nested_body(constant.body);
}
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_id(expression.id);
walk_list!(visitor, visit_attribute, expression.attrs.iter());
@ -954,9 +962,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
ExprArray(ref subexpressions) => {
walk_list!(visitor, visit_expr, subexpressions);
}
ExprRepeat(ref element, count) => {
ExprRepeat(ref element, ref count) => {
visitor.visit_expr(element);
visitor.visit_nested_body(count)
visitor.visit_anon_const(count)
}
ExprStruct(ref qpath, ref fields, ref optional_base) => {
visitor.visit_qpath(qpath, expression.id, expression.span);

View File

@ -1080,12 +1080,10 @@ impl<'a> LoweringContext<'a> {
}),
)),
TyKind::Array(ref ty, ref length) => {
let length = self.lower_body(None, |this| this.lower_expr(length));
hir::TyArray(self.lower_ty(ty, itctx), length)
hir::TyArray(self.lower_ty(ty, itctx), self.lower_anon_const(length))
}
TyKind::Typeof(ref expr) => {
let expr = self.lower_body(None, |this| this.lower_expr(expr));
hir::TyTypeof(expr)
hir::TyTypeof(self.lower_anon_const(expr))
}
TyKind::TraitObject(ref bounds, kind) => {
let mut lifetime_bound = None;
@ -1365,10 +1363,7 @@ impl<'a> LoweringContext<'a> {
name: v.node.ident.name,
attrs: self.lower_attrs(&v.node.attrs),
data: self.lower_variant_data(&v.node.data),
disr_expr: v.node
.disr_expr
.as_ref()
.map(|e| self.lower_body(None, |this| this.lower_expr(e))),
disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
},
span: v.span,
}
@ -2927,6 +2922,16 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(c.id);
hir::AnonConst {
id: node_id,
hir_id,
body: self.lower_body(None, |this| this.lower_expr(&c.value)),
}
}
fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
let kind = match e.node {
ExprKind::Box(ref inner) => hir::ExprBox(P(self.lower_expr(inner))),
@ -2936,7 +2941,7 @@ impl<'a> LoweringContext<'a> {
}
ExprKind::Repeat(ref expr, ref count) => {
let expr = P(self.lower_expr(expr));
let count = self.lower_body(None, |this| this.lower_expr(count));
let count = self.lower_anon_const(count);
hir::ExprRepeat(expr, count)
}
ExprKind::Tup(ref elts) => {

View File

@ -202,6 +202,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n),
NodeVariant(n) => EntryVariant(parent, dep_node_index, n),
NodeField(n) => EntryField(parent, dep_node_index, n),
NodeAnonConst(n) => EntryAnonConst(parent, dep_node_index, n),
NodeExpr(n) => EntryExpr(parent, dep_node_index, n),
NodeStmt(n) => EntryStmt(parent, dep_node_index, n),
NodeTy(n) => EntryTy(parent, dep_node_index, n),
@ -390,6 +391,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
});
}
fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
self.insert(constant.id, NodeAnonConst(constant));
self.with_parent(constant.id, |this| {
intravisit::walk_anon_const(this, constant);
});
}
fn visit_expr(&mut self, expr: &'hir Expr) {
self.insert(expr.id, NodeExpr(expr));

View File

@ -33,7 +33,6 @@ pub struct DefCollector<'a> {
pub struct MacroInvocationData {
pub mark: Mark,
pub def_index: DefIndex,
pub const_expr: bool,
}
impl<'a> DefCollector<'a> {
@ -74,25 +73,10 @@ impl<'a> DefCollector<'a> {
self.parent_def = parent;
}
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_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.
ExprKind::Closure(..) => return,
_ => {}
}
self.create_def(expr.id, DefPathData::Initializer, REGULAR_SPACE, expr.span);
}
fn visit_macro_invoc(&mut self, id: NodeId, const_expr: bool) {
fn visit_macro_invoc(&mut self, id: NodeId) {
if let Some(ref mut visit) = self.visit_macro_invoc {
visit(MacroInvocationData {
mark: id.placeholder_to_mark(),
const_expr,
def_index: self.parent_def.unwrap(),
})
}
@ -119,7 +103,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
DefPathData::ValueNs(i.ident.name.as_interned_str()),
ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_interned_str()),
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id),
ItemKind::GlobalAsm(..) => DefPathData::Misc,
ItemKind::Use(..) => {
return visit::walk_item(self, i);
@ -129,30 +113,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
self.with_parent(def, |this| {
match i.node {
ItemKind::Enum(ref enum_definition, _) => {
for v in &enum_definition.variants {
let variant_def_index =
this.create_def(v.node.data.id(),
DefPathData::EnumVariant(v.node.ident
.name.as_interned_str()),
REGULAR_SPACE,
v.span);
this.with_parent(variant_def_index, |this| {
for (index, field) in v.node.data.fields().iter().enumerate() {
let name = field.ident.map(|ident| ident.name)
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
this.create_def(field.id,
DefPathData::Field(name.as_interned_str()),
REGULAR_SPACE,
field.span);
}
if let Some(ref expr) = v.node.disr_expr {
this.visit_const_expr(expr);
}
});
}
}
ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
@ -161,15 +121,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
REGULAR_SPACE,
i.span);
}
for (index, field) in struct_def.fields().iter().enumerate() {
let name = field.ident.map(|ident| ident.name)
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
this.create_def(field.id,
DefPathData::Field(name.as_interned_str()),
REGULAR_SPACE,
field.span);
}
}
_ => {}
}
@ -184,7 +135,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
if let ForeignItemKind::Macro(_) = foreign_item.node {
return self.visit_macro_invoc(foreign_item.id, false);
return self.visit_macro_invoc(foreign_item.id);
}
let def = self.create_def(foreign_item.id,
@ -197,6 +148,28 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
});
}
fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
let def = self.create_def(v.node.data.id(),
DefPathData::EnumVariant(v.node.ident
.name.as_interned_str()),
REGULAR_SPACE,
v.span);
self.with_parent(def, |this| visit::walk_variant(this, v, g, item_id));
}
fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident,
_: &'a Generics, _: NodeId, _: Span) {
for (index, field) in data.fields().iter().enumerate() {
let name = field.ident.map(|ident| ident.name)
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
let def = self.create_def(field.id,
DefPathData::Field(name.as_interned_str()),
REGULAR_SPACE,
field.span);
self.with_parent(def, |this| this.visit_struct_field(field));
}
}
fn visit_generic_param(&mut self, param: &'a GenericParam) {
match *param {
GenericParam::Lifetime(ref lifetime_def) => {
@ -227,7 +200,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
TraitItemKind::Type(..) => {
DefPathData::AssocTypeInTrait(ti.ident.name.as_interned_str())
},
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id),
};
let def = self.create_def(ti.id, def_data, ITEM_LIKE_SPACE, ti.span);
@ -239,7 +212,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
DefPathData::ValueNs(ii.ident.name.as_interned_str()),
ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_interned_str()),
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
};
let def = self.create_def(ii.id, def_data, ITEM_LIKE_SPACE, ii.span);
@ -248,17 +221,24 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
fn visit_pat(&mut self, pat: &'a Pat) {
match pat.node {
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id),
_ => visit::walk_pat(self, pat),
}
}
fn visit_anon_const(&mut self, constant: &'a AnonConst) {
let def = self.create_def(constant.id,
DefPathData::AnonConst,
REGULAR_SPACE,
constant.value.span);
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
}
fn visit_expr(&mut self, expr: &'a Expr) {
let parent_def = self.parent_def;
match expr.node {
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false),
ExprKind::Repeat(_, ref count) => self.visit_const_expr(count),
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
ExprKind::Closure(..) => {
let def = self.create_def(expr.id,
DefPathData::ClosureExpr,
@ -275,12 +255,10 @@ 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_const_expr(length),
TyKind::Mac(..) => return self.visit_macro_invoc(ty.id),
TyKind::ImplTrait(..) => {
self.create_def(ty.id, DefPathData::ImplTrait, REGULAR_SPACE, ty.span);
}
TyKind::Typeof(ref expr) => self.visit_const_expr(expr),
_ => {}
}
visit::walk_ty(self, ty);
@ -288,7 +266,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
fn visit_stmt(&mut self, stmt: &'a Stmt) {
match stmt.node {
StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id, false),
StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id),
_ => visit::walk_stmt(self, stmt),
}
}
@ -298,7 +276,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
match nt.0 {
token::NtExpr(ref expr) => {
if let ExprKind::Mac(..) = expr.node {
self.visit_macro_invoc(expr.id, false);
self.visit_macro_invoc(expr.id);
}
}
_ => {}

View File

@ -231,9 +231,8 @@ impl DefKey {
DefPathData::Misc |
DefPathData::ClosureExpr |
DefPathData::StructCtor |
DefPathData::Initializer |
DefPathData::ImplTrait |
DefPathData::Typeof => {}
DefPathData::AnonConst |
DefPathData::ImplTrait => {}
};
disambiguator.hash(&mut hasher);
@ -389,12 +388,10 @@ pub enum DefPathData {
Field(InternedString),
/// Implicit ctor for a tuple-like struct
StructCtor,
/// Initializer for a const
Initializer,
/// A constant expression (see {ast,hir}::AnonConst).
AnonConst,
/// An `impl Trait` type node.
ImplTrait,
/// A `typeof` type node.
Typeof,
/// GlobalMetaData identifies a piece of crate metadata that is global to
/// a whole crate (as opposed to just one item). GlobalMetaData components
@ -665,9 +662,8 @@ impl DefPathData {
Misc |
ClosureExpr |
StructCtor |
Initializer |
ImplTrait |
Typeof => None
AnonConst |
ImplTrait => None
}
}
@ -696,9 +692,8 @@ impl DefPathData {
Misc => "{{?}}",
ClosureExpr => "{{closure}}",
StructCtor => "{{constructor}}",
Initializer => "{{initializer}}",
AnonConst => "{{constant}}",
ImplTrait => "{{impl-Trait}}",
Typeof => "{{typeof}}",
};
Symbol::intern(s).as_interned_str()

View File

@ -53,6 +53,7 @@ pub enum Node<'hir> {
NodeImplItem(&'hir ImplItem),
NodeVariant(&'hir Variant),
NodeField(&'hir StructField),
NodeAnonConst(&'hir AnonConst),
NodeExpr(&'hir Expr),
NodeStmt(&'hir Stmt),
NodeTy(&'hir Ty),
@ -85,6 +86,7 @@ enum MapEntry<'hir> {
EntryImplItem(NodeId, DepNodeIndex, &'hir ImplItem),
EntryVariant(NodeId, DepNodeIndex, &'hir Variant),
EntryField(NodeId, DepNodeIndex, &'hir StructField),
EntryAnonConst(NodeId, DepNodeIndex, &'hir AnonConst),
EntryExpr(NodeId, DepNodeIndex, &'hir Expr),
EntryStmt(NodeId, DepNodeIndex, &'hir Stmt),
EntryTy(NodeId, DepNodeIndex, &'hir Ty),
@ -120,6 +122,7 @@ impl<'hir> MapEntry<'hir> {
EntryImplItem(id, _, _) => id,
EntryVariant(id, _, _) => id,
EntryField(id, _, _) => id,
EntryAnonConst(id, _, _) => id,
EntryExpr(id, _, _) => id,
EntryStmt(id, _, _) => id,
EntryTy(id, _, _) => id,
@ -147,6 +150,7 @@ impl<'hir> MapEntry<'hir> {
EntryImplItem(_, _, n) => NodeImplItem(n),
EntryVariant(_, _, n) => NodeVariant(n),
EntryField(_, _, n) => NodeField(n),
EntryAnonConst(_, _, n) => NodeAnonConst(n),
EntryExpr(_, _, n) => NodeExpr(n),
EntryStmt(_, _, n) => NodeStmt(n),
EntryTy(_, _, n) => NodeTy(n),
@ -193,6 +197,8 @@ impl<'hir> MapEntry<'hir> {
}
}
EntryAnonConst(_, _, constant) => Some(constant.body),
EntryExpr(_, _, expr) => {
match expr.node {
ExprClosure(.., body, _, _) => Some(body),
@ -290,6 +296,7 @@ impl<'hir> Map<'hir> {
EntryLifetime(_, dep_node_index, _) |
EntryTyParam(_, dep_node_index, _) |
EntryVisibility(_, dep_node_index, _) |
EntryAnonConst(_, dep_node_index, _) |
EntryExpr(_, dep_node_index, _) |
EntryLocal(_, dep_node_index, _) |
EntryMacroDef(dep_node_index, _) |
@ -434,6 +441,7 @@ impl<'hir> Map<'hir> {
Some(Def::Variant(def_id))
}
NodeField(_) |
NodeAnonConst(_) |
NodeExpr(_) |
NodeStmt(_) |
NodeTy(_) |
@ -495,15 +503,11 @@ impl<'hir> Map<'hir> {
/// Returns the `NodeId` that corresponds to the definition of
/// which this is the body of, i.e. a `fn`, `const` or `static`
/// item (possibly associated), or a closure, or the body itself
/// for embedded constant expressions (e.g. `N` in `[T; N]`).
/// item (possibly associated), a closure, or a `hir::AnonConst`.
pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
let parent = self.get_parent_node(node_id);
if self.map[parent.as_usize()].is_body_owner(node_id) {
parent
} else {
node_id
}
assert!(self.map[parent.as_usize()].is_body_owner(node_id));
parent
}
pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
@ -520,19 +524,7 @@ impl<'hir> Map<'hir> {
self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
}
if let Some(body_id) = entry.associated_body() {
// For item-like things and closures, the associated
// body has its own distinct id, and that is returned
// by `associated_body`.
Some(body_id)
} else {
// For some expressions, the expression is its own body.
if let EntryExpr(_, _, expr) = entry {
Some(BodyId { node_id: expr.id })
} else {
None
}
}
entry.associated_body()
} else {
bug!("no entry for id `{}`", id)
}
@ -547,17 +539,11 @@ impl<'hir> Map<'hir> {
}
pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind {
// Handle constants in enum discriminants, types, and repeat expressions.
let def_id = self.local_def_id(id);
let def_key = self.def_key(def_id);
if def_key.disambiguated_data.data == DefPathData::Initializer {
return BodyOwnerKind::Const;
}
match self.get(id) {
NodeItem(&Item { node: ItemConst(..), .. }) |
NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) |
NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => {
NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) |
NodeAnonConst(_) => {
BodyOwnerKind::Const
}
NodeItem(&Item { node: ItemStatic(_, m, _), .. }) => {
@ -982,6 +968,7 @@ impl<'hir> Map<'hir> {
Some(EntryImplItem(_, _, impl_item)) => impl_item.span,
Some(EntryVariant(_, _, variant)) => variant.span,
Some(EntryField(_, _, field)) => field.span,
Some(EntryAnonConst(_, _, constant)) => self.body(constant.body).value.span,
Some(EntryExpr(_, _, expr)) => expr.span,
Some(EntryStmt(_, _, stmt)) => stmt.span,
Some(EntryTy(_, _, ty)) => ty.span,
@ -1201,6 +1188,7 @@ impl<'a> print::State<'a> {
NodeTraitItem(a) => self.print_trait_item(a),
NodeImplItem(a) => self.print_impl_item(a),
NodeVariant(a) => self.print_variant(&a),
NodeAnonConst(a) => self.print_anon_const(&a),
NodeExpr(a) => self.print_expr(&a),
NodeStmt(a) => self.print_stmt(&a),
NodeTy(a) => self.print_type(&a),
@ -1306,6 +1294,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
field.name,
path_str(), id_str)
}
Some(NodeAnonConst(_)) => {
format!("const {}{}", map.node_to_pretty_string(id), id_str)
}
Some(NodeExpr(_)) => {
format!("expr {}{}", map.node_to_pretty_string(id), id_str)
}

View File

@ -1272,6 +1272,18 @@ pub enum BodyOwnerKind {
Static(Mutability),
}
/// A constant (expression) that's not an item or associated item,
/// but needs its own `DefId` for type-checking, const-eval, etc.
/// These are usually found nested inside types (e.g. array lengths)
/// or expressions (e.g. repeat counts), and also used to define
/// explicit discriminant values for enum variants.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct AnonConst {
pub id: NodeId,
pub hir_id: HirId,
pub body: BodyId,
}
/// An expression
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
pub struct Expr {
@ -1419,7 +1431,7 @@ pub enum Expr_ {
///
/// For example, `[1; 5]`. The first expression is the element
/// to be repeated; the second is the number of times to repeat it.
ExprRepeat(P<Expr>, BodyId),
ExprRepeat(P<Expr>, AnonConst),
/// A suspension point for generators. This is `yield <expr>` in Rust.
ExprYield(P<Expr>),
@ -1677,7 +1689,7 @@ pub enum Ty_ {
/// A variable length slice (`[T]`)
TySlice(P<Ty>),
/// A fixed length array (`[T; n]`)
TyArray(P<Ty>, BodyId),
TyArray(P<Ty>, AnonConst),
/// A raw pointer (`*const T` or `*mut T`)
TyPtr(MutTy),
/// A reference (`&'a T` or `&'a mut T`)
@ -1709,7 +1721,7 @@ pub enum Ty_ {
/// so they are resolved directly through the parent `Generics`.
TyImplTraitExistential(ExistTy, HirVec<Lifetime>),
/// Unused for now
TyTypeof(BodyId),
TyTypeof(AnonConst),
/// TyInfer means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type.
TyInfer,
@ -1882,7 +1894,7 @@ pub struct Variant_ {
pub attrs: HirVec<Attribute>,
pub data: VariantData,
/// Explicit discriminant, eg `Foo = 1`
pub disr_expr: Option<BodyId>,
pub disr_expr: Option<AnonConst>,
}
pub type Variant = Spanned<Variant_>;

View File

@ -416,16 +416,16 @@ impl<'a> State<'a> {
hir::TyImplTraitExistential(ref existty, ref _lifetimes) => {
self.print_bounds("impl", &existty.bounds[..])?;
}
hir::TyArray(ref ty, v) => {
hir::TyArray(ref ty, ref length) => {
self.s.word("[")?;
self.print_type(&ty)?;
self.s.word("; ")?;
self.ann.nested(self, Nested::Body(v))?;
self.print_anon_const(length)?;
self.s.word("]")?;
}
hir::TyTypeof(e) => {
hir::TyTypeof(ref e) => {
self.s.word("typeof(")?;
self.ann.nested(self, Nested::Body(e))?;
self.print_anon_const(e)?;
self.s.word(")")?;
}
hir::TyInfer => {
@ -871,10 +871,10 @@ impl<'a> State<'a> {
self.head("")?;
let generics = hir::Generics::empty();
self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?;
if let Some(d) = v.node.disr_expr {
if let Some(ref d) = v.node.disr_expr {
self.s.space()?;
self.word_space("=")?;
self.ann.nested(self, Nested::Body(d))?;
self.print_anon_const(d)?;
}
Ok(())
}
@ -1091,6 +1091,9 @@ impl<'a> State<'a> {
self.print_else(elseopt)
}
pub fn print_anon_const(&mut self, constant: &hir::AnonConst) -> io::Result<()> {
self.ann.nested(self, Nested::Body(constant.body))
}
fn print_call_post(&mut self, args: &[hir::Expr]) -> io::Result<()> {
self.popen()?;
@ -1141,12 +1144,12 @@ impl<'a> State<'a> {
self.end()
}
fn print_expr_repeat(&mut self, element: &hir::Expr, count: hir::BodyId) -> io::Result<()> {
fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::AnonConst) -> io::Result<()> {
self.ibox(indent_unit)?;
self.s.word("[")?;
self.print_expr(element)?;
self.word_space(";")?;
self.ann.nested(self, Nested::Body(count))?;
self.print_anon_const(count)?;
self.s.word("]")?;
self.end()
}
@ -1288,7 +1291,7 @@ impl<'a> State<'a> {
hir::ExprArray(ref exprs) => {
self.print_expr_vec(exprs)?;
}
hir::ExprRepeat(ref element, count) => {
hir::ExprRepeat(ref element, ref count) => {
self.print_expr_repeat(&element, count)?;
}
hir::ExprStruct(ref qpath, ref fields, ref wth) => {

View File

@ -553,6 +553,12 @@ impl_stable_hash_for!(enum hir::UnsafeSource {
UserProvided
});
impl_stable_hash_for!(struct hir::AnonConst {
id,
hir_id,
body
});
impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,

View File

@ -214,11 +214,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
data @ DefPathData::LifetimeDef(..) |
data @ DefPathData::EnumVariant(..) |
data @ DefPathData::Field(..) |
data @ DefPathData::Initializer |
data @ DefPathData::AnonConst |
data @ DefPathData::MacroDef(..) |
data @ DefPathData::ClosureExpr |
data @ DefPathData::ImplTrait |
data @ DefPathData::Typeof |
data @ DefPathData::GlobalMetaData(..) => {
let parent_def_id = self.parent_def_id(def_id).unwrap();
self.push_item_path(buffer, parent_def_id);

View File

@ -290,9 +290,8 @@ impl PrintContext {
DefPathData::LifetimeDef(_) |
DefPathData::Field(_) |
DefPathData::StructCtor |
DefPathData::Initializer |
DefPathData::AnonConst |
DefPathData::ImplTrait |
DefPathData::Typeof |
DefPathData::GlobalMetaData(_) => {
// if we're making a symbol for something, there ought
// to be a value or type-def or something in there

View File

@ -1359,8 +1359,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
}
fn encode_info_for_embedded_const(&mut self, def_id: DefId) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_embedded_const({:?})", def_id);
fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_anon_const({:?})", def_id);
let tcx = self.tcx;
let id = tcx.hir.as_local_node_id(def_id).unwrap();
let body_id = tcx.hir.body_owned_by(id);
@ -1623,9 +1623,9 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
id: ast::NodeId) {
intravisit::walk_variant(self, v, g, id);
if let Some(discr) = v.node.disr_expr {
let def_id = self.index.tcx.hir.body_owner_def_id(discr);
self.index.record(def_id, IsolatedEncoder::encode_info_for_embedded_const, def_id);
if let Some(ref discr) = v.node.disr_expr {
let def_id = self.index.tcx.hir.local_def_id(discr.id);
self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
}
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
@ -1668,9 +1668,9 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
let def_id = self.tcx.hir.local_def_id(ty.id);
self.record(def_id, IsolatedEncoder::encode_info_for_anon_ty, def_id);
}
hir::TyArray(_, len) => {
let def_id = self.tcx.hir.body_owner_def_id(len);
self.record(def_id, IsolatedEncoder::encode_info_for_embedded_const, def_id);
hir::TyArray(_, ref length) => {
let def_id = self.tcx.hir.local_def_id(length.id);
self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
}
_ => {}
}

View File

@ -42,46 +42,15 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
// Figure out what primary body this item has.
let body_id = match tcx.hir.get(id) {
hir::map::NodeItem(item) => {
match item.node {
hir::ItemConst(_, body) |
hir::ItemStatic(_, _, body) |
hir::ItemFn(.., body) => body,
_ => unsupported()
}
}
hir::map::NodeTraitItem(item) => {
match item.node {
hir::TraitItemKind::Const(_, Some(body)) |
hir::TraitItemKind::Method(_,
hir::TraitMethod::Provided(body)) => body,
_ => unsupported()
}
}
hir::map::NodeImplItem(item) => {
match item.node {
hir::ImplItemKind::Const(_, body) |
hir::ImplItemKind::Method(_, body) => body,
_ => unsupported()
}
}
hir::map::NodeExpr(expr) => {
// FIXME(eddyb) Closures should have separate
// function definition IDs and expression IDs.
// Type-checking should not let closures get
// this far in a constant position.
// Assume that everything other than closures
// is a constant "initializer" expression.
match expr.node {
hir::ExprClosure(_, _, body, _, _) => body,
_ => hir::BodyId { node_id: expr.id },
}
}
hir::map::NodeVariant(variant) =>
return create_constructor_shim(tcx, id, &variant.node.data),
hir::map::NodeStructCtor(ctor) =>
return create_constructor_shim(tcx, id, ctor),
_ => unsupported(),
_ => match tcx.hir.maybe_body_owned_by(id) {
Some(body) => body,
None => unsupported(),
},
};
tcx.infer_ctxt().enter(|infcx| {

View File

@ -506,9 +506,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
// Now comes the rote stuff:
hir::ExprRepeat(ref v, count) => {
let c = &cx.tcx.hir.body(count).value;
let def_id = cx.tcx.hir.body_owner_def_id(count);
hir::ExprRepeat(ref v, ref count) => {
let def_id = cx.tcx.hir.local_def_id(count.id);
let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
let instance = ty::Instance::resolve(
cx.tcx.global_tcx(),
@ -520,7 +519,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
instance,
promoted: None
};
let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and(global_id)) {
let span = cx.tcx.def_span(def_id);
let count = match cx.tcx.at(span).const_eval(cx.param_env.and(global_id)) {
Ok(cv) => cv.unwrap_usize(cx.tcx),
Err(e) => {
e.report(cx.tcx, cx.tcx.def_span(def_id), "array length");

View File

@ -802,6 +802,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
fn visit_block(&mut self, block: &'tcx Block) {
self.resolve_block(block);
}
fn visit_anon_const(&mut self, constant: &'tcx ast::AnonConst) {
self.with_constant_rib(|this| {
visit::walk_anon_const(this, constant);
});
}
fn visit_expr(&mut self, expr: &'tcx Expr) {
self.resolve_expr(expr, None);
}
@ -819,13 +824,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
.map_or(Def::Err, |d| d.def());
self.record_def(ty.id, PathResolution::new(def));
}
TyKind::Array(ref element, ref length) => {
self.visit_ty(element);
self.with_constant_rib(|this| {
this.visit_expr(length);
});
return;
}
_ => (),
}
visit::walk_ty(self, ty);
@ -837,24 +835,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
&tref.trait_ref.path, PathSource::Trait(AliasPossibility::Maybe));
visit::walk_poly_trait_ref(self, tref, m);
}
fn visit_variant(&mut self,
variant: &'tcx ast::Variant,
generics: &'tcx Generics,
item_id: ast::NodeId) {
if let Some(ref dis_expr) = variant.node.disr_expr {
// resolve the discriminator expr as a constant
self.with_constant_rib(|this| {
this.visit_expr(dis_expr);
});
}
// `visit::walk_variant` without the discriminant expression.
self.visit_variant_data(&variant.node.data,
variant.node.ident,
generics,
item_id,
variant.span);
}
fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
let type_parameters = match foreign_item.node {
ForeignItemKind::Fn(_, ref generics) => {
@ -3820,12 +3800,6 @@ impl<'a> Resolver<'a> {
self.visit_path_segment(expr.span, segment);
}
ExprKind::Repeat(ref element, ref count) => {
self.visit_expr(element);
self.with_constant_rib(|this| {
this.visit_expr(count);
});
}
ExprKind::Call(ref callee, ref arguments) => {
self.resolve_expr(callee, Some(expr));
for argument in arguments {

View File

@ -45,9 +45,6 @@ use rustc_data_structures::sync::Lrc;
pub struct InvocationData<'a> {
pub module: Cell<Module<'a>>,
pub def_index: DefIndex,
// 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,
@ -60,7 +57,6 @@ impl<'a> InvocationData<'a> {
InvocationData {
module: Cell::new(graph_root),
def_index: CRATE_DEF_INDEX,
const_expr: false,
legacy_scope: Cell::new(LegacyScope::Empty),
expansion: Cell::new(LegacyScope::Empty),
}
@ -124,7 +120,6 @@ 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_expr: false,
legacy_scope: Cell::new(LegacyScope::Empty),
expansion: Cell::new(LegacyScope::Empty),
}));
@ -716,13 +711,12 @@ impl<'a> Resolver<'a> {
invocation: &'a InvocationData<'a>,
expansion: &Expansion) {
let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
let InvocationData { def_index, const_expr, .. } = *invocation;
let InvocationData { def_index, .. } = *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_expr: invoc.const_expr,
module: Cell::new(graph_root),
expansion: Cell::new(LegacyScope::Empty),
legacy_scope: Cell::new(LegacyScope::Empty),
@ -733,11 +727,6 @@ impl<'a> Resolver<'a> {
let mut def_collector = DefCollector::new(&mut self.definitions, mark);
def_collector.visit_macro_invoc = Some(visit_macro_invoc);
def_collector.with_parent(def_index, |def_collector| {
if const_expr {
if let Expansion::Expr(ref expr) = *expansion {
def_collector.visit_const_expr(expr);
}
}
expansion.visit_with(def_collector)
});
}

View File

@ -1516,7 +1516,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
}
ast::TyKind::Array(ref element, ref length) => {
self.visit_ty(element);
self.nest_tables(length.id, |v| v.visit_expr(length));
self.nest_tables(length.id, |v| v.visit_expr(&length.value));
}
_ => visit::walk_ty(self, t),
}
@ -1589,7 +1589,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
}
ast::ExprKind::Repeat(ref element, ref count) => {
self.visit_expr(element);
self.nest_tables(count.id, |v| v.visit_expr(count));
self.nest_tables(count.id, |v| v.visit_expr(&count.value));
}
// In particular, we take this branch for call and path expressions,
// where we'll index the idents involved just by continuing to walk.

View File

@ -313,7 +313,7 @@ impl Sig for ast::Ty {
}
ast::TyKind::Array(ref ty, ref v) => {
let nested_ty = ty.make(offset + 1, id, scx)?;
let expr = pprust::expr_to_string(v).replace('\n', " ");
let expr = pprust::expr_to_string(&v.value).replace('\n', " ");
let text = format!("[{}; {}]", nested_ty.text, expr);
Ok(replace_text(nested_ty, text))
}

View File

@ -1116,8 +1116,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
};
self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0
}
hir::TyArray(ref ty, length) => {
let length_def_id = tcx.hir.body_owner_def_id(length);
hir::TyArray(ref ty, ref length) => {
let length_def_id = tcx.hir.local_def_id(length.id);
let substs = Substs::identity_for_item(tcx, length_def_id);
let length = ty::Const::unevaluated(tcx, length_def_id, substs, tcx.types.usize);
let array_ty = tcx.mk_ty(ty::TyArray(self.ast_ty_to_ty(&ty), length));

View File

@ -787,20 +787,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
None,
}
}
hir::map::NodeExpr(expr) => {
// FIXME(eddyb) Closures should have separate
// function definition IDs and expression IDs.
// Type-checking should not let closures get
// this far in a constant position.
// Assume that everything other than closures
// is a constant "initializer" expression.
match expr.node {
hir::ExprClosure(..) =>
None,
_ =>
Some((hir::BodyId { node_id: expr.id }, None)),
}
}
hir::map::NodeAnonConst(constant) => Some((constant.body, None)),
_ => None,
}
}
@ -1674,8 +1661,8 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
for v in vs {
if let Some(e) = v.node.disr_expr {
tcx.typeck_tables_of(tcx.hir.local_def_id(e.node_id));
if let Some(ref e) = v.node.disr_expr {
tcx.typeck_tables_of(tcx.hir.local_def_id(e.id));
}
}
@ -1686,11 +1673,11 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let variant_i_node_id = tcx.hir.as_local_node_id(def.variants[i].did).unwrap();
let variant_i = tcx.hir.expect_variant(variant_i_node_id);
let i_span = match variant_i.node.disr_expr {
Some(expr) => tcx.hir.span(expr.node_id),
Some(ref expr) => tcx.hir.span(expr.id),
None => tcx.hir.span(variant_i_node_id)
};
let span = match v.node.disr_expr {
Some(expr) => tcx.hir.span(expr.node_id),
Some(ref expr) => tcx.hir.span(expr.id),
None => v.span
};
struct_span_err!(tcx.sess, span, E0081,
@ -3975,8 +3962,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
};
tcx.mk_array(element_ty, args.len() as u64)
}
hir::ExprRepeat(ref element, count) => {
let count_def_id = tcx.hir.body_owner_def_id(count);
hir::ExprRepeat(ref element, ref count) => {
let count_def_id = tcx.hir.local_def_id(count.id);
let param_env = ty::ParamEnv::empty();
let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
let instance = ty::Instance::resolve(

View File

@ -481,8 +481,8 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// fill the discriminant values and field types
for variant in variants {
let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
prev_discr = Some(if let Some(e) = variant.node.disr_expr {
let expr_did = tcx.hir.local_def_id(e.node_id);
prev_discr = Some(if let Some(ref e) = variant.node.disr_expr {
let expr_did = tcx.hir.local_def_id(e.id);
def.eval_explicit_discr(tcx, expr_did)
} else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
Some(discr)
@ -565,9 +565,9 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut distance_from_explicit = 0;
(AdtKind::Enum, def.variants.iter().map(|v| {
let did = tcx.hir.local_def_id(v.node.data.id());
let discr = if let Some(e) = v.node.disr_expr {
let discr = if let Some(ref e) = v.node.disr_expr {
distance_from_explicit = 0;
ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.node_id))
ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.id))
} else {
ty::VariantDiscr::Relative(distance_from_explicit)
};
@ -1102,20 +1102,20 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
tcx.mk_closure(def_id, substs)
}
NodeExpr(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) {
NodeTy(&hir::Ty { node: TyArray(_, body), .. }) |
NodeTy(&hir::Ty { node: TyTypeof(body), .. }) |
NodeExpr(&hir::Expr { node: ExprRepeat(_, body), .. })
if body.node_id == node_id => tcx.types.usize,
NodeAnonConst(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) {
NodeTy(&hir::Ty { node: TyArray(_, ref constant), .. }) |
NodeTy(&hir::Ty { node: TyTypeof(ref constant), .. }) |
NodeExpr(&hir::Expr { node: ExprRepeat(_, ref constant), .. })
if constant.id == node_id => tcx.types.usize,
NodeVariant(&Spanned { node: Variant_ { disr_expr: Some(e), .. }, .. })
if e.node_id == node_id => {
NodeVariant(&Spanned { node: Variant_ { disr_expr: Some(ref e), .. }, .. })
if e.id == node_id => {
tcx.adt_def(tcx.hir.get_parent_did(node_id))
.repr.discr_type().to_ty(tcx)
}
x => {
bug!("unexpected expr parent in type_of_def_id(): {:?}", x);
bug!("unexpected const parent in type_of_def_id(): {:?}", x);
}
},

View File

@ -2669,19 +2669,19 @@ impl Clean<Type> for hir::Ty {
type_: box m.ty.clean(cx)}
}
TySlice(ref ty) => Slice(box ty.clean(cx)),
TyArray(ref ty, n) => {
let def_id = cx.tcx.hir.body_owner_def_id(n);
TyArray(ref ty, ref length) => {
let def_id = cx.tcx.hir.local_def_id(length.id);
let param_env = cx.tcx.param_env(def_id);
let substs = Substs::identity_for_item(cx.tcx, def_id);
let cid = GlobalId {
instance: ty::Instance::new(def_id, substs),
promoted: None
};
let n = cx.tcx.const_eval(param_env.and(cid)).unwrap_or_else(|_| {
let length = cx.tcx.const_eval(param_env.and(cid)).unwrap_or_else(|_| {
ty::Const::unevaluated(cx.tcx, def_id, substs, cx.tcx.types.usize)
});
let n = print_const(cx, n);
Array(box ty.clean(cx), n)
let length = print_const(cx, length);
Array(box ty.clean(cx), length)
},
TyTup(ref tys) => Tuple(tys.clean(cx)),
TyPath(hir::QPath::Resolved(None, ref path)) => {

View File

@ -920,6 +920,18 @@ pub enum UnsafeSource {
UserProvided,
}
/// A constant (expression) that's not an item or associated item,
/// but needs its own `DefId` for type-checking, const-eval, etc.
/// These are usually found nested inside types (e.g. array lengths)
/// or expressions (e.g. repeat counts), and also used to define
/// explicit discriminant values for enum variants.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct AnonConst {
pub id: NodeId,
pub value: P<Expr>,
}
/// An expression
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash,)]
pub struct Expr {
@ -1168,9 +1180,9 @@ pub enum ExprKind {
/// An array literal constructed from one repeated element.
///
/// For example, `[1; 5]`. The first expression is the element
/// to be repeated; the second is the number of times to repeat it.
Repeat(P<Expr>, P<Expr>),
/// For example, `[1; 5]`. The expression is the element to be
/// repeated; the constant is the number of times to repeat it.
Repeat(P<Expr>, AnonConst),
/// No-op: used solely so we can pretty-print faithfully
Paren(P<Expr>),
@ -1565,7 +1577,7 @@ pub enum TyKind {
/// A variable-length slice (`[T]`)
Slice(P<Ty>),
/// A fixed length array (`[T; n]`)
Array(P<Ty>, P<Expr>),
Array(P<Ty>, AnonConst),
/// A raw pointer (`*const T` or `*mut T`)
Ptr(MutTy),
/// A reference (`&'a T` or `&'a mut T`)
@ -1590,7 +1602,7 @@ pub enum TyKind {
/// No-op; kept solely so that we can pretty-print faithfully
Paren(P<Ty>),
/// Unused for now
Typeof(P<Expr>),
Typeof(AnonConst),
/// TyKind::Infer means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type.
Infer,
@ -1856,7 +1868,7 @@ pub struct Variant_ {
pub attrs: Vec<Attribute>,
pub data: VariantData,
/// Explicit discriminant, e.g. `Foo = 1`
pub disr_expr: Option<P<Expr>>,
pub disr_expr: Option<AnonConst>,
}
pub type Variant = Spanned<Variant_>;

View File

@ -207,7 +207,10 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
span,
ast::TyKind::Tup(vec![ty_str.clone(), ty_str])
),
ecx.expr_usize(span, count),
ast::AnonConst {
id: ast::DUMMY_NODE_ID,
value: ecx.expr_usize(span, count),
},
),
);

View File

@ -112,6 +112,10 @@ pub trait Folder : Sized {
noop_fold_pat(p, self)
}
fn fold_anon_const(&mut self, c: AnonConst) -> AnonConst {
noop_fold_anon_const(c, self)
}
fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
e.map(|e| noop_fold_expr(e, self))
}
@ -394,11 +398,11 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
});
TyKind::Path(qself, fld.fold_path(path))
}
TyKind::Array(ty, e) => {
TyKind::Array(fld.fold_ty(ty), fld.fold_expr(e))
TyKind::Array(ty, length) => {
TyKind::Array(fld.fold_ty(ty), fld.fold_anon_const(length))
}
TyKind::Typeof(expr) => {
TyKind::Typeof(fld.fold_expr(expr))
TyKind::Typeof(fld.fold_anon_const(expr))
}
TyKind::TraitObject(bounds, syntax) => {
TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), syntax)
@ -433,7 +437,7 @@ pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
ident: fld.fold_ident(v.node.ident),
attrs: fold_attrs(v.node.attrs, fld),
data: fld.fold_variant_data(v.node.data),
disr_expr: v.node.disr_expr.map(|e| fld.fold_expr(e)),
disr_expr: v.node.disr_expr.map(|e| fld.fold_anon_const(e)),
},
span: fld.new_span(v.span),
}
@ -1170,6 +1174,14 @@ pub fn noop_fold_range_end<T: Folder>(end: RangeEnd, _folder: &mut T) -> RangeEn
end
}
pub fn noop_fold_anon_const<T: Folder>(constant: AnonConst, folder: &mut T) -> AnonConst {
let AnonConst {id, value} = constant;
AnonConst {
id: folder.new_id(id),
value: folder.fold_expr(value),
}
}
pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mut T) -> Expr {
Expr {
node: match node {
@ -1180,7 +1192,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
ExprKind::Array(folder.fold_exprs(exprs))
}
ExprKind::Repeat(expr, count) => {
ExprKind::Repeat(folder.fold_expr(expr), folder.fold_expr(count))
ExprKind::Repeat(folder.fold_expr(expr), folder.fold_anon_const(count))
}
ExprKind::Tup(exprs) => ExprKind::Tup(folder.fold_exprs(exprs)),
ExprKind::Call(f, args) => {

View File

@ -12,7 +12,7 @@ use rustc_target::spec::abi::{self, Abi};
use ast::{AngleBracketedParameterData, ParenthesizedParameterData, AttrStyle, BareFnTy};
use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
use ast::Unsafety;
use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind};
use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind};
use ast::Block;
use ast::{BlockCheckMode, CaptureBy, Movability};
use ast::{Constness, Crate};
@ -1543,7 +1543,10 @@ impl<'a> Parser<'a> {
// Parse optional `; EXPR` in `[TYPE; EXPR]`
let t = match self.maybe_parse_fixed_length_of_vec()? {
None => TyKind::Slice(t),
Some(suffix) => TyKind::Array(t, suffix),
Some(length) => TyKind::Array(t, AnonConst {
id: ast::DUMMY_NODE_ID,
value: length,
}),
};
self.expect(&token::CloseDelim(token::Bracket))?;
t
@ -1555,7 +1558,10 @@ impl<'a> Parser<'a> {
// `typeof(EXPR)`
// In order to not be ambiguous, the type must be surrounded by parens.
self.expect(&token::OpenDelim(token::Paren))?;
let e = self.parse_expr()?;
let e = AnonConst {
id: ast::DUMMY_NODE_ID,
value: self.parse_expr()?,
};
self.expect(&token::CloseDelim(token::Paren))?;
TyKind::Typeof(e)
} else if self.eat_keyword(keywords::Underscore) {
@ -2264,7 +2270,10 @@ impl<'a> Parser<'a> {
if self.check(&token::Semi) {
// Repeating array syntax: [ 0; 512 ]
self.bump();
let count = self.parse_expr()?;
let count = AnonConst {
id: ast::DUMMY_NODE_ID,
value: self.parse_expr()?,
};
self.expect(&token::CloseDelim(token::Bracket))?;
ex = ExprKind::Repeat(first_expr, count);
} else if self.check(&token::Comma) {
@ -6353,8 +6362,11 @@ impl<'a> Parser<'a> {
struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?,
ast::DUMMY_NODE_ID);
} else if self.eat(&token::Eq) {
disr_expr = Some(self.parse_expr()?);
any_disr = disr_expr.as_ref().map(|expr| expr.span);
disr_expr = Some(AnonConst {
id: ast::DUMMY_NODE_ID,
value: self.parse_expr()?,
});
any_disr = disr_expr.as_ref().map(|c| c.value.span);
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
} else {
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);

View File

@ -1076,16 +1076,16 @@ impl<'a> State<'a> {
ast::TyKind::ImplTrait(ref bounds) => {
self.print_bounds("impl", &bounds[..])?;
}
ast::TyKind::Array(ref ty, ref v) => {
ast::TyKind::Array(ref ty, ref length) => {
self.s.word("[")?;
self.print_type(ty)?;
self.s.word("; ")?;
self.print_expr(v)?;
self.print_expr(&length.value)?;
self.s.word("]")?;
}
ast::TyKind::Typeof(ref e) => {
self.s.word("typeof(")?;
self.print_expr(e)?;
self.print_expr(&e.value)?;
self.s.word(")")?;
}
ast::TyKind::Infer => {
@ -1552,7 +1552,7 @@ impl<'a> State<'a> {
Some(ref d) => {
self.s.space()?;
self.word_space("=")?;
self.print_expr(d)
self.print_expr(&d.value)
}
_ => Ok(())
}
@ -1905,14 +1905,14 @@ impl<'a> State<'a> {
fn print_expr_repeat(&mut self,
element: &ast::Expr,
count: &ast::Expr,
count: &ast::AnonConst,
attrs: &[Attribute]) -> io::Result<()> {
self.ibox(INDENT_UNIT)?;
self.s.word("[")?;
self.print_inner_attributes_inline(attrs)?;
self.print_expr(element)?;
self.word_space(";")?;
self.print_expr(count)?;
self.print_expr(&count.value)?;
self.s.word("]")?;
self.end()
}

View File

@ -69,6 +69,7 @@ pub trait Visitor<'ast>: Sized {
fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) }
fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) }
fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) }
fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) }
fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) }
fn visit_expr_post(&mut self, _ex: &'ast Expr) { }
fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) }
@ -296,7 +297,7 @@ pub fn walk_variant<'a, V>(visitor: &mut V,
visitor.visit_ident(variant.node.ident);
visitor.visit_variant_data(&variant.node.data, variant.node.ident,
generics, item_id, variant.span);
walk_list!(visitor, visit_expr, &variant.node.disr_expr);
walk_list!(visitor, visit_anon_const, &variant.node.disr_expr);
walk_list!(visitor, visit_attribute, &variant.node.attrs);
}
@ -326,16 +327,16 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
}
visitor.visit_path(path, typ.id);
}
TyKind::Array(ref ty, ref expression) => {
TyKind::Array(ref ty, ref length) => {
visitor.visit_ty(ty);
visitor.visit_expr(expression)
visitor.visit_anon_const(length)
}
TyKind::TraitObject(ref bounds, ..) |
TyKind::ImplTrait(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyKind::Typeof(ref expression) => {
visitor.visit_expr(expression)
visitor.visit_anon_const(expression)
}
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
TyKind::Mac(ref mac) => {
@ -647,6 +648,10 @@ pub fn walk_mac<'a, V: Visitor<'a>>(_: &mut V, _: &Mac) {
// Empty!
}
pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) {
visitor.visit_expr(&constant.value);
}
pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
for attr in expression.attrs.iter() {
visitor.visit_attribute(attr);
@ -660,7 +665,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
}
ExprKind::Repeat(ref element, ref count) => {
visitor.visit_expr(element);
visitor.visit_expr(count)
visitor.visit_anon_const(count)
}
ExprKind::Struct(ref path, ref fields, ref optional_base) => {
visitor.visit_path(path, expression.id);

View File

@ -0,0 +1,15 @@
// Copyright 2018 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.
enum Functions {
Square = |x| x, //~ ERROR mismatched types
}
fn main() {}

View File

@ -0,0 +1,15 @@
// Copyright 2018 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.
struct Foo (
fn([u8; |x: u8| {}]), //~ ERROR mismatched types
);
fn main() {}

View File

@ -0,0 +1,13 @@
// Copyright 2018 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.
fn main() {
[1; || {}]; //~ ERROR mismatched types
}

View File

@ -0,0 +1,17 @@
// Copyright 2018 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.
enum Foo {
Bar = (|x: i32| { }, 42).1,
}
fn main() {
assert_eq!(Foo::Bar as usize, 42);
}

View File

@ -1,11 +1,11 @@
error[E0391]: cycle detected when processing `X::A::{{initializer}}`
error[E0391]: cycle detected when processing `X::A::{{constant}}`
--> $DIR/issue-23302-1.rs:14:9
|
LL | A = X::A as isize, //~ ERROR E0391
| ^^^^^^^^^^^^^
|
= note: ...which again requires processing `X::A::{{initializer}}`, completing the cycle
note: cycle used when const-evaluating `X::A::{{initializer}}`
= note: ...which again requires processing `X::A::{{constant}}`, completing the cycle
note: cycle used when const-evaluating `X::A::{{constant}}`
--> $DIR/issue-23302-1.rs:14:9
|
LL | A = X::A as isize, //~ ERROR E0391

View File

@ -1,11 +1,11 @@
error[E0391]: cycle detected when processing `Y::A::{{initializer}}`
error[E0391]: cycle detected when processing `Y::A::{{constant}}`
--> $DIR/issue-23302-2.rs:14:9
|
LL | A = Y::B as isize, //~ ERROR E0391
| ^^^^^^^^^^^^^
|
= note: ...which again requires processing `Y::A::{{initializer}}`, completing the cycle
note: cycle used when const-evaluating `Y::A::{{initializer}}`
= note: ...which again requires processing `Y::A::{{constant}}`, completing the cycle
note: cycle used when const-evaluating `Y::A::{{constant}}`
--> $DIR/issue-23302-2.rs:14:9
|
LL | A = Y::B as isize, //~ ERROR E0391

View File

@ -1,4 +1,4 @@
error[E0391]: cycle detected when processing `Foo::B::{{initializer}}`
error[E0391]: cycle detected when processing `Foo::B::{{constant}}`
--> $DIR/issue-36163.rs:14:9
|
LL | B = A, //~ ERROR E0391
@ -9,8 +9,8 @@ note: ...which requires processing `A`...
|
LL | const A: isize = Foo::B as isize;
| ^^^^^^^^^^^^^^^
= note: ...which again requires processing `Foo::B::{{initializer}}`, completing the cycle
note: cycle used when const-evaluating `Foo::B::{{initializer}}`
= note: ...which again requires processing `Foo::B::{{constant}}`, completing the cycle
note: cycle used when const-evaluating `Foo::B::{{constant}}`
--> $DIR/issue-36163.rs:14:9
|
LL | B = A, //~ ERROR E0391