diff --git a/src/etc/generate-deriving-span-tests.py b/src/etc/generate-deriving-span-tests.py index 790fc8942873e..6642da858e551 100755 --- a/src/etc/generate-deriving-span-tests.py +++ b/src/etc/generate-deriving-span-tests.py @@ -37,8 +37,6 @@ // This file was auto-generated using 'src/etc/generate-deriving-span-tests.py' -extern crate rand; - {error_deriving} struct Error; {code} @@ -106,7 +104,6 @@ def write_file(name, string): ALL = STRUCT | ENUM traits = { - 'Zero': (STRUCT, [], 1), 'Default': (STRUCT, [], 1), 'FromPrimitive': (0, [], 0), # only works for C-like enums @@ -116,7 +113,7 @@ def write_file(name, string): for (trait, supers, errs) in [('Clone', [], 1), ('PartialEq', [], 2), - ('PartialOrd', ['PartialEq'], 8), + ('PartialOrd', ['PartialEq'], 9), ('Eq', ['PartialEq'], 1), ('Ord', ['Eq', 'PartialOrd', 'PartialEq'], 1), ('Debug', [], 1), diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index c399623462b5d..f21d98a0fc7f9 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -10,8 +10,6 @@ use rustc_data_structures::graph; use cfg::*; -use hir::def::Def; -use hir::pat_util; use ty::{self, TyCtxt}; use syntax::ast; use syntax::ptr::P; @@ -100,7 +98,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex { match pat.node { PatKind::Binding(.., None) | - PatKind::Path(..) | + PatKind::Path(_) | PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => { @@ -284,7 +282,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprBreak(label, ref opt_expr) => { let v = self.opt_expr(opt_expr, pred); - let loop_scope = self.find_scope(expr, label.map(|l| l.node)); + let loop_scope = self.find_scope(expr, label); let b = self.add_ast_node(expr.id, &[v]); self.add_exiting_edge(expr, b, loop_scope, loop_scope.break_index); @@ -292,7 +290,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprAgain(label) => { - let loop_scope = self.find_scope(expr, label.map(|l| l.node)); + let loop_scope = self.find_scope(expr, label); let a = self.add_ast_node(expr.id, &[pred]); self.add_exiting_edge(expr, a, loop_scope, loop_scope.continue_index); @@ -361,7 +359,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprClosure(..) | hir::ExprLit(..) | - hir::ExprPath(..) => { + hir::ExprPath(_) => { self.straightline(expr, pred, None::.iter()) } } @@ -457,7 +455,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Visit the guard expression let guard_exit = self.expr(&guard, guard_start); - let this_has_bindings = pat_util::pat_contains_bindings_or_wild(&pat); + let this_has_bindings = pat.contains_bindings_or_wild(); // If both this pattern and the previous pattern // were free of bindings, they must consist only @@ -570,23 +568,16 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn find_scope(&self, expr: &hir::Expr, - label: Option) -> LoopScope { - if label.is_none() { - return *self.loop_scopes.last().unwrap(); - } - - match self.tcx.expect_def(expr.id) { - Def::Label(loop_id) => { + label: Option) -> LoopScope { + match label { + None => *self.loop_scopes.last().unwrap(), + Some(label) => { for l in &self.loop_scopes { - if l.loop_id == loop_id { + if l.loop_id == label.loop_id { return *l; } } - span_bug!(expr.span, "no loop scope for id {}", loop_id); - } - - r => { - span_bug!(expr.span, "bad entry `{:?}` in def_map for label", r); + span_bug!(expr.span, "no loop scope for id {}", label.loop_id); } } } diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 351feaba0346a..397d61d5372e0 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -90,7 +90,7 @@ pub enum DepNode { RvalueCheck(D), Reachability, DeadCheck, - StabilityCheck, + StabilityCheck(D), LateLintCheck, TransCrate, TransCrateItem(D), @@ -189,7 +189,6 @@ impl DepNode { Privacy => Some(Privacy), Reachability => Some(Reachability), DeadCheck => Some(DeadCheck), - StabilityCheck => Some(StabilityCheck), LateLintCheck => Some(LateLintCheck), TransCrate => Some(TransCrate), TransWriteMetadata => Some(TransWriteMetadata), @@ -217,6 +216,7 @@ impl DepNode { Mir(ref d) => op(d).map(Mir), BorrowCheck(ref d) => op(d).map(BorrowCheck), RvalueCheck(ref d) => op(d).map(RvalueCheck), + StabilityCheck(ref d) => op(d).map(StabilityCheck), TransCrateItem(ref d) => op(d).map(TransCrateItem), TransInlinedItem(ref d) => op(d).map(TransInlinedItem), AssociatedItems(ref d) => op(d).map(AssociatedItems), diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index feefc43f4013e..b6fce2d6ca0be 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -83,14 +83,6 @@ impl PathResolution { PathResolution { base_def: def, depth: 0 } } - /// Get the definition, if fully resolved, otherwise panic. - pub fn full_def(&self) -> Def { - if self.depth != 0 { - bug!("path not fully resolved: {:?}", self); - } - self.base_def - } - pub fn kind_name(&self) -> &'static str { if self.depth != 0 { "associated item" diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 7dd88e36dd1f5..94da10d33f818 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -38,6 +38,7 @@ use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute}; use syntax::codemap::Spanned; use syntax_pos::Span; use hir::*; +use hir::def::Def; use hir::map::Map; use super::itemlikevisit::DeepVisitor; @@ -155,6 +156,9 @@ pub trait Visitor<'v> : Sized { fn visit_id(&mut self, _node_id: NodeId) { // Nothing to do. } + fn visit_def_mention(&mut self, _def: Def) { + // Nothing to do. + } fn visit_name(&mut self, _span: Span, _name: Name) { // Nothing to do. } @@ -244,12 +248,12 @@ pub trait Visitor<'v> : Sized { fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) { walk_lifetime_def(self, lifetime) } + fn visit_qpath(&mut self, qpath: &'v QPath, id: NodeId, span: Span) { + walk_qpath(self, qpath, id, span) + } fn visit_path(&mut self, path: &'v Path, _id: NodeId) { walk_path(self, path) } - fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) { - walk_path_list_item(self, prefix, item) - } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { walk_path_segment(self, path_span, path_segment) } @@ -349,23 +353,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_id(item.id); walk_opt_name(visitor, item.span, opt_name) } - ItemUse(ref vp) => { + ItemUse(ref path, _) => { visitor.visit_id(item.id); - match vp.node { - ViewPathSimple(name, ref path) => { - visitor.visit_name(vp.span, name); - visitor.visit_path(path, item.id); - } - ViewPathGlob(ref path) => { - visitor.visit_path(path, item.id); - } - ViewPathList(ref prefix, ref list) => { - visitor.visit_path(prefix, item.id); - for item in list { - visitor.visit_path_list_item(prefix, item) - } - } - } + visitor.visit_path(path, item.id); } ItemStatic(ref typ, _, ref expr) | ItemConst(ref typ, ref expr) => { @@ -481,11 +471,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_fn_decl(visitor, &function_declaration.decl); walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes); } - TyPath(ref maybe_qself, ref path) => { - if let Some(ref qself) = *maybe_qself { - visitor.visit_ty(&qself.ty); - } - visitor.visit_path(path, typ.id); + TyPath(ref qpath) => { + visitor.visit_qpath(qpath, typ.id, typ.span); } TyObjectSum(ref ty, ref bounds) => { visitor.visit_ty(ty); @@ -508,20 +495,28 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { } } +pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath, id: NodeId, span: Span) { + match *qpath { + QPath::Resolved(ref maybe_qself, ref path) => { + if let Some(ref qself) = *maybe_qself { + visitor.visit_ty(qself); + } + visitor.visit_path(path, id) + } + QPath::TypeRelative(ref qself, ref segment) => { + visitor.visit_ty(qself); + visitor.visit_path_segment(span, segment); + } + } +} + pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { + visitor.visit_def_mention(path.def); for segment in &path.segments { visitor.visit_path_segment(path.span, segment); } } -pub fn walk_path_list_item<'v, V>(visitor: &mut V, _prefix: &'v Path, item: &'v PathListItem) - where V: Visitor<'v>, -{ - visitor.visit_id(item.node.id); - visitor.visit_name(item.span, item.node.name); - walk_opt_name(visitor, item.span, item.node.rename); -} - pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, path_span: Span, segment: &'v PathSegment) { @@ -555,18 +550,15 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { visitor.visit_id(pattern.id); match pattern.node { - PatKind::TupleStruct(ref path, ref children, _) => { - visitor.visit_path(path, pattern.id); + PatKind::TupleStruct(ref qpath, ref children, _) => { + visitor.visit_qpath(qpath, pattern.id, pattern.span); walk_list!(visitor, visit_pat, children); } - PatKind::Path(ref opt_qself, ref path) => { - if let Some(ref qself) = *opt_qself { - visitor.visit_ty(&qself.ty); - } - visitor.visit_path(path, pattern.id) + PatKind::Path(ref qpath) => { + visitor.visit_qpath(qpath, pattern.id, pattern.span); } - PatKind::Struct(ref path, ref fields, _) => { - visitor.visit_path(path, pattern.id); + PatKind::Struct(ref qpath, ref fields, _) => { + visitor.visit_qpath(qpath, pattern.id, pattern.span); for field in fields { visitor.visit_name(field.span, field.node.name); visitor.visit_pat(&field.node.pat) @@ -579,7 +571,8 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { PatKind::Ref(ref subpattern, _) => { visitor.visit_pat(subpattern) } - PatKind::Binding(_, ref pth1, ref optional_subpattern) => { + PatKind::Binding(_, def_id, ref pth1, ref optional_subpattern) => { + visitor.visit_def_mention(Def::Local(def_id)); visitor.visit_name(pth1.span, pth1.node); walk_list!(visitor, visit_pat, optional_subpattern); } @@ -840,8 +833,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(element); visitor.visit_expr(count) } - ExprStruct(ref path, ref fields, ref optional_base) => { - visitor.visit_path(path, expression.id); + ExprStruct(ref qpath, ref fields, ref optional_base) => { + visitor.visit_qpath(qpath, expression.id, expression.span); for field in fields { visitor.visit_name(field.name.span, field.name.node); visitor.visit_expr(&field.expr) @@ -917,18 +910,21 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(main_expression); visitor.visit_expr(index_expression) } - ExprPath(ref maybe_qself, ref path) => { - if let Some(ref qself) = *maybe_qself { - visitor.visit_ty(&qself.ty); - } - visitor.visit_path(path, expression.id) + ExprPath(ref qpath) => { + visitor.visit_qpath(qpath, expression.id, expression.span); } - ExprBreak(ref opt_sp_name, ref opt_expr) => { - walk_opt_sp_name(visitor, opt_sp_name); + ExprBreak(None, ref opt_expr) => { walk_list!(visitor, visit_expr, opt_expr); } - ExprAgain(ref opt_sp_name) => { - walk_opt_sp_name(visitor, opt_sp_name); + ExprBreak(Some(label), ref opt_expr) => { + visitor.visit_def_mention(Def::Label(label.loop_id)); + visitor.visit_name(label.span, label.name); + walk_list!(visitor, visit_expr, opt_expr); + } + ExprAgain(None) => {} + ExprAgain(Some(label)) => { + visitor.visit_def_mention(Def::Label(label.loop_id)); + visitor.visit_name(label.span, label.name); } ExprRet(ref optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5af7c18e1a107..39d0ed9a67b09 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -52,9 +52,10 @@ use std::iter; use syntax::ast::*; use syntax::errors; use syntax::ptr::P; -use syntax::codemap::{respan, Spanned}; +use syntax::codemap::{self, respan, Spanned}; use syntax::std_inject; use syntax::symbol::{Symbol, keywords}; +use syntax::util::small_vector::SmallVector; use syntax::visit::{self, Visitor}; use syntax_pos::Span; @@ -67,11 +68,16 @@ pub struct LoweringContext<'a> { // a definition, then we can properly create the def id. parent_def: Option, resolver: &'a mut Resolver, + + /// The items being lowered are collected here. + items: BTreeMap, + + impl_items: BTreeMap, } pub trait Resolver { // Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc. - fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def; + fn resolve_generated_global_path(&mut self, path: &mut hir::Path, is_value: bool); // Obtain the resolution for a node id fn get_resolution(&mut self, id: NodeId) -> Option; @@ -98,45 +104,49 @@ pub fn lower_crate(sess: &Session, sess: sess, parent_def: None, resolver: resolver, + items: BTreeMap::new(), + impl_items: BTreeMap::new(), }.lower_crate(krate) } +#[derive(Copy, Clone, PartialEq, Eq)] +enum ParamMode { + /// Any path in a type context. + Explicit, + /// The `module::Type` in `module::Type::method` in an expression. + Optional +} + impl<'a> LoweringContext<'a> { - fn lower_crate(&mut self, c: &Crate) -> hir::Crate { + fn lower_crate(mut self, c: &Crate) -> hir::Crate { struct ItemLowerer<'lcx, 'interner: 'lcx> { - items: BTreeMap, - impl_items: BTreeMap, lctx: &'lcx mut LoweringContext<'interner>, } impl<'lcx, 'interner> Visitor for ItemLowerer<'lcx, 'interner> { fn visit_item(&mut self, item: &Item) { - self.items.insert(item.id, self.lctx.lower_item(item)); + let hir_item = self.lctx.lower_item(item); + self.lctx.items.insert(item.id, hir_item); visit::walk_item(self, item); } fn visit_impl_item(&mut self, item: &ImplItem) { let id = self.lctx.lower_impl_item_ref(item).id; - self.impl_items.insert(id, self.lctx.lower_impl_item(item)); + let hir_item = self.lctx.lower_impl_item(item); + self.lctx.impl_items.insert(id, hir_item); visit::walk_impl_item(self, item); } } - let (items, impl_items) = { - let mut item_lowerer = ItemLowerer { items: BTreeMap::new(), - impl_items: BTreeMap::new(), - lctx: self }; - visit::walk_crate(&mut item_lowerer, c); - (item_lowerer.items, item_lowerer.impl_items) - }; + visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c); hir::Crate { module: self.lower_mod(&c.module), attrs: self.lower_attrs(&c.attrs), span: c.span, exported_macros: c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(), - items: items, - impl_items: impl_items, + items: self.items, + impl_items: self.impl_items, } } @@ -144,6 +154,15 @@ impl<'a> LoweringContext<'a> { self.sess.next_node_id() } + fn expect_full_def(&mut self, id: NodeId) -> Def { + self.resolver.get_resolution(id).map_or(Def::Err, |pr| { + if pr.depth != 0 { + bug!("path not fully resolved: {:?}", pr); + } + pr.base_def + }) + } + fn diagnostic(&self) -> &errors::Handler { self.sess.diagnostic() } @@ -152,6 +171,18 @@ impl<'a> LoweringContext<'a> { Symbol::gensym(s) } + fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span { + span.expn_id = self.sess.codemap().record_expansion(codemap::ExpnInfo { + call_site: span, + callee: codemap::NameAndSpan { + format: codemap::CompilerDesugaring(Symbol::intern(reason)), + span: Some(span), + allow_internal_unstable: true, + }, + }); + span + } + fn with_parent_def(&mut self, parent_id: NodeId, f: F) -> T where F: FnOnce(&mut LoweringContext) -> T { @@ -171,39 +202,21 @@ impl<'a> LoweringContext<'a> { o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name)) } - fn lower_attrs(&mut self, attrs: &Vec) -> hir::HirVec { - attrs.clone().into() - } - - fn lower_view_path(&mut self, view_path: &ViewPath) -> P { - P(Spanned { - node: match view_path.node { - ViewPathSimple(ident, ref path) => { - hir::ViewPathSimple(ident.name, self.lower_path(path)) - } - ViewPathGlob(ref path) => { - hir::ViewPathGlob(self.lower_path(path)) + fn lower_label(&mut self, id: NodeId, label: Option>) -> Option { + label.map(|sp_ident| { + hir::Label { + span: sp_ident.span, + name: sp_ident.node.name, + loop_id: match self.expect_full_def(id) { + Def::Label(loop_id) => loop_id, + _ => DUMMY_NODE_ID } - ViewPathList(ref path, ref path_list_idents) => { - hir::ViewPathList(self.lower_path(path), - path_list_idents.iter() - .map(|item| self.lower_path_list_item(item)) - .collect()) - } - }, - span: view_path.span, + } }) } - fn lower_path_list_item(&mut self, path_list_ident: &PathListItem) -> hir::PathListItem { - Spanned { - node: hir::PathListItem_ { - id: path_list_ident.node.id, - name: path_list_ident.node.name.name, - rename: path_list_ident.node.rename.map(|rename| rename.name), - }, - span: path_list_ident.span, - } + fn lower_attrs(&mut self, attrs: &Vec) -> hir::HirVec { + attrs.clone().into() } fn lower_arm(&mut self, arm: &Arm) -> hir::Arm { @@ -250,13 +263,7 @@ impl<'a> LoweringContext<'a> { return self.lower_ty(ty); } TyKind::Path(ref qself, ref path) => { - let qself = qself.as_ref().map(|&QSelf { ref ty, position }| { - hir::QSelf { - ty: self.lower_ty(ty), - position: position, - } - }); - hir::TyPath(qself, self.lower_path(path)) + hir::TyPath(self.lower_qpath(t.id, qself, path, ParamMode::Explicit)) } TyKind::ObjectSum(ref ty, ref bounds) => { hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds)) @@ -298,38 +305,145 @@ impl<'a> LoweringContext<'a> { } } - fn lower_path(&mut self, p: &Path) -> hir::Path { + fn lower_qpath(&mut self, + id: NodeId, + qself: &Option, + p: &Path, + param_mode: ParamMode) + -> hir::QPath { + let qself_position = qself.as_ref().map(|q| q.position); + let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty)); + + let resolution = self.resolver.get_resolution(id) + .unwrap_or(PathResolution::new(Def::Err)); + + let proj_start = p.segments.len() - resolution.depth; + let path = P(hir::Path { + global: p.global, + def: resolution.base_def, + segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| { + let param_mode = match (qself_position, param_mode) { + (Some(j), ParamMode::Optional) if i < j => { + // This segment is part of the trait path in a + // qualified path - one of `a`, `b` or `Trait` + // in `::T::U::method`. + ParamMode::Explicit + } + _ => param_mode + }; + self.lower_path_segment(segment, param_mode) + }).collect(), + span: p.span, + }); + + // Simple case, either no projections, or only fully-qualified. + // E.g. `std::mem::size_of` or `::Item`. + if resolution.depth == 0 { + return hir::QPath::Resolved(qself, path); + } + + // Create the innermost type that we're projecting from. + let mut ty = if path.segments.is_empty() { + // If the base path is empty that means there exists a + // syntactical `Self`, e.g. `&i32` in `<&i32>::clone`. + qself.expect("missing QSelf for ::...") + } else { + // Otherwise, the base path is an implicit `Self` type path, + // e.g. `Vec` in `Vec::new` or `::Item` in + // `::Item::default`. + let ty = self.ty(p.span, hir::TyPath(hir::QPath::Resolved(qself, path))); + + // Associate that innermost path type with the base Def. + self.resolver.record_resolution(ty.id, resolution.base_def); + + ty + }; + + // Anything after the base path are associated "extensions", + // out of which all but the last one are associated types, + // e.g. for `std::vec::Vec::::IntoIter::Item::clone`: + // * base path is `std::vec::Vec` + // * "extensions" are `IntoIter`, `Item` and `clone` + // * type nodes are: + // 1. `std::vec::Vec` (created above) + // 2. `>::IntoIter` + // 3. `<>::IntoIter>::Item` + // * final path is `<<>::IntoIter>::Item>::clone` + for (i, segment) in p.segments.iter().enumerate().skip(proj_start) { + let segment = P(self.lower_path_segment(segment, param_mode)); + let qpath = hir::QPath::TypeRelative(ty, segment); + + // It's finished, return the extension of the right node type. + if i == p.segments.len() - 1 { + return qpath; + } + + // Wrap the associated extension in another type node. + ty = self.ty(p.span, hir::TyPath(qpath)); + } + + // Should've returned in the for loop above. + span_bug!(p.span, "lower_qpath: no final extension segment in {}..{}", + proj_start, p.segments.len()) + } + + fn lower_path_extra(&mut self, + id: NodeId, + p: &Path, + name: Option, + param_mode: ParamMode) + -> hir::Path { hir::Path { global: p.global, - segments: p.segments - .iter() - .map(|&PathSegment { identifier, ref parameters }| { - hir::PathSegment { - name: identifier.name, - parameters: self.lower_path_parameters(parameters), - } - }) - .collect(), + def: self.expect_full_def(id), + segments: p.segments.iter().map(|segment| { + self.lower_path_segment(segment, param_mode) + }).chain(name.map(|name| { + hir::PathSegment { + name: name, + parameters: hir::PathParameters::none() + } + })).collect(), span: p.span, } } - fn lower_path_parameters(&mut self, path_parameters: &PathParameters) -> hir::PathParameters { - match *path_parameters { - PathParameters::AngleBracketed(ref data) => - hir::AngleBracketedParameters(self.lower_angle_bracketed_parameter_data(data)), + fn lower_path(&mut self, + id: NodeId, + p: &Path, + param_mode: ParamMode) + -> hir::Path { + self.lower_path_extra(id, p, None, param_mode) + } + + fn lower_path_segment(&mut self, + segment: &PathSegment, + param_mode: ParamMode) + -> hir::PathSegment { + let parameters = match segment.parameters { + PathParameters::AngleBracketed(ref data) => { + let data = self.lower_angle_bracketed_parameter_data(data, param_mode); + hir::AngleBracketedParameters(data) + } PathParameters::Parenthesized(ref data) => hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)), + }; + + hir::PathSegment { + name: segment.identifier.name, + parameters: parameters, } } fn lower_angle_bracketed_parameter_data(&mut self, - data: &AngleBracketedParameterData) + data: &AngleBracketedParameterData, + param_mode: ParamMode) -> hir::AngleBracketedParameterData { let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data; hir::AngleBracketedParameterData { lifetimes: self.lower_lifetimes(lifetimes), types: types.iter().map(|ty| self.lower_ty(ty)).collect(), + infer_types: types.is_empty() && param_mode == ParamMode::Optional, bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(), } } @@ -493,7 +607,7 @@ impl<'a> LoweringContext<'a> { span}) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { id: id, - path: self.lower_path(path), + path: self.lower_path(id, path, ParamMode::Explicit), ty: self.lower_ty(ty), span: span, }) @@ -523,7 +637,7 @@ impl<'a> LoweringContext<'a> { fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef { hir::TraitRef { - path: self.lower_path(&p.path), + path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit), ref_id: p.ref_id, } } @@ -568,12 +682,10 @@ impl<'a> LoweringContext<'a> { } fn lower_block(&mut self, b: &Block) -> P { - let mut stmts = Vec::new(); let mut expr = None; - if let Some((last, rest)) = b.stmts.split_last() { - stmts = rest.iter().map(|s| self.lower_stmt(s)).collect::>(); - let last = self.lower_stmt(last); + let mut stmts = b.stmts.iter().flat_map(|s| self.lower_stmt(s)).collect::>(); + if let Some(last) = stmts.pop() { if let hir::StmtExpr(e, _) = last.node { expr = Some(e); } else { @@ -590,11 +702,66 @@ impl<'a> LoweringContext<'a> { }) } - fn lower_item_kind(&mut self, i: &ItemKind) -> hir::Item_ { + fn lower_item_kind(&mut self, + id: NodeId, + name: &mut Name, + attrs: &hir::HirVec, + vis: &mut hir::Visibility, + i: &ItemKind) + -> hir::Item_ { match *i { ItemKind::ExternCrate(string) => hir::ItemExternCrate(string), ItemKind::Use(ref view_path) => { - hir::ItemUse(self.lower_view_path(view_path)) + let path = match view_path.node { + ViewPathSimple(_, ref path) => path, + ViewPathGlob(ref path) => path, + ViewPathList(ref path, ref path_list_idents) => { + for &Spanned { node: ref import, span } in path_list_idents { + // `use a::{self as x, b as y};` lowers to + // `use a as x; use a::b as y;` + let mut ident = import.name; + let suffix = if ident.name == keywords::SelfValue.name() { + if let Some(last) = path.segments.last() { + ident = last.identifier; + } + None + } else { + Some(ident.name) + }; + + let mut path = self.lower_path_extra(import.id, path, suffix, + ParamMode::Explicit); + path.span = span; + self.items.insert(import.id, hir::Item { + id: import.id, + name: import.rename.unwrap_or(ident).name, + attrs: attrs.clone(), + node: hir::ItemUse(P(path), hir::UseKind::Single), + vis: vis.clone(), + span: span, + }); + } + path + } + }; + let path = P(self.lower_path(id, path, ParamMode::Explicit)); + let kind = match view_path.node { + ViewPathSimple(ident, _) => { + *name = ident.name; + hir::UseKind::Single + } + ViewPathGlob(_) => { + hir::UseKind::Glob + } + ViewPathList(..) => { + // Privatize the degenerate import base, used only to check + // the stability of `use a::{};`, to avoid it showing up as + // a reexport by accident when `pub`, e.g. in documentation. + *vis = hir::Inherited; + hir::UseKind::ListStem + } + }; + hir::ItemUse(path, kind) } ItemKind::Static(ref t, m, ref e) => { hir::ItemStatic(self.lower_ty(t), @@ -742,7 +909,7 @@ impl<'a> LoweringContext<'a> { fn lower_mod(&mut self, m: &Mod) -> hir::Mod { hir::Mod { inner: m.inner, - item_ids: m.items.iter().map(|x| self.lower_item_id(x)).collect(), + item_ids: m.items.iter().flat_map(|x| self.lower_item_id(x)).collect(), } } @@ -758,21 +925,30 @@ impl<'a> LoweringContext<'a> { } } - fn lower_item_id(&mut self, i: &Item) -> hir::ItemId { - hir::ItemId { id: i.id } + fn lower_item_id(&mut self, i: &Item) -> SmallVector { + if let ItemKind::Use(ref view_path) = i.node { + if let ViewPathList(_, ref imports) = view_path.node { + return iter::once(i.id).chain(imports.iter().map(|import| import.node.id)) + .map(|id| hir::ItemId { id: id }).collect(); + } + } + SmallVector::one(hir::ItemId { id: i.id }) } pub fn lower_item(&mut self, i: &Item) -> hir::Item { + let mut name = i.ident.name; + let attrs = self.lower_attrs(&i.attrs); + let mut vis = self.lower_visibility(&i.vis); let node = self.with_parent_def(i.id, |this| { - this.lower_item_kind(&i.node) + this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node) }); hir::Item { id: i.id, - name: i.ident.name, - attrs: self.lower_attrs(&i.attrs), + name: name, + attrs: attrs, node: node, - vis: self.lower_visibility(&i.vis), + vis: vis, span: i.span, } } @@ -875,29 +1051,41 @@ impl<'a> LoweringContext<'a> { self.with_parent_def(p.id, |this| { match this.resolver.get_resolution(p.id).map(|d| d.base_def) { // `None` can occur in body-less function signatures - None | Some(Def::Local(..)) => { + def @ None | def @ Some(Def::Local(_)) => { + let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| { + this.resolver.definitions().local_def_id(p.id) + }); hir::PatKind::Binding(this.lower_binding_mode(binding_mode), + def_id, respan(pth1.span, pth1.node.name), sub.as_ref().map(|x| this.lower_pat(x))) } - _ => hir::PatKind::Path(None, hir::Path::from_name(pth1.span, - pth1.node.name)) + Some(def) => { + hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path { + span: pth1.span, + global: false, + def: def, + segments: hir_vec![ + hir::PathSegment::from_name(pth1.node.name) + ], + }))) + } } }) } PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))), PatKind::TupleStruct(ref path, ref pats, ddpos) => { - hir::PatKind::TupleStruct(self.lower_path(path), - pats.iter().map(|x| self.lower_pat(x)).collect(), ddpos) + let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional); + hir::PatKind::TupleStruct(qpath, + pats.iter().map(|x| self.lower_pat(x)).collect(), + ddpos) } - PatKind::Path(ref opt_qself, ref path) => { - let opt_qself = opt_qself.as_ref().map(|qself| { - hir::QSelf { ty: self.lower_ty(&qself.ty), position: qself.position } - }); - hir::PatKind::Path(opt_qself, self.lower_path(path)) + PatKind::Path(ref qself, ref path) => { + hir::PatKind::Path(self.lower_qpath(p.id, qself, path, ParamMode::Optional)) } - PatKind::Struct(ref pth, ref fields, etc) => { - let pth = self.lower_path(pth); + PatKind::Struct(ref path, ref fields, etc) => { + let qpath = self.lower_qpath(p.id, &None, path, ParamMode::Optional); + let fs = fields.iter() .map(|f| { Spanned { @@ -910,7 +1098,7 @@ impl<'a> LoweringContext<'a> { } }) .collect(); - hir::PatKind::Struct(pth, fs, etc) + hir::PatKind::Struct(qpath, fs, etc) } PatKind::Tuple(ref elts, ddpos) => { hir::PatKind::Tuple(elts.iter().map(|x| self.lower_pat(x)).collect(), ddpos) @@ -980,9 +1168,9 @@ impl<'a> LoweringContext<'a> { let move_val_init = ["intrinsics", "move_val_init"]; let inplace_finalize = ["ops", "InPlace", "finalize"]; + let unstable_span = self.allow_internal_unstable("<-", e.span); let make_call = |this: &mut LoweringContext, p, args| { - let path = this.std_path(e.span, p); - let path = this.expr_path(path, ThinVec::new()); + let path = P(this.expr_std_path(unstable_span, p, ThinVec::new())); P(this.expr_call(e.span, path, args)) }; @@ -996,11 +1184,6 @@ impl<'a> LoweringContext<'a> { // let placer = ; let (s1, placer_binding) = { - let placer_expr = P(self.signal_block_expr(hir_vec![], - placer_expr, - e.span, - hir::PopUnstableBlock, - ThinVec::new())); mk_stmt_let(self, placer_ident, placer_expr) }; @@ -1021,11 +1204,6 @@ impl<'a> LoweringContext<'a> { // pop_unsafe!(EXPR)); let pop_unsafe_expr = { - let value_expr = P(self.signal_block_expr(hir_vec![], - value_expr, - e.span, - hir::PopUnstableBlock, - ThinVec::new())); self.signal_block_expr(hir_vec![], value_expr, e.span, @@ -1054,11 +1232,9 @@ impl<'a> LoweringContext<'a> { ThinVec::new())) }; - return self.signal_block_expr(hir_vec![s1, s2, s3], - expr, - e.span, - hir::PushUnstableBlock, - e.attrs.clone()); + let block = self.block_all(e.span, hir_vec![s1, s2, s3], Some(expr)); + // add the attributes to the outer returned expr node + return self.expr_block(P(block), e.attrs.clone()); } ExprKind::Vec(ref exprs) => { @@ -1176,33 +1352,23 @@ impl<'a> LoweringContext<'a> { ast_expr: &Expr, path: &[&str], fields: &[(&str, &P)]) -> hir::Expr { - let struct_path = this.std_path(ast_expr.span, - &iter::once(&"ops").chain(path) - .map(|s| *s) - .collect::>()); + let struct_path = &iter::once(&"ops").chain(path).map(|s| *s) + .collect::>(); + let unstable_span = this.allow_internal_unstable("...", ast_expr.span); - let hir_expr = if fields.len() == 0 { - this.expr_path(struct_path, ast_expr.attrs.clone()) + if fields.len() == 0 { + this.expr_std_path(unstable_span, struct_path, + ast_expr.attrs.clone()) } else { let fields = fields.into_iter().map(|&(s, e)| { let expr = P(this.lower_expr(&e)); - let signal_block = P(this.signal_block_expr(hir_vec![], - expr, - e.span, - hir::PopUnstableBlock, - ThinVec::new())); - this.field(Symbol::intern(s), signal_block, ast_expr.span) + let unstable_span = this.allow_internal_unstable("...", e.span); + this.field(Symbol::intern(s), expr, unstable_span) }).collect(); let attrs = ast_expr.attrs.clone(); - this.expr_struct(ast_expr.span, struct_path, fields, None, attrs) - }; - - this.signal_block_expr(hir_vec![], - hir_expr, - ast_expr.span, - hir::PushUnstableBlock, - ThinVec::new()) + this.expr_std_struct(unstable_span, struct_path, fields, None, attrs) + } } use syntax::ast::RangeLimits::*; @@ -1236,19 +1402,13 @@ impl<'a> LoweringContext<'a> { }; } ExprKind::Path(ref qself, ref path) => { - let hir_qself = qself.as_ref().map(|&QSelf { ref ty, position }| { - hir::QSelf { - ty: self.lower_ty(ty), - position: position, - } - }); - hir::ExprPath(hir_qself, self.lower_path(path)) + hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional)) } ExprKind::Break(opt_ident, ref opt_expr) => { - hir::ExprBreak(self.lower_opt_sp_ident(opt_ident), + hir::ExprBreak(self.lower_label(e.id, opt_ident), opt_expr.as_ref().map(|x| P(self.lower_expr(x)))) } - ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)), + ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_label(e.id, opt_ident)), ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))), ExprKind::InlineAsm(ref asm) => { let hir_asm = hir::InlineAsm { @@ -1275,7 +1435,7 @@ impl<'a> LoweringContext<'a> { hir::ExprInlineAsm(P(hir_asm), outputs, inputs) } ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { - hir::ExprStruct(P(self.lower_path(path)), + hir::ExprStruct(self.lower_qpath(e.id, &None, path, ParamMode::Optional), fields.iter().map(|x| self.lower_field(x)).collect(), maybe_expr.as_ref().map(|x| P(self.lower_expr(x)))) } @@ -1475,10 +1635,10 @@ impl<'a> LoweringContext<'a> { // `match ::std::iter::Iterator::next(&mut iter) { ... }` let match_expr = { - let next_path = self.std_path(e.span, &["iter", "Iterator", "next"]); let iter = P(self.expr_ident(e.span, iter, iter_pat.id)); let ref_mut_iter = self.expr_mut_addr_of(e.span, iter); - let next_path = self.expr_path(next_path, ThinVec::new()); + let next_path = &["iter", "Iterator", "next"]; + let next_path = P(self.expr_std_path(e.span, next_path, ThinVec::new())); let next_expr = P(self.expr_call(e.span, next_path, hir_vec![ref_mut_iter])); let arms = hir_vec![pat_arm, break_arm]; @@ -1505,10 +1665,9 @@ impl<'a> LoweringContext<'a> { // `match ::std::iter::IntoIterator::into_iter() { ... }` let into_iter_expr = { - let into_iter_path = self.std_path(e.span, - &["iter", "IntoIterator", "into_iter"]); - - let into_iter = self.expr_path(into_iter_path, ThinVec::new()); + let into_iter_path = &["iter", "IntoIterator", "into_iter"]; + let into_iter = P(self.expr_std_path(e.span, into_iter_path, + ThinVec::new())); P(self.expr_call(e.span, into_iter, hir_vec![head])) }; @@ -1534,32 +1693,20 @@ impl<'a> LoweringContext<'a> { ExprKind::Try(ref sub_expr) => { // to: // - // { - // match { Carrier::translate( { } ) } { - // Ok(val) => val, - // Err(err) => { return Carrier::from_error(From::from(err)); } - // } + // match Carrier::translate() { + // Ok(val) => val, + // Err(err) => return Carrier::from_error(From::from(err)) // } + let unstable_span = self.allow_internal_unstable("?", e.span); - // { Carrier::translate( { } ) } + // Carrier::translate() let discr = { // expand - let sub_expr = P(self.lower_expr(sub_expr)); - let sub_expr = self.signal_block_expr(hir_vec![], - sub_expr, - e.span, - hir::PopUnstableBlock, - ThinVec::new()); - - let path = self.std_path(e.span, &["ops", "Carrier", "translate"]); - let path = self.expr_path(path, ThinVec::new()); - let call = P(self.expr_call(e.span, path, hir_vec![sub_expr])); - - P(self.signal_block_expr(hir_vec![], - call, - e.span, - hir::PushUnstableBlock, - ThinVec::new())) + let sub_expr = self.lower_expr(sub_expr); + + let path = &["ops", "Carrier", "translate"]; + let path = P(self.expr_std_path(unstable_span, path, ThinVec::new())); + P(self.expr_call(e.span, path, hir_vec![sub_expr])) }; // Ok(val) => val @@ -1572,33 +1719,30 @@ impl<'a> LoweringContext<'a> { self.arm(hir_vec![ok_pat], val_expr) }; - // Err(err) => { return Carrier::from_error(From::from(err)); } + // Err(err) => return Carrier::from_error(From::from(err)) let err_arm = { let err_ident = self.str_to_ident("err"); let err_local = self.pat_ident(e.span, err_ident); let from_expr = { - let path = self.std_path(e.span, &["convert", "From", "from"]); - let from = self.expr_path(path, ThinVec::new()); + let path = &["convert", "From", "from"]; + let from = P(self.expr_std_path(e.span, path, ThinVec::new())); let err_expr = self.expr_ident(e.span, err_ident, err_local.id); self.expr_call(e.span, from, hir_vec![err_expr]) }; let from_err_expr = { - let path = self.std_path(e.span, &["ops", "Carrier", "from_error"]); - let from_err = self.expr_path(path, ThinVec::new()); + let path = &["ops", "Carrier", "from_error"]; + let from_err = P(self.expr_std_path(unstable_span, path, + ThinVec::new())); P(self.expr_call(e.span, from_err, hir_vec![from_expr])) }; let ret_expr = P(self.expr(e.span, hir::Expr_::ExprRet(Some(from_err_expr)), ThinVec::new())); - let ret_stmt = self.stmt_expr(ret_expr); - let block = P(self.signal_block_stmt(ret_stmt, e.span, - hir::PushUnstableBlock, - ThinVec::new())); let err_pat = self.pat_err(e.span, err_local); - self.arm(hir_vec![err_pat], block) + self.arm(hir_vec![err_pat], ret_expr) }; return self.expr_match(e.span, discr, hir_vec![err_arm, ok_arm], @@ -1612,8 +1756,8 @@ impl<'a> LoweringContext<'a> { } } - fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt { - match s.node { + fn lower_stmt(&mut self, s: &Stmt) -> SmallVector { + SmallVector::one(match s.node { StmtKind::Local(ref l) => Spanned { node: hir::StmtDecl(P(Spanned { node: hir::DeclLocal(self.lower_local(l)), @@ -1621,13 +1765,17 @@ impl<'a> LoweringContext<'a> { }), s.id), span: s.span, }, - StmtKind::Item(ref it) => Spanned { - node: hir::StmtDecl(P(Spanned { - node: hir::DeclItem(self.lower_item_id(it)), + StmtKind::Item(ref it) => { + // Can only use the ID once. + let mut id = Some(s.id); + return self.lower_item_id(it).into_iter().map(|item_id| Spanned { + node: hir::StmtDecl(P(Spanned { + node: hir::DeclItem(item_id), + span: s.span, + }), id.take().unwrap_or_else(|| self.next_id())), span: s.span, - }), s.id), - span: s.span, - }, + }).collect(); + } StmtKind::Expr(ref e) => { Spanned { node: hir::StmtExpr(P(self.lower_expr(e)), s.id), @@ -1641,7 +1789,7 @@ impl<'a> LoweringContext<'a> { } } StmtKind::Mac(..) => panic!("Shouldn't exist here"), - } + }) } fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause { @@ -1655,8 +1803,12 @@ impl<'a> LoweringContext<'a> { match *v { Visibility::Public => hir::Public, Visibility::Crate(_) => hir::Visibility::Crate, - Visibility::Restricted { ref path, id } => - hir::Visibility::Restricted { path: P(self.lower_path(path)), id: id }, + Visibility::Restricted { ref path, id } => { + hir::Visibility::Restricted { + path: P(self.lower_path(id, path, ParamMode::Explicit)), + id: id + } + } Visibility::Inherited => hir::Inherited, } } @@ -1739,13 +1891,18 @@ impl<'a> LoweringContext<'a> { } fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr { - let expr_path = hir::ExprPath(None, self.path_ident(span, id)); - let expr = self.expr(span, expr_path, ThinVec::new()); - let def = { let defs = self.resolver.definitions(); Def::Local(defs.local_def_id(binding)) }; + + let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path { + span: span, + global: false, + def: def, + segments: hir_vec![hir::PathSegment::from_name(id)], + }))); + let expr = self.expr(span, expr_path, ThinVec::new()); self.resolver.record_resolution(expr.id, def); expr @@ -1755,9 +1912,14 @@ impl<'a> LoweringContext<'a> { self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new()) } - fn expr_path(&mut self, path: hir::Path, attrs: ThinVec) -> P { - let def = self.resolver.resolve_generated_global_path(&path, true); - let expr = P(self.expr(path.span, hir::ExprPath(None, path), attrs)); + fn expr_std_path(&mut self, + span: Span, + components: &[&str], + attrs: ThinVec) + -> hir::Expr { + let path = self.std_path(span, components, true); + let def = path.def; + let expr = self.expr(span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs); self.resolver.record_resolution(expr.id, def); expr } @@ -1779,14 +1941,16 @@ impl<'a> LoweringContext<'a> { P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new())) } - fn expr_struct(&mut self, - sp: Span, - path: hir::Path, - fields: hir::HirVec, - e: Option>, - attrs: ThinVec) -> P { - let def = self.resolver.resolve_generated_global_path(&path, false); - let expr = P(self.expr(sp, hir::ExprStruct(P(path), fields, e), attrs)); + fn expr_std_struct(&mut self, + span: Span, + components: &[&str], + fields: hir::HirVec, + e: Option>, + attrs: ThinVec) -> hir::Expr { + let path = self.std_path(span, components, false); + let def = path.def; + let qpath = hir::QPath::Resolved(None, P(path)); + let expr = self.expr(span, hir::ExprStruct(qpath, fields, e), attrs); self.resolver.record_resolution(expr.id, def); expr } @@ -1820,15 +1984,6 @@ impl<'a> LoweringContext<'a> { (respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id) } - // Turns `` into `;`, note that this produces a StmtSemi, not a - // StmtExpr. - fn stmt_expr(&self, expr: P) -> hir::Stmt { - hir::Stmt { - span: expr.span, - node: hir::StmtSemi(expr, self.next_id()), - } - } - fn block_expr(&mut self, expr: P) -> hir::Block { self.block_all(expr.span, hir::HirVec::new(), Some(expr)) } @@ -1845,32 +2000,33 @@ impl<'a> LoweringContext<'a> { } fn pat_ok(&mut self, span: Span, pat: P) -> P { - let path = self.std_path(span, &["result", "Result", "Ok"]); - self.pat_enum(span, path, hir_vec![pat]) + self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat]) } fn pat_err(&mut self, span: Span, pat: P) -> P { - let path = self.std_path(span, &["result", "Result", "Err"]); - self.pat_enum(span, path, hir_vec![pat]) + self.pat_std_enum(span, &["result", "Result", "Err"], hir_vec![pat]) } fn pat_some(&mut self, span: Span, pat: P) -> P { - let path = self.std_path(span, &["option", "Option", "Some"]); - self.pat_enum(span, path, hir_vec![pat]) + self.pat_std_enum(span, &["option", "Option", "Some"], hir_vec![pat]) } fn pat_none(&mut self, span: Span) -> P { - let path = self.std_path(span, &["option", "Option", "None"]); - self.pat_enum(span, path, hir_vec![]) + self.pat_std_enum(span, &["option", "Option", "None"], hir_vec![]) } - fn pat_enum(&mut self, span: Span, path: hir::Path, subpats: hir::HirVec>) - -> P { - let def = self.resolver.resolve_generated_global_path(&path, true); + fn pat_std_enum(&mut self, + span: Span, + components: &[&str], + subpats: hir::HirVec>) + -> P { + let path = self.std_path(span, components, true); + let def = path.def; + let qpath = hir::QPath::Resolved(None, P(path)); let pt = if subpats.is_empty() { - hir::PatKind::Path(None, path) + hir::PatKind::Path(qpath) } else { - hir::PatKind::TupleStruct(path, subpats, None) + hir::PatKind::TupleStruct(qpath, subpats, None) }; let pat = self.pat(span, pt); self.resolver.record_resolution(pat.id, def); @@ -1883,25 +2039,27 @@ impl<'a> LoweringContext<'a> { fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMode) -> P { - let pat_ident = hir::PatKind::Binding(bm, - Spanned { - span: span, - node: name, - }, - None); - - let pat = self.pat(span, pat_ident); - + let id = self.next_id(); let parent_def = self.parent_def; - let def = { + let def_id = { let defs = self.resolver.definitions(); let def_path_data = DefPathData::Binding(name.as_str()); - let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data); - Def::Local(DefId::local(def_index)) + let def_index = defs.create_def_with_parent(parent_def, id, def_path_data); + DefId::local(def_index) }; - self.resolver.record_resolution(pat.id, def); + self.resolver.record_resolution(id, Def::Local(def_id)); - pat + P(hir::Pat { + id: id, + node: hir::PatKind::Binding(bm, + def_id, + Spanned { + span: span, + node: name, + }, + None), + span: span, + }) } fn pat_wild(&mut self, span: Span) -> P { @@ -1916,63 +2074,25 @@ impl<'a> LoweringContext<'a> { }) } - fn path_ident(&mut self, span: Span, id: Name) -> hir::Path { - self.path(span, vec![id]) - } - - fn path(&mut self, span: Span, strs: Vec) -> hir::Path { - self.path_all(span, false, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new()) - } - - fn path_global(&mut self, span: Span, strs: Vec) -> hir::Path { - self.path_all(span, true, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new()) - } + /// Given suffix ["b","c","d"], returns path `::std::b::c::d` when + /// `fld.cx.use_std`, and `::core::b::c::d` otherwise. + /// The path is also resolved according to `is_value`. + fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path { + let idents = self.crate_root.iter().chain(components); - fn path_all(&mut self, - sp: Span, - global: bool, - mut names: Vec, - lifetimes: hir::HirVec, - types: hir::HirVec>, - bindings: hir::HirVec) - -> hir::Path { - let last_identifier = names.pop().unwrap(); - let mut segments: Vec = names.into_iter().map(|name| { - hir::PathSegment { - name: name, - parameters: hir::PathParameters::none(), - } + let segments: Vec<_> = idents.map(|name| { + hir::PathSegment::from_name(Symbol::intern(name)) }).collect(); - segments.push(hir::PathSegment { - name: last_identifier, - parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData { - lifetimes: lifetimes, - types: types, - bindings: bindings, - }), - }); - hir::Path { - span: sp, - global: global, + let mut path = hir::Path { + span: span, + global: true, + def: Def::Err, segments: segments.into(), - } - } - - fn std_path_components(&mut self, components: &[&str]) -> Vec { - let mut v = Vec::new(); - if let Some(s) = self.crate_root { - v.push(Symbol::intern(s)); - } - v.extend(components.iter().map(|s| Symbol::intern(s))); - return v; - } + }; - // Given suffix ["b","c","d"], returns path `::std::b::c::d` when - // `fld.cx.use_std`, and `::core::b::c::d` otherwise. - fn std_path(&mut self, span: Span, components: &[&str]) -> hir::Path { - let idents = self.std_path_components(components); - self.path_global(span, idents) + self.resolver.resolve_generated_global_path(&mut path, is_value); + path } fn signal_block_expr(&mut self, @@ -1993,20 +2113,11 @@ impl<'a> LoweringContext<'a> { self.expr_block(block, attrs) } - fn signal_block_stmt(&mut self, - stmt: hir::Stmt, - span: Span, - rule: hir::BlockCheckMode, - attrs: ThinVec) - -> hir::Expr { - let id = self.next_id(); - let block = P(hir::Block { - rules: rule, + fn ty(&mut self, span: Span, node: hir::Ty_) -> P { + P(hir::Ty { + id: self.next_id(), + node: node, span: span, - id: id, - stmts: hir_vec![stmt], - expr: None, - }); - self.expr_block(block, attrs) + }) } } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 89217e83ca22e..26fd2b736a42c 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -124,23 +124,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { this.insert(struct_def.id(), NodeStructCtor(struct_def)); } } - ItemTrait(.., ref bounds, _) => { - for b in bounds.iter() { - if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b { - this.insert(t.trait_ref.ref_id, NodeItem(i)); - } - } - } - ItemUse(ref view_path) => { - match view_path.node { - ViewPathList(_, ref paths) => { - for path in paths { - this.insert(path.node.id, NodeItem(i)); - } - } - _ => () - } - } _ => {} } intravisit::walk_item(this, i); @@ -217,6 +200,14 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { }); } + fn visit_trait_ref(&mut self, tr: &'ast TraitRef) { + self.insert(tr.ref_id, NodeTraitRef(tr)); + + self.with_parent(tr.ref_id, |this| { + intravisit::walk_trait_ref(this, tr); + }); + } + fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl, b: &'ast Expr, s: Span, id: NodeId) { assert_eq!(self.parent_node, id); @@ -234,7 +225,28 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { self.insert(lifetime.id, NodeLifetime(lifetime)); } + fn visit_vis(&mut self, visibility: &'ast Visibility) { + match *visibility { + Visibility::Public | + Visibility::Crate | + Visibility::Inherited => {} + Visibility::Restricted { id, .. } => { + self.insert(id, NodeVisibility(visibility)); + self.with_parent(id, |this| { + intravisit::walk_vis(this, visibility); + }); + } + } + } + fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) { self.insert_entry(macro_def.id, NotPresent); } + + fn visit_struct_field(&mut self, field: &'ast StructField) { + self.insert(field.id, NodeField(field)); + self.with_parent(field.id, |this| { + intravisit::walk_struct_field(this, field); + }); + } } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 7486d954c4802..a08060e792778 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -155,7 +155,20 @@ impl<'a> visit::Visitor for DefCollector<'a> { DefPathData::ValueNs(i.ident.name.as_str()), ItemKind::Mac(..) if i.id == DUMMY_NODE_ID => return, // Scope placeholder ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false), - ItemKind::Use(..) => DefPathData::Misc, + ItemKind::Use(ref view_path) => { + match view_path.node { + ViewPathGlob(..) => {} + + // FIXME(eddyb) Should use the real name. Which namespace? + ViewPathSimple(..) => {} + ViewPathList(_, ref imports) => { + for import in imports { + self.create_def(import.node.id, DefPathData::Misc); + } + } + } + DefPathData::Misc + } }; let def = self.create_def(i.id, def_data); @@ -423,7 +436,7 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> { fn visit_pat(&mut self, pat: &'ast hir::Pat) { let parent_def = self.parent_def; - if let hir::PatKind::Binding(_, name, _) = pat.node { + if let hir::PatKind::Binding(_, _, name, _) = pat.node { let def = self.create_def(pat.id, DefPathData::Binding(name.node.as_str())); self.parent_def = Some(def); } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index a90577b34261c..b9763e6ea0dcb 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -46,9 +46,11 @@ pub enum Node<'ast> { NodeTraitItem(&'ast TraitItem), NodeImplItem(&'ast ImplItem), NodeVariant(&'ast Variant), + NodeField(&'ast StructField), NodeExpr(&'ast Expr), NodeStmt(&'ast Stmt), NodeTy(&'ast Ty), + NodeTraitRef(&'ast TraitRef), NodeLocal(&'ast Pat), NodePat(&'ast Pat), NodeBlock(&'ast Block), @@ -57,7 +59,8 @@ pub enum Node<'ast> { NodeStructCtor(&'ast VariantData), NodeLifetime(&'ast Lifetime), - NodeTyParam(&'ast TyParam) + NodeTyParam(&'ast TyParam), + NodeVisibility(&'ast Visibility), } /// Represents an entry and its parent NodeID. @@ -73,15 +76,18 @@ pub enum MapEntry<'ast> { EntryTraitItem(NodeId, &'ast TraitItem), EntryImplItem(NodeId, &'ast ImplItem), EntryVariant(NodeId, &'ast Variant), + EntryField(NodeId, &'ast StructField), EntryExpr(NodeId, &'ast Expr), EntryStmt(NodeId, &'ast Stmt), EntryTy(NodeId, &'ast Ty), + EntryTraitRef(NodeId, &'ast TraitRef), EntryLocal(NodeId, &'ast Pat), EntryPat(NodeId, &'ast Pat), EntryBlock(NodeId, &'ast Block), EntryStructCtor(NodeId, &'ast VariantData), EntryLifetime(NodeId, &'ast Lifetime), EntryTyParam(NodeId, &'ast TyParam), + EntryVisibility(NodeId, &'ast Visibility), /// Roots for node trees. RootCrate, @@ -102,15 +108,18 @@ impl<'ast> MapEntry<'ast> { NodeTraitItem(n) => EntryTraitItem(p, n), NodeImplItem(n) => EntryImplItem(p, n), NodeVariant(n) => EntryVariant(p, n), + NodeField(n) => EntryField(p, n), NodeExpr(n) => EntryExpr(p, n), NodeStmt(n) => EntryStmt(p, n), NodeTy(n) => EntryTy(p, n), + NodeTraitRef(n) => EntryTraitRef(p, n), NodeLocal(n) => EntryLocal(p, n), NodePat(n) => EntryPat(p, n), NodeBlock(n) => EntryBlock(p, n), NodeStructCtor(n) => EntryStructCtor(p, n), NodeLifetime(n) => EntryLifetime(p, n), NodeTyParam(n) => EntryTyParam(p, n), + NodeVisibility(n) => EntryVisibility(p, n), } } @@ -121,15 +130,18 @@ impl<'ast> MapEntry<'ast> { EntryTraitItem(id, _) => id, EntryImplItem(id, _) => id, EntryVariant(id, _) => id, + EntryField(id, _) => id, EntryExpr(id, _) => id, EntryStmt(id, _) => id, EntryTy(id, _) => id, + EntryTraitRef(id, _) => id, EntryLocal(id, _) => id, EntryPat(id, _) => id, EntryBlock(id, _) => id, EntryStructCtor(id, _) => id, EntryLifetime(id, _) => id, EntryTyParam(id, _) => id, + EntryVisibility(id, _) => id, NotPresent | RootCrate | @@ -144,15 +156,18 @@ impl<'ast> MapEntry<'ast> { EntryTraitItem(_, n) => NodeTraitItem(n), EntryImplItem(_, n) => NodeImplItem(n), EntryVariant(_, n) => NodeVariant(n), + EntryField(_, n) => NodeField(n), EntryExpr(_, n) => NodeExpr(n), EntryStmt(_, n) => NodeStmt(n), EntryTy(_, n) => NodeTy(n), + EntryTraitRef(_, n) => NodeTraitRef(n), EntryLocal(_, n) => NodeLocal(n), EntryPat(_, n) => NodePat(n), EntryBlock(_, n) => NodeBlock(n), EntryStructCtor(_, n) => NodeStructCtor(n), EntryLifetime(_, n) => NodeLifetime(n), EntryTyParam(_, n) => NodeTyParam(n), + EntryVisibility(_, n) => NodeVisibility(n), _ => return None }) } @@ -240,16 +255,8 @@ impl<'ast> Map<'ast> { loop { match map[id.as_usize()] { EntryItem(_, item) => { - let def_id = self.local_def_id(item.id); - // NB ^~~~~~~ - // - // You would expect that `item.id == id`, but this - // is not always the case. In particular, for a - // ViewPath item like `use self::{mem, foo}`, we - // map the ids for `mem` and `foo` to the - // enclosing view path item. This seems mega super - // ultra wrong, but then who am I to judge? - // -nmatsakis + assert_eq!(id, item.id); + let def_id = self.local_def_id(id); assert!(!self.is_inlined_def_id(def_id)); return DepNode::Hir(def_id); } @@ -263,15 +270,18 @@ impl<'ast> Map<'ast> { EntryForeignItem(p, _) | EntryTraitItem(p, _) | EntryVariant(p, _) | + EntryField(p, _) | EntryExpr(p, _) | EntryStmt(p, _) | EntryTy(p, _) | + EntryTraitRef(p, _) | EntryLocal(p, _) | EntryPat(p, _) | EntryBlock(p, _) | EntryStructCtor(p, _) | EntryLifetime(p, _) | - EntryTyParam(p, _) => + EntryTyParam(p, _) | + EntryVisibility(p, _) => id = p, RootCrate => @@ -304,15 +314,18 @@ impl<'ast> Map<'ast> { EntryTraitItem(p, _) | EntryImplItem(p, _) | EntryVariant(p, _) | + EntryField(p, _) | EntryExpr(p, _) | EntryStmt(p, _) | EntryTy(p, _) | + EntryTraitRef(p, _) | EntryLocal(p, _) | EntryPat(p, _) | EntryBlock(p, _) | EntryStructCtor(p, _) | EntryLifetime(p, _) | - EntryTyParam(p, _) => + EntryTyParam(p, _) | + EntryVisibility(p, _) => id = p, RootInlinedParent(parent) => match *parent { @@ -650,9 +663,10 @@ impl<'ast> Map<'ast> { NodeImplItem(ii) => ii.name, NodeTraitItem(ti) => ti.name, NodeVariant(v) => v.node.name, + NodeField(f) => f.name, NodeLifetime(lt) => lt.name, NodeTyParam(tp) => tp.name, - NodeLocal(&Pat { node: PatKind::Binding(_,l,_), .. }) => l.node, + NodeLocal(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node, NodeStructCtor(_) => self.name(self.get_parent(id)), _ => bug!("no name for {}", self.node_to_string(id)) } @@ -668,6 +682,7 @@ impl<'ast> Map<'ast> { Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]), Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]), Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]), + Some(NodeField(ref f)) => Some(&f.attrs[..]), Some(NodeExpr(ref e)) => Some(&*e.attrs), Some(NodeStmt(ref s)) => Some(s.node.attrs()), // unit/tuple structs take the attributes straight from @@ -704,14 +719,17 @@ impl<'ast> Map<'ast> { Some(NodeTraitItem(trait_method)) => trait_method.span, Some(NodeImplItem(ref impl_item)) => impl_item.span, Some(NodeVariant(variant)) => variant.span, + Some(NodeField(field)) => field.span, Some(NodeExpr(expr)) => expr.span, Some(NodeStmt(stmt)) => stmt.span, Some(NodeTy(ty)) => ty.span, + Some(NodeTraitRef(tr)) => tr.path.span, Some(NodeLocal(pat)) => pat.span, Some(NodePat(pat)) => pat.span, Some(NodeBlock(block)) => block.span, Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span, Some(NodeTyParam(ty_param)) => ty_param.span, + Some(NodeVisibility(&Visibility::Restricted { ref path, .. })) => path.span, _ => return None, }; Some(sp) @@ -823,6 +841,7 @@ impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> { Some(EntryTraitItem(_, n)) => n.name(), Some(EntryImplItem(_, n)) => n.name(), Some(EntryVariant(_, n)) => n.name(), + Some(EntryField(_, n)) => n.name(), _ => continue, }; if self.matches_names(self.map.get_parent(idx), name) { @@ -841,6 +860,7 @@ impl Named for Spanned { fn name(&self) -> Name { self.node.name() } impl Named for Item { fn name(&self) -> Name { self.name } } impl Named for ForeignItem { fn name(&self) -> Name { self.name } } impl Named for Variant_ { fn name(&self) -> Name { self.name } } +impl Named for StructField { fn name(&self) -> Name { self.name } } impl Named for TraitItem { fn name(&self) -> Name { self.name } } impl Named for ImplItem { fn name(&self) -> Name { self.name } } @@ -926,10 +946,13 @@ impl<'a> NodePrinter for pprust::State<'a> { NodeExpr(a) => self.print_expr(&a), NodeStmt(a) => self.print_stmt(&a), NodeTy(a) => self.print_type(&a), + NodeTraitRef(a) => self.print_trait_ref(&a), NodePat(a) => self.print_pat(&a), NodeBlock(a) => self.print_block(&a), NodeLifetime(a) => self.print_lifetime(&a), + NodeVisibility(a) => self.print_visibility(&a), NodeTyParam(_) => bug!("cannot print TyParam"), + NodeField(_) => bug!("cannot print StructField"), // these cases do not carry enough information in the // ast_map to reconstruct their full structure for pretty // printing. @@ -1009,6 +1032,11 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { variant.node.name, path_str(), id_str) } + Some(NodeField(ref field)) => { + format!("field {} in {}{}", + field.name, + path_str(), id_str) + } Some(NodeExpr(ref expr)) => { format!("expr {}{}", pprust::expr_to_string(&expr), id_str) } @@ -1018,6 +1046,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeTy(ref ty)) => { format!("type {}{}", pprust::ty_to_string(&ty), id_str) } + Some(NodeTraitRef(ref tr)) => { + format!("trait_ref {}{}", pprust::path_to_string(&tr.path), id_str) + } Some(NodeLocal(ref pat)) => { format!("local {}{}", pprust::pat_to_string(&pat), id_str) } @@ -1037,6 +1068,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeTyParam(ref ty_param)) => { format!("typaram {:?}{}", ty_param, id_str) } + Some(NodeVisibility(ref vis)) => { + format!("visibility {:?}{}", vis, id_str) + } None => { format!("unknown node{}", id_str) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3164876522425..d494299a3c388 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -27,7 +27,6 @@ pub use self::Ty_::*; pub use self::TyParamBound::*; pub use self::UnOp::*; pub use self::UnsafeSource::*; -pub use self::ViewPath_::*; pub use self::Visibility::{Public, Inherited}; pub use self::PathParameters::*; @@ -108,6 +107,8 @@ pub struct Path { /// A `::foo` path, is relative to the crate root rather than current /// module (like paths in an import). pub global: bool, + /// The definition that the path resolved to. + pub def: Def, /// The segments in the path: the things separated by `::`. pub segments: HirVec, } @@ -124,21 +125,6 @@ impl fmt::Display for Path { } } -impl Path { - /// Convert a span and an identifier to the corresponding - /// 1-segment path. - pub fn from_name(s: Span, name: Name) -> Path { - Path { - span: s, - global: false, - segments: hir_vec![PathSegment { - name: name, - parameters: PathParameters::none() - }], - } - } -} - /// A segment of a path: an identifier, an optional lifetime, and a set of /// types. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] @@ -154,6 +140,16 @@ pub struct PathSegment { pub parameters: PathParameters, } +impl PathSegment { + /// Convert an identifier to the corresponding segment. + pub fn from_name(name: Name) -> PathSegment { + PathSegment { + name: name, + parameters: PathParameters::none() + } + } +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum PathParameters { /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>` @@ -167,6 +163,7 @@ impl PathParameters { AngleBracketedParameters(AngleBracketedParameterData { lifetimes: HirVec::new(), types: HirVec::new(), + infer_types: true, bindings: HirVec::new(), }) } @@ -241,6 +238,11 @@ pub struct AngleBracketedParameterData { pub lifetimes: HirVec, /// The type parameters for this path segment, if present. pub types: HirVec>, + /// Whether to infer remaining type parameters, if any. + /// This only applies to expression and pattern paths, and + /// out of those only the segments with no type parameters + /// to begin with, e.g. `Vec::new` is `>::new::<..>`. + pub infer_types: bool, /// Bindings (equality constraints) on associated types, if present. /// E.g., `Foo`. pub bindings: HirVec, @@ -527,7 +529,7 @@ impl Pat { PatKind::Lit(_) | PatKind::Range(..) | PatKind::Binding(..) | - PatKind::Path(..) => { + PatKind::Path(_) => { true } } @@ -566,20 +568,20 @@ pub enum PatKind { Wild, /// A fresh binding `ref mut binding @ OPT_SUBPATTERN`. - Binding(BindingMode, Spanned, Option>), + /// The `DefId` is for the definition of the variable being bound. + Binding(BindingMode, DefId, Spanned, Option>), /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. /// The `bool` is `true` in the presence of a `..`. - Struct(Path, HirVec>, bool), + Struct(QPath, HirVec>, bool), /// A tuple struct/variant pattern `Variant(x, y, .., z)`. /// If the `..` pattern fragment is present, then `Option` denotes its position. /// 0 <= position <= subpats.len() - TupleStruct(Path, HirVec>, Option), + TupleStruct(QPath, HirVec>, Option), - /// A possibly qualified path pattern. - /// Such pattern can be resolved to a unit struct/variant or a constant. - Path(Option, Path), + /// A path pattern for an unit struct/variant or a (maybe-associated) constant. + Path(QPath), /// A tuple pattern `(a, b)`. /// If the `..` pattern fragment is present, then `Option` denotes its position. @@ -836,9 +838,6 @@ pub enum BlockCheckMode { UnsafeBlock(UnsafeSource), PushUnsafeBlock(UnsafeSource), PopUnsafeBlock(UnsafeSource), - // Within this block (but outside a PopUnstableBlock), we suspend checking of stability. - PushUnstableBlock, - PopUnstableBlock, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -934,19 +933,15 @@ pub enum Expr_ { /// An indexing operation (`foo[2]`) ExprIndex(P, P), - /// Variable reference, possibly containing `::` and/or type - /// parameters, e.g. foo::bar::. - /// - /// Optionally "qualified", - /// e.g. ` as SomeTrait>::SomeType`. - ExprPath(Option, Path), + /// Path to a definition, possibly containing lifetime or type parameters. + ExprPath(QPath), /// A referencing operation (`&a` or `&mut a`) ExprAddrOf(Mutability, P), /// A `break`, with an optional label to break - ExprBreak(Option>, Option>), + ExprBreak(Option