Skip to content

Rollup of 7 pull requests #36255

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Sep 4, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
@@ -144,6 +144,7 @@ struct Rust {
rpath: Option<bool>,
optimize_tests: Option<bool>,
debuginfo_tests: Option<bool>,
codegen_tests: Option<bool>,
}

/// TOML representation of how each build target is configured.
@@ -232,6 +233,7 @@ impl Config {
set(&mut config.rust_optimize, rust.optimize);
set(&mut config.rust_optimize_tests, rust.optimize_tests);
set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests);
set(&mut config.codegen_tests, rust.codegen_tests);
set(&mut config.rust_rpath, rust.rpath);
set(&mut config.debug_jemalloc, rust.debug_jemalloc);
set(&mut config.use_jemalloc, rust.use_jemalloc);
7 changes: 7 additions & 0 deletions src/bootstrap/config.toml.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Sample TOML configuration file for building Rust.
#
# To configure rustbuild, copy this file to the directory from which you will be
# running the build, and name it config.toml.
#
# All options are commented out by default in this file, and they're commented
# out with their default values. The build system by default looks for
# `config.toml` in the current directory of a build for build configuration, but
@@ -130,6 +133,10 @@
#optimize-tests = true
#debuginfo-tests = true

# Flag indicating whether codegen tests will be run or not. If you get an error
# saying that the FileCheck executable is missing, you may want to disable this.
#codegen-tests = true

# =============================================================================
# Options for specific targets
#
2 changes: 1 addition & 1 deletion src/doc/book/nightly-rust.md
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ binary downloads][install-page].

Oh, we should also mention the officially supported platforms:

* Windows (7, 8, Server 2008 R2)
* Windows (7+)
* Linux (2.6.18 or later, various distributions), x86 and x86-64
* OSX 10.7 (Lion) or greater, x86 and x86-64

10 changes: 8 additions & 2 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
@@ -849,9 +849,13 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
ls: bool = (false, parse_bool, [UNTRACKED],
"list the symbols defined by a library crate"),
save_analysis: bool = (false, parse_bool, [UNTRACKED],
"write syntax and type analysis (in JSON format) information in addition to normal output"),
"write syntax and type analysis (in JSON format) information, in \
addition to normal output"),
save_analysis_csv: bool = (false, parse_bool, [UNTRACKED],
"write syntax and type analysis (in CSV format) information in addition to normal output"),
"write syntax and type analysis (in CSV format) information, in addition to normal output"),
save_analysis_api: bool = (false, parse_bool, [UNTRACKED],
"write syntax and type analysis information for opaque libraries (in JSON format), \
in addition to normal output"),
print_move_fragments: bool = (false, parse_bool, [UNTRACKED],
"print out move-fragment data for every fn"),
flowgraph_print_loans: bool = (false, parse_bool, [UNTRACKED],
@@ -2365,6 +2369,8 @@ mod tests {
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.save_analysis_csv = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.save_analysis_api = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_move_fragments = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.flowgraph_print_loans = true;
3 changes: 2 additions & 1 deletion src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
@@ -250,7 +250,8 @@ fn keep_hygiene_data(sess: &Session) -> bool {
fn keep_ast(sess: &Session) -> bool {
sess.opts.debugging_opts.keep_ast ||
sess.opts.debugging_opts.save_analysis ||
sess.opts.debugging_opts.save_analysis_csv
sess.opts.debugging_opts.save_analysis_csv ||
sess.opts.debugging_opts.save_analysis_api
}

/// The name used for source code that doesn't originate in a file
5 changes: 4 additions & 1 deletion src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
@@ -555,14 +555,17 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {

fn save_analysis(sess: &Session) -> bool {
sess.opts.debugging_opts.save_analysis ||
sess.opts.debugging_opts.save_analysis_csv
sess.opts.debugging_opts.save_analysis_csv ||
sess.opts.debugging_opts.save_analysis_api
}

fn save_analysis_format(sess: &Session) -> save::Format {
if sess.opts.debugging_opts.save_analysis {
save::Format::Json
} else if sess.opts.debugging_opts.save_analysis_csv {
save::Format::Csv
} else if sess.opts.debugging_opts.save_analysis_api {
save::Format::JsonApi
} else {
unreachable!();
}
10 changes: 6 additions & 4 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
@@ -1056,8 +1056,9 @@ impl<'a> LocalCrateReader<'a> {
Some("dylib") => cstore::NativeUnknown,
Some("framework") => cstore::NativeFramework,
Some(k) => {
span_err!(self.sess, m.span, E0458,
"unknown kind: `{}`", k);
struct_span_err!(self.sess, m.span, E0458,
"unknown kind: `{}`", k)
.span_label(m.span, &format!("unknown kind")).emit();
cstore::NativeUnknown
}
None => cstore::NativeUnknown
@@ -1068,8 +1069,9 @@ impl<'a> LocalCrateReader<'a> {
let n = match n {
Some(n) => n,
None => {
span_err!(self.sess, m.span, E0459,
"#[link(...)] specified without `name = \"foo\"`");
struct_span_err!(self.sess, m.span, E0459,
"#[link(...)] specified without `name = \"foo\"`")
.span_label(m.span, &format!("missing `name` argument")).emit();
InternedString::new("foo")
}
};
33 changes: 33 additions & 0 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc::dep_graph::DepNode;
use rustc::hir;
use rustc::hir::map as hir_map;
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::FnKind;
use rustc::hir::map::blocks::FnLikeNode;
@@ -252,14 +253,46 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {

let mut err =
struct_span_err!(self.tcx.sess, self.span, E0493, "{}", msg);

if self.mode != Mode::Const {
help!(&mut err,
"in Nightly builds, add `#![feature(drop_types_in_const)]` \
to the crate attributes to enable");
} else {
self.find_drop_implementation_method_span()
.map(|span| err.span_label(span, &format!("destructor defined here")));

err.span_label(self.span, &format!("constants cannot have destructors"));
}

err.emit();
}

fn find_drop_implementation_method_span(&self) -> Option<Span> {
self.tcx.lang_items
.drop_trait()
.and_then(|drop_trait_id| {
let mut span = None;

self.tcx
.lookup_trait_def(drop_trait_id)
.for_each_relevant_impl(self.tcx, self.mir.return_ty, |impl_did| {
self.tcx.map
.as_local_node_id(impl_did)
.and_then(|impl_node_id| self.tcx.map.find(impl_node_id))
.map(|node| {
if let hir_map::NodeItem(item) = node {
if let hir::ItemImpl(_, _, _, _, _, ref methods) = item.node {
span = methods.first().map(|method| method.span);
}
}
});
});

span
})
}

/// Check if an Lvalue with the current qualifications could
/// be consumed, by either an operand or a Deref projection.
fn try_consume(&mut self) -> bool {
56 changes: 50 additions & 6 deletions src/librustc_save_analysis/data.rs
Original file line number Diff line number Diff line change
@@ -13,8 +13,9 @@
//! The `Dump` trait can be used together with `DumpVisitor` in order to
//! retrieve the data from a crate.
use rustc::hir;
use rustc::hir::def_id::DefId;
use syntax::ast::{CrateNum, NodeId};
use syntax::ast::{self, CrateNum, NodeId};
use syntax_pos::Span;

pub struct CrateData {
@@ -76,6 +77,35 @@ pub enum Data {
VariableRefData(VariableRefData),
}

#[derive(Eq, PartialEq, Clone, Copy, Debug, RustcEncodable)]
pub enum Visibility {
Public,
Restricted,
Inherited,
}

impl<'a> From<&'a ast::Visibility> for Visibility {
fn from(v: &'a ast::Visibility) -> Visibility {
match *v {
ast::Visibility::Public => Visibility::Public,
ast::Visibility::Crate(_) => Visibility::Restricted,
ast::Visibility::Restricted { .. } => Visibility::Restricted,
ast::Visibility::Inherited => Visibility::Inherited,
}
}
}

impl<'a> From<&'a hir::Visibility> for Visibility {
fn from(v: &'a hir::Visibility) -> Visibility {
match *v {
hir::Visibility::Public => Visibility::Public,
hir::Visibility::Crate => Visibility::Restricted,
hir::Visibility::Restricted { .. } => Visibility::Restricted,
hir::Visibility::Inherited => Visibility::Inherited,
}
}
}

/// Data for the prelude of a crate.
#[derive(Debug, RustcEncodable)]
pub struct CratePreludeData {
@@ -103,7 +133,7 @@ pub struct EnumData {
pub span: Span,
pub scope: NodeId,
pub variants: Vec<NodeId>,

pub visibility: Visibility,
}

/// Data for extern crates.
@@ -135,6 +165,8 @@ pub struct FunctionData {
pub span: Span,
pub scope: NodeId,
pub value: String,
pub visibility: Visibility,
pub parent: Option<NodeId>,
}

/// Data about a function call.
@@ -215,6 +247,7 @@ pub struct MethodData {
pub scope: NodeId,
pub value: String,
pub decl_id: Option<DefId>,
pub visibility: Visibility,
}

/// Data for modules.
@@ -227,6 +260,7 @@ pub struct ModData {
pub scope: NodeId,
pub filename: String,
pub items: Vec<NodeId>,
pub visibility: Visibility,
}

/// Data for a reference to a module.
@@ -248,6 +282,7 @@ pub struct StructData {
pub scope: NodeId,
pub value: String,
pub fields: Vec<NodeId>,
pub visibility: Visibility,
}

#[derive(Debug, RustcEncodable)]
@@ -258,7 +293,8 @@ pub struct StructVariantData {
pub qualname: String,
pub type_value: String,
pub value: String,
pub scope: NodeId
pub scope: NodeId,
pub parent: Option<NodeId>,
}

#[derive(Debug, RustcEncodable)]
@@ -270,6 +306,7 @@ pub struct TraitData {
pub scope: NodeId,
pub value: String,
pub items: Vec<NodeId>,
pub visibility: Visibility,
}

#[derive(Debug, RustcEncodable)]
@@ -280,7 +317,8 @@ pub struct TupleVariantData {
pub qualname: String,
pub type_value: String,
pub value: String,
pub scope: NodeId
pub scope: NodeId,
pub parent: Option<NodeId>,
}

/// Data for a typedef.
@@ -291,6 +329,8 @@ pub struct TypeDefData {
pub span: Span,
pub qualname: String,
pub value: String,
pub visibility: Visibility,
pub parent: Option<NodeId>,
}

/// Data for a reference to a type or trait.
@@ -308,15 +348,17 @@ pub struct UseData {
pub span: Span,
pub name: String,
pub mod_id: Option<DefId>,
pub scope: NodeId
pub scope: NodeId,
pub visibility: Visibility,
}

#[derive(Debug, RustcEncodable)]
pub struct UseGlobData {
pub id: NodeId,
pub span: Span,
pub names: Vec<String>,
pub scope: NodeId
pub scope: NodeId,
pub visibility: Visibility,
}

/// Data for local and global variables (consts and statics).
@@ -328,8 +370,10 @@ pub struct VariableData {
pub qualname: String,
pub span: Span,
pub scope: NodeId,
pub parent: Option<NodeId>,
pub value: String,
pub type_value: String,
pub visibility: Visibility,
}

#[derive(Debug, RustcEncodable)]
154 changes: 91 additions & 63 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
@@ -365,7 +365,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: format!("{}::{}", qualname, path_to_string(p)),
type_value: typ,
value: String::new(),
scope: 0
scope: 0,
parent: None,
visibility: Visibility::Inherited,
}.lower(self.tcx));
}
}
@@ -377,6 +379,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
body: Option<&ast::Block>,
id: ast::NodeId,
name: ast::Name,
vis: Visibility,
span: Span) {
debug!("process_method: {}:{}", id, name);

@@ -417,6 +420,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: method_data.qualname.clone(),
value: sig_str,
decl_id: decl_id,
visibility: vis,
}.lower(self.tcx));
}

@@ -484,7 +488,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
name: name,
id: param.id,
qualname: qualname,
value: String::new()
value: String::new(),
visibility: Visibility::Inherited,
parent: None,
}.lower(self.tcx));
}
}
@@ -528,12 +534,14 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
self.visit_expr(expr);
}

