Auto merge of #50851 - eddyb:the-only-constant, r=nikomatsakis
rustc: introduce {ast,hir}::AnonConst to consolidate so-called "embedded constants". Previously, constants in array lengths and enum variant discriminants were "merely an expression", and had no separate ID for, e.g. type-checking or const-eval, instead reusing the expression's. That complicated code working with bodies, because such constants were the only special case where the "owner" of the body wasn't the HIR parent, but rather the same node as the body itself. Also, if the body happened to be a closure, we had no way to allocate a `DefId` for both the constant *and* the closure, leading to *several* bugs (mostly ICEs where type errors were expected). This PR rectifies the situation by adding another (`{ast,hir}::AnonConst`) node around every such constant. Also, const generics are expected to rely on the new `AnonConst` nodes, as well (cc @varkor). * fixes #48838 * fixes #50600 * fixes #50688 * fixes #50689 * obsoletes #50623 r? @nikomatsakis
This commit is contained in:
commit
538fea5757
|
@ -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);
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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,17 +200,11 @@ 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);
|
||||
self.with_parent(def, |this| {
|
||||
if let TraitItemKind::Const(_, Some(ref expr)) = ti.node {
|
||||
this.visit_const_expr(expr);
|
||||
}
|
||||
|
||||
visit::walk_trait_item(this, ti);
|
||||
});
|
||||
self.with_parent(def, |this| visit::walk_trait_item(this, ti));
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
||||
|
@ -245,32 +212,33 @@ 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);
|
||||
self.with_parent(def, |this| {
|
||||
if let ImplItemKind::Const(_, ref expr) = ii.node {
|
||||
this.visit_const_expr(expr);
|
||||
}
|
||||
|
||||
visit::walk_impl_item(this, ii);
|
||||
});
|
||||
self.with_parent(def, |this| visit::walk_impl_item(this, ii));
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -287,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);
|
||||
|
@ -300,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),
|
||||
}
|
||||
}
|
||||
|
@ -310,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);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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_>;
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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) => {
|
||||
|
@ -3816,12 +3796,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 {
|
||||
|
|
|
@ -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),
|
||||
}));
|
||||
|
@ -715,13 +710,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),
|
||||
|
@ -732,11 +726,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)
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -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)) => {
|
||||
|
|
|
@ -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_>;
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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};
|
||||
|
@ -1544,7 +1544,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
|
||||
|
@ -1556,7 +1559,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) {
|
||||
|
@ -2265,7 +2271,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) {
|
||||
|
@ -6354,8 +6363,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);
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
15
src/test/compile-fail/issue-48838.rs
Normal file
15
src/test/compile-fail/issue-48838.rs
Normal 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() {}
|
15
src/test/compile-fail/issue-50600.rs
Normal file
15
src/test/compile-fail/issue-50600.rs
Normal 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() {}
|
13
src/test/compile-fail/issue-50688.rs
Normal file
13
src/test/compile-fail/issue-50688.rs
Normal 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
|
||||
}
|
17
src/test/run-pass/issue-50689.rs
Normal file
17
src/test/run-pass/issue-50689.rs
Normal 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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue