未验证 提交 2b8ed1e1 编写于 作者: M Mazdak Farrokhzad 提交者: GitHub

Rollup merge of #58233 - taiki-e:librustc_save_analysis-2018, r=Centril

librustc_save_analysis => 2018

Transitions `librustc_save_analysis` to Rust 2018; cc #58099

r? @Centril
......@@ -2,6 +2,7 @@
authors = ["The Rust Project Developers"]
name = "rustc_save_analysis"
version = "0.0.0"
edition = "2018"
[lib]
name = "rustc_save_analysis"
......
......@@ -16,6 +16,7 @@
use rustc::hir::def::Def as HirDef;
use rustc::hir::def_id::DefId;
use rustc::session::config::Input;
use rustc::span_bug;
use rustc::ty::{self, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
......@@ -32,16 +33,20 @@
};
use syntax::ptr::P;
use syntax::source_map::{Spanned, DUMMY_SP, respan};
use syntax::walk_list;
use syntax_pos::*;
use {escape, generated_code, lower_attributes, PathCollector, SaveContext};
use json_dumper::{Access, DumpOutput, JsonDumper};
use span_utils::SpanUtils;
use sig;
use crate::{escape, generated_code, id_from_def_id, id_from_node_id, lower_attributes,
PathCollector, SaveContext};
use crate::json_dumper::{Access, DumpOutput, JsonDumper};
use crate::span_utils::SpanUtils;
use crate::sig;
use rls_data::{CompilationOptions, CratePreludeData, Def, DefKind, GlobalCrateId, Import,
ImportKind, Ref, RefKind, Relation, RelationKind, SpanData};
use log::{debug, error};
macro_rules! down_cast_data {
($id:ident, $kind:ident, $sp:expr) => {
let $id = if let super::Data::$kind(data) = $id {
......@@ -68,7 +73,7 @@
};
}
pub struct DumpVisitor<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> {
pub struct DumpVisitor<'l, 'tcx: 'l, 'll, O: DumpOutput> {
save_ctxt: SaveContext<'l, 'tcx>,
tcx: TyCtxt<'l, 'tcx, 'tcx>,
dumper: &'ll mut JsonDumper<O>,
......@@ -245,7 +250,7 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
None => continue,
};
if !self.span.filter_generated(ident.span) {
let id = ::id_from_node_id(id, &self.save_ctxt);
let id = id_from_node_id(id, &self.save_ctxt);
let span = self.span_from_span(ident.span);
self.dumper.dump_def(
......@@ -286,7 +291,7 @@ fn process_method(
debug!("process_method: {}:{}", id, ident);
if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident, span) {
let sig_str = ::make_signature(&sig.decl, &generics);
let sig_str = crate::make_signature(&sig.decl, &generics);
if body.is_some() {
self.nest_tables(
id,
......@@ -339,7 +344,7 @@ fn process_generic_params(
// Append $id to name to make sure each one is unique.
let qualname = format!("{}::{}${}", prefix, name, id);
if !self.span.filter_generated(param_ss) {
let id = ::id_from_node_id(param.id, &self.save_ctxt);
let id = id_from_node_id(param.id, &self.save_ctxt);
let span = self.span_from_span(param_ss);
self.dumper.dump_def(
......@@ -434,12 +439,12 @@ fn process_assoc_const(
&access_from!(self.save_ctxt, vis, id),
Def {
kind: DefKind::Const,
id: ::id_from_node_id(id, &self.save_ctxt),
id: id_from_node_id(id, &self.save_ctxt),
span,
name: ident.name.to_string(),
qualname,
value: ty_to_string(&typ),
parent: Some(::id_from_def_id(parent_id)),
parent: Some(id_from_def_id(parent_id)),
children: vec![],
decl_id: None,
docs: self.save_ctxt.docs_for_attrs(attrs),
......@@ -496,7 +501,7 @@ fn process_struct(
value,
fields
.iter()
.map(|f| ::id_from_node_id(f.id, &self.save_ctxt))
.map(|f| id_from_node_id(f.id, &self.save_ctxt))
.collect(),
)
}
......@@ -509,7 +514,7 @@ fn process_struct(
&access_from!(self.save_ctxt, item),
Def {
kind,
id: ::id_from_node_id(item.id, &self.save_ctxt),
id: id_from_node_id(item.id, &self.save_ctxt),
span,
name,
qualname: qualname.clone(),
......@@ -565,8 +570,8 @@ fn process_enum(
let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
if !self.span.filter_generated(name_span) {
let span = self.span_from_span(name_span);
let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt);
let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
let id = id_from_node_id(variant.node.data.id(), &self.save_ctxt);
let parent = Some(id_from_node_id(item.id, &self.save_ctxt));
self.dumper.dump_def(
&access,
......@@ -603,8 +608,8 @@ fn process_enum(
}
if !self.span.filter_generated(name_span) {
let span = self.span_from_span(name_span);
let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt);
let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
let id = id_from_node_id(variant.node.data.id(), &self.save_ctxt);
let parent = Some(id_from_node_id(item.id, &self.save_ctxt));
self.dumper.dump_def(
&access,
......@@ -687,11 +692,11 @@ fn process_trait(
val.push_str(&bounds_to_string(trait_refs));
}
if !self.span.filter_generated(item.ident.span) {
let id = ::id_from_node_id(item.id, &self.save_ctxt);
let id = id_from_node_id(item.id, &self.save_ctxt);
let span = self.span_from_span(item.ident.span);
let children = methods
.iter()
.map(|i| ::id_from_node_id(i.id, &self.save_ctxt))
.map(|i| id_from_node_id(i.id, &self.save_ctxt))
.collect();
self.dumper.dump_def(
&access_from!(self.save_ctxt, item),
......@@ -727,14 +732,14 @@ fn process_trait(
self.dumper.dump_ref(Ref {
kind: RefKind::Type,
span: span.clone(),
ref_id: ::id_from_def_id(id),
ref_id: id_from_def_id(id),
});
self.dumper.dump_relation(Relation {
kind: RelationKind::SuperTrait,
span,
from: ::id_from_def_id(id),
to: ::id_from_node_id(item.id, &self.save_ctxt),
from: id_from_def_id(id),
to: id_from_node_id(item.id, &self.save_ctxt),
});
}
}
......@@ -874,7 +879,7 @@ fn process_pat(&mut self, p: &'l ast::Pat) {
self.dumper.dump_ref(Ref {
kind: RefKind::Variable,
span,
ref_id: ::id_from_def_id(variant.fields[index].did),
ref_id: id_from_def_id(variant.fields[index].did),
});
}
}
......@@ -913,7 +918,7 @@ fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) {
if !self.span.filter_generated(ident.span) {
let qualname = format!("{}${}", ident.to_string(), id);
let id = ::id_from_node_id(id, &self.save_ctxt);
let id = id_from_node_id(id, &self.save_ctxt);
let span = self.span_from_span(ident.span);
self.dumper.dump_def(
......@@ -989,7 +994,7 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
// Rust uses the id of the pattern for var lookups, so we'll use it too.
if !self.span.filter_generated(ident.span) {
let qualname = format!("{}${}", ident.to_string(), id);
let id = ::id_from_node_id(id, &self.save_ctxt);
let id = id_from_node_id(id, &self.save_ctxt);
let span = self.span_from_span(ident.span);
self.dumper.dump_def(
......@@ -1092,7 +1097,7 @@ fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId
if !self.span.filter_generated(trait_item.ident.span) {
let span = self.span_from_span(trait_item.ident.span);
let id = ::id_from_node_id(trait_item.id, &self.save_ctxt);
let id = id_from_node_id(trait_item.id, &self.save_ctxt);
self.dumper.dump_def(
&Access {
......@@ -1106,7 +1111,7 @@ fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId
name,
qualname,
value: self.span.snippet(trait_item.span),
parent: Some(::id_from_def_id(trait_id)),
parent: Some(id_from_def_id(trait_id)),
children: vec![],
decl_id: None,
docs: self.save_ctxt.docs_for_attrs(&trait_item.attrs),
......@@ -1197,7 +1202,7 @@ fn process_use_tree(&mut self,
// The parent def id of a given use tree is always the enclosing item.
let parent = self.save_ctxt.tcx.hir().opt_local_def_id(id)
.and_then(|id| self.save_ctxt.tcx.parent_def_id(id))
.map(::id_from_def_id);
.map(id_from_def_id);
match use_tree.kind {
ast::UseTreeKind::Simple(alias, ..) => {
......@@ -1213,7 +1218,7 @@ fn process_use_tree(&mut self,
let sub_span = path.segments.last().unwrap().ident.span;
if !self.span.filter_generated(sub_span) {
let ref_id = self.lookup_def_id(id).map(|id| ::id_from_def_id(id));
let ref_id = self.lookup_def_id(id).map(|id| id_from_def_id(id));
let alias_span = alias.map(|i| self.span_from_span(i.span));
let span = self.span_from_span(sub_span);
self.dumper.import(&access, Import {
......@@ -1299,10 +1304,10 @@ fn visit_mod(&mut self, m: &'l ast::Mod, span: Span, attrs: &[ast::Attribute], i
let cm = self.tcx.sess.source_map();
let filename = cm.span_to_filename(span);
let data_id = ::id_from_node_id(id, &self.save_ctxt);
let data_id = id_from_node_id(id, &self.save_ctxt);
let children = m.items
.iter()
.map(|i| ::id_from_node_id(i.id, &self.save_ctxt))
.map(|i| id_from_node_id(i.id, &self.save_ctxt))
.collect();
let span = self.span_from_span(span);
......@@ -1346,7 +1351,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
let span = self.span_from_span(name_span);
let parent = self.save_ctxt.tcx.hir().opt_local_def_id(item.id)
.and_then(|id| self.save_ctxt.tcx.parent_def_id(id))
.map(::id_from_def_id);
.map(id_from_def_id);
self.dumper.import(
&Access {
public: false,
......@@ -1388,7 +1393,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
let value = ty_to_string(&ty);
if !self.span.filter_generated(item.ident.span) {
let span = self.span_from_span(item.ident.span);
let id = ::id_from_node_id(item.id, &self.save_ctxt);
let id = id_from_node_id(item.id, &self.save_ctxt);
self.dumper.dump_def(
&access_from!(self.save_ctxt, item),
......@@ -1418,7 +1423,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
let value = String::new();
if !self.span.filter_generated(item.ident.span) {
let span = self.span_from_span(item.ident.span);
let id = ::id_from_node_id(item.id, &self.save_ctxt);
let id = id_from_node_id(item.id, &self.save_ctxt);
self.dumper.dump_def(
&access_from!(self.save_ctxt, item),
......@@ -1484,7 +1489,7 @@ fn visit_ty(&mut self, t: &'l ast::Ty) {
self.dumper.dump_ref(Ref {
kind: RefKind::Type,
span,
ref_id: ::id_from_def_id(id),
ref_id: id_from_def_id(id),
});
}
......
......@@ -7,6 +7,8 @@
MacroRef, Ref, RefKind, Relation};
use rls_span::{Column, Row};
use log::error;
#[derive(Debug)]
pub struct Access {
pub reachable: bool,
......@@ -23,7 +25,7 @@ pub trait DumpOutput {
fn dump(&mut self, result: &Analysis);
}
pub struct WriteOutput<'b, W: Write + 'b> {
pub struct WriteOutput<'b, W: Write> {
output: &'b mut W,
}
......
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(custom_attribute)]
#![feature(nll)]
#![deny(rust_2018_idioms)]
#![allow(unused_attributes)]
#![recursion_limit="256"]
#[macro_use]
extern crate rustc;
#[macro_use]
extern crate log;
extern crate rustc_data_structures;
extern crate rustc_codegen_utils;
extern crate rustc_serialize;
extern crate rustc_target;
extern crate rustc_typeck;
#[macro_use]
extern crate syntax;
extern crate syntax_pos;
extern crate rls_data;
extern crate rls_span;
mod json_dumper;
mod dump_visitor;
......@@ -37,6 +20,7 @@
use rustc::middle::cstore::ExternCrate;
use rustc::session::config::{CrateType, Input, OutputType};
use rustc::ty::{self, TyCtxt};
use rustc::{bug, span_bug};
use rustc_typeck::hir_ty_to_ty;
use rustc_codegen_utils::link::{filename_for_metadata, out_filename};
use rustc_data_structures::sync::Lrc;
......@@ -64,6 +48,8 @@
RelationKind, SpanData, Impl, ImplKind};
use rls_data::config::Config;
use log::{debug, error, info};
pub struct SaveContext<'l, 'tcx: 'l> {
tcx: TyCtxt<'l, 'tcx, 'tcx>,
......@@ -170,7 +156,7 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
ast::ForeignItemKind::Static(ref ty, _) => {
filter!(self.span_utils, item.ident.span);
let id = ::id_from_node_id(item.id, self);
let id = id_from_node_id(item.id, self);
let span = self.span_from_span(item.ident.span);
Some(Data::DefData(Def {
......@@ -1034,7 +1020,7 @@ pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> {
}
}
fn output_file(&self, ctx: &SaveContext) -> File {
fn output_file(&self, ctx: &SaveContext<'_, '_>) -> File {
let sess = &ctx.tcx.sess;
let file_name = match ctx.config.output_file {
Some(ref s) => PathBuf::from(s),
......@@ -1185,7 +1171,7 @@ fn id_from_def_id(id: DefId) -> rls_data::Id {
}
}
fn id_from_node_id(id: NodeId, scx: &SaveContext) -> rls_data::Id {
fn id_from_node_id(id: NodeId, scx: &SaveContext<'_, '_>) -> rls_data::Id {
let def_id = scx.tcx.hir().opt_local_def_id(id);
def_id.map(|id| id_from_def_id(id)).unwrap_or_else(|| {
// Create a *fake* `DefId` out of a `NodeId` by subtracting the `NodeId`
......@@ -1205,7 +1191,7 @@ fn null_id() -> rls_data::Id {
}
}
fn lower_attributes(attrs: Vec<Attribute>, scx: &SaveContext) -> Vec<rls_data::Attribute> {
fn lower_attributes(attrs: Vec<Attribute>, scx: &SaveContext<'_, '_>) -> Vec<rls_data::Attribute> {
attrs.into_iter()
// Only retain real attributes. Doc comments are lowered separately.
.filter(|attr| attr.path != "doc")
......
......@@ -25,7 +25,7 @@
//
// FIXME where clauses need implementing, defs/refs in generics are mostly missing.
use {id_from_def_id, id_from_node_id, SaveContext};
use crate::{id_from_def_id, id_from_node_id, SaveContext};
use rls_data::{SigElement, Signature};
......@@ -34,14 +34,17 @@
use syntax::print::pprust;
pub fn item_signature(item: &ast::Item, scx: &SaveContext) -> Option<Signature> {
pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
item.make(0, None, scx).ok()
}
pub fn foreign_item_signature(item: &ast::ForeignItem, scx: &SaveContext) -> Option<Signature> {
pub fn foreign_item_signature(
item: &ast::ForeignItem,
scx: &SaveContext<'_, '_>
) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
......@@ -50,7 +53,7 @@ pub fn foreign_item_signature(item: &ast::ForeignItem, scx: &SaveContext) -> Opt
/// Signature for a struct or tuple field declaration.
/// Does not include a trailing comma.
pub fn field_signature(field: &ast::StructField, scx: &SaveContext) -> Option<Signature> {
pub fn field_signature(field: &ast::StructField, scx: &SaveContext<'_, '_>) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
......@@ -58,7 +61,7 @@ pub fn field_signature(field: &ast::StructField, scx: &SaveContext) -> Option<Si
}
/// Does not include a trailing comma.
pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext) -> Option<Signature> {
pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext<'_, '_>) -> Option<Signature> {
if !scx.config.signatures {
return None;
}
......@@ -70,7 +73,7 @@ pub fn method_signature(
ident: ast::Ident,
generics: &ast::Generics,
m: &ast::MethodSig,
scx: &SaveContext,
scx: &SaveContext<'_, '_>,
) -> Option<Signature> {
if !scx.config.signatures {
return None;
......@@ -83,7 +86,7 @@ pub fn assoc_const_signature(
ident: ast::Name,
ty: &ast::Ty,
default: Option<&ast::Expr>,
scx: &SaveContext,
scx: &SaveContext<'_, '_>,
) -> Option<Signature> {
if !scx.config.signatures {
return None;
......@@ -96,7 +99,7 @@ pub fn assoc_type_signature(
ident: ast::Ident,
bounds: Option<&ast::GenericBounds>,
default: Option<&ast::Ty>,
scx: &SaveContext,
scx: &SaveContext<'_, '_>,
) -> Option<Signature> {
if !scx.config.signatures {
return None;
......@@ -104,10 +107,10 @@ pub fn assoc_type_signature(
make_assoc_type_signature(id, ident, bounds, default, scx).ok()
}
type Result = ::std::result::Result<Signature, &'static str>;
type Result = std::result::Result<Signature, &'static str>;
trait Sig {
fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext) -> Result;
fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result;
}
fn extend_sig(
......@@ -155,7 +158,7 @@ fn text_sig(text: String) -> Signature {
}
impl Sig for ast::Ty {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) -> Result {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
let id = Some(self.id);
match self.node {
ast::TyKind::Slice(ref ty) => {
......@@ -227,7 +230,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
if f.unsafety == ast::Unsafety::Unsafe {
text.push_str("unsafe ");
}
if f.abi != ::rustc_target::spec::abi::Abi::Rust {
if f.abi != rustc_target::spec::abi::Abi::Rust {
text.push_str("extern");
text.push_str(&f.abi.to_string());
text.push(' ');
......@@ -317,7 +320,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
}
impl Sig for ast::Item {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) -> Result {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
let id = Some(self.id);
match self.node {
......@@ -381,7 +384,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
if header.unsafety == ast::Unsafety::Unsafe {
text.push_str("unsafe ");
}
if header.abi != ::rustc_target::spec::abi::Abi::Rust {
if header.abi != rustc_target::spec::abi::Abi::Rust {
text.push_str("extern");
text.push_str(&header.abi.to_string());
text.push(' ');
......@@ -571,7 +574,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
}
impl Sig for ast::Path {
fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext) -> Result {
fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
let def = scx.get_path_def(id.ok_or("Missing id for Path")?);
let (name, start, end) = match def {
......@@ -613,7 +616,7 @@ fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext) -> Result {
// This does not cover the where clause, which must be processed separately.
impl Sig for ast::Generics {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) -> Result {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
if self.params.is_empty() {
return Ok(text_sig(String::new()));
}
......@@ -673,7 +676,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
}
impl Sig for ast::StructField {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) -> Result {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
let mut text = String::new();
let mut defs = None;
if let Some(ident) = self.ident {
......@@ -696,7 +699,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
impl Sig for ast::Variant_ {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) -> Result {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
let mut text = self.ident.to_string();
match self.data {
ast::VariantData::Struct(ref fields, id) => {
......@@ -754,7 +757,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
}
impl Sig for ast::ForeignItem {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) -> Result {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
let id = Some(self.id);
match self.node {
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
......@@ -838,7 +841,7 @@ fn name_and_generics(
generics: &ast::Generics,
id: NodeId,
name: ast::Ident,
scx: &SaveContext,
scx: &SaveContext<'_, '_>,
) -> Result {
let name = name.to_string();
let def = SigElement {
......@@ -859,7 +862,7 @@ fn make_assoc_type_signature(
ident: ast::Ident,
bounds: Option<&ast::GenericBounds>,
default: Option<&ast::Ty>,
scx: &SaveContext,
scx: &SaveContext<'_, '_>,
) -> Result {
let mut text = "type ".to_owned();
let name = ident.to_string();
......@@ -893,7 +896,7 @@ fn make_assoc_const_signature(
ident: ast::Name,
ty: &ast::Ty,
default: Option<&ast::Expr>,
scx: &SaveContext,
scx: &SaveContext<'_, '_>,
) -> Result {
let mut text = "const ".to_owned();
let name = ident.to_string();
......@@ -926,7 +929,7 @@ fn make_method_signature(
ident: ast::Ident,
generics: &ast::Generics,
m: &ast::MethodSig,
scx: &SaveContext,
scx: &SaveContext<'_, '_>,
) -> Result {
// FIXME code dup with function signature
let mut text = String::new();
......@@ -939,7 +942,7 @@ fn make_method_signature(
if m.header.unsafety == ast::Unsafety::Unsafe {
text.push_str("unsafe ");
}
if m.header.abi != ::rustc_target::spec::abi::Abi::Rust {
if m.header.abi != rustc_target::spec::abi::Abi::Rust {
text.push_str("extern");
text.push_str(&m.header.abi.to_string());
text.push(' ');
......
use rustc::session::Session;
use generated_code;
use crate::generated_code;
use std::cell::Cell;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册