fn process_const(&mut self,
id: ast::NodeId,
name: ast::Name,
span: Span,
typ: &ast::Ty,
expr: &ast::Expr) {
fn process_assoc_const(&mut self,
id: ast::NodeId,
name: ast::Name,
span: Span,
typ: &ast::Ty,
expr: &ast::Expr,
parent_id: NodeId,
vis: Visibility) {
let qualname = format!("::{}", self.tcx.node_path_str(id));

let sub_span = self.span.sub_span_after_keyword(span, keywords::Const);
@@ -547,7 +555,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: qualname,
value: self.span.snippet(expr.span),
type_value: ty_to_string(&typ),
scope: self.cur_scope
scope: self.cur_scope,
parent: Some(parent_id),
visibility: vis,
}.lower(self.tcx));
}

@@ -589,6 +599,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
scope: self.cur_scope,
value: val,
fields: fields,
visibility: From::from(&item.vis),
}.lower(self.tcx));
}

@@ -640,7 +651,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: qualname,
type_value: enum_data.qualname.clone(),
value: val,
scope: enum_data.scope
scope: enum_data.scope,
parent: Some(item.id),
}.lower(self.tcx));
}
}
@@ -663,7 +675,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: qualname,
type_value: enum_data.qualname.clone(),
value: val,
scope: enum_data.scope
scope: enum_data.scope,
parent: Some(item.id),
}.lower(self.tcx));
}
}
@@ -716,7 +729,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
}
self.process_generic_params(type_parameters, item.span, "", item.id);
for impl_item in impl_items {
self.visit_impl_item(impl_item);
self.process_impl_item(impl_item, item.id);
}
}

@@ -745,6 +758,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
scope: self.cur_scope,
value: val,
items: methods.iter().map(|i| i.id).collect(),
visibility: From::from(&item.vis),
}.lower(self.tcx));
}

@@ -785,7 +799,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
// walk generics and methods
self.process_generic_params(generics, item.span, &qualname, item.id);
for method in methods {
self.visit_trait_item(method)
self.process_trait_item(method, item.id)
}
}

@@ -990,7 +1004,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
qualname: format!("{}${}", path_to_string(p), id),
value: value,
type_value: typ,
scope: 0
scope: 0,
parent: None,
visibility: Visibility::Inherited,
}.lower(self.tcx));
}
}
@@ -1038,6 +1054,57 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
}
}
}

fn process_trait_item(&mut self, trait_item: &ast::TraitItem, trait_id: NodeId) {
self.process_macro_use(trait_item.span, trait_item.id);
match trait_item.node {
ast::TraitItemKind::Const(ref ty, Some(ref expr)) => {
self.process_assoc_const(trait_item.id,
trait_item.ident.name,
trait_item.span,
&ty,
&expr,
trait_id,
Visibility::Public);
}
ast::TraitItemKind::Method(ref sig, ref body) => {
self.process_method(sig,
body.as_ref().map(|x| &**x),
trait_item.id,
trait_item.ident.name,
Visibility::Public,
trait_item.span);
}
ast::TraitItemKind::Const(_, None) |
ast::TraitItemKind::Type(..) |
ast::TraitItemKind::Macro(_) => {}
}
}

