Skip to content

Commit

Permalink
Rollup merge of rust-lang#66072 - Mark-Simulacrum:next-node-id, r=nik…
Browse files Browse the repository at this point in the history
…omatsakis

Move next node ID to Resolver

This moves the `next_node_id` method(s) and related tracking information to the resolver. By doing so, we also remove the OneThread and Cell on next_node_id in Session in this move, which means that the new code is simpler and less "interesting" as it doesn't tie itself to a single thread.

This required moving some of the pretty-printing logic around, but this was just copying the code without any semantic changes, so it's just a second commit instead of a separate PR; I can polish it up a bit more if desired.
  • Loading branch information
Centril authored Nov 8, 2019
2 parents ab99502 + 85f08b5 commit ae0373e
Show file tree
Hide file tree
Showing 14 changed files with 354 additions and 343 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3506,6 +3506,7 @@ dependencies = [
"rustc_mir",
"rustc_plugin",
"rustc_plugin_impl",
"rustc_resolve",
"rustc_save_analysis",
"rustc_target",
"serialize",
Expand Down
18 changes: 11 additions & 7 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ pub trait Resolver {
) -> (ast::Path, Res<NodeId>);

fn lint_buffer(&mut self) -> &mut lint::LintBuffer;

fn next_node_id(&mut self) -> NodeId;
}

type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream;
Expand Down Expand Up @@ -672,7 +674,8 @@ impl<'a> LoweringContext<'a> {
}

fn next_id(&mut self) -> hir::HirId {
self.lower_node_id(self.sess.next_node_id())
let node_id = self.resolver.next_node_id();
self.lower_node_id(node_id)
}