fn process_impl_item(&mut self, impl_item: &ast::ImplItem, impl_id: NodeId) {
self.process_macro_use(impl_item.span, impl_item.id);
match impl_item.node {
ast::ImplItemKind::Const(ref ty, ref expr) => {
self.process_assoc_const(impl_item.id,
impl_item.ident.name,
impl_item.span,
&ty,
&expr,
impl_id,
From::from(&impl_item.vis));
}
ast::ImplItemKind::Method(ref sig, ref body) => {
self.process_method(sig,
Some(body),
impl_item.id,
impl_item.ident.name,
From::from(&impl_item.vis),
impl_item.span);
}
ast::ImplItemKind::Type(_) |
ast::ImplItemKind::Macro(_) => {}
}
}
}

impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> {
@@ -1073,7 +1140,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
id: item.id,
mod_id: mod_id,
name: ident.to_string(),
scope: self.cur_scope
scope: self.cur_scope,
visibility: From::from(&item.vis),
}.lower(self.tcx));
}
self.write_sub_paths_truncated(path, true);
@@ -1096,7 +1164,8 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
span: sub_span.expect("No span found for use glob"),
id: item.id,
names: names,
scope: self.cur_scope
scope: self.cur_scope,
visibility: From::from(&item.vis),
}.lower(self.tcx));
}
self.write_sub_paths(path, true);
@@ -1168,7 +1237,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
name: item.ident.to_string(),
id: item.id,
qualname: qualname.clone(),
value: value
value: value,
visibility: From::from(&item.vis),
parent: None,
}.lower(self.tcx));
}

@@ -1193,51 +1264,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
}
}

fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
self.process_macro_use(trait_item.span, trait_item.id);
match trait_item.node {
ast::TraitItemKind::Const(ref ty, Some(ref expr)) => {
self.process_const(trait_item.id,
trait_item.ident.name,
trait_item.span,
&ty,
&expr);
}
ast::TraitItemKind::Method(ref sig, ref body) => {
self.process_method(sig,
body.as_ref().map(|x| &**x),
trait_item.id,
trait_item.ident.name,
trait_item.span);
}
ast::TraitItemKind::Const(_, None) |
ast::TraitItemKind::Type(..) |
ast::TraitItemKind::Macro(_) => {}
}
}

fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
self.process_macro_use(impl_item.span, impl_item.id);
match impl_item.node {
ast::ImplItemKind::Const(ref ty, ref expr) => {
self.process_const(impl_item.id,
impl_item.ident.name,
impl_item.span,
&ty,
&expr);
}
ast::ImplItemKind::Method(ref sig, ref body) => {
self.process_method(sig,
Some(body),
impl_item.id,
impl_item.ident.name,
impl_item.span);
}
ast::ImplItemKind::Type(_) |
ast::ImplItemKind::Macro(_) => {}
}
}

fn visit_ty(&mut self, t: &ast::Ty) {
self.process_macro_use(t.span, t.id);
match t.node {
@@ -1400,7 +1426,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
qualname: format!("{}${}", path_to_string(p), id),
value: value,
type_value: String::new(),
scope: 0
scope: 0,
parent: None,
visibility: Visibility::Inherited,
}.lower(self.tcx));
}
}
42 changes: 37 additions & 5 deletions src/librustc_save_analysis/external_data.rs
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ use syntax::ast::{CrateNum, NodeId};
use syntax::codemap::CodeMap;
use syntax_pos::Span;

use data;
use data::{self, Visibility};

// FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet
pub trait Lower {
@@ -91,7 +91,8 @@ pub struct EnumData {
pub qualname: String,
pub span: SpanData,
pub scope: DefId,
pub variants: Vec<DefId>
pub variants: Vec<DefId>,
pub visibility: Visibility,
}

impl Lower for data::EnumData {
@@ -106,6 +107,7 @@ impl Lower for data::EnumData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: make_def_id(self.scope, &tcx.map),
variants: self.variants.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
visibility: self.visibility,
}
}
}
@@ -166,6 +168,8 @@ pub struct FunctionData {
pub span: SpanData,
pub scope: DefId,
pub value: String,
pub visibility: Visibility,
pub parent: Option<DefId>,
}

impl Lower for data::FunctionData {
@@ -180,6 +184,8 @@ impl Lower for data::FunctionData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
scope: make_def_id(self.scope, &tcx.map),
value: self.value,
visibility: self.visibility,
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
}
}
}
@@ -323,6 +329,8 @@ pub struct MethodData {
pub scope: DefId,
pub value: String,
pub decl_id: Option<DefId>,
pub visibility: Visibility,
pub parent: Option<DefId>
}

impl Lower for data::MethodData {
@@ -337,6 +345,8 @@ impl Lower for data::MethodData {
qualname: self.qualname,
value: self.value,
decl_id: self.decl_id,
visibility: self.visibility,
parent: Some(make_def_id(self.scope, &tcx.map)),
}
}
}
@@ -351,6 +361,7 @@ pub struct ModData {
pub scope: DefId,
pub filename: String,
pub items: Vec<DefId>,
pub visibility: Visibility,
}

impl Lower for data::ModData {
@@ -365,6 +376,7 @@ impl Lower for data::ModData {
scope: make_def_id(self.scope, &tcx.map),
filename: self.filename,
items: self.items.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
visibility: self.visibility,
}
}
}
@@ -401,6 +413,7 @@ pub struct StructData {
pub scope: DefId,
pub value: String,
pub fields: Vec<DefId>,
pub visibility: Visibility,
}

impl Lower for data::StructData {
@@ -416,6 +429,7 @@ impl Lower for data::StructData {
scope: make_def_id(self.scope, &tcx.map),
value: self.value,
fields: self.fields.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
visibility: self.visibility,
}
}
}
@@ -428,7 +442,8 @@ pub struct StructVariantData {
pub qualname: String,
pub type_value: String,
pub value: String,
pub scope: DefId
pub scope: DefId,
pub parent: Option<DefId>,
}

impl Lower for data::StructVariantData {
@@ -443,6 +458,7 @@ impl Lower for data::StructVariantData {
type_value: self.type_value,
value: self.value,
scope: make_def_id(self.scope, &tcx.map),
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
}
}
}
@@ -456,6 +472,7 @@ pub struct TraitData {
pub scope: DefId,
pub value: String,
pub items: Vec<DefId>,
pub visibility: Visibility,
}

impl Lower for data::TraitData {
@@ -470,6 +487,7 @@ impl Lower for data::TraitData {
scope: make_def_id(self.scope, &tcx.map),
value: self.value,
items: self.items.into_iter().map(|id| make_def_id(id, &tcx.map)).collect(),
visibility: self.visibility,
}
}
}
@@ -483,6 +501,7 @@ pub struct TupleVariantData {
pub type_value: String,
pub value: String,
pub scope: DefId,
pub parent: Option<DefId>,
}

impl Lower for data::TupleVariantData {
@@ -497,6 +516,7 @@ impl Lower for data::TupleVariantData {
type_value: self.type_value,
value: self.value,
scope: make_def_id(self.scope, &tcx.map),
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
}
}
}
@@ -509,6 +529,8 @@ pub struct TypeDefData {
pub span: SpanData,
pub qualname: String,
pub value: String,
pub visibility: Visibility,
pub parent: Option<DefId>,
}

impl Lower for data::TypeDefData {
@@ -521,6 +543,8 @@ impl Lower for data::TypeDefData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
qualname: self.qualname,
value: self.value,
visibility: self.visibility,
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
}
}
}
@@ -553,7 +577,8 @@ pub struct UseData {
pub span: SpanData,
pub name: String,
pub mod_id: Option<DefId>,
pub scope: DefId
pub scope: DefId,
pub visibility: Visibility,
}

impl Lower for data::UseData {
@@ -566,6 +591,7 @@ impl Lower for data::UseData {
name: self.name,
mod_id: self.mod_id,
scope: make_def_id(self.scope, &tcx.map),
visibility: self.visibility,
}
}
}
@@ -575,7 +601,8 @@ pub struct UseGlobData {
pub id: DefId,
pub span: SpanData,
pub names: Vec<String>,
pub scope: DefId
pub scope: DefId,
pub visibility: Visibility,
}

impl Lower for data::UseGlobData {
@@ -587,6 +614,7 @@ impl Lower for data::UseGlobData {
span: SpanData::from_span(self.span, tcx.sess.codemap()),
names: self.names,
scope: make_def_id(self.scope, &tcx.map),
visibility: self.visibility,
}
}
}
@@ -602,6 +630,8 @@ pub struct VariableData {
pub scope: DefId,
pub value: String,
pub type_value: String,
pub parent: Option<DefId>,
pub visibility: Visibility,
}

impl Lower for data::VariableData {
@@ -617,6 +647,8 @@ impl Lower for data::VariableData {
scope: make_def_id(self.scope, &tcx.map),
value: self.value,
type_value: self.type_value,
parent: self.parent.map(|id| make_def_id(id, &tcx.map)),
visibility: self.visibility,
}
}
}
393 changes: 393 additions & 0 deletions src/librustc_save_analysis/json_api_dumper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,393 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io::Write;

use rustc::hir::def_id::DefId;
use rustc_serialize::json::as_json;

use external_data::*;
use data::{VariableKind, Visibility};
use dump::Dump;

// A dumper to dump a restricted set of JSON information, designed for use with
// libraries distributed without their source. Clients are likely to use type
// information here, and (for example) generate Rustdoc URLs, but don't need
// information for navigating the source of the crate.
// Relative to the regular JSON save-analysis info, this form is filtered to
// remove non-visible items, but includes some extra info for items (e.g., the
// parent field for finding the struct to which a field belongs).
pub struct JsonApiDumper<'b, W: Write + 'b> {
output: &'b mut W,
result: Analysis,
}