fn lower_res(&mut self, res: Res<NodeId>) -> Res {
Expand Down Expand Up @@ -781,7 +784,7 @@ impl<'a> LoweringContext<'a> {
hir_name: ParamName,
parent_index: DefIndex,
) -> hir::GenericParam {
let node_id = self.sess.next_node_id();
let node_id = self.resolver.next_node_id();

// Get the name we'll use to make the def-path. Note
// that collisions are ok here and this shouldn't
Expand Down Expand Up @@ -1106,7 +1109,7 @@ impl<'a> LoweringContext<'a> {
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
// constructing the HIR for `impl bounds...` and then lowering that.

let impl_trait_node_id = self.sess.next_node_id();
let impl_trait_node_id = self.resolver.next_node_id();
let parent_def_index = self.current_hir_id_owner.last().unwrap().0;
self.resolver.definitions().create_def_with_parent(
parent_def_index,
Expand All @@ -1117,9 +1120,10 @@ impl<'a> LoweringContext<'a> {
);

self.with_dyn_type_scope(false, |this| {
let node_id = this.resolver.next_node_id();
let ty = this.lower_ty(
&Ty {
id: this.sess.next_node_id(),
id: node_id,
kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
span: constraint.span,
},
Expand Down Expand Up @@ -1586,7 +1590,7 @@ impl<'a> LoweringContext<'a> {
name,
}));

let def_node_id = self.context.sess.next_node_id();
let def_node_id = self.context.resolver.next_node_id();
let hir_id =
self.context.lower_node_id_with_owner(def_node_id, self.opaque_ty_id);
self.context.resolver.definitions().create_def_with_parent(
Expand Down Expand Up @@ -3244,7 +3248,7 @@ impl<'a> LoweringContext<'a> {
Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"),

None => (
self.sess.next_node_id(),
self.resolver.next_node_id(),
"`&` without an explicit lifetime name cannot be used here",
"explicit lifetime name needed here",
),
Expand Down Expand Up @@ -3281,7 +3285,7 @@ impl<'a> LoweringContext<'a> {
span,
"expected 'implicit elided lifetime not allowed' error",
);
let id = self.sess.next_node_id();
let id = self.resolver.next_node_id();
self.new_named_lifetime(id, span, hir::LifetimeName::Error)
}
// `PassThrough` is the normal case.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/lowering/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ impl LoweringContext<'_> {
};

// `::std::task::Poll::Ready(result) => break result`
let loop_node_id = self.sess.next_node_id();
let loop_node_id = self.resolver.next_node_id();
let loop_hir_id = self.lower_node_id(loop_node_id);
let ready_arm = {
let x_ident = Ident::with_dummy_span(sym::result);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/hir/lowering/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ impl LoweringContext<'_> {
let ident = *ident;
let mut path = path.clone();
for seg in &mut path.segments {
seg.id = self.sess.next_node_id();
seg.id = self.resolver.next_node_id();
}
let span = path.span;

Expand Down Expand Up @@ -599,7 +599,7 @@ impl LoweringContext<'_> {

// Give the segments new node-ids since they are being cloned.
for seg in &mut prefix.segments {
seg.id = self.sess.next_node_id();
seg.id = self.resolver.next_node_id();
}

// Each `use` import is an item and thus are owners of the
Expand Down
220 changes: 220 additions & 0 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
//! Contains infrastructure for configuring the compiler, including parsing
//! command-line options.

// ignore-tidy-filelength

use crate::lint;
use crate::middle::cstore;
use crate::session::{early_error, early_warn, Session};
use crate::session::search_paths::SearchPath;
use crate::hir::map as hir_map;

use rustc_data_structures::fx::FxHashSet;

Expand Down Expand Up @@ -440,6 +443,8 @@ top_level_options!(
// `true` if we're emitting JSON blobs about each artifact produced
// by the compiler.
json_artifact_notifications: bool [TRACKED],

pretty: Option<(PpMode, Option<UserIdentifiedItem>)> [UNTRACKED],
}
);

Expand Down Expand Up @@ -621,6 +626,7 @@ impl Default for Options {
remap_path_prefix: Vec::new(),
edition: DEFAULT_EDITION,
json_artifact_notifications: false,
pretty: None,
}
}
}
Expand Down Expand Up @@ -2516,6 +2522,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {

let remap_path_prefix = parse_remap_path_prefix(matches, error_format);

let pretty = parse_pretty(matches, &debugging_opts, error_format);

Options {
crate_types,
optimize: opt_level,
Expand Down Expand Up @@ -2546,6 +2554,73 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
remap_path_prefix,
edition,
json_artifact_notifications,
pretty,
}
}

fn parse_pretty(
matches: &getopts::Matches,
debugging_opts: &DebuggingOptions,
efmt: ErrorOutputType,
) -> Option<(PpMode, Option<UserIdentifiedItem>)> {
let pretty = if debugging_opts.unstable_options {
matches.opt_default("pretty", "normal").map(|a| {
// stable pretty-print variants only
parse_pretty_inner(efmt, &a, false)
})
} else {
None
};

return if pretty.is_none() {
debugging_opts.unpretty.as_ref().map(|a| {
// extended with unstable pretty-print variants
parse_pretty_inner(efmt, &a, true)
})
} else {
pretty
};

fn parse_pretty_inner(
efmt: ErrorOutputType,
name: &str,
extended: bool,
) -> (PpMode, Option<UserIdentifiedItem>) {
use PpMode::*;
use PpSourceMode::*;
let mut split = name.splitn(2, '=');
let first = split.next().unwrap();
let opt_second = split.next();
let first = match (first, extended) {
("normal", _) => PpmSource(PpmNormal),
("identified", _) => PpmSource(PpmIdentified),
("everybody_loops", true) => PpmSource(PpmEveryBodyLoops),
("expanded", _) => PpmSource(PpmExpanded),
("expanded,identified", _) => PpmSource(PpmExpandedIdentified),
("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene),
("hir", true) => PpmHir(PpmNormal),
("hir,identified", true) => PpmHir(PpmIdentified),
("hir,typed", true) => PpmHir(PpmTyped),
("hir-tree", true) => PpmHirTree(PpmNormal),
("mir", true) => PpmMir,
("mir-cfg", true) => PpmMirCFG,
_ => {
if extended {
early_error(efmt, &format!("argument to `unpretty` must be one of `normal`, \
`expanded`, `identified`, `expanded,identified`, \
`expanded,hygiene`, `everybody_loops`, \
`hir`, `hir,identified`, `hir,typed`, `hir-tree`, \
`mir` or `mir-cfg`; got {}",
name));
} else {
early_error(efmt, &format!("argument to `pretty` must be one of `normal`, \
`expanded`, `identified`, or `expanded,identified`; got {}",
name));
}
}
};
let opt_second = opt_second.and_then(|s| s.parse::<UserIdentifiedItem>().ok());
(first, opt_second)
}
}

Expand Down Expand Up @@ -2656,6 +2731,151 @@ impl fmt::Display for CrateType {
}
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PpSourceMode {
PpmNormal,
PpmEveryBodyLoops,
PpmExpanded,
PpmIdentified,
PpmExpandedIdentified,
PpmExpandedHygiene,
PpmTyped,
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PpMode {
PpmSource(PpSourceMode),
PpmHir(PpSourceMode),
PpmHirTree(PpSourceMode),
PpmMir,
PpmMirCFG,
}

impl PpMode {
pub fn needs_ast_map(&self, opt_uii: &Option<UserIdentifiedItem>) -> bool {
use PpMode::*;
use PpSourceMode::*;
match *self {
PpmSource(PpmNormal) |
PpmSource(PpmEveryBodyLoops) |
PpmSource(PpmIdentified) => opt_uii.is_some(),

PpmSource(PpmExpanded) |
PpmSource(PpmExpandedIdentified) |
PpmSource(PpmExpandedHygiene) |
PpmHir(_) |
PpmHirTree(_) |
PpmMir |
PpmMirCFG => true,
PpmSource(PpmTyped) => panic!("invalid state"),
}
}

pub fn needs_analysis(&self) -> bool {
use PpMode::*;
match *self {
PpmMir | PpmMirCFG => true,
_ => false,
}
}
}

#[derive(Clone, Debug)]
pub enum UserIdentifiedItem {
ItemViaNode(ast::NodeId),
ItemViaPath(Vec<String>),
}

impl FromStr for UserIdentifiedItem {
type Err = ();
fn from_str(s: &str) -> Result<UserIdentifiedItem, ()> {
use UserIdentifiedItem::*;
Ok(s.parse()
.map(ast::NodeId::from_u32)
.map(ItemViaNode)
.unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect())))
}
}

pub enum NodesMatchingUII<'a> {
NodesMatchingDirect(std::option::IntoIter<ast::NodeId>),
NodesMatchingSuffix(Box<dyn Iterator<Item = ast::NodeId> + 'a>),
}

impl<'a> Iterator for NodesMatchingUII<'a> {
type Item = ast::NodeId;

fn next(&mut self) -> Option<ast::NodeId> {
use NodesMatchingUII::*;
match self {
&mut NodesMatchingDirect(ref mut iter) => iter.next(),
&mut NodesMatchingSuffix(ref mut iter) => iter.next(),
}
}

fn size_hint(&self) -> (usize, Option<usize>) {
use NodesMatchingUII::*;
match self {
&NodesMatchingDirect(ref iter) => iter.size_hint(),
&NodesMatchingSuffix(ref iter) => iter.size_hint(),
}
}
}

impl UserIdentifiedItem {
pub fn reconstructed_input(&self) -> String {
use UserIdentifiedItem::*;
match *self {
ItemViaNode(node_id) => node_id.to_string(),
ItemViaPath(ref parts) => parts.join("::"),
}
}

pub fn all_matching_node_ids<'a, 'hir>(&'a self,
map: &'a hir_map::Map<'hir>)
-> NodesMatchingUII<'a> {
use UserIdentifiedItem::*;
use NodesMatchingUII::*;
match *self {
ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()),
ItemViaPath(ref parts) => {
NodesMatchingSuffix(Box::new(map.nodes_matching_suffix(&parts)))
}
}
}

pub fn to_one_node_id(self,
user_option: &str,
sess: &Session,
map: &hir_map::Map<'_>)
-> ast::NodeId {
let fail_because = |is_wrong_because| -> ast::NodeId {
let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \
{}, which {}",
user_option,
self.reconstructed_input(),
is_wrong_because);
sess.fatal(&message)
};

let mut saw_node = ast::DUMMY_NODE_ID;
let mut seen = 0;
for node in self.all_matching_node_ids(map) {
saw_node = node;
seen += 1;
if seen > 1 {
fail_because("does not resolve uniquely");
}
}
if seen == 0 {
fail_because("does not resolve to any item");
}

assert!(seen == 1);
return saw_node;
}
}

/// Command-line arguments passed to the compiler have to be incorporated with
/// the dependency tracking system for incremental compilation. This module
/// provides some utilities to make this more convenient.
Expand Down
Loading

0 comments on commit ae0373e

Please sign in to comment.