impl<'b, W: Write> JsonApiDumper<'b, W> {
pub fn new(writer: &'b mut W) -> JsonApiDumper<'b, W> {
JsonApiDumper { output: writer, result: Analysis::new() }
}
}

impl<'b, W: Write> Drop for JsonApiDumper<'b, W> {
fn drop(&mut self) {
if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
error!("Error writing output");
}
}
}

macro_rules! impl_fn {
($fn_name: ident, $data_type: ident, $bucket: ident) => {
fn $fn_name(&mut self, data: $data_type) {
if let Some(datum) = From::from(data) {
self.result.$bucket.push(datum);
}
}
}
}

impl<'b, W: Write + 'b> Dump for JsonApiDumper<'b, W> {
fn crate_prelude(&mut self, data: CratePreludeData) {
self.result.prelude = Some(data)
}

impl_fn!(use_data, UseData, imports);
impl_fn!(use_glob, UseGlobData, imports);

impl_fn!(enum_data, EnumData, defs);
impl_fn!(tuple_variant, TupleVariantData, defs);
impl_fn!(struct_variant, StructVariantData, defs);
impl_fn!(struct_data, StructData, defs);
impl_fn!(trait_data, TraitData, defs);
impl_fn!(function, FunctionData, defs);
impl_fn!(method, MethodData, defs);
impl_fn!(macro_data, MacroData, defs);
impl_fn!(mod_data, ModData, defs);
impl_fn!(typedef, TypeDefData, defs);
impl_fn!(variable, VariableData, defs);
}

// FIXME methods. The defs have information about possible overriding and the
// refs have decl information (e.g., a trait method where we know the required
// method, but not the supplied method). In both cases, we are currently
// ignoring it.

#[derive(Debug, RustcEncodable)]
struct Analysis {
prelude: Option<CratePreludeData>,
imports: Vec<Import>,
defs: Vec<Def>,
}

impl Analysis {
fn new() -> Analysis {
Analysis {
prelude: None,
imports: vec![],
defs: vec![],
}
}
}

// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
// we use our own Id which is the same, but without the newtype.
#[derive(Debug, RustcEncodable)]
struct Id {
krate: u32,
index: u32,
}

impl From<DefId> for Id {
fn from(id: DefId) -> Id {
Id {
krate: id.krate,
index: id.index.as_u32(),
}
}
}

#[derive(Debug, RustcEncodable)]
struct Import {
kind: ImportKind,
id: Id,
span: SpanData,
name: String,
value: String,
}

#[derive(Debug, RustcEncodable)]
enum ImportKind {
Use,
GlobUse,
}

impl From<UseData> for Option<Import> {
fn from(data: UseData) -> Option<Import> {
match data.visibility {
Visibility::Public => Some(Import {
kind: ImportKind::Use,
id: From::from(data.id),
span: data.span,
name: data.name,
value: String::new(),
}),
_ => None,
}
}
}
impl From<UseGlobData> for Option<Import> {
fn from(data: UseGlobData) -> Option<Import> {
match data.visibility {
Visibility::Public => Some(Import {
kind: ImportKind::GlobUse,
id: From::from(data.id),
span: data.span,
name: "*".to_owned(),
value: data.names.join(", "),
}),
_ => None,
}
}
}

#[derive(Debug, RustcEncodable)]
struct Def {
kind: DefKind,
id: Id,
span: SpanData,
name: String,
qualname: String,
value: String,
parent: Option<Id>,
children: Vec<Id>,
decl_id: Option<Id>,
}

#[derive(Debug, RustcEncodable)]
enum DefKind {
// value = variant names
Enum,
// value = enum name + variant name + types
Tuple,
// value = [enum name +] name + fields
Struct,
// value = signature
Trait,
// value = type + generics
Function,
// value = type + generics
Method,
// No id, no value.
Macro,
// value = file_name
Mod,
// value = aliased type
Type,
// value = type and init expression (for all variable kinds).
Static,
Const,
Field,
}

impl From<EnumData> for Option<Def> {
fn from(data: EnumData) -> Option<Def> {
match data.visibility {
Visibility::Public => Some(Def {
kind: DefKind::Enum,
id: From::from(data.id),
span: data.span,
name: data.name,
qualname: data.qualname,
value: data.value,
parent: None,
children: data.variants.into_iter().map(|id| From::from(id)).collect(),
decl_id: None,
}),
_ => None,
}
}
}

impl From<TupleVariantData> for Option<Def> {
fn from(data: TupleVariantData) -> Option<Def> {
Some(Def {
kind: DefKind::Tuple,
id: From::from(data.id),
span: data.span,
name: data.name,
qualname: data.qualname,
value: data.value,
parent: data.parent.map(|id| From::from(id)),
children: vec![],
decl_id: None,
})
}
}
impl From<StructVariantData> for Option<Def> {
fn from(data: StructVariantData) -> Option<Def> {
Some(Def {
kind: DefKind::Struct,
id: From::from(data.id),
span: data.span,
name: data.name,
qualname: data.qualname,
value: data.value,
parent: data.parent.map(|id| From::from(id)),
children: vec![],
decl_id: None,
})
}
}
impl From<StructData> for Option<Def> {
fn from(data: StructData) -> Option<Def> {
match data.visibility {
Visibility::Public => Some(Def {
kind: DefKind::Struct,
id: From::from(data.id),
span: data.span,
name: data.name,
qualname: data.qualname,
value: data.value,
parent: None,
children: data.fields.into_iter().map(|id| From::from(id)).collect(),
decl_id: None,
}),
_ => None,
}
}
}
impl From<TraitData> for Option<Def> {
fn from(data: TraitData) -> Option<Def> {
match data.visibility {
Visibility::Public => Some(Def {
kind: DefKind::Trait,
id: From::from(data.id),
span: data.span,
name: data.name,
qualname: data.qualname,
value: data.value,
children: data.items.into_iter().map(|id| From::from(id)).collect(),
parent: None,
decl_id: None,
}),
_ => None,
}
}
}
impl From<FunctionData> for Option<Def> {
fn from(data: FunctionData) -> Option<Def> {
match data.visibility {
Visibility::Public => Some(Def {
kind: DefKind::Function,
id: From::from(data.id),
span: data.span,
name: data.name,
qualname: data.qualname,
value: data.value,
children: vec![],
parent: data.parent.map(|id| From::from(id)),
decl_id: None,
}),
_ => None,
}
}
}
impl From<MethodData> for Option<Def> {
fn from(data: MethodData) -> Option<Def> {
match data.visibility {
Visibility::Public => Some(Def {
kind: DefKind::Method,
id: From::from(data.id),
span: data.span,
name: data.name,
qualname: data.qualname,
value: data.value,
children: vec![],
parent: data.parent.map(|id| From::from(id)),
decl_id: data.decl_id.map(|id| From::from(id)),
}),
_ => None,
}
}
}
impl From<MacroData> for Option<Def> {
fn from(data: MacroData) -> Option<Def> {
Some(Def {
kind: DefKind::Macro,
id: From::from(null_def_id()),
span: data.span,
name: data.name,
qualname: data.qualname,
value: String::new(),
children: vec![],
parent: None,
decl_id: None,
})
}
}
impl From<ModData> for Option<Def> {
fn from(data:ModData) -> Option<Def> {
match data.visibility {
Visibility::Public => Some(Def {
kind: DefKind::Mod,
id: From::from(data.id),
span: data.span,
name: data.name,
qualname: data.qualname,
value: data.filename,
children: data.items.into_iter().map(|id| From::from(id)).collect(),
parent: None,
decl_id: None,
}),
_ => None,
}
}
}
impl From<TypeDefData> for Option<Def> {
fn from(data: TypeDefData) -> Option<Def> {
match data.visibility {
Visibility::Public => Some(Def {
kind: DefKind::Type,
id: From::from(data.id),
span: data.span,
name: data.name,
qualname: data.qualname,
value: data.value,
children: vec![],
parent: data.parent.map(|id| From::from(id)),
decl_id: None,
}),
_ => None,
}
}
}
impl From<VariableData> for Option<Def> {
fn from(data: VariableData) -> Option<Def> {
match data.visibility {
Visibility::Public => Some(Def {
kind: match data.kind {
VariableKind::Static => DefKind::Static,
VariableKind::Const => DefKind::Const,
VariableKind::Local => { return None }
VariableKind::Field => DefKind::Field,
},
id: From::from(data.id),
span: data.span,
name: data.name,
qualname: data.qualname,
value: data.value,
children: vec![],
parent: data.parent.map(|id| From::from(id)),
decl_id: None,
}),
_ => None,
}
}
}
27 changes: 22 additions & 5 deletions src/librustc_save_analysis/lib.rs
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@ extern crate serialize as rustc_serialize;
extern crate syntax_pos;

mod csv_dumper;
mod json_api_dumper;
mod json_dumper;
mod data;
mod dump;
@@ -57,6 +58,7 @@ use syntax::codemap::MacroAttribute;
use syntax_pos::*;

pub use self::csv_dumper::CsvDumper;
pub use self::json_api_dumper::JsonApiDumper;
pub use self::json_dumper::JsonDumper;
pub use self::data::*;
pub use self::dump::Dump;
@@ -138,6 +140,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
span: sub_span.unwrap(),
scope: self.enclosing_scope(item.id),
value: make_signature(decl, generics),
visibility: From::from(&item.vis),
parent: None,
}))
}
ast::ItemKind::Static(ref typ, mt, ref expr) => {
@@ -160,8 +164,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
qualname: qualname,
span: sub_span.unwrap(),
scope: self.enclosing_scope(item.id),
parent: None,
value: value,
type_value: ty_to_string(&typ),
visibility: From::from(&item.vis),
}))
}
ast::ItemKind::Const(ref typ, ref expr) => {
@@ -175,8 +181,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
qualname: qualname,
span: sub_span.unwrap(),
scope: self.enclosing_scope(item.id),
parent: None,
value: self.span_utils.snippet(expr.span),
type_value: ty_to_string(&typ),
visibility: From::from(&item.vis),
}))
}
ast::ItemKind::Mod(ref m) => {
@@ -195,6 +203,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
scope: self.enclosing_scope(item.id),
filename: filename,
items: m.items.iter().map(|i| i.id).collect(),
visibility: From::from(&item.vis),
}))
}
ast::ItemKind::Enum(ref def, _) => {
@@ -215,6 +224,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
qualname: qualname,
scope: self.enclosing_scope(item.id),
variants: def.variants.iter().map(|v| v.node.data.id()).collect(),
visibility: From::from(&item.vis),
}))
}
ast::ItemKind::Impl(_, _, _, ref trait_ref, ref typ, _) => {
@@ -277,8 +287,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
qualname: qualname,
span: sub_span.unwrap(),
scope: scope,
parent: Some(scope),
value: "".to_owned(),
type_value: typ,
visibility: From::from(&field.vis),
})
} else {
None
@@ -291,7 +303,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
name: ast::Name, span: Span) -> Option<FunctionData> {
// The qualname for a method is the trait name or name of the struct in an impl in
// which the method is declared in, followed by the method's name.
let qualname = match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) {
let (qualname, vis) = match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) {
Some(impl_id) => match self.tcx.map.get_if_local(impl_id) {
Some(NodeItem(item)) => {
match item.node {
@@ -304,7 +316,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
result.push_str(&self.tcx.item_path_str(def_id));
}
result.push_str(">");
result
(result, From::from(&item.vis))
}
_ => {
span_bug!(span,
@@ -325,8 +337,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
None => match self.tcx.trait_of_item(self.tcx.map.local_def_id(id)) {
Some(def_id) => {
match self.tcx.map.get_if_local(def_id) {
Some(NodeItem(_)) => {
format!("::{}", self.tcx.item_path_str(def_id))
Some(NodeItem(item)) => {
(format!("::{}", self.tcx.item_path_str(def_id)), From::from(&item.vis))
}
r => {
span_bug!(span,
@@ -358,6 +370,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {

let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
filter!(self.span_utils, sub_span, span, None);
let parent_scope = self.enclosing_scope(id);
Some(FunctionData {
id: id,
name: name.to_string(),
@@ -367,6 +380,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
scope: self.enclosing_scope(id),
// FIXME you get better data here by using the visitor.
value: String::new(),
visibility: vis,
parent: Some(parent_scope),
})
}

@@ -728,13 +743,14 @@ impl Visitor for PathCollector {
pub enum Format {
Csv,
Json,
JsonApi,
}

impl Format {
fn extension(&self) -> &'static str {
match *self {
Format::Csv => ".csv",
Format::Json => ".json",
Format::Json | Format::JsonApi => ".json",
}
}
}
@@ -804,6 +820,7 @@ pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
match format {
Format::Csv => dump!(CsvDumper::new(output)),
Format::Json => dump!(JsonDumper::new(output)),
Format::JsonApi => dump!(JsonApiDumper::new(output)),
}
}

4 changes: 3 additions & 1 deletion src/test/compile-fail/E0458.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,9 @@
// except according to those terms.

#[link(kind = "wonderful_unicorn")] extern {} //~ ERROR E0458
//~^ ERROR E0459
//~| NOTE unknown kind
//~| ERROR E0459
//~| NOTE missing `name` argument

fn main() {
}
1 change: 1 addition & 0 deletions src/test/compile-fail/E0459.rs
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
// except according to those terms.

#[link(kind = "dylib")] extern {} //~ ERROR E0459
//~| NOTE missing `name` argument

fn main() {
}
1 change: 1 addition & 0 deletions src/test/run-make/save-analysis/Makefile
Original file line number Diff line number Diff line change
@@ -5,3 +5,4 @@ krate2: krate2.rs
code: foo.rs krate2
$(RUSTC) foo.rs -Zsave-analysis-csv
$(RUSTC) foo.rs -Zsave-analysis
$(RUSTC) foo.rs -Zsave-analysis-api
10 changes: 9 additions & 1 deletion src/test/compile-fail/E0493.rs → src/test/ui/span/E0493.rs
Original file line number Diff line number Diff line change
@@ -16,7 +16,15 @@ impl Drop for Foo {
fn drop(&mut self) {}
}

const F : Foo = Foo { a : 0 }; //~ ERROR E0493
struct Bar {
a: u32
}

impl Drop for Bar {
fn drop(&mut self) {}
}

const F : Foo = Foo { a : 0 };

fn main() {
}
11 changes: 11 additions & 0 deletions src/test/ui/span/E0493.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0493]: constants are not allowed to have destructors
--> $DIR/E0493.rs:27:17
|
16 | fn drop(&mut self) {}
| --------------------- destructor defined here
...
27 | const F : Foo = Foo { a : 0 };
| ^^^^^^^^^^^^^ constants cannot have destructors

error: aborting due to previous error