From 9942012f41620e097d37a6d737584a3790f6b88b Mon Sep 17 00:00:00 2001 From: Chris Manchester Date: Tue, 27 Mar 2018 13:49:06 -0700 Subject: [PATCH 01/32] Run make tests for file resolution --- .../run-make-fulldeps/resolve-rename/Makefile | 7 +++++++ src/test/run-make-fulldeps/resolve-rename/bar.rs | 15 +++++++++++++++ src/test/run-make-fulldeps/resolve-rename/baz.rs | 15 +++++++++++++++ src/test/run-make-fulldeps/resolve-rename/foo.rs | 13 +++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 src/test/run-make-fulldeps/resolve-rename/Makefile create mode 100644 src/test/run-make-fulldeps/resolve-rename/bar.rs create mode 100644 src/test/run-make-fulldeps/resolve-rename/baz.rs create mode 100644 src/test/run-make-fulldeps/resolve-rename/foo.rs diff --git a/src/test/run-make-fulldeps/resolve-rename/Makefile b/src/test/run-make-fulldeps/resolve-rename/Makefile new file mode 100644 index 0000000000000..4b0c36d01b7a8 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/Makefile @@ -0,0 +1,7 @@ +-include ../tools.mk + +all: + $(RUSTC) -C extra-filename=-hash foo.rs + $(RUSTC) bar.rs + mv $(TMPDIR)/libfoo-hash.rlib $(TMPDIR)/libfoo-another-hash.rlib + $(RUSTC) baz.rs diff --git a/src/test/run-make-fulldeps/resolve-rename/bar.rs b/src/test/run-make-fulldeps/resolve-rename/bar.rs new file mode 100644 index 0000000000000..1552b45f2fc16 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/bar.rs @@ -0,0 +1,15 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +extern crate foo; + +pub fn bar() { foo::foo() } diff --git a/src/test/run-make-fulldeps/resolve-rename/baz.rs b/src/test/run-make-fulldeps/resolve-rename/baz.rs new file mode 100644 index 0000000000000..27d801490e425 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/baz.rs @@ -0,0 +1,15 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +extern crate bar; + +pub fn baz() { bar::bar() } diff --git a/src/test/run-make-fulldeps/resolve-rename/foo.rs b/src/test/run-make-fulldeps/resolve-rename/foo.rs new file mode 100644 index 0000000000000..830c289b65f11 --- /dev/null +++ b/src/test/run-make-fulldeps/resolve-rename/foo.rs @@ -0,0 +1,13 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +pub fn foo() {} From d2b9a77bdfd3451f5e55f96d383f97aefb76e97e Mon Sep 17 00:00:00 2001 From: tinaun Date: Sat, 3 Mar 2018 17:07:48 -0500 Subject: [PATCH 02/32] check impl trait first --- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/mod.rs | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index b777ac30920cd..c7cebda95a1c5 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -309,7 +309,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // variables. let method_generics = self.tcx.generics_of(pick.item.def_id); let mut fn_segment = Some((segment, method_generics)); - self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true); + self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true, false); // Create subst for early-bound lifetime parameters, combining // parameters from the type and those from the method. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index db5a458bb8ce4..36ed6864f3af0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4764,9 +4764,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // variables. If the user provided some types, we may still need // to add defaults. If the user provided *too many* types, that's // a problem. - self.check_path_parameter_count(span, &mut type_segment, false); - self.check_path_parameter_count(span, &mut fn_segment, false); - self.check_impl_trait(span, &mut fn_segment); + let supress_mismatch = self.check_impl_trait(span, &mut fn_segment); + self.check_path_parameter_count(span, &mut type_segment, false, supress_mismatch); + self.check_path_parameter_count(span, &mut fn_segment, false, supress_mismatch); let (fn_start, has_self) = match (type_segment, fn_segment) { (_, Some((_, generics))) => { @@ -4919,7 +4919,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_path_parameter_count(&self, span: Span, segment: &mut Option<(&hir::PathSegment, &ty::Generics)>, - is_method_call: bool) { + is_method_call: bool, + supress_mismatch_error: bool) { let (lifetimes, types, infer_types, bindings) = segment.map_or( (&[][..], &[][..], true, &[][..]), |(s, _)| s.parameters.as_ref().map_or( @@ -4959,7 +4960,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // type parameters, we force instantiate_value_path to // use inference variables instead of the provided types. *segment = None; - } else if types.len() < required_len && !infer_types { + } else if types.len() < required_len && !infer_types && !supress_mismatch_error { let expected_text = count_type_params(required_len); let actual_text = count_type_params(types.len()); struct_span_err!(self.tcx.sess, span, E0089, @@ -5026,10 +5027,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Report error if there is an explicit type parameter when using `impl Trait`. fn check_impl_trait(&self, span: Span, - segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) { + segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) + -> bool { use hir::SyntheticTyParamKind::*; - segment.map(|(path_segment, generics)| { + let segment = segment.map(|(path_segment, generics)| { let explicit = !path_segment.infer_types; let impl_trait = generics.types.iter() .any(|ty_param| { @@ -5050,7 +5052,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.emit(); } + + impl_trait }); + + segment.unwrap_or(false) } // Resolves `typ` by a single level if `typ` is a type variable. From 97e0dc330fb4dfc3fc5161fbba1f0b4193d80bc9 Mon Sep 17 00:00:00 2001 From: tinaun Date: Sat, 3 Mar 2018 17:32:47 -0500 Subject: [PATCH 03/32] added test --- .../ui/impl-trait/universal-issue-48703.rs | 19 +++++++++++++++++++ .../impl-trait/universal-issue-48703.stderr | 9 +++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/ui/impl-trait/universal-issue-48703.rs create mode 100644 src/test/ui/impl-trait/universal-issue-48703.stderr diff --git a/src/test/ui/impl-trait/universal-issue-48703.rs b/src/test/ui/impl-trait/universal-issue-48703.rs new file mode 100644 index 0000000000000..e017b37b7b733 --- /dev/null +++ b/src/test/ui/impl-trait/universal-issue-48703.rs @@ -0,0 +1,19 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(universal_impl_trait)] + +use std::fmt::Debug; + +fn foo(x: impl Debug) { } + +fn main() { + foo::('a'); //~ ERROR cannot provide explicit type parameters +} diff --git a/src/test/ui/impl-trait/universal-issue-48703.stderr b/src/test/ui/impl-trait/universal-issue-48703.stderr new file mode 100644 index 0000000000000..ea509684f9efc --- /dev/null +++ b/src/test/ui/impl-trait/universal-issue-48703.stderr @@ -0,0 +1,9 @@ +error[E0632]: cannot provide explicit type parameters when `impl Trait` is used in argument position. + --> $DIR/universal-issue-48703.rs:18:5 + | +LL | foo::('a'); //~ ERROR cannot provide explicit type parameters + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0632`. From bd8154784ea205d78c30c18a5908e97718f7a489 Mon Sep 17 00:00:00 2001 From: Chris Manchester Date: Tue, 13 Mar 2018 11:58:53 -0700 Subject: [PATCH 04/32] Take the original extra-filename passed to a crate into account when resolving it as a dependency. Fixes #46816 --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/ty/maps/config.rs | 6 ++++++ src/librustc/ty/maps/mod.rs | 1 + src/librustc/ty/maps/plumbing.rs | 1 + src/librustc_metadata/creader.rs | 22 +++++++++++++------- src/librustc_metadata/cstore_impl.rs | 3 +++ src/librustc_metadata/encoder.rs | 2 ++ src/librustc_metadata/locator.rs | 30 ++++++++++++++++++++++------ src/librustc_metadata/schema.rs | 5 ++++- 9 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 42cda6a05a1a7..d1f3736556c5d 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -589,6 +589,7 @@ define_dep_nodes!( <'tcx> [input] CrateDisambiguator(CrateNum), [input] CrateHash(CrateNum), [input] OriginalCrateName(CrateNum), + [input] ExtraFileName(CrateNum), [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId }, [] AllTraitImplementations(CrateNum), diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index bb9467305e335..a08cd57b1f7e2 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -466,6 +466,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::original_crate_name<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::extra_filename<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up the extra filename for a crate") + } +} + impl<'tcx> QueryDescription<'tcx> for queries::implementations_of_trait<'tcx> { fn describe(_tcx: TyCtxt, _: (CrateNum, DefId)) -> String { format!("looking up implementations of a trait in a crate") diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 2bfb687032923..8651619705b42 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -328,6 +328,7 @@ define_maps! { <'tcx> [] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator, [] fn crate_hash: CrateHash(CrateNum) -> Svh, [] fn original_crate_name: OriginalCrateName(CrateNum) -> Symbol, + [] fn extra_filename: ExtraFileName(CrateNum) -> String, [] fn implementations_of_trait: implementations_of_trait_node((CrateNum, DefId)) -> Lrc>, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 50a19526ba8c4..fa69eb8e5bc66 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -881,6 +881,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); } DepKind::CrateHash => { force!(crate_hash, krate!()); } DepKind::OriginalCrateName => { force!(original_crate_name, krate!()); } + DepKind::ExtraFileName => { force!(extra_filename, krate!()); } DepKind::AllTraitImplementations => { force!(all_trait_implementations, krate!()); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 13ebb5f61660f..86f495c5fac3a 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -262,6 +262,7 @@ impl<'a> CrateLoader<'a> { ident: Symbol, name: Symbol, hash: Option<&Svh>, + extra_filename: Option<&str>, span: Span, path_kind: PathKind, mut dep_kind: DepKind) @@ -277,6 +278,7 @@ impl<'a> CrateLoader<'a> { ident, crate_name: name, hash: hash.map(|a| &*a), + extra_filename: extra_filename, filesearch: self.sess.target_filesearch(path_kind), target: &self.sess.target.target, triple: &self.sess.opts.target_triple, @@ -409,7 +411,8 @@ impl<'a> CrateLoader<'a> { ::std::iter::once(krate).chain(crate_root.crate_deps .decode(metadata) .map(|dep| { - debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); + info!("resolving dep crate {} hash: `{}` extra filename: `{}`", dep.name, dep.hash, + dep.extra_filename); if dep.kind == DepKind::UnexportedMacrosOnly { return krate; } @@ -418,7 +421,8 @@ impl<'a> CrateLoader<'a> { _ => dep.kind, }; let (local_cnum, ..) = self.resolve_crate( - root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind, + root, dep.name, dep.name, Some(&dep.hash), Some(&dep.extra_filename), span, + PathKind::Dependency, dep_kind, ); local_cnum })).collect() @@ -437,6 +441,7 @@ impl<'a> CrateLoader<'a> { ident: orig_name, crate_name: rename, hash: None, + extra_filename: None, filesearch: self.sess.host_filesearch(PathKind::Crate), target: &self.sess.host, triple: &host_triple, @@ -664,7 +669,7 @@ impl<'a> CrateLoader<'a> { let dep_kind = DepKind::Implicit; let (cnum, data) = - self.resolve_crate(&None, name, name, None, DUMMY_SP, PathKind::Crate, dep_kind); + self.resolve_crate(&None, name, name, None, None, DUMMY_SP, PathKind::Crate, dep_kind); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. @@ -771,7 +776,7 @@ impl<'a> CrateLoader<'a> { let symbol = Symbol::intern(name); let dep_kind = DepKind::Explicit; let (_, data) = - self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, + self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, PathKind::Crate, dep_kind); // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime @@ -794,7 +799,7 @@ impl<'a> CrateLoader<'a> { let symbol = Symbol::intern("profiler_builtins"); let dep_kind = DepKind::Implicit; let (_, data) = - self.resolve_crate(&None, symbol, symbol, None, DUMMY_SP, + self.resolve_crate(&None, symbol, symbol, None, None, DUMMY_SP, PathKind::Crate, dep_kind); // Sanity check the loaded crate to ensure it is indeed a profiler runtime @@ -909,6 +914,7 @@ impl<'a> CrateLoader<'a> { name, name, None, + None, DUMMY_SP, PathKind::Crate, DepKind::Implicit); @@ -1059,7 +1065,8 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { }; let (cnum, ..) = self.resolve_crate( - &None, item.ident.name, orig_name, None, item.span, PathKind::Crate, dep_kind, + &None, item.ident.name, orig_name, None, None, + item.span, PathKind::Crate, dep_kind, ); let def_id = definitions.opt_local_def_id(item.id).unwrap(); @@ -1074,6 +1081,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { } fn resolve_crate_from_path(&mut self, name: Symbol, span: Span) -> CrateNum { - self.resolve_crate(&None, name, name, None, span, PathKind::Crate, DepKind::Explicit).0 + self.resolve_crate(&None, name, name, None, None, span, PathKind::Crate, + DepKind::Explicit).0 } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 5fd8ebaa9b4a6..f63edf07fa8ba 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -213,6 +213,9 @@ provide! { <'tcx> tcx, def_id, other, cdata, crate_hash => { cdata.hash() } original_crate_name => { cdata.name() } + extra_filename => { cdata.root.extra_filename.clone() } + + implementations_of_trait => { let mut result = vec![]; let filter = Some(other); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 39de1ec852ec4..0da6fc5b9eda1 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -462,6 +462,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let has_global_allocator = tcx.sess.has_global_allocator.get(); let root = self.lazy(&CrateRoot { name: tcx.crate_name(LOCAL_CRATE), + extra_filename: tcx.sess.opts.cg.extra_filename.clone(), triple: tcx.sess.opts.target_triple.clone(), hash: link_meta.crate_hash, disambiguator: tcx.sess.local_crate_disambiguator(), @@ -1357,6 +1358,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { name: self.tcx.original_crate_name(cnum), hash: self.tcx.crate_hash(cnum), kind: self.tcx.dep_kind(cnum), + extra_filename: self.tcx.extra_filename(cnum), }; (cnum, dep) }) diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 41e10b4755d01..f553c55ae56fa 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -83,7 +83,10 @@ //! 1. Does the filename match an rlib/dylib pattern? That is to say, does the //! filename have the right prefix/suffix? //! 2. Does the filename have the right prefix for the crate name being queried? -//! This is filtering for files like `libfoo*.rlib` and such. +//! This is filtering for files like `libfoo*.rlib` and such. If the crate +//! we're looking for was originally compiled with -C extra-filename, the +//! extra filename will be included in this prefix to reduce reading +//! metadata from crates that would otherwise share our prefix. //! 3. Is the file an actual rust library? This is done by loading the metadata //! from the library and making sure it's actually there. //! 4. Does the name in the metadata agree with the name of the library? @@ -236,6 +239,7 @@ use syntax_pos::Span; use rustc_back::target::{Target, TargetTriple}; use std::cmp; +use std::collections::HashSet; use std::fmt; use std::fs; use std::io::{self, Read}; @@ -256,6 +260,7 @@ pub struct Context<'a> { pub ident: Symbol, pub crate_name: Symbol, pub hash: Option<&'a Svh>, + pub extra_filename: Option<&'a str>, // points to either self.sess.target.target or self.sess.host, must match triple pub target: &'a Target, pub triple: &'a TargetTriple, @@ -303,7 +308,12 @@ impl CratePaths { impl<'a> Context<'a> { pub fn maybe_load_library_crate(&mut self) -> Option { - self.find_library_crate() + let mut seen_paths = HashSet::new(); + match self.extra_filename { + Some(s) => self.find_library_crate(s, &mut seen_paths) + .or_else(|| self.find_library_crate("", &mut seen_paths)), + None => self.find_library_crate("", &mut seen_paths) + } } pub fn report_errs(&mut self) -> ! { @@ -419,7 +429,10 @@ impl<'a> Context<'a> { unreachable!(); } - fn find_library_crate(&mut self) -> Option { + fn find_library_crate(&mut self, + extra_prefix: &str, + seen_paths: &mut HashSet) + -> Option { // If an SVH is specified, then this is a transitive dependency that // must be loaded via -L plus some filtering. if self.hash.is_none() { @@ -434,9 +447,9 @@ impl<'a> Context<'a> { let staticpair = self.staticlibname(); // want: crate_name.dir_part() + prefix + crate_name.file_part + "-" - let dylib_prefix = format!("{}{}", dypair.0, self.crate_name); - let rlib_prefix = format!("lib{}", self.crate_name); - let staticlib_prefix = format!("{}{}", staticpair.0, self.crate_name); + let dylib_prefix = format!("{}{}{}", dypair.0, self.crate_name, extra_prefix); + let rlib_prefix = format!("lib{}{}", self.crate_name, extra_prefix); + let staticlib_prefix = format!("{}{}{}", staticpair.0, self.crate_name, extra_prefix); let mut candidates = FxHashMap(); let mut staticlibs = vec![]; @@ -476,6 +489,7 @@ impl<'a> Context<'a> { } return FileDoesntMatch; }; + info!("lib candidate: {}", path.display()); let hash_str = hash.to_string(); @@ -484,6 +498,10 @@ impl<'a> Context<'a> { let (ref mut rlibs, ref mut rmetas, ref mut dylibs) = *slot; fs::canonicalize(path) .map(|p| { + if seen_paths.contains(&p) { + return FileDoesntMatch + }; + seen_paths.insert(p.clone()); match found_kind { CrateFlavor::Rlib => { rlibs.insert(p, kind); } CrateFlavor::Rmeta => { rmetas.insert(p, kind); } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d04a4001c5023..a7ee0e7e9a961 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -188,6 +188,7 @@ pub enum LazyState { pub struct CrateRoot { pub name: Symbol, pub triple: TargetTriple, + pub extra_filename: String, pub hash: hir::svh::Svh, pub disambiguator: CrateDisambiguator, pub panic_strategy: PanicStrategy, @@ -216,12 +217,14 @@ pub struct CrateDep { pub name: ast::Name, pub hash: hir::svh::Svh, pub kind: DepKind, + pub extra_filename: String, } impl_stable_hash_for!(struct CrateDep { name, hash, - kind + kind, + extra_filename }); #[derive(RustcEncodable, RustcDecodable)] From cd09c2b2abf2c03b80d0d48c9828004ade64a8f8 Mon Sep 17 00:00:00 2001 From: nabijaczleweli Date: Tue, 27 Mar 2018 23:09:35 +0200 Subject: [PATCH 05/32] Flush executables to disk after linkage A problem caused by not doing so in Chrome has been reported here: https://randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/amp/ File::sync_all() calls FlushFileBuffers() down the line, causing potentially unflushed buffers on high I/O-load systems to flush and prevent nasty non-reproducible bugs. The force-flush is only done on Windows and if the linker exited successfully Closes #48545 --- src/librustc_trans/back/link.rs | 36 ++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 75ba83a7c620a..33f6ce9975e53 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -692,7 +692,7 @@ fn link_natively(sess: &Session, loop { i += 1; prog = time(sess, "running linker", || { - exec_linker(sess, &mut cmd, tmpdir) + exec_linker(sess, &mut cmd, out_filename, tmpdir) }); let output = match prog { Ok(ref output) => output, @@ -819,7 +819,7 @@ fn link_natively(sess: &Session, } } -fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path) +fn exec_linker(sess: &Session, cmd: &mut Command, out_filename: &Path, tmpdir: &Path) -> io::Result { // When attempting to spawn the linker we run a risk of blowing out the @@ -867,7 +867,37 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path) fs::write(&file, &bytes)?; cmd2.arg(format!("@{}", file.display())); info!("invoking linker {:?}", cmd2); - return cmd2.output(); + let output = cmd2.output(); + flush_linked_file(&output, out_filename)?; + return output; + + #[cfg(unix)] + fn flush_linked_file(_: &io::Result, _: &Path) -> io::Result<()> { + Ok(()) + } + + #[cfg(windows)] + fn flush_linked_file(command_output: &io::Result, out_filename: &Path) + -> io::Result<()> + { + // On Windows, under high I/O load, output buffers are sometimes not flushed, + // even long after process exit, causing nasty, non-reproducible output bugs. + // + // File::sync_all() calls FlushFileBuffers() down the line, which solves the problem. + // + // А full writeup of the original Chrome bug can be found at + // randomascii.wordpress.com/2018/02/25/compiler-bug-linker-bug-windows-kernel-bug/amp + + if let &Ok(ref out) = command_output { + if out.status.success() { + if let Ok(of) = fs::File::open(out_filename) { + of.sync_all()?; + } + } + } + + Ok(()) + } #[cfg(unix)] fn command_line_too_big(err: &io::Error) -> bool { From 3787106be6e3a9be377aecc8600a2e57aa1afb58 Mon Sep 17 00:00:00 2001 From: nabijaczleweli Date: Thu, 29 Mar 2018 17:50:57 +0200 Subject: [PATCH 06/32] Also protect first attempt --- src/librustc_trans/back/link.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 33f6ce9975e53..46defb9e73343 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -833,7 +833,11 @@ fn exec_linker(sess: &Session, cmd: &mut Command, out_filename: &Path, tmpdir: & // there instead of looking at the command line. if !cmd.very_likely_to_exceed_some_spawn_limit() { match cmd.command().stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() { - Ok(child) => return child.wait_with_output(), + Ok(child) => { + let output = child.wait_with_output(); + flush_linked_file(&output, out_filename)?; + return output; + } Err(ref e) if command_line_too_big(e) => { info!("command line to linker was too big: {}", e); } From e1d3c471d75bbc4360eee17178ccb32dce348542 Mon Sep 17 00:00:00 2001 From: nabijaczleweli Date: Sat, 31 Mar 2018 19:12:29 +0200 Subject: [PATCH 07/32] Open the file as write before trying to flush it This should be enough and shouldn't require append(true) since we're not explicitly writing anything so we're not flushing it so we've no risk of overwriting it --- src/librustc_trans/back/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 46defb9e73343..5da4667af910c 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -894,7 +894,7 @@ fn exec_linker(sess: &Session, cmd: &mut Command, out_filename: &Path, tmpdir: & if let &Ok(ref out) = command_output { if out.status.success() { - if let Ok(of) = fs::File::open(out_filename) { + if let Ok(of) = fs::OpenOptions::new().write(true).open(out_filename) { of.sync_all()?; } } From 68b54a5f4368ba1a66ae7d330bb95a8d6eb08c3c Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 1 Apr 2018 18:50:21 +0200 Subject: [PATCH 08/32] add a dist-thumb builder to build rust-std for the THUMB targets the rust-std component only contains the core and compiler-builtins (+c +mem) crates cc #49382 --- src/bootstrap/compile.rs | 75 +++++++++++---------- src/bootstrap/config.rs | 1 + src/bootstrap/dist.rs | 7 +- src/bootstrap/lib.rs | 6 ++ src/bootstrap/sanity.rs | 13 ++++ src/ci/docker/dist-various-3/Dockerfile | 19 ++++++ src/rustc/compiler_builtins_shim/Cargo.toml | 1 + 7 files changed, 87 insertions(+), 35 deletions(-) create mode 100644 src/ci/docker/dist-various-3/Dockerfile diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 9f33935b6e933..eaf4ab272c68e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -140,48 +140,55 @@ pub fn std_cargo(build: &Builder, compiler: &Compiler, target: Interned, cargo: &mut Command) { - let mut features = build.std_features(); - if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } - // When doing a local rebuild we tell cargo that we're stage1 rather than - // stage0. This works fine if the local rust and being-built rust have the - // same view of what the default allocator is, but fails otherwise. Since - // we don't have a way to express an allocator preference yet, work - // around the issue in the case of a local rebuild with jemalloc disabled. - if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { - features.push_str(" force_alloc_system"); - } + if build.no_std(target) == Some(true) { + // for no-std targets we only compile core and compiler-builtins + cargo.arg("--features").arg("c mem") + .arg("--manifest-path") + .arg(build.src.join("src/rustc/compiler_builtins_shim/Cargo.toml")); + } else { + let mut features = build.std_features(); + + // When doing a local rebuild we tell cargo that we're stage1 rather than + // stage0. This works fine if the local rust and being-built rust have the + // same view of what the default allocator is, but fails otherwise. Since + // we don't have a way to express an allocator preference yet, work + // around the issue in the case of a local rebuild with jemalloc disabled. + if compiler.stage == 0 && build.local_rebuild && !build.config.use_jemalloc { + features.push_str(" force_alloc_system"); + } - if compiler.stage != 0 && build.config.sanitizers { - // This variable is used by the sanitizer runtime crates, e.g. - // rustc_lsan, to build the sanitizer runtime from C code - // When this variable is missing, those crates won't compile the C code, - // so we don't set this variable during stage0 where llvm-config is - // missing - // We also only build the runtimes when --enable-sanitizers (or its - // config.toml equivalent) is used - let llvm_config = build.ensure(native::Llvm { - target: build.config.build, - emscripten: false, - }); - cargo.env("LLVM_CONFIG", llvm_config); - } + if compiler.stage != 0 && build.config.sanitizers { + // This variable is used by the sanitizer runtime crates, e.g. + // rustc_lsan, to build the sanitizer runtime from C code + // When this variable is missing, those crates won't compile the C code, + // so we don't set this variable during stage0 where llvm-config is + // missing + // We also only build the runtimes when --enable-sanitizers (or its + // config.toml equivalent) is used + let llvm_config = build.ensure(native::Llvm { + target: build.config.build, + emscripten: false, + }); + cargo.env("LLVM_CONFIG", llvm_config); + } - cargo.arg("--features").arg(features) - .arg("--manifest-path") - .arg(build.src.join("src/libstd/Cargo.toml")); + cargo.arg("--features").arg(features) + .arg("--manifest-path") + .arg(build.src.join("src/libstd/Cargo.toml")); - if let Some(target) = build.config.target_config.get(&target) { - if let Some(ref jemalloc) = target.jemalloc { - cargo.env("JEMALLOC_OVERRIDE", jemalloc); + if let Some(target) = build.config.target_config.get(&target) { + if let Some(ref jemalloc) = target.jemalloc { + cargo.env("JEMALLOC_OVERRIDE", jemalloc); + } } - } - if target.contains("musl") { - if let Some(p) = build.musl_root(target) { - cargo.env("MUSL_ROOT", p); + if target.contains("musl") { + if let Some(p) = build.musl_root(target) { + cargo.env("MUSL_ROOT", p); + } } } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 33850debd3bdb..81b60364ebba1 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -159,6 +159,7 @@ pub struct Target { pub crt_static: Option, pub musl_root: Option, pub qemu_rootfs: Option, + pub no_std: bool, } /// Structure of the `config.toml` file that configuration is read from. diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 23b7b265a94be..32257fefbf97b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -649,7 +649,12 @@ impl Step for Std { if build.hosts.iter().any(|t| t == target) { builder.ensure(compile::Rustc { compiler, target }); } else { - builder.ensure(compile::Test { compiler, target }); + if build.no_std(target) == Some(true) { + // the `test` doesn't compile for no-std targets + builder.ensure(compile::Std { compiler, target }); + } else { + builder.ensure(compile::Test { compiler, target }); + } } let image = tmpdir(build).join(format!("{}-{}-image", name, target)); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 833faf3618d67..d1765b3def998 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -709,6 +709,12 @@ impl Build { .map(|p| &**p) } + /// Returns true if this is a no-std `target`, if defined + fn no_std(&self, target: Interned) -> Option { + self.config.target_config.get(&target) + .map(|t| t.no_std) + } + /// Returns whether the target will be tested using the `remote-test-client` /// and `remote-test-server` binaries. fn remote_tested(&self, target: Interned) -> bool { diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 5184cca653c4b..cd67f1eb46414 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -169,6 +169,19 @@ pub fn check(build: &mut Build) { panic!("the iOS target is only supported on macOS"); } + if target.starts_with("thumbv") { + if build.no_std(*target).is_none() { + let target = build.config.target_config.entry(target.clone()) + .or_insert(Default::default()); + + target.no_std = true; + } + + if build.no_std(*target) == Some(false) { + panic!("All the THUMB targets are no-std targets") + } + } + // Make sure musl-root is valid if target.contains("musl") { // If this is a native target (host is also musl) and no musl-root is given, diff --git a/src/ci/docker/dist-various-3/Dockerfile b/src/ci/docker/dist-various-3/Dockerfile new file mode 100644 index 0000000000000..06c80982f3cd2 --- /dev/null +++ b/src/ci/docker/dist-various-3/Dockerfile @@ -0,0 +1,19 @@ +FROM ubuntu:17.10 + +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +RUN apt-get build-dep -y clang llvm && apt-get install -y --no-install-recommends \ + gcc-arm-none-eabi \ + libnewlib-arm-none-eabi + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV TARGETS=thumbv6m-none-eabi +ENV TARGETS=$TARGETS,thumbv7m-none-eabi +ENV TARGETS=$TARGETS,thumbv7em-none-eabi +ENV TARGETS=$TARGETS,thumbv7em-none-eabihf + +ENV RUST_CONFIGURE_ARGS --disable-docs +ENV SCRIPT python2.7 ../x.py dist --target $TARGETS diff --git a/src/rustc/compiler_builtins_shim/Cargo.toml b/src/rustc/compiler_builtins_shim/Cargo.toml index 608e5f5f36d02..7d8423ca84eb4 100644 --- a/src/rustc/compiler_builtins_shim/Cargo.toml +++ b/src/rustc/compiler_builtins_shim/Cargo.toml @@ -35,5 +35,6 @@ cc = "1.0.1" [features] c = [] default = ["c", "rustbuild", "compiler-builtins"] +mem = [] rustbuild = [] compiler-builtins = [] From 2a99c027eb95c471daf50815ec30504c42179300 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 1 Apr 2018 18:56:13 +0200 Subject: [PATCH 09/32] add new image to .travis.yml --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 091a5abdaa216..a67c6c79bbdf8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -116,6 +116,8 @@ matrix: if: branch = auto - env: IMAGE=dist-various-2 DEPLOY=1 if: branch = auto + - env: IMAGE=dist-various-3 DEPLOY=1 + if: branch = auto - env: IMAGE=dist-aarch64-linux DEPLOY=1 if: branch = auto - env: IMAGE=dist-android DEPLOY=1 From cc939ac345091327b23f807b7d1f6a7c75c03f36 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Fri, 30 Mar 2018 16:10:47 +0900 Subject: [PATCH 10/32] Add vec![ptr::null{,_mut}(); n] optimization, like vec![0; n] vec![0; n], via implementations of SpecFromElem, has an optimization that uses with_capacity_zeroed instead of with_capacity, which will use calloc instead of malloc, and avoid an extra memset. This adds the same optimization for vec![ptr::null(); n] and vec![ptr::null_mut(); n], assuming their bit value is 0 (which is true on all currently supported platforms). This does so by adding an intermediate trait IsZero, which looks very much like nonzero::Zeroable, but that one is on the way out, and doesn't apply to pointers anyways. Adding such a trait allows to avoid repeating the logic using with_capacity_zeroed or with_capacity, or making the macro more complex to support generics. --- src/liballoc/vec.rs | 79 ++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 2eedb964f88ba..512c74d9d7704 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1567,40 +1567,67 @@ impl SpecFromElem for u8 { } } -macro_rules! impl_spec_from_elem { +impl SpecFromElem for T { + #[inline] + fn from_elem(elem: T, n: usize) -> Vec { + if elem.is_zero() { + return Vec { + buf: RawVec::with_capacity_zeroed(n), + len: n, + } + } + let mut v = Vec::with_capacity(n); + v.extend_with(n, ExtendElement(elem)); + v + } +} + +unsafe trait IsZero { + /// Whether this value is zero + fn is_zero(&self) -> bool; +} + +macro_rules! impl_is_zero { ($t: ty, $is_zero: expr) => { - impl SpecFromElem for $t { + unsafe impl IsZero for $t { #[inline] - fn from_elem(elem: $t, n: usize) -> Vec<$t> { - if $is_zero(elem) { - return Vec { - buf: RawVec::with_capacity_zeroed(n), - len: n, - } - } - let mut v = Vec::with_capacity(n); - v.extend_with(n, ExtendElement(elem)); - v + fn is_zero(&self) -> bool { + $is_zero(*self) } } - }; + } } -impl_spec_from_elem!(i8, |x| x == 0); -impl_spec_from_elem!(i16, |x| x == 0); -impl_spec_from_elem!(i32, |x| x == 0); -impl_spec_from_elem!(i64, |x| x == 0); -impl_spec_from_elem!(i128, |x| x == 0); -impl_spec_from_elem!(isize, |x| x == 0); +impl_is_zero!(i8, |x| x == 0); +impl_is_zero!(i16, |x| x == 0); +impl_is_zero!(i32, |x| x == 0); +impl_is_zero!(i64, |x| x == 0); +impl_is_zero!(i128, |x| x == 0); +impl_is_zero!(isize, |x| x == 0); -impl_spec_from_elem!(u16, |x| x == 0); -impl_spec_from_elem!(u32, |x| x == 0); -impl_spec_from_elem!(u64, |x| x == 0); -impl_spec_from_elem!(u128, |x| x == 0); -impl_spec_from_elem!(usize, |x| x == 0); +impl_is_zero!(u16, |x| x == 0); +impl_is_zero!(u32, |x| x == 0); +impl_is_zero!(u64, |x| x == 0); +impl_is_zero!(u128, |x| x == 0); +impl_is_zero!(usize, |x| x == 0); + +impl_is_zero!(f32, |x: f32| x.to_bits() == 0); +impl_is_zero!(f64, |x: f64| x.to_bits() == 0); + +unsafe impl IsZero for *const T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} + +unsafe impl IsZero for *mut T { + #[inline] + fn is_zero(&self) -> bool { + (*self).is_null() + } +} -impl_spec_from_elem!(f32, |x: f32| x.to_bits() == 0); -impl_spec_from_elem!(f64, |x: f64| x.to_bits() == 0); //////////////////////////////////////////////////////////////////////////////// // Common trait implementations for Vec From 0df837f79289819f9b671b67d4e63dfe5c80d419 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Mon, 2 Apr 2018 10:44:38 +0900 Subject: [PATCH 11/32] Add vec!['\0'; n] optimization, like vec![0; n] Similarly to vec![ptr::null{,_mut}(); n] in previous change, this adds the optimization for vec!['\0'; n]. --- src/liballoc/vec.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 512c74d9d7704..515b79e5acdc7 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1611,6 +1611,8 @@ impl_is_zero!(u64, |x| x == 0); impl_is_zero!(u128, |x| x == 0); impl_is_zero!(usize, |x| x == 0); +impl_is_zero!(char, |x| x == '\0'); + impl_is_zero!(f32, |x: f32| x.to_bits() == 0); impl_is_zero!(f64, |x: f64| x.to_bits() == 0); From f886518c3a2daa3e1239b76bbc0f7a92792d5465 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 29 Mar 2018 14:59:13 -0700 Subject: [PATCH 12/32] std: Minimize size of panicking on wasm This commit applies a few code size optimizations for the wasm target to the standard library, namely around panics. We notably know that in most configurations it's impossible for us to print anything in wasm32-unknown-unknown so we can skip larger portions of panicking that are otherwise simply informative. This allows us to get quite a nice size reduction. Finally we can also tweak where the allocation happens for the `Box` that we panic with. By only allocating once unwinding starts we can reduce the size of a panicking wasm module from 44k to 350 bytes. --- src/ci/docker/wasm32-unknown/Dockerfile | 6 ++ src/libcore/panic.rs | 10 +++ src/libpanic_abort/lib.rs | 2 +- src/libpanic_unwind/lib.rs | 12 +-- src/libstd/lib.rs | 1 + src/libstd/panicking.rs | 88 ++++++++++++++++----- src/libstd/sys/cloudabi/stdio.rs | 4 + src/libstd/sys/redox/stdio.rs | 4 + src/libstd/sys/unix/stdio.rs | 4 + src/libstd/sys/wasm/rwlock.rs | 4 +- src/libstd/sys/wasm/stdio.rs | 4 + src/libstd/sys/windows/stdio.rs | 4 + src/libstd/sys_common/backtrace.rs | 13 ++- src/libstd/sys_common/mod.rs | 14 +++- src/libstd/sys_common/thread_local.rs | 4 +- src/libstd/sys_common/util.rs | 5 +- src/libstd/thread/local.rs | 41 +++++++++- src/libstd/thread/mod.rs | 3 + src/test/run-make/wasm-panic-small/Makefile | 11 +++ src/test/run-make/wasm-panic-small/foo.rs | 16 ++++ 20 files changed, 205 insertions(+), 45 deletions(-) create mode 100644 src/test/run-make/wasm-panic-small/Makefile create mode 100644 src/test/run-make/wasm-panic-small/foo.rs diff --git a/src/ci/docker/wasm32-unknown/Dockerfile b/src/ci/docker/wasm32-unknown/Dockerfile index 6c0ec1ad9d4e1..28d11064c6bba 100644 --- a/src/ci/docker/wasm32-unknown/Dockerfile +++ b/src/ci/docker/wasm32-unknown/Dockerfile @@ -25,6 +25,12 @@ ENV RUST_CONFIGURE_ARGS \ --set build.nodejs=/node-v9.2.0-linux-x64/bin/node \ --set rust.lld +# Some run-make tests have assertions about code size, and enabling debug +# assertions in libstd causes the binary to be much bigger than it would +# otherwise normally be. We already test libstd with debug assertions in lots of +# other contexts as well +ENV NO_DEBUG_ASSERTIONS=1 + ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \ src/test/run-make \ src/test/ui \ diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index 4e72eaa57c73e..212139f1f7a41 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -249,3 +249,13 @@ impl<'a> fmt::Display for Location<'a> { write!(formatter, "{}:{}:{}", self.file, self.line, self.col) } } + +/// An internal trait used by libstd to pass data from libstd to `panic_unwind` +/// and other panic runtimes. Not intended to be stabilized any time soon, do +/// not use. +#[unstable(feature = "std_internals", issue = "0")] +#[doc(hidden)] +pub unsafe trait BoxMeUp { + fn box_me_up(&mut self) -> *mut (Any + Send); + fn get(&self) -> &(Any + Send); +} diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 5f768ef4399e8..a1c4555d0b0e9 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -53,7 +53,7 @@ pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8), // now hopefully. #[no_mangle] #[rustc_std_internal_symbol] -pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 { +pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 { abort(); #[cfg(any(unix, target_os = "cloudabi"))] diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index a5cebc3e4d04b..cd7a643140239 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -30,6 +30,7 @@ issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] #![deny(warnings)] +#![feature(allocator_api)] #![feature(alloc)] #![feature(core_intrinsics)] #![feature(lang_items)] @@ -37,6 +38,7 @@ #![feature(panic_unwind)] #![feature(raw)] #![feature(staged_api)] +#![feature(std_internals)] #![feature(unwind_attributes)] #![cfg_attr(target_env = "msvc", feature(raw))] @@ -48,9 +50,11 @@ extern crate libc; #[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))] extern crate unwind; +use alloc::boxed::Box; use core::intrinsics; use core::mem; use core::raw; +use core::panic::BoxMeUp; // Rust runtime's startup objects depend on these symbols, so make them public. #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] @@ -114,9 +118,7 @@ pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8), #[no_mangle] #[cfg_attr(stage0, unwind)] #[cfg_attr(not(stage0), unwind(allowed))] -pub unsafe extern "C" fn __rust_start_panic(data: usize, vtable: usize) -> u32 { - imp::panic(mem::transmute(raw::TraitObject { - data: data as *mut (), - vtable: vtable as *mut (), - })) +pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 { + let payload = payload as *mut &mut BoxMeUp; + imp::panic(Box::from_raw((*payload).box_me_up())) } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 68d3b946d9ef5..d2b32b0f037e0 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -297,6 +297,7 @@ #![feature(rand)] #![feature(raw)] #![feature(rustc_attrs)] +#![feature(std_internals)] #![feature(stdsimd)] #![feature(shrink_to)] #![feature(slice_bytes)] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 454ac64735c67..e5d30e81a8d76 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -17,6 +17,8 @@ //! * Executing a panic up to doing the actual implementation //! * Shims around "try" +use core::panic::BoxMeUp; + use io::prelude::*; use any::Any; @@ -27,7 +29,7 @@ use intrinsics; use mem; use ptr; use raw; -use sys::stdio::Stderr; +use sys::stdio::{Stderr, stderr_prints_nothing}; use sys_common::rwlock::RWLock; use sys_common::thread_info; use sys_common::util; @@ -57,7 +59,7 @@ extern { vtable_ptr: *mut usize) -> u32; #[cfg_attr(stage0, unwind)] #[cfg_attr(not(stage0), unwind(allowed))] - fn __rust_start_panic(data: usize, vtable: usize) -> u32; + fn __rust_start_panic(payload: usize) -> u32; } #[derive(Copy, Clone)] @@ -164,6 +166,12 @@ fn default_hook(info: &PanicInfo) { #[cfg(feature = "backtrace")] use sys_common::backtrace; + // Some platforms know that printing to stderr won't ever actually print + // anything, and if that's the case we can skip everything below. + if stderr_prints_nothing() { + return + } + // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. #[cfg(feature = "backtrace")] @@ -213,15 +221,15 @@ fn default_hook(info: &PanicInfo) { let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take()); match (prev, err.as_mut()) { - (Some(mut stderr), _) => { - write(&mut *stderr); - let mut s = Some(stderr); - LOCAL_STDERR.with(|slot| { - *slot.borrow_mut() = s.take(); - }); - } - (None, Some(ref mut err)) => { write(err) } - _ => {} + (Some(mut stderr), _) => { + write(&mut *stderr); + let mut s = Some(stderr); + LOCAL_STDERR.with(|slot| { + *slot.borrow_mut() = s.take(); + }); + } + (None, Some(ref mut err)) => { write(err) } + _ => {} } } @@ -346,7 +354,7 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments, let mut s = String::new(); let _ = s.write_fmt(*msg); - rust_panic_with_hook(Box::new(s), Some(msg), file_line_col) + rust_panic_with_hook(&mut PanicPayload::new(s), Some(msg), file_line_col) } /// This is the entry point of panicking for panic!() and assert!(). @@ -362,7 +370,34 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 // be performed in the parent of this thread instead of the thread that's // panicking. - rust_panic_with_hook(Box::new(msg), None, file_line_col) + rust_panic_with_hook(&mut PanicPayload::new(msg), None, file_line_col) +} + +struct PanicPayload { + inner: Option, +} + +impl PanicPayload { + fn new(inner: A) -> PanicPayload { + PanicPayload { inner: Some(inner) } + } +} + +unsafe impl BoxMeUp for PanicPayload { + fn box_me_up(&mut self) -> *mut (Any + Send) { + let data = match self.inner.take() { + Some(a) => Box::new(a) as Box, + None => Box::new(()), + }; + Box::into_raw(data) + } + + fn get(&self) -> &(Any + Send) { + match self.inner { + Some(ref a) => a, + None => &(), + } + } } /// Executes the primary logic for a panic, including checking for recursive @@ -371,9 +406,7 @@ pub fn begin_panic(msg: M, file_line_col: &(&'static str, u32, u3 /// This is the entry point or panics from libcore, formatted panics, and /// `Box` panics. Here we'll verify that we're not panicking recursively, /// run panic hooks, and then delegate to the actual implementation of panics. -#[inline(never)] -#[cold] -fn rust_panic_with_hook(payload: Box, +fn rust_panic_with_hook(payload: &mut BoxMeUp, message: Option<&fmt::Arguments>, file_line_col: &(&'static str, u32, u32)) -> ! { let (file, line, col) = *file_line_col; @@ -393,7 +426,7 @@ fn rust_panic_with_hook(payload: Box, unsafe { let info = PanicInfo::internal_constructor( - &*payload, + payload.get(), message, Location::internal_constructor(file, line, col), ); @@ -421,16 +454,29 @@ fn rust_panic_with_hook(payload: Box, /// Shim around rust_panic. Called by resume_unwind. pub fn update_count_then_panic(msg: Box) -> ! { update_panic_count(1); - rust_panic(msg) + + struct RewrapBox(Box); + + unsafe impl BoxMeUp for RewrapBox { + fn box_me_up(&mut self) -> *mut (Any + Send) { + Box::into_raw(mem::replace(&mut self.0, Box::new(()))) + } + + fn get(&self) -> &(Any + Send) { + &*self.0 + } + } + + rust_panic(&mut RewrapBox(msg)) } /// A private no-mangle function on which to slap yer breakpoints. #[no_mangle] #[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints -pub fn rust_panic(msg: Box) -> ! { +pub fn rust_panic(mut msg: &mut BoxMeUp) -> ! { let code = unsafe { - let obj = mem::transmute::<_, raw::TraitObject>(msg); - __rust_start_panic(obj.data as usize, obj.vtable as usize) + let obj = &mut msg as *mut &mut BoxMeUp; + __rust_start_panic(obj as usize) }; rtabort!("failed to initiate panic, error {}", code) } diff --git a/src/libstd/sys/cloudabi/stdio.rs b/src/libstd/sys/cloudabi/stdio.rs index 9519a92647108..1d7344f921c9d 100644 --- a/src/libstd/sys/cloudabi/stdio.rs +++ b/src/libstd/sys/cloudabi/stdio.rs @@ -77,3 +77,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { } pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs index 3abb094ac34e3..7a4d11b0ecb9a 100644 --- a/src/libstd/sys/redox/stdio.rs +++ b/src/libstd/sys/redox/stdio.rs @@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { } pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index e9b3d4affc7dd..87ba2aef4f1d3 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -75,3 +75,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { } pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys/wasm/rwlock.rs b/src/libstd/sys/wasm/rwlock.rs index 8b06f54167487..6516010af4759 100644 --- a/src/libstd/sys/wasm/rwlock.rs +++ b/src/libstd/sys/wasm/rwlock.rs @@ -30,7 +30,7 @@ impl RWLock { if *mode >= 0 { *mode += 1; } else { - panic!("rwlock locked for writing"); + rtabort!("rwlock locked for writing"); } } @@ -51,7 +51,7 @@ impl RWLock { if *mode == 0 { *mode = -1; } else { - panic!("rwlock locked for reading") + rtabort!("rwlock locked for reading") } } diff --git a/src/libstd/sys/wasm/stdio.rs b/src/libstd/sys/wasm/stdio.rs index beb19c0ed2c1f..023f29576a27d 100644 --- a/src/libstd/sys/wasm/stdio.rs +++ b/src/libstd/sys/wasm/stdio.rs @@ -69,3 +69,7 @@ pub const STDIN_BUF_SIZE: usize = 0; pub fn is_ebadf(_err: &io::Error) -> bool { true } + +pub fn stderr_prints_nothing() -> bool { + !cfg!(feature = "wasm_syscall") +} diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index b43df20bddd08..81b89da21d3c6 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -227,3 +227,7 @@ pub fn is_ebadf(err: &io::Error) -> bool { // idea is that on windows we use a slightly smaller buffer that's // been seen to be acceptable. pub const STDIN_BUF_SIZE: usize = 8 * 1024; + +pub fn stderr_prints_nothing() -> bool { + false +} diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 1955f3ec9a28f..20109d2d0d5ac 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -139,10 +139,10 @@ pub fn __rust_begin_short_backtrace(f: F) -> T /// Controls how the backtrace should be formatted. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum PrintFormat { - /// Show all the frames with absolute path for files. - Full = 2, /// Show only relevant data from the backtrace. - Short = 3, + Short = 2, + /// Show all the frames with absolute path for files. + Full = 3, } // For now logging is turned off by default, and this function checks to see @@ -150,11 +150,10 @@ pub enum PrintFormat { pub fn log_enabled() -> Option { static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0); match ENABLED.load(Ordering::SeqCst) { - 0 => {}, + 0 => {} 1 => return None, - 2 => return Some(PrintFormat::Full), - 3 => return Some(PrintFormat::Short), - _ => unreachable!(), + 2 => return Some(PrintFormat::Short), + _ => return Some(PrintFormat::Full), } let val = match env::var_os("RUST_BACKTRACE") { diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 27504d374ddbf..d0c4d6a773746 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -28,6 +28,16 @@ use sync::Once; use sys; +macro_rules! rtabort { + ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*))) +} + +macro_rules! rtassert { + ($e:expr) => (if !$e { + rtabort!(concat!("assertion failed: ", stringify!($e))); + }) +} + pub mod at_exit_imp; #[cfg(feature = "backtrace")] pub mod backtrace; @@ -101,10 +111,6 @@ pub fn at_exit(f: F) -> Result<(), ()> { if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())} } -macro_rules! rtabort { - ($($t:tt)*) => (::sys_common::util::abort(format_args!($($t)*))) -} - /// One-time runtime cleanup. pub fn cleanup() { static CLEANUP: Once = Once::new(); diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs index a4aa3d96d25c0..d0d6224de0a15 100644 --- a/src/libstd/sys_common/thread_local.rs +++ b/src/libstd/sys_common/thread_local.rs @@ -169,7 +169,7 @@ impl StaticKey { self.key.store(key, Ordering::SeqCst); } INIT_LOCK.unlock(); - assert!(key != 0); + rtassert!(key != 0); return key } @@ -190,7 +190,7 @@ impl StaticKey { imp::destroy(key1); key2 }; - assert!(key != 0); + rtassert!(key != 0); match self.key.compare_and_swap(0, key as usize, Ordering::SeqCst) { // The CAS succeeded, so we've created the actual key 0 => key as usize, diff --git a/src/libstd/sys_common/util.rs b/src/libstd/sys_common/util.rs index a391c7cc6ef0c..a373e980b970d 100644 --- a/src/libstd/sys_common/util.rs +++ b/src/libstd/sys_common/util.rs @@ -10,10 +10,13 @@ use fmt; use io::prelude::*; -use sys::stdio::Stderr; +use sys::stdio::{Stderr, stderr_prints_nothing}; use thread; pub fn dumb_print(args: fmt::Arguments) { + if stderr_prints_nothing() { + return + } let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args)); } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 99479bc56eff3..40d3280baa687 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -172,12 +172,16 @@ macro_rules! __thread_local_inner { &'static $crate::cell::UnsafeCell< $crate::option::Option<$t>>> { + #[cfg(target_arch = "wasm32")] + static __KEY: $crate::thread::__StaticLocalKeyInner<$t> = + $crate::thread::__StaticLocalKeyInner::new(); + #[thread_local] - #[cfg(target_thread_local)] + #[cfg(all(target_thread_local, not(target_arch = "wasm32")))] static __KEY: $crate::thread::__FastLocalKeyInner<$t> = $crate::thread::__FastLocalKeyInner::new(); - #[cfg(not(target_thread_local))] + #[cfg(all(not(target_thread_local), not(target_arch = "wasm32")))] static __KEY: $crate::thread::__OsLocalKeyInner<$t> = $crate::thread::__OsLocalKeyInner::new(); @@ -295,6 +299,39 @@ impl LocalKey { } } +/// On some platforms like wasm32 there's no threads, so no need to generate +/// thread locals and we can instead just use plain statics! +#[doc(hidden)] +#[cfg(target_arch = "wasm32")] +pub mod statik { + use cell::UnsafeCell; + use fmt; + + pub struct Key { + inner: UnsafeCell>, + } + + unsafe impl ::marker::Sync for Key { } + + impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Key { .. }") + } + } + + impl Key { + pub const fn new() -> Key { + Key { + inner: UnsafeCell::new(None), + } + } + + pub unsafe fn get(&self) -> Option<&'static UnsafeCell>> { + Some(&*(&self.inner as *const _)) + } + } +} + #[doc(hidden)] #[cfg(target_thread_local)] pub mod fast { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 71aee673cfe3e..1b976b79b4c98 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -202,6 +202,9 @@ pub use self::local::{LocalKey, AccessError}; // where fast TLS was not available; end-user code is compiled with fast TLS // where available, but both are needed. +#[unstable(feature = "libstd_thread_internals", issue = "0")] +#[cfg(target_arch = "wasm32")] +#[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "0")] #[cfg(target_thread_local)] #[doc(hidden)] pub use self::local::fast::Key as __FastLocalKeyInner; diff --git a/src/test/run-make/wasm-panic-small/Makefile b/src/test/run-make/wasm-panic-small/Makefile new file mode 100644 index 0000000000000..a11fba235957b --- /dev/null +++ b/src/test/run-make/wasm-panic-small/Makefile @@ -0,0 +1,11 @@ +-include ../../run-make-fulldeps/tools.mk + +ifeq ($(TARGET),wasm32-unknown-unknown) +all: + $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown + wc -c < $(TMPDIR)/foo.wasm + [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "1024" ] +else +all: +endif + diff --git a/src/test/run-make/wasm-panic-small/foo.rs b/src/test/run-make/wasm-panic-small/foo.rs new file mode 100644 index 0000000000000..9654d5f7c0991 --- /dev/null +++ b/src/test/run-make/wasm-panic-small/foo.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "cdylib"] + +#[no_mangle] +pub fn foo() { + panic!("test"); +} From 138472bdc6b428eafc755dbc97b2706fa13a268c Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 24 Mar 2018 18:07:18 +0000 Subject: [PATCH 13/32] Checking location and syntax of non_exhaustive attribute. --- src/librustc/diagnostics.rs | 27 ++++++++++++++++++ src/librustc/hir/check_attr.rs | 27 ++++++++++++++++++ .../invalid-attribute.rs | 28 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index c74ae2343b866..2662e70999196 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -2058,6 +2058,33 @@ where 'x: 'y ``` "##, +E0910: r##" +This error indicates that a `#[non_exhaustive]` attribute was incorrectly placed +on something other than a struct or enum. + +Examples of erroneous code: + +```compile_fail,E0910 +# #![feature(non_exhaustive)] + +#[non_exhaustive] +trait Foo { } +``` +"##, + +E0911: r##" +This error indicates that a `#[non_exhaustive]` attribute had a value. The +`#[non_exhaustive]` should be empty. + +Examples of erroneous code: + +```compile_fail,E0911 +# #![feature(non_exhaustive)] + +#[non_exhaustive(anything)] +struct Foo; +``` +"##, } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 316ed07ca05d9..956cd17f38f21 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -66,6 +66,8 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { for attr in &item.attrs { if attr.check_name("inline") { self.check_inline(attr, &item.span, target) + } else if attr.check_name("non_exhaustive") { + self.check_non_exhaustive(attr, item, target) } else if attr.check_name("wasm_import_module") { has_wasm_import_module = true; if attr.value_str().is_none() { @@ -113,6 +115,31 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { } } + /// Check if the `#[non_exhaustive]` attribute on an `item` is valid. + fn check_non_exhaustive(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) { + match target { + Target::Struct | Target::Enum => { /* Valid */ }, + _ => { + struct_span_err!(self.tcx.sess, + attr.span, + E0910, + "attribute can only be applied to a struct or enum") + .span_label(item.span, "not a struct or enum") + .emit(); + return; + } + } + + if attr.meta_item_list().is_some() || attr.value_str().is_some() { + struct_span_err!(self.tcx.sess, + attr.span, + E0911, + "attribute should be empty") + .span_label(item.span, "not empty") + .emit(); + } + } + /// Check if the `#[repr]` attributes on `item` are valid. fn check_repr(&self, item: &hir::Item, target: Target) { // Extract the names of all repr hints, e.g., [foo, bar, align] for: diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs new file mode 100644 index 0000000000000..e48d989c01d61 --- /dev/null +++ b/src/test/compile-fail/rfc-2008-non-exhaustive/invalid-attribute.rs @@ -0,0 +1,28 @@ +// Copyright 2012 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(non_exhaustive)] + +#[non_exhaustive(anything)] +//~^ ERROR attribute should be empty [E0911] +struct Foo; + +#[non_exhaustive] +//~^ ERROR attribute can only be applied to a struct or enum [E0910] +trait Bar { } + +#[non_exhaustive] +//~^ ERROR attribute can only be applied to a struct or enum [E0910] +union Baz { + f1: u16, + f2: u16 +} + +fn main() { } From d0693548cdb4fe9e380f7c607c53a2e16821ebc2 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 3 Apr 2018 08:26:24 +0200 Subject: [PATCH 14/32] merge dist-various-3 into dist-various-1 --- .travis.yml | 2 -- src/ci/docker/dist-various-1/Dockerfile | 8 +++++++- src/ci/docker/dist-various-3/Dockerfile | 19 ------------------- 3 files changed, 7 insertions(+), 22 deletions(-) delete mode 100644 src/ci/docker/dist-various-3/Dockerfile diff --git a/.travis.yml b/.travis.yml index a67c6c79bbdf8..091a5abdaa216 100644 --- a/.travis.yml +++ b/.travis.yml @@ -116,8 +116,6 @@ matrix: if: branch = auto - env: IMAGE=dist-various-2 DEPLOY=1 if: branch = auto - - env: IMAGE=dist-various-3 DEPLOY=1 - if: branch = auto - env: IMAGE=dist-aarch64-linux DEPLOY=1 if: branch = auto - env: IMAGE=dist-android DEPLOY=1 diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index b398e9a3c92ef..e61757ff5eea9 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -20,7 +20,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ bzip2 \ patch \ libssl-dev \ - pkg-config + pkg-config \ + gcc-arm-none-eabi \ + libnewlib-arm-none-eabi WORKDIR /build @@ -78,6 +80,10 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu ENV TARGETS=$TARGETS,x86_64-unknown-redox +ENV TARGETS=$TARGETS,thumbv6m-none-eabi +ENV TARGETS=$TARGETS,thumbv7m-none-eabi +ENV TARGETS=$TARGETS,thumbv7em-none-eabi +ENV TARGETS=$TARGETS,thumbv7em-none-eabihf # FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271 # get fixed and cc update diff --git a/src/ci/docker/dist-various-3/Dockerfile b/src/ci/docker/dist-various-3/Dockerfile deleted file mode 100644 index 06c80982f3cd2..0000000000000 --- a/src/ci/docker/dist-various-3/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM ubuntu:17.10 - -COPY scripts/cross-apt-packages.sh /scripts/ -RUN sh /scripts/cross-apt-packages.sh - -RUN apt-get build-dep -y clang llvm && apt-get install -y --no-install-recommends \ - gcc-arm-none-eabi \ - libnewlib-arm-none-eabi - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV TARGETS=thumbv6m-none-eabi -ENV TARGETS=$TARGETS,thumbv7m-none-eabi -ENV TARGETS=$TARGETS,thumbv7em-none-eabi -ENV TARGETS=$TARGETS,thumbv7em-none-eabihf - -ENV RUST_CONFIGURE_ARGS --disable-docs -ENV SCRIPT python2.7 ../x.py dist --target $TARGETS From 862c839fb9e0ad5615443b7e8fa21b421e2e74eb Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 3 Apr 2018 08:29:09 +0200 Subject: [PATCH 15/32] extend no-std-ness check to all *-none-* targets --- src/bootstrap/sanity.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index cd67f1eb46414..1b1cec5f18c07 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -169,7 +169,7 @@ pub fn check(build: &mut Build) { panic!("the iOS target is only supported on macOS"); } - if target.starts_with("thumbv") { + if target.contains("-none-") { if build.no_std(*target).is_none() { let target = build.config.target_config.entry(target.clone()) .or_insert(Default::default()); @@ -178,7 +178,7 @@ pub fn check(build: &mut Build) { } if build.no_std(*target) == Some(false) { - panic!("All the THUMB targets are no-std targets") + panic!("All the *-none-* targets are no-std targets") } } From 21641d6d2ce6e7f8c81817c1848499ddc635440b Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Mon, 26 Mar 2018 19:19:25 -0300 Subject: [PATCH 16/32] Refactor inner function into closure. So we can cut some params by using stuff from the environment. --- src/librustc_typeck/check/mod.rs | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f1896be000f63..3c41e4042b952 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2531,16 +2531,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut expected_arg_tys = expected_arg_tys; let expected_arg_count = fn_inputs.len(); - fn parameter_count_error<'tcx>(sess: &Session, - sp: Span, - expr_sp: Span, - expected_count: usize, - arg_count: usize, - error_code: &str, - variadic: bool, - def_span: Option, - sugg_unit: bool) { - let mut err = sess.struct_span_err_with_code(sp, + let param_count_error = |expected_count: usize, + arg_count: usize, + error_code: &str, + variadic: bool, + sugg_unit: bool| { + let mut err = tcx.sess.struct_span_err_with_code(sp, &format!("this function takes {}{} parameter{} but {} parameter{} supplied", if variadic {"at least "} else {""}, expected_count, @@ -2549,11 +2545,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if arg_count == 1 {" was"} else {"s were"}), DiagnosticId::Error(error_code.to_owned())); - if let Some(def_s) = def_span.map(|sp| sess.codemap().def_span(sp)) { + if let Some(def_s) = def_span.map(|sp| tcx.sess.codemap().def_span(sp)) { err.span_label(def_s, "defined here"); } if sugg_unit { - let sugg_span = sess.codemap().end_point(expr_sp); + let sugg_span = tcx.sess.codemap().end_point(expr_sp); // remove closing `)` from the span let sugg_span = sugg_span.shrink_to_lo(); err.span_suggestion( @@ -2567,14 +2563,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if expected_count == 1 {""} else {"s"})); } err.emit(); - } + }; let formal_tys = if tuple_arguments == TupleArguments { let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); match tuple_type.sty { ty::TyTuple(arg_types) if arg_types.len() != args.len() => { - parameter_count_error(tcx.sess, sp, expr_sp, arg_types.len(), args.len(), - "E0057", false, def_span, false); + param_count_error(arg_types.len(), args.len(), "E0057", false, false); expected_arg_tys = &[]; self.err_args(args.len()) } @@ -2602,8 +2597,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if supplied_arg_count >= expected_arg_count { fn_inputs.to_vec() } else { - parameter_count_error(tcx.sess, sp, expr_sp, expected_arg_count, - supplied_arg_count, "E0060", true, def_span, false); + param_count_error(expected_arg_count, supplied_arg_count, "E0060", true, false); expected_arg_tys = &[]; self.err_args(supplied_arg_count) } @@ -2616,8 +2610,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { false }; - parameter_count_error(tcx.sess, sp, expr_sp, expected_arg_count, - supplied_arg_count, "E0061", false, def_span, sugg_unit); + param_count_error(expected_arg_count, supplied_arg_count, "E0061", false, sugg_unit); + expected_arg_tys = &[]; self.err_args(supplied_arg_count) }; From ba5a5cf2199ab55e9b47820c32e11a27d93df519 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Tue, 27 Mar 2018 08:25:31 -0300 Subject: [PATCH 17/32] Remove single use helper function. --- src/librustc_typeck/check/mod.rs | 14 +------------- src/librustc_typeck/check/op.rs | 6 +++--- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3c41e4042b952..bfe92fc5be802 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2833,19 +2833,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_expr_coercable_to_type(&self, expr: &'gcx hir::Expr, expected: Ty<'tcx>) -> Ty<'tcx> { - self.check_expr_coercable_to_type_with_needs(expr, expected, Needs::None) - } - - fn check_expr_coercable_to_type_with_needs(&self, - expr: &'gcx hir::Expr, - expected: Ty<'tcx>, - needs: Needs) - -> Ty<'tcx> { - let ty = self.check_expr_with_expectation_and_needs( - expr, - ExpectHasType(expected), - needs); - // checks don't need two phase + let ty = self.check_expr_with_hint(expr, expected); self.demand_coerce(expr, ty, expected, AllowTwoPhase::No) } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index efc1e2a80cebe..4a175248d74a3 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -174,9 +174,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // trait matching creating lifetime constraints that are too strict. // E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result // in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`. - let lhs_ty = self.check_expr_coercable_to_type_with_needs(lhs_expr, - self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)), - lhs_needs); + let lhs_ty = self.check_expr_with_needs(lhs_expr, lhs_needs); + let fresh_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)); + let lhs_ty = self.demand_coerce(lhs_expr, lhs_ty, fresh_var, AllowTwoPhase::No); let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty); // NB: As we have not yet type-checked the RHS, we don't have the From 0a3eb5c508bce50873401ca942e3cb1d4a0ce21f Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Tue, 27 Mar 2018 11:27:02 -0300 Subject: [PATCH 18/32] Simplify code around expected argument types. --- src/librustc_typeck/check/mod.rs | 99 ++++++++++++++++---------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bfe92fc5be802..5ca8d1b06e127 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2507,7 +2507,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { sp: Span, expr_sp: Span, fn_inputs: &[Ty<'tcx>], - expected_arg_tys: &[Ty<'tcx>], + mut expected_arg_tys: &[Ty<'tcx>], args: &'gcx [hir::Expr], variadic: bool, tuple_arguments: TupleArgumentsFlag, @@ -2528,7 +2528,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.register_wf_obligation(fn_input_ty, sp, traits::MiscObligation); } - let mut expected_arg_tys = expected_arg_tys; let expected_arg_count = fn_inputs.len(); let param_count_error = |expected_count: usize, @@ -2615,6 +2614,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected_arg_tys = &[]; self.err_args(supplied_arg_count) }; + // If there is no expectation, expect formal_tys. + let expected_arg_tys = if !expected_arg_tys.is_empty() { + expected_arg_tys + } else { + &formal_tys + }; debug!("check_argument_types: formal_tys={:?}", formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::>()); @@ -2666,28 +2671,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // The special-cased logic below has three functions: // 1. Provide as good of an expected type as possible. - let expected = expected_arg_tys.get(i).map(|&ty| { - Expectation::rvalue_hint(self, ty) - }); + let expected = Expectation::rvalue_hint(self, expected_arg_tys[i]); - let checked_ty = self.check_expr_with_expectation( - &arg, - expected.unwrap_or(ExpectHasType(formal_ty))); + let checked_ty = self.check_expr_with_expectation(&arg, expected); // 2. Coerce to the most detailed type that could be coerced // to, which is `expected_ty` if `rvalue_hint` returns an // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. - let coerce_ty = expected.and_then(|e| e.only_has_type(self)); + let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty); // We're processing function arguments so we definitely want to use // two-phase borrows. - self.demand_coerce(&arg, - checked_ty, - coerce_ty.unwrap_or(formal_ty), - AllowTwoPhase::Yes); + self.demand_coerce(&arg, checked_ty, coerce_ty, AllowTwoPhase::Yes); // 3. Relate the expected type and the formal one, // if the expected type was used for the coercion. - coerce_ty.map(|ty| self.demand_suptype(arg.span, formal_ty, ty)); + self.demand_suptype(arg.span, formal_ty, coerce_ty); } } @@ -2834,6 +2832,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr: &'gcx hir::Expr, expected: Ty<'tcx>) -> Ty<'tcx> { let ty = self.check_expr_with_hint(expr, expected); + // checks don't need two phase self.demand_coerce(expr, ty, expected, AllowTwoPhase::No) } @@ -2882,45 +2881,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { formal_args: &[Ty<'tcx>]) -> Vec> { let formal_ret = self.resolve_type_vars_with_obligations(formal_ret); - let expected_args = expected_ret.only_has_type(self).and_then(|ret_ty| { - self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || { - // Attempt to apply a subtyping relationship between the formal - // return type (likely containing type variables if the function - // is polymorphic) and the expected return type. - // No argument expectations are produced if unification fails. - let origin = self.misc(call_span); - let ures = self.at(&origin, self.param_env).sup(ret_ty, &formal_ret); - - // FIXME(#27336) can't use ? here, Try::from_error doesn't default - // to identity so the resulting type is not constrained. - match ures { - Ok(ok) => { - // Process any obligations locally as much as - // we can. We don't care if some things turn - // out unconstrained or ambiguous, as we're - // just trying to get hints here. - self.save_and_restore_in_snapshot_flag(|_| { - let mut fulfill = TraitEngine::new(self.tcx); - for obligation in ok.obligations { - fulfill.register_predicate_obligation(self, obligation); - } - fulfill.select_where_possible(self) - }).map_err(|_| ())?; - } - Err(_) => return Err(()), + let ret_ty = match expected_ret.only_has_type(self) { + Some(ret) => ret, + None => return Vec::new() + }; + let expect_args = self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || { + // Attempt to apply a subtyping relationship between the formal + // return type (likely containing type variables if the function + // is polymorphic) and the expected return type. + // No argument expectations are produced if unification fails. + let origin = self.misc(call_span); + let ures = self.at(&origin, self.param_env).sup(ret_ty, &formal_ret); + + // FIXME(#27336) can't use ? here, Try::from_error doesn't default + // to identity so the resulting type is not constrained. + match ures { + Ok(ok) => { + // Process any obligations locally as much as + // we can. We don't care if some things turn + // out unconstrained or ambiguous, as we're + // just trying to get hints here. + self.save_and_restore_in_snapshot_flag(|_| { + let mut fulfill = TraitEngine::new(self.tcx); + for obligation in ok.obligations { + fulfill.register_predicate_obligation(self, obligation); + } + fulfill.select_where_possible(self) + }).map_err(|_| ())?; } + Err(_) => return Err(()), + } - // Record all the argument types, with the substitutions - // produced from the above subtyping unification. - Ok(formal_args.iter().map(|ty| { - self.resolve_type_vars_if_possible(ty) - }).collect()) - }).ok() - }).unwrap_or(vec![]); + // Record all the argument types, with the substitutions + // produced from the above subtyping unification. + Ok(formal_args.iter().map(|ty| { + self.resolve_type_vars_if_possible(ty) + }).collect()) + }).unwrap_or(Vec::new()); debug!("expected_inputs_for_expected_output(formal={:?} -> {:?}, expected={:?} -> {:?})", formal_args, formal_ret, - expected_args, expected_ret); - expected_args + expect_args, expected_ret); + expect_args } // Checks a method call. From 14768f9b636ef345320ded41da5e9f3da7af3a81 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 4 Apr 2018 19:24:57 +0200 Subject: [PATCH 19/32] create a nostd crate the goal is to build, in a single Cargo invocation, several no-std crates that we want to put in the rust-std component of no-std targets. The nostd crate builds these crates: - core - compiler-builtin (with the "c" and "mem" features enabled) - alloc - std_unicode --- src/Cargo.lock | 10 ++++++++++ src/Cargo.toml | 1 + src/bootstrap/compile.rs | 8 ++++---- src/libnostd/Cargo.toml | 17 +++++++++++++++++ src/libnostd/lib.rs | 3 +++ 5 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 src/libnostd/Cargo.toml create mode 100644 src/libnostd/lib.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 1f7cf84cedbda..42ac9b3c49dee 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1081,6 +1081,16 @@ name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "nostd" +version = "0.0.0" +dependencies = [ + "alloc 0.0.0", + "compiler_builtins 0.0.0", + "core 0.0.0", + "std_unicode 0.0.0", +] + [[package]] name = "num" version = "0.1.42" diff --git a/src/Cargo.toml b/src/Cargo.toml index 814c054c51e41..babf35d570b51 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -2,6 +2,7 @@ members = [ "bootstrap", "rustc", + "libnostd", "libstd", "libtest", "librustc_trans", diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index eaf4ab272c68e..a93b26ac2bae0 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -145,10 +145,10 @@ pub fn std_cargo(build: &Builder, } if build.no_std(target) == Some(true) { - // for no-std targets we only compile core and compiler-builtins - cargo.arg("--features").arg("c mem") - .arg("--manifest-path") - .arg(build.src.join("src/rustc/compiler_builtins_shim/Cargo.toml")); + // for no-std targets we compile a minimal nostd crate that only depends on crates that work + // without an OS + cargo.arg("--manifest-path") + .arg(build.src.join("src/libnostd/Cargo.toml")); } else { let mut features = build.std_features(); diff --git a/src/libnostd/Cargo.toml b/src/libnostd/Cargo.toml new file mode 100644 index 0000000000000..6919390d3e2a7 --- /dev/null +++ b/src/libnostd/Cargo.toml @@ -0,0 +1,17 @@ +[package] +authors = ["The Rust Project Developers"] +name = "nostd" +version = "0.0.0" +license = "MIT/Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "(not) The Rust Standard Library" + +[lib] +name = "nostd" +path = "lib.rs" + +[dependencies] +alloc = { path = "../liballoc" } +compiler_builtins = { path = "../rustc/compiler_builtins_shim", features = ["c", "mem"] } +core = { path = "../libcore" } +std_unicode = { path = "../libstd_unicode" } \ No newline at end of file diff --git a/src/libnostd/lib.rs b/src/libnostd/lib.rs new file mode 100644 index 0000000000000..d28afe2838e28 --- /dev/null +++ b/src/libnostd/lib.rs @@ -0,0 +1,3 @@ +#![feature(staged_api)] +#![no_std] +#![unstable(feature = "nostd", issue = "0")] From bca569f57c53e219270be72ed5976b8167fcd246 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 4 Apr 2018 22:23:33 +0200 Subject: [PATCH 20/32] Revert "create a nostd crate" This reverts commit 14768f9b636ef345320ded41da5e9f3da7af3a81. --- src/Cargo.lock | 10 ---------- src/Cargo.toml | 1 - src/bootstrap/compile.rs | 8 ++++---- src/libnostd/Cargo.toml | 17 ----------------- src/libnostd/lib.rs | 3 --- 5 files changed, 4 insertions(+), 35 deletions(-) delete mode 100644 src/libnostd/Cargo.toml delete mode 100644 src/libnostd/lib.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 42ac9b3c49dee..1f7cf84cedbda 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1081,16 +1081,6 @@ name = "nodrop" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "nostd" -version = "0.0.0" -dependencies = [ - "alloc 0.0.0", - "compiler_builtins 0.0.0", - "core 0.0.0", - "std_unicode 0.0.0", -] - [[package]] name = "num" version = "0.1.42" diff --git a/src/Cargo.toml b/src/Cargo.toml index babf35d570b51..814c054c51e41 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -2,7 +2,6 @@ members = [ "bootstrap", "rustc", - "libnostd", "libstd", "libtest", "librustc_trans", diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index a93b26ac2bae0..eaf4ab272c68e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -145,10 +145,10 @@ pub fn std_cargo(build: &Builder, } if build.no_std(target) == Some(true) { - // for no-std targets we compile a minimal nostd crate that only depends on crates that work - // without an OS - cargo.arg("--manifest-path") - .arg(build.src.join("src/libnostd/Cargo.toml")); + // for no-std targets we only compile core and compiler-builtins + cargo.arg("--features").arg("c mem") + .arg("--manifest-path") + .arg(build.src.join("src/rustc/compiler_builtins_shim/Cargo.toml")); } else { let mut features = build.std_features(); diff --git a/src/libnostd/Cargo.toml b/src/libnostd/Cargo.toml deleted file mode 100644 index 6919390d3e2a7..0000000000000 --- a/src/libnostd/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "nostd" -version = "0.0.0" -license = "MIT/Apache-2.0" -repository = "https://github.com/rust-lang/rust.git" -description = "(not) The Rust Standard Library" - -[lib] -name = "nostd" -path = "lib.rs" - -[dependencies] -alloc = { path = "../liballoc" } -compiler_builtins = { path = "../rustc/compiler_builtins_shim", features = ["c", "mem"] } -core = { path = "../libcore" } -std_unicode = { path = "../libstd_unicode" } \ No newline at end of file diff --git a/src/libnostd/lib.rs b/src/libnostd/lib.rs deleted file mode 100644 index d28afe2838e28..0000000000000 --- a/src/libnostd/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![feature(staged_api)] -#![no_std] -#![unstable(feature = "nostd", issue = "0")] From b1015f5c5a4dcd6118b86ef5361371f04a7bce8b Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 4 Apr 2018 22:42:56 +0200 Subject: [PATCH 21/32] compile other no-std crates --- src/bootstrap/compile.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index eaf4ab272c68e..51e7a78831585 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -145,8 +145,11 @@ pub fn std_cargo(build: &Builder, } if build.no_std(target) == Some(true) { - // for no-std targets we only compile core and compiler-builtins + // for no-std targets we only compile a few no_std crates cargo.arg("--features").arg("c mem") + .args(&["-p", "alloc"]) + .args(&["-p", "compiler_builtins"]) + .args(&["-p", "std_unicode"]) .arg("--manifest-path") .arg(build.src.join("src/rustc/compiler_builtins_shim/Cargo.toml")); } else { From 1b1df3efc7fc99b366c968a8005cc88eb2b47f0a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 18 Mar 2018 02:57:23 +0300 Subject: [PATCH 22/32] Use `Span` instead of `SyntaxContext` in `Ident` --- src/libproc_macro/lib.rs | 2 +- src/librustc/hir/lowering.rs | 7 +-- src/librustc/ich/impls_hir.rs | 2 +- src/librustc/ty/mod.rs | 6 +-- src/librustc_driver/pretty.rs | 4 +- src/librustc_privacy/lib.rs | 13 +++-- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/lib.rs | 53 +++++++++++---------- src/librustc_resolve/macros.rs | 4 +- src/librustc_resolve/resolve_imports.rs | 8 ++-- src/librustc_typeck/check/mod.rs | 6 +-- src/libsyntax/ast.rs | 2 +- src/libsyntax/ext/base.rs | 4 +- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/ext/tt/quoted.rs | 11 ++--- src/libsyntax/ext/tt/transcribe.rs | 2 +- src/libsyntax/parse/lexer/mod.rs | 2 +- src/libsyntax/print/pprust.rs | 4 +- src/libsyntax_ext/concat_idents.rs | 9 ++-- src/libsyntax_ext/deriving/generic/ty.rs | 7 ++- src/libsyntax_pos/hygiene.rs | 6 +-- src/libsyntax_pos/lib.rs | 48 ++++++++++++++++++- src/libsyntax_pos/symbol.rs | 35 ++++++++++---- 23 files changed, 146 insertions(+), 93 deletions(-) diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 007093981d3e1..319873c64ff9a 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -720,7 +720,7 @@ impl TokenTree { }).into(); }, TokenNode::Term(symbol) => { - let ident = ast::Ident { name: symbol.0, ctxt: self.span.0.ctxt() }; + let ident = ast::Ident::new(symbol.0, self.span.0); let sym_str = symbol.0.as_str(); let token = if sym_str.starts_with("'") { Lifetime(ident) } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 5f9f37094f579..382a77a140ba0 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -909,7 +909,7 @@ impl<'a> LoweringContext<'a> { fn lower_ident(&mut self, ident: Ident) -> Name { let ident = ident.modern(); - if ident.ctxt == SyntaxContext::empty() { + if ident.span.ctxt() == SyntaxContext::empty() { return ident.name; } *self.name_map @@ -2089,10 +2089,7 @@ impl<'a> LoweringContext<'a> { name: self.lower_ident(match f.ident { Some(ident) => ident, // FIXME(jseyfried) positional field hygiene - None => Ident { - name: Symbol::intern(&index.to_string()), - ctxt: f.span.ctxt(), - }, + None => Ident::new(Symbol::intern(&index.to_string()), f.span), }), vis: self.lower_visibility(&f.vis, None), ty: self.lower_ty(&f.ty, ImplTraitContext::Disallowed), diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index c3b3e10201f99..7335511a5a051 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -655,7 +655,7 @@ impl<'a> HashStable> for ast::Ident { hasher: &mut StableHasher) { let ast::Ident { ref name, - ctxt: _ // Ignore this + span: _ // Ignore this } = *self; name.hash_stable(hcx, hasher); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 72ba199eb2412..b920553ec3698 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2088,8 +2088,8 @@ impl<'a, 'gcx, 'tcx> VariantDef { return Some(index); } let mut ident = name.to_ident(); - while ident.ctxt != SyntaxContext::empty() { - ident.ctxt.remove_mark(); + while ident.span.ctxt() != SyntaxContext::empty() { + ident.span.remove_mark(); if let Some(field) = self.fields.iter().position(|f| f.name.to_ident() == ident) { return Some(field); } @@ -2558,7 +2558,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { LOCAL_CRATE => self.hir.definitions().expansion(scope.index), _ => Mark::root(), }; - let scope = match ident.ctxt.adjust(expansion) { + let scope = match ident.span.adjust(expansion) { Some(macro_def) => self.hir.definitions().macro_def_scope(macro_def), None if block == DUMMY_NODE_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId None => self.hir.get_module_parent(block), diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index c5e7fdb30d36a..70b73ebb8cdeb 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -466,11 +466,11 @@ impl<'a> PrinterSupport for HygieneAnnotation<'a> { impl<'a> pprust::PpAnn for HygieneAnnotation<'a> { fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { match node { - pprust::NodeIdent(&ast::Ident { name, ctxt }) => { + pprust::NodeIdent(&ast::Ident { name, span }) => { s.s.space()?; // FIXME #16420: this doesn't display the connections // between syntax contexts - s.synth_comment(format!("{}{:?}", name.as_u32(), ctxt)) + s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt())) } pprust::NodeName(&name) => { s.s.space()?; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 95be691b30c79..d951a7f1cc1cd 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -35,7 +35,6 @@ use rustc::util::nodemap::NodeSet; use syntax::ast::{self, CRATE_NODE_ID, Ident}; use syntax::symbol::keywords; use syntax_pos::Span; -use syntax_pos::hygiene::SyntaxContext; use std::cmp; use std::mem::replace; @@ -495,11 +494,11 @@ struct NamePrivacyVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { // Checks that a field in a struct constructor (expression or pattern) is accessible. fn check_field(&mut self, - use_ctxt: SyntaxContext, // Syntax context of the field name at the use site + use_ctxt: Span, // Syntax context of the field name at the use site span: Span, // Span of the field pattern, e.g. `x: 0` def: &'tcx ty::AdtDef, // Definition of the struct or enum field: &'tcx ty::FieldDef) { // Definition of the field - let ident = Ident { ctxt: use_ctxt.modern(), ..keywords::Invalid.ident() }; + let ident = Ident::new(keywords::Invalid.name(), use_ctxt.modern()); let def_id = self.tcx.adjust_ident(ident, def.did, self.current_item).1; if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) { struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private", @@ -573,14 +572,14 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { for variant_field in &variant.fields { let field = fields.iter().find(|f| f.name.node == variant_field.name); let (use_ctxt, span) = match field { - Some(field) => (field.name.node.to_ident().ctxt, field.span), - None => (base.span.ctxt(), base.span), + Some(field) => (field.name.node.to_ident().span, field.span), + None => (base.span, base.span), }; self.check_field(use_ctxt, span, adt, variant_field); } } else { for field in fields { - let use_ctxt = field.name.node.to_ident().ctxt; + let use_ctxt = field.name.node.to_ident().span; let field_def = variant.field_named(field.name.node); self.check_field(use_ctxt, field.span, adt, field_def); } @@ -599,7 +598,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap(); let variant = adt.variant_of_def(def); for field in fields { - let use_ctxt = field.node.name.to_ident().ctxt; + let use_ctxt = field.node.name.to_ident().span; let field_def = variant.field_named(field.node.name); self.check_field(use_ctxt, field.span, adt, field_def); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index c192f349c2019..695dbeb7b633e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -157,7 +157,7 @@ impl<'a> Resolver<'a> { // Disallow `use $crate;` if source.name == keywords::DollarCrate.name() && path.segments.len() == 1 { - let crate_root = self.resolve_crate_root(source.ctxt, true); + let crate_root = self.resolve_crate_root(source.span.ctxt(), true); let crate_name = match crate_root.kind { ModuleKind::Def(_, name) => name, ModuleKind::Block(..) => unreachable!(), diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 97dcf081f8c8d..443a2a938c7ae 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1911,10 +1911,11 @@ impl<'a> Resolver<'a> { path_span: Span) -> Option> { if ns == TypeNS { - ident.ctxt = if ident.name == keywords::SelfType.name() { - SyntaxContext::empty() // FIXME(jseyfried) improve `Self` hygiene + ident.span = if ident.name == keywords::SelfType.name() { + // FIXME(jseyfried) improve `Self` hygiene + ident.span.with_ctxt(SyntaxContext::empty()) } else { - ident.ctxt.modern() + ident.span.modern() } } @@ -1930,10 +1931,10 @@ impl<'a> Resolver<'a> { module = match self.ribs[ns][i].kind { ModuleRibKind(module) => module, - MacroDefinition(def) if def == self.macro_def(ident.ctxt) => { + MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. - ident.ctxt.remove_mark(); + ident.span.remove_mark(); continue } _ => continue, @@ -1953,9 +1954,9 @@ impl<'a> Resolver<'a> { } } - ident.ctxt = ident.ctxt.modern(); + ident.span = ident.span.modern(); loop { - module = unwrap_or!(self.hygienic_lexical_parent(module, &mut ident.ctxt), break); + module = unwrap_or!(self.hygienic_lexical_parent(module, &mut ident.span), break); let orig_current_module = self.current_module; self.current_module = module; // Lexical resolutions can never be a privacy error. let result = self.resolve_ident_in_module_unadjusted( @@ -1979,10 +1980,10 @@ impl<'a> Resolver<'a> { } } - fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, ctxt: &mut SyntaxContext) + fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span) -> Option> { - if !module.expansion.is_descendant_of(ctxt.outer()) { - return Some(self.macro_def_scope(ctxt.remove_mark())); + if !module.expansion.is_descendant_of(span.ctxt().outer()) { + return Some(self.macro_def_scope(span.remove_mark())); } if let ModuleKind::Block(..) = module.kind { @@ -1994,7 +1995,7 @@ impl<'a> Resolver<'a> { let parent_expansion = parent.expansion.modern(); if module_expansion.is_descendant_of(parent_expansion) && parent_expansion != module_expansion { - return if parent_expansion.is_descendant_of(ctxt.outer()) { + return if parent_expansion.is_descendant_of(span.ctxt().outer()) { Some(parent) } else { None @@ -2015,9 +2016,9 @@ impl<'a> Resolver<'a> { record_used: bool, span: Span) -> Result<&'a NameBinding<'a>, Determinacy> { - ident.ctxt = ident.ctxt.modern(); + ident.span = ident.span.modern(); let orig_current_module = self.current_module; - if let Some(def) = ident.ctxt.adjust(module.expansion) { + if let Some(def) = ident.span.adjust(module.expansion) { self.current_module = self.macro_def_scope(def); } let result = self.resolve_ident_in_module_unadjusted( @@ -2107,8 +2108,8 @@ impl<'a> Resolver<'a> { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. MacroDefinition(def) => { - if def == self.macro_def(ident.ctxt) { - ident.ctxt.remove_mark(); + if def == self.macro_def(ident.span.ctxt()) { + ident.span.remove_mark(); } } _ => { @@ -2872,7 +2873,7 @@ impl<'a> Resolver<'a> { } if path.len() == 1 && this.self_type_is_available(span) { if let Some(candidate) = this.lookup_assoc_candidate(ident.node, ns, is_expected) { - let self_is_available = this.self_value_is_available(path[0].node.ctxt, span); + let self_is_available = this.self_value_is_available(path[0].node.span, span); match candidate { AssocSuggestion::Field => { err.span_suggestion(span, "try", @@ -3083,9 +3084,9 @@ impl<'a> Resolver<'a> { if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false } } - fn self_value_is_available(&mut self, ctxt: SyntaxContext, span: Span) -> bool { - let ident = Ident { name: keywords::SelfValue.name(), ctxt: ctxt }; - let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, span); + fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool { + let ident = Ident::new(keywords::SelfValue.name(), self_span); + let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, path_span); if let Some(LexicalScopeBinding::Def(def)) = binding { def != Def::Err } else { false } } @@ -3218,11 +3219,11 @@ impl<'a> Resolver<'a> { let name = ident.node.name; if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() { - let mut ctxt = ident.node.ctxt.modern(); + let mut ctxt = ident.node.span.ctxt().modern(); module = Some(self.resolve_self(&mut ctxt, self.current_module)); continue } else if allow_super && ns == TypeNS && name == keywords::Super.name() { - let mut ctxt = ident.node.ctxt.modern(); + let mut ctxt = ident.node.span.ctxt().modern(); let self_module = match i { 0 => self.resolve_self(&mut ctxt, self.current_module), _ => module.unwrap(), @@ -3244,11 +3245,11 @@ impl<'a> Resolver<'a> { (i == 1 && name == keywords::Crate.name() && path[0].node.name == keywords::CrateRoot.name()) { // `::a::b` or `::crate::a::b` - module = Some(self.resolve_crate_root(ident.node.ctxt, false)); + module = Some(self.resolve_crate_root(ident.node.span.ctxt(), false)); continue } else if i == 0 && name == keywords::DollarCrate.name() { // `$crate::a::b` - module = Some(self.resolve_crate_root(ident.node.ctxt, true)); + module = Some(self.resolve_crate_root(ident.node.span.ctxt(), true)); continue } else if i == 1 && !token::is_path_segment_keyword(ident.node) { let prev_name = path[0].node.name; @@ -3770,12 +3771,12 @@ impl<'a> Resolver<'a> { } } - ident.ctxt = ident.ctxt.modern(); + ident.span = ident.span.modern(); let mut search_module = self.current_module; loop { self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits); search_module = - unwrap_or!(self.hygienic_lexical_parent(search_module, &mut ident.ctxt), break); + unwrap_or!(self.hygienic_lexical_parent(search_module, &mut ident.span), break); } if let Some(prelude) = self.prelude { @@ -3807,7 +3808,7 @@ impl<'a> Resolver<'a> { for &(trait_name, binding) in traits.as_ref().unwrap().iter() { let module = binding.module().unwrap(); let mut ident = ident; - if ident.ctxt.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() { + if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() { continue } if self.resolve_ident_in_module_unadjusted(module, ident, ns, false, false, module.span) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0692a1e0d7f8a..289556cd45e0f 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -140,7 +140,7 @@ impl<'a> base::Resolver for Resolver<'a> { let ident = path.segments[0].identifier; if ident.name == keywords::DollarCrate.name() { path.segments[0].identifier.name = keywords::CrateRoot.name(); - let module = self.0.resolve_crate_root(ident.ctxt, true); + let module = self.0.resolve_crate_root(ident.span.ctxt(), true); if !module.is_local() { let span = path.segments[0].span; path.segments.insert(1, match module.kind { @@ -534,7 +534,7 @@ impl<'a> Resolver<'a> { } module = match module { - Some(module) => self.hygienic_lexical_parent(module, &mut ident.ctxt), + Some(module) => self.hygienic_lexical_parent(module, &mut ident.span), None => return potential_illegal_shadower, } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 7036bdd0e2b07..90a90d731534b 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -238,7 +238,7 @@ impl<'a> Resolver<'a> { } let module = unwrap_or!(directive.imported_module.get(), return Err(Undetermined)); let (orig_current_module, mut ident) = (self.current_module, ident.modern()); - match ident.ctxt.glob_adjust(module.expansion, directive.span.ctxt().modern()) { + match ident.span.glob_adjust(module.expansion, directive.span.ctxt().modern()) { Some(Some(def)) => self.current_module = self.macro_def_scope(def), Some(None) => {} None => continue, @@ -398,7 +398,7 @@ impl<'a> Resolver<'a> { // Define `binding` in `module`s glob importers. for directive in module.glob_importers.borrow_mut().iter() { let mut ident = ident.modern(); - let scope = match ident.ctxt.reverse_glob_adjust(module.expansion, + let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span.ctxt().modern()) { Some(Some(def)) => self.macro_def_scope(def), Some(None) => directive.parent, @@ -623,7 +623,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { "crate root imports need to be explicitly named: \ `use crate as name;`".to_string())); } else { - Some(self.resolve_crate_root(source.ctxt.modern(), false)) + Some(self.resolve_crate_root(source.span.ctxt().modern(), false)) } } else if is_extern && !token::is_path_segment_keyword(source) { let crate_id = @@ -860,7 +860,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { resolution.borrow().binding().map(|binding| (ident, binding)) }).collect::>(); for ((mut ident, ns), binding) in bindings { - let scope = match ident.ctxt.reverse_glob_adjust(module.expansion, + let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span.ctxt().modern()) { Some(Some(def)) => self.macro_def_scope(def), Some(None) => self.current_module, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f1896be000f63..d3a39b86d169e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3213,10 +3213,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !tuple_like { continue } debug!("tuple struct named {:?}", base_t); - let ident = ast::Ident { - name: Symbol::intern(&idx.node.to_string()), - ctxt: idx.span.ctxt().modern(), - }; + let ident = + ast::Ident::new(Symbol::intern(&idx.node.to_string()), idx.span.modern()); let (ident, def_scope) = self.tcx.adjust_ident(ident, base_def.did, self.body_id); let fields = &base_def.non_enum_variant().fields; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 31bb1c88b8712..63ac4c38a7957 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -150,7 +150,7 @@ impl PathSegment { } pub fn crate_root(span: Span) -> Self { PathSegment { - identifier: Ident { ctxt: span.ctxt(), ..keywords::CrateRoot.ident() }, + identifier: Ident::new(keywords::CrateRoot.name(), span), span, parameters: None, } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index d3157af984e80..e64f97d58f449 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -848,8 +848,8 @@ impl<'a> ExtCtxt<'a> { ast::Ident::from_str(st) } pub fn std_path(&self, components: &[&str]) -> Vec { - let def_site = SyntaxContext::empty().apply_mark(self.current_expansion.mark); - iter::once(Ident { ctxt: def_site, ..keywords::DollarCrate.ident() }) + let def_site = DUMMY_SP.apply_mark(self.current_expansion.mark); + iter::once(Ident::new(keywords::DollarCrate.name(), def_site)) .chain(components.iter().map(|s| self.ident_of(s))) .collect() } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 864969c40750b..148eb71f70ee5 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1320,7 +1320,7 @@ pub struct Marker(pub Mark); impl Folder for Marker { fn fold_ident(&mut self, mut ident: Ident) -> Ident { - ident.ctxt = ident.ctxt.apply_mark(self.0); + ident.span = ident.span.apply_mark(self.0); ident } diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index f324edeb1178a..01b971976a763 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -289,14 +289,11 @@ where // `tree` is followed by an `ident`. This could be `$meta_var` or the `$crate` special // metavariable that names the crate of the invokation. Some(tokenstream::TokenTree::Token(ident_span, ref token)) if token.is_ident() => { - let (ident, _) = token.ident().unwrap(); + let (ident, is_raw) = token.ident().unwrap(); let span = ident_span.with_lo(span.lo()); - if ident.name == keywords::Crate.name() { - let ident = ast::Ident { - name: keywords::DollarCrate.name(), - ..ident - }; - TokenTree::Token(span, token::Ident(ident, false)) + if ident.name == keywords::Crate.name() && !is_raw { + let ident = ast::Ident::new(keywords::DollarCrate.name(), ident.span); + TokenTree::Token(span, token::Ident(ident, is_raw)) } else { TokenTree::MetaVar(span, ident) } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 3f01d5ec6dd87..12ada3bdbc0b9 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -166,7 +166,7 @@ pub fn transcribe(cx: &ExtCtxt, } } else { let ident = - Ident { ctxt: ident.ctxt.apply_mark(cx.current_expansion.mark), ..ident }; + Ident::new(ident.name, ident.span.apply_mark(cx.current_expansion.mark)); sp = sp.with_ctxt(sp.ctxt().apply_mark(cx.current_expansion.mark)); result.push(TokenTree::Token(sp, token::Dollar).into()); result.push(TokenTree::Token(sp, token::Token::from_ast_ident(ident)).into()); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 068929c8948df..152c4c31eb3e3 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -76,7 +76,7 @@ impl<'a> StringReader<'a> { fn mk_ident(&self, string: &str) -> Ident { let mut ident = Ident::from_str(string); if let Some(span) = self.override_span { - ident.ctxt = span.ctxt(); + ident.span = span; } ident } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index c3785c10f6905..93afaceec4833 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -738,7 +738,7 @@ pub trait PrintState<'a> { segment.identifier.name != keywords::DollarCrate.name() { self.writer().word(&segment.identifier.name.as_str())?; } else if segment.identifier.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.identifier.ctxt)?; + self.print_dollar_crate(segment.identifier.span.ctxt())?; } } self.writer().space()?; @@ -2415,7 +2415,7 @@ impl<'a> State<'a> { self.print_path_parameters(parameters, colons_before_params)?; } } else if segment.identifier.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.identifier.ctxt)?; + self.print_dollar_crate(segment.identifier.span.ctxt())?; } Ok(()) } diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index d513008f0e2d3..2b80d69876423 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -9,6 +9,7 @@ // except according to those terms. use syntax::ast; +use syntax::codemap::DUMMY_SP; use syntax::ext::base::*; use syntax::ext::base; use syntax::feature_gate; @@ -16,7 +17,6 @@ use syntax::parse::token; use syntax::ptr::P; use syntax_pos::Span; use syntax_pos::symbol::Symbol; -use syntax_pos::hygiene::SyntaxContext; use syntax::tokenstream::TokenTree; pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, @@ -53,11 +53,8 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, } } } - let res = ast::Ident { - name: Symbol::intern(&res_str), - ctxt: SyntaxContext::empty().apply_mark(cx.current_expansion.mark), - }; - + let res = ast::Ident::new(Symbol::intern(&res_str), + DUMMY_SP.apply_mark(cx.current_expansion.mark)); struct Result { ident: ast::Ident, span: Span, diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index cc3e8b6e6b7c0..25a2969448835 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -18,10 +18,9 @@ use syntax::ast; use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind}; use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; -use syntax::codemap::respan; +use syntax::codemap::{respan, DUMMY_SP}; use syntax::ptr::P; use syntax_pos::Span; -use syntax_pos::hygiene::SyntaxContext; use syntax_pos::symbol::keywords; /// The types of pointers @@ -93,8 +92,8 @@ impl<'a> Path<'a> { PathKind::Global => cx.path_all(span, true, idents, lt, tys, Vec::new()), PathKind::Local => cx.path_all(span, false, idents, lt, tys, Vec::new()), PathKind::Std => { - let def_site = SyntaxContext::empty().apply_mark(cx.current_expansion.mark); - idents.insert(0, Ident { ctxt: def_site, ..keywords::DollarCrate.ident() }); + let def_site = DUMMY_SP.apply_mark(cx.current_expansion.mark); + idents.insert(0, Ident::new(keywords::DollarCrate.name(), def_site)); cx.path_all(span, false, idents, lt, tys, Vec::new()) } } diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index aba71bd046831..c180563450f83 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -123,7 +123,7 @@ pub struct HygieneData { marks: Vec, syntax_contexts: Vec, markings: HashMap<(SyntaxContext, Mark), SyntaxContext>, - gensym_to_ctxt: HashMap, + gensym_to_ctxt: HashMap, } impl HygieneData { @@ -461,7 +461,7 @@ impl Symbol { pub fn from_ident(ident: Ident) -> Symbol { HygieneData::with(|data| { let gensym = ident.name.gensymed(); - data.gensym_to_ctxt.insert(gensym, ident.ctxt); + data.gensym_to_ctxt.insert(gensym, ident.span); gensym }) } @@ -469,7 +469,7 @@ impl Symbol { pub fn to_ident(self) -> Ident { HygieneData::with(|data| { match data.gensym_to_ctxt.get(&self) { - Some(&ctxt) => Ident { name: self.interned(), ctxt: ctxt }, + Some(&span) => Ident::new(self.interned(), span), None => Ident::with_empty_ctxt(self), } }) diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index eb345200f413d..8b2ebfef2504e 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -50,7 +50,7 @@ extern crate serialize as rustc_serialize; // used by deriving extern crate unicode_width; pub mod hygiene; -pub use hygiene::{SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind}; +pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind}; mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; @@ -422,6 +422,52 @@ impl Span { if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt }, ) } + + #[inline] + pub fn apply_mark(self, mark: Mark) -> Span { + let span = self.data(); + span.with_ctxt(span.ctxt.apply_mark(mark)) + } + + #[inline] + pub fn remove_mark(&mut self) -> Mark { + let mut span = self.data(); + let mark = span.ctxt.remove_mark(); + *self = Span::new(span.lo, span.hi, span.ctxt); + mark + } + + #[inline] + pub fn adjust(&mut self, expansion: Mark) -> Option { + let mut span = self.data(); + let mark = span.ctxt.adjust(expansion); + *self = Span::new(span.lo, span.hi, span.ctxt); + mark + } + + #[inline] + pub fn glob_adjust(&mut self, expansion: Mark, glob_ctxt: SyntaxContext) + -> Option> { + let mut span = self.data(); + let mark = span.ctxt.glob_adjust(expansion, glob_ctxt); + *self = Span::new(span.lo, span.hi, span.ctxt); + mark + } + + #[inline] + pub fn reverse_glob_adjust(&mut self, expansion: Mark, glob_ctxt: SyntaxContext) + -> Option> { + let mut span = self.data(); + let mark = span.ctxt.reverse_glob_adjust(expansion, glob_ctxt); + *self = Span::new(span.lo, span.hi, span.ctxt); + mark + } + + #[inline] + pub fn modern(self) -> Span { + let span = self.data(); + span.with_ctxt(span.ctxt.modern()) + } } #[derive(Clone, Debug)] diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 098eafef2585c..661a28d837535 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -13,21 +13,27 @@ //! type, and vice versa. use hygiene::SyntaxContext; -use GLOBALS; +use {Span, DUMMY_SP, GLOBALS}; use serialize::{Decodable, Decoder, Encodable, Encoder}; use std::collections::HashMap; use std::fmt; +use std::hash::{Hash, Hasher}; -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Eq)] pub struct Ident { pub name: Symbol, - pub ctxt: SyntaxContext, + pub span: Span, } impl Ident { + #[inline] + pub const fn new(name: Symbol, span: Span) -> Ident { + Ident { name, span } + } + #[inline] pub const fn with_empty_ctxt(name: Symbol) -> Ident { - Ident { name: name, ctxt: SyntaxContext::empty() } + Ident::new(name, DUMMY_SP) } /// Maps a string to an identifier with an empty syntax context. @@ -36,17 +42,30 @@ impl Ident { } pub fn without_first_quote(&self) -> Ident { - Ident { name: Symbol::from(self.name.as_str().trim_left_matches('\'')), ctxt: self.ctxt } + Ident::new(Symbol::from(self.name.as_str().trim_left_matches('\'')), self.span) } pub fn modern(self) -> Ident { - Ident { name: self.name, ctxt: self.ctxt.modern() } + Ident::new(self.name, self.span.modern()) + } +} + +impl PartialEq for Ident { + fn eq(&self, rhs: &Self) -> bool { + self.name == rhs.name && self.span.ctxt() == rhs.span.ctxt() + } +} + +impl Hash for Ident { + fn hash(&self, state: &mut H) { + self.name.hash(state); + self.span.ctxt().hash(state); } } impl fmt::Debug for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}{:?}", self.name, self.ctxt) + write!(f, "{}{:?}", self.name, self.span.ctxt()) } } @@ -58,7 +77,7 @@ impl fmt::Display for Ident { impl Encodable for Ident { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - if self.ctxt.modern() == SyntaxContext::empty() { + if self.span.ctxt().modern() == SyntaxContext::empty() { s.emit_str(&self.name.as_str()) } else { // FIXME(jseyfried) intercrate hygiene let mut string = "#".to_owned(); From 8cde9ad682b075ccee7cc06ab8d677090a3b61f5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 18 Mar 2018 03:53:41 +0300 Subject: [PATCH 23/32] Rename `PathSegment::identifier` to `ident` --- src/librustc/hir/lowering.rs | 6 ++-- src/librustc/ich/impls_syntax.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 8 ++--- src/librustc_resolve/lib.rs | 12 ++++---- src/librustc_resolve/macros.rs | 12 ++++---- src/librustdoc/clean/mod.rs | 12 ++------ src/libsyntax/ast.rs | 20 +++++-------- src/libsyntax/attr.rs | 6 ++-- src/libsyntax/ext/build.rs | 6 ++-- src/libsyntax/ext/derive.rs | 2 +- src/libsyntax/ext/expand.rs | 8 ++--- src/libsyntax/ext/quote.rs | 2 +- src/libsyntax/feature_gate.rs | 4 +-- src/libsyntax/fold.rs | 6 ++-- src/libsyntax/parse/parser.rs | 4 +-- src/libsyntax/print/pprust.rs | 24 +++++++-------- src/libsyntax/visit.rs | 2 +- src/libsyntax_ext/deriving/generic/mod.rs | 4 +-- .../pprust-expr-roundtrip.rs | 29 ++++--------------- 19 files changed, 67 insertions(+), 102 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 382a77a140ba0..84687353e47f5 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1607,7 +1607,7 @@ impl<'a> LoweringContext<'a> { } hir::PathSegment::new( - self.lower_ident(segment.identifier), + self.lower_ident(segment.ident), parameters, infer_types, ) @@ -2356,11 +2356,11 @@ impl<'a> LoweringContext<'a> { // Correctly resolve `self` imports if path.segments.len() > 1 - && path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() + && path.segments.last().unwrap().ident.name == keywords::SelfValue.name() { let _ = path.segments.pop(); if rename.is_none() { - *name = path.segments.last().unwrap().identifier.name; + *name = path.segments.last().unwrap().ident.name; } } diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 425459f448fad..e3b0d2c9d2cc5 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -211,7 +211,7 @@ impl<'a> HashStable> for ast::Attribute { style.hash_stable(hcx, hasher); path.segments.len().hash_stable(hcx, hasher); for segment in &path.segments { - segment.identifier.name.hash_stable(hcx, hasher); + segment.ident.name.hash_stable(hcx, hasher); } for tt in tokens.trees() { tt.hash_stable(hcx, hasher); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 695dbeb7b633e..654ba34fe21db 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -115,7 +115,7 @@ impl<'a> Resolver<'a> { let mut module_path: Vec<_> = prefix.segments.iter() .chain(path.segments.iter()) - .map(|seg| respan(seg.span, seg.identifier)) + .map(|seg| respan(seg.span, seg.ident)) .collect(); match use_tree.kind { @@ -196,11 +196,7 @@ impl<'a> Resolver<'a> { ast::UseTreeKind::Nested(ref items) => { let prefix = ast::Path { segments: module_path.iter() - .map(|s| ast::PathSegment { - identifier: s.node, - span: s.span, - parameters: None, - }) + .map(|s| ast::PathSegment::from_ident(s.node, s.span)) .collect(), span: path.span, }; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 443a2a938c7ae..cd06d431c78d1 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2350,7 +2350,7 @@ impl<'a> Resolver<'a> { let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { let path: Vec<_> = trait_ref.path.segments.iter() - .map(|seg| respan(seg.span, seg.identifier)) + .map(|seg| respan(seg.span, seg.ident)) .collect(); let def = self.smart_resolve_path_fragment( trait_ref.ref_id, @@ -2785,7 +2785,7 @@ impl<'a> Resolver<'a> { source: PathSource) -> PathResolution { let segments = &path.segments.iter() - .map(|seg| respan(seg.span, seg.identifier)) + .map(|seg| respan(seg.span, seg.ident)) .collect::>(); self.smart_resolve_path_fragment(id, qself, segments, path.span, source) } @@ -2923,7 +2923,7 @@ impl<'a> Resolver<'a> { } ExprKind::MethodCall(ref segment, ..) => { err.span_label(parent.span, format!("did you mean `{}::{}(...)`?", - path_str, segment.identifier)); + path_str, segment.ident)); return (err, candidates); } _ => {} @@ -3749,7 +3749,7 @@ impl<'a> Resolver<'a> { ExprKind::MethodCall(ref segment, ..) => { debug!("(recording candidate traits for expr) recording traits for {}", expr.id); - let traits = self.get_traits_containing_item(segment.identifier, ValueNS); + let traits = self.get_traits_containing_item(segment.ident, ValueNS); self.trait_map.insert(expr.id, traits); } _ => { @@ -4221,7 +4221,7 @@ impl<'a> Resolver<'a> { if attr.path.segments.len() > 1 { continue } - let ident = attr.path.segments[0].identifier; + let ident = attr.path.segments[0].ident; let result = self.resolve_lexical_macro_path_segment(ident, MacroNS, false, @@ -4266,7 +4266,7 @@ fn names_to_string(idents: &[SpannedIdent]) -> String { fn path_names_to_string(path: &Path) -> String { names_to_string(&path.segments.iter() - .map(|seg| respan(seg.span, seg.identifier)) + .map(|seg| respan(seg.span, seg.ident)) .collect::>()) } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 289556cd45e0f..c65ee11e427fa 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -137,9 +137,9 @@ impl<'a> base::Resolver for Resolver<'a> { impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> { fn fold_path(&mut self, mut path: ast::Path) -> ast::Path { - let ident = path.segments[0].identifier; + let ident = path.segments[0].ident; if ident.name == keywords::DollarCrate.name() { - path.segments[0].identifier.name = keywords::CrateRoot.name(); + path.segments[0].ident.name = keywords::CrateRoot.name(); let module = self.0.resolve_crate_root(ident.span.ctxt(), true); if !module.is_local() { let span = path.segments[0].span; @@ -249,7 +249,7 @@ impl<'a> base::Resolver for Resolver<'a> { if traits[j].segments.len() > 1 { continue } - let trait_name = traits[j].segments[0].identifier.name; + let trait_name = traits[j].segments[0].ident.name; let legacy_name = Symbol::intern(&format!("derive_{}", trait_name)); if !self.global_macros.contains_key(&legacy_name) { continue @@ -268,7 +268,7 @@ impl<'a> base::Resolver for Resolver<'a> { if k > 0 { tokens.push(TokenTree::Token(path.span, Token::ModSep).into()); } - let tok = Token::from_ast_ident(segment.identifier); + let tok = Token::from_ast_ident(segment.ident); tokens.push(TokenTree::Token(path.span, tok).into()); } } @@ -365,7 +365,7 @@ impl<'a> Resolver<'a> { } let attr_name = match path.segments.len() { - 1 => path.segments[0].identifier.name, + 1 => path.segments[0].ident.name, _ => return Err(determinacy), }; for path in traits { @@ -413,7 +413,7 @@ impl<'a> Resolver<'a> { kind: MacroKind, force: bool) -> Result { let ast::Path { ref segments, span } = *path; - let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.identifier)).collect(); + let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.ident)).collect(); let invocation = self.invocations[&scope]; let module = invocation.module.get(); self.current_module = if module.is_trait() { module.parent.unwrap() } else { module }; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e3ba482eecfee..147730673cd86 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1121,16 +1121,8 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option fn macro_resolve(cx: &DocContext, path_str: &str) -> Option { use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::hygiene::Mark; - let segment = ast::PathSegment { - identifier: ast::Ident::from_str(path_str), - span: DUMMY_SP, - parameters: None, - }; - let path = ast::Path { - span: DUMMY_SP, - segments: vec![segment], - }; - + let segment = ast::PathSegment::from_ident(ast::Ident::from_str(path_str), DUMMY_SP); + let path = ast::Path { segments: vec![segment], span: DUMMY_SP }; let mut resolver = cx.resolver.borrow_mut(); let mark = Mark::root(); let res = resolver diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 63ac4c38a7957..3f4cb52903c34 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -82,7 +82,7 @@ pub struct Path { impl<'a> PartialEq<&'a str> for Path { fn eq(&self, string: &&'a str) -> bool { - self.segments.len() == 1 && self.segments[0].identifier.name == *string + self.segments.len() == 1 && self.segments[0].ident.name == *string } } @@ -101,17 +101,17 @@ impl fmt::Display for Path { impl Path { // convert a span and an identifier to the corresponding // 1-segment path - pub fn from_ident(s: Span, identifier: Ident) -> Path { + pub fn from_ident(s: Span, ident: Ident) -> Path { Path { span: s, - segments: vec![PathSegment::from_ident(identifier, s)], + segments: vec![PathSegment::from_ident(ident, s)], } } // Make a "crate root" segment for this path unless it already has it // or starts with something like `self`/`super`/`$crate`/etc. pub fn make_root(&self) -> Option { - if let Some(ident) = self.segments.get(0).map(|seg| seg.identifier) { + if let Some(ident) = self.segments.get(0).map(|seg| seg.ident) { if ::parse::token::is_path_segment_keyword(ident) && ident.name != keywords::Crate.name() { return None; @@ -121,7 +121,7 @@ impl Path { } pub fn is_global(&self) -> bool { - !self.segments.is_empty() && self.segments[0].identifier.name == keywords::CrateRoot.name() + !self.segments.is_empty() && self.segments[0].ident.name == keywords::CrateRoot.name() } } @@ -131,7 +131,7 @@ impl Path { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct PathSegment { /// The identifier portion of this path segment. - pub identifier: Ident, + pub ident: Ident, /// Span of the segment identifier. pub span: Span, @@ -146,14 +146,10 @@ pub struct PathSegment { impl PathSegment { pub fn from_ident(ident: Ident, span: Span) -> Self { - PathSegment { identifier: ident, span: span, parameters: None } + PathSegment { ident, span, parameters: None } } pub fn crate_root(span: Span) -> Self { - PathSegment { - identifier: Ident::new(keywords::CrateRoot.name(), span), - span, - parameters: None, - } + PathSegment::from_ident(Ident::new(keywords::CrateRoot.name(), span), span) } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 5954b9eb27475..739679b71d5b1 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -215,7 +215,7 @@ impl Attribute { pub fn name(&self) -> Option { match self.path.segments.len() { - 1 => Some(self.path.segments[0].identifier.name), + 1 => Some(self.path.segments[0].ident.name), _ => None, } } @@ -301,7 +301,7 @@ impl Attribute { let mut tokens = self.tokens.trees().peekable(); Some(MetaItem { name: match self.path.segments.len() { - 1 => self.path.segments[0].identifier.name, + 1 => self.path.segments[0].ident.name, _ => return None, }, node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) { @@ -353,7 +353,7 @@ impl Attribute { } Ok(MetaItem { - name: self.path.segments.last().unwrap().identifier.name, + name: self.path.segments.last().unwrap().ident.name, node: self.parse(sess, |parser| parser.parse_meta_item_kind())?, span: self.span, }) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 269517e998f5b..8dabc03c2f95b 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -319,7 +319,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { types: Vec>, bindings: Vec ) -> ast::Path { - let last_identifier = idents.pop().unwrap(); + let last_ident = idents.pop().unwrap(); let mut segments: Vec = Vec::new(); segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, span))); @@ -328,7 +328,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } else { None }; - segments.push(ast::PathSegment { identifier: last_identifier, span, parameters }); + segments.push(ast::PathSegment { ident: last_ident, span, parameters }); let mut path = ast::Path { span, segments }; if global { if let Some(seg) = path.make_root() { @@ -367,7 +367,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { None }; path.segments.push(ast::PathSegment { - identifier: ident.node, + ident: ident.node, span: ident.span, parameters, }); diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index c7fa0331c1bd5..6bf166dfe950a 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -54,7 +54,7 @@ pub fn add_derived_markers(cx: &mut ExtCtxt, span: Span, traits: &[ast::Path] pretty_name.push_str(", "); } pretty_name.push_str(&path.to_string()); - names.insert(unwrap_or!(path.segments.get(0), continue).identifier.name); + names.insert(unwrap_or!(path.segments.get(0), continue).ident.name); } pretty_name.push(')'); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 148eb71f70ee5..eb33cbc21c343 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -164,10 +164,10 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat { path_str.push_str("::"); } - if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != keywords::DollarCrate.name() + if segment.ident.name != keywords::CrateRoot.name() && + segment.ident.name != keywords::DollarCrate.name() { - path_str.push_str(&segment.identifier.name.as_str()) + path_str.push_str(&segment.ident.name.as_str()) } } @@ -678,7 +678,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { opt_expanded } else { let msg = format!("non-{kind} macro in {kind} position: {name}", - name = path.segments[0].identifier.name, kind = kind.name()); + name = path.segments[0].ident.name, kind = kind.name()); self.cx.span_err(path.span, &msg); self.cx.trace_macros_diag(); kind.dummy(span) diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 540a03ff032ff..b412c2fbc7f7c 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -239,7 +239,7 @@ pub mod rt { inner.push(TokenTree::Token(self.span, token::Colon).into()); } inner.push(TokenTree::Token( - self.span, token::Token::from_ast_ident(segment.identifier) + self.span, token::Token::from_ast_ident(segment.ident) ).into()); } inner.push(self.tokens.clone()); diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e734a4e373534..2a3cf4960d265 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1756,10 +1756,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) { for segment in &path.segments { - if segment.identifier.name == keywords::Crate.name() { + if segment.ident.name == keywords::Crate.name() { gate_feature_post!(&self, crate_in_paths, segment.span, "`crate` in paths is experimental"); - } else if segment.identifier.name == keywords::Extern.name() { + } else if segment.ident.name == keywords::Extern.name() { gate_feature_post!(&self, extern_in_paths, segment.span, "`extern` in paths is experimental"); } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index e702bf56e7f83..06d0033000172 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -445,8 +445,8 @@ pub fn noop_fold_usize(i: usize, _: &mut T) -> usize { pub fn noop_fold_path(Path { segments, span }: Path, fld: &mut T) -> Path { Path { - segments: segments.move_map(|PathSegment {identifier, span, parameters}| PathSegment { - identifier: fld.fold_ident(identifier), + segments: segments.move_map(|PathSegment {ident, span, parameters}| PathSegment { + ident: fld.fold_ident(ident), span: fld.new_span(span), parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))), }), @@ -1181,7 +1181,7 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::MethodCall(seg, args) => { ExprKind::MethodCall( PathSegment { - identifier: folder.fold_ident(seg.identifier), + ident: folder.fold_ident(seg.ident), span: folder.new_span(seg.span), parameters: seg.parameters.map(|ps| { ps.map(|ps| folder.fold_path_parameters(ps)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f5ab023b30e8f..2ddc54967b55c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2071,7 +2071,7 @@ impl<'a> Parser<'a> { ParenthesizedParameterData { inputs, output, span }.into() }; - PathSegment { identifier: ident, span: ident_span, parameters } + PathSegment { ident, span: ident_span, parameters } } else { // Generic arguments are not found. PathSegment::from_ident(ident, ident_span) @@ -2612,7 +2612,7 @@ impl<'a> Parser<'a> { } let span = lo.to(self.prev_span); - let ident = respan(segment.span, segment.identifier); + let ident = respan(segment.span, segment.ident); self.mk_expr(span, ExprKind::Field(self_arg, ident), ThinVec::new()) } }) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 93afaceec4833..f7a1acb169f61 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -734,11 +734,11 @@ pub trait PrintState<'a> { if i > 0 { self.writer().word("::")? } - if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != keywords::DollarCrate.name() { - self.writer().word(&segment.identifier.name.as_str())?; - } else if segment.identifier.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.identifier.span.ctxt())?; + if segment.ident.name != keywords::CrateRoot.name() && + segment.ident.name != keywords::DollarCrate.name() { + self.writer().word(&segment.ident.name.as_str())?; + } else if segment.ident.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.ident.span.ctxt())?; } } self.writer().space()?; @@ -1972,7 +1972,7 @@ impl<'a> State<'a> { let base_args = &args[1..]; self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?; self.s.word(".")?; - self.print_ident(segment.identifier)?; + self.print_ident(segment.ident)?; if let Some(ref parameters) = segment.parameters { self.print_path_parameters(parameters, true)?; } @@ -2408,14 +2408,14 @@ impl<'a> State<'a> { colons_before_params: bool) -> io::Result<()> { - if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != keywords::DollarCrate.name() { - self.print_ident(segment.identifier)?; + if segment.ident.name != keywords::CrateRoot.name() && + segment.ident.name != keywords::DollarCrate.name() { + self.print_ident(segment.ident)?; if let Some(ref parameters) = segment.parameters { self.print_path_parameters(parameters, colons_before_params)?; } - } else if segment.identifier.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.identifier.span.ctxt())?; + } else if segment.ident.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.ident.span.ctxt())?; } Ok(()) } @@ -2437,7 +2437,7 @@ impl<'a> State<'a> { self.s.word(">")?; self.s.word("::")?; let item_segment = path.segments.last().unwrap(); - self.print_ident(item_segment.identifier)?; + self.print_ident(item_segment.ident)?; match item_segment.parameters { Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params), None => Ok(()), diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index d8de78054ab6f..9a1a2a30b9fa3 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -372,7 +372,7 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>( pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V, path_span: Span, segment: &'a PathSegment) { - visitor.visit_ident(path_span, segment.identifier); + visitor.visit_ident(path_span, segment.ident); if let Some(ref parameters) = segment.parameters { visitor.visit_path_parameters(path_span, parameters); } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 3935f1722b615..c51f44cdeced2 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -367,7 +367,7 @@ fn find_type_parameters(ty: &ast::Ty, fn visit_ty(&mut self, ty: &'a ast::Ty) { if let ast::TyKind::Path(_, ref path) = ty.node { if let Some(segment) = path.segments.first() { - if self.ty_param_names.contains(&segment.identifier.name) { + if self.ty_param_names.contains(&segment.ident.name) { self.types.push(P(ty.clone())); } } @@ -622,7 +622,7 @@ impl<'a> TraitDef<'a> { // if we have already handled this type, skip it if let ast::TyKind::Path(_, ref p) = ty.node { if p.segments.len() == 1 && - ty_param_names.contains(&p.segments[0].identifier.name) || + ty_param_names.contains(&p.segments[0].ident.name) || processed_field_types.contains(&p.segments) { continue; }; diff --git a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs index 920760cd34ac8..0406d2d22f435 100644 --- a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs @@ -61,15 +61,8 @@ fn expr(kind: ExprKind) -> P { } fn make_x() -> P { - let seg = PathSegment { - identifier: Ident::from_str("x"), - span: DUMMY_SP, - parameters: None, - }; - let path = Path { - span: DUMMY_SP, - segments: vec![seg], - }; + let seg = PathSegment::from_ident(Ident::from_str("x"), DUMMY_SP); + let path = Path { segments: vec![seg], span: DUMMY_SP }; expr(ExprKind::Path(None, path)) } @@ -89,12 +82,7 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P)) { 0 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Box(e))), 1 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))), 2 => { - let seg = PathSegment { - identifier: Ident::from_str("x"), - span: DUMMY_SP, - parameters: None, - }; - + let seg = PathSegment::from_ident(Ident::from_str("x"), DUMMY_SP); iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall( seg.clone(), vec![e, make_x()]))); iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall( @@ -163,15 +151,8 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P)) { iter_exprs(depth - 1, &mut |e| g(ExprKind::Ret(Some(e)))); }, 14 => { - let seg = PathSegment { - identifier: Ident::from_str("S"), - span: DUMMY_SP, - parameters: None, - }; - let path = Path { - span: DUMMY_SP, - segments: vec![seg], - }; + let seg = PathSegment::new(Ident::from_str("S"), DUMMY_SP); + let path = Path { segments: vec![seg], span: DUMMY_SP }; g(ExprKind::Struct(path, vec![], Some(make_x()))); }, 15 => { From 2e622b138ce13f7ac52dfaa5f1fc9d39f370b633 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 18 Mar 2018 16:47:09 +0300 Subject: [PATCH 24/32] Get rid of `SpannedIdent` --- src/librustc/hir/lowering.rs | 14 +-- src/librustc_lint/builtin.rs | 10 +- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/hair/pattern/mod.rs | 6 +- src/librustc_resolve/build_reduced_graph.rs | 15 ++- src/librustc_resolve/lib.rs | 133 ++++++++++---------- src/librustc_resolve/macros.rs | 17 +-- src/librustc_resolve/resolve_imports.rs | 28 ++--- src/librustc_save_analysis/lib.rs | 12 +- src/librustc_save_analysis/sig.rs | 2 +- src/libsyntax/ast.rs | 16 ++- src/libsyntax/attr.rs | 2 +- src/libsyntax/ext/base.rs | 2 +- src/libsyntax/ext/build.rs | 23 ++-- src/libsyntax/ext/quote.rs | 2 +- src/libsyntax/ext/tt/macro_parser.rs | 6 +- src/libsyntax/fold.rs | 26 ++-- src/libsyntax/parse/parser.rs | 67 +++++----- src/libsyntax/parse/token.rs | 6 +- src/libsyntax/print/pprust.rs | 50 ++++---- src/libsyntax/visit.rs | 10 +- src/libsyntax_ext/concat_idents.rs | 33 ++--- src/libsyntax_ext/deriving/generic/mod.rs | 10 +- src/libsyntax_pos/symbol.rs | 7 +- 24 files changed, 230 insertions(+), 271 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 84687353e47f5..73bc2c4259d1c 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1720,7 +1720,7 @@ impl<'a> LoweringContext<'a> { decl.inputs .iter() .map(|arg| match arg.pat.node { - PatKind::Ident(_, ident, None) => respan(ident.span, ident.node.name), + PatKind::Ident(_, ident, None) => respan(ident.span, ident.name), _ => respan(arg.pat.span, keywords::Invalid.name()), }) .collect() @@ -2099,7 +2099,7 @@ impl<'a> LoweringContext<'a> { fn lower_field(&mut self, f: &Field) -> hir::Field { hir::Field { - name: respan(f.ident.span, self.lower_ident(f.ident.node)), + name: respan(f.ident.span, self.lower_ident(f.ident)), expr: P(self.lower_expr(&f.expr)), span: f.span, is_shorthand: f.is_shorthand, @@ -2800,7 +2800,7 @@ impl<'a> LoweringContext<'a> { fn lower_pat(&mut self, p: &Pat) -> P { let node = match p.node { PatKind::Wild => hir::PatKind::Wild, - PatKind::Ident(ref binding_mode, pth1, ref sub) => { + PatKind::Ident(ref binding_mode, ident, ref sub) => { match self.resolver.get_resolution(p.id).map(|d| d.base_def()) { // `None` can occur in body-less function signatures def @ None | def @ Some(Def::Local(_)) => { @@ -2811,16 +2811,16 @@ impl<'a> LoweringContext<'a> { hir::PatKind::Binding( self.lower_binding_mode(binding_mode), canonical_id, - respan(pth1.span, pth1.node.name), + respan(ident.span, ident.name), sub.as_ref().map(|x| self.lower_pat(x)), ) } Some(def) => hir::PatKind::Path(hir::QPath::Resolved( None, P(hir::Path { - span: pth1.span, + span: ident.span, def, - segments: hir_vec![hir::PathSegment::from_name(pth1.node.name)], + segments: hir_vec![hir::PathSegment::from_name(ident.name)], }), )), } @@ -3070,7 +3070,7 @@ impl<'a> LoweringContext<'a> { ), ExprKind::Field(ref el, ident) => hir::ExprField( P(self.lower_expr(el)), - respan(ident.span, self.lower_ident(ident.node)), + respan(ident.span, self.lower_ident(ident)), ), ExprKind::TupField(ref el, ident) => hir::ExprTupField(P(self.lower_expr(el)), ident), ExprKind::Index(ref el, ref er) => { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c0728cb2b6669..2cc6708bc034e 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -171,16 +171,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns { if fieldpat.node.is_shorthand { continue; } - if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node { - if ident.node == fieldpat.node.name { + if let PatKind::Binding(_, _, name, None) = fieldpat.node.pat.node { + if name.node == fieldpat.node.name { let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, &format!("the `{}:` in this pattern is redundant", - ident.node)); + name.node)); let subspan = cx.tcx.sess.codemap().span_through_char(fieldpat.span, ':'); err.span_suggestion_short(subspan, "remove this", - format!("{}", ident.node)); + format!("{}", name.node)); err.emit(); } } @@ -625,7 +625,7 @@ impl EarlyLintPass for AnonymousParameters { for arg in sig.decl.inputs.iter() { match arg.pat.node { ast::PatKind::Ident(_, ident, None) => { - if ident.node.name == keywords::Invalid.name() { + if ident.name == keywords::Invalid.name() { cx.span_lint(ANONYMOUS_PARAMETERS, arg.pat.span, "use of deprecated anonymous parameter"); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 8494c043f90fc..576f48afc9373 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -467,8 +467,8 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, mutability: Mutability::Not, }; if let Some(hir::map::NodeBinding(pat)) = tcx.hir.find(var_id) { - if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node { - decl.debug_name = ident.node; + if let hir::PatKind::Binding(_, _, ref name, _) = pat.node { + decl.debug_name = name.node; let bm = *hir.tables.pat_binding_modes() .get(pat.hir_id) diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 798d635318180..c3f41e8ac4827 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -466,7 +466,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } } - PatKind::Binding(_, id, ref ident, ref sub) => { + PatKind::Binding(_, id, ref name, ref sub) => { let var_ty = self.tables.node_id_to_type(pat.hir_id); let region = match var_ty.sty { ty::TyRef(r, _) => Some(r), @@ -493,14 +493,14 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { if let ty::TyRef(_, mt) = ty.sty { ty = mt.ty; } else { - bug!("`ref {}` has wrong type {}", ident.node, ty); + bug!("`ref {}` has wrong type {}", name.node, ty); } } PatternKind::Binding { mutability, mode, - name: ident.node, + name: name.node, var: id, ty: var_ty, subpattern: self.lower_opt_pattern(sub), diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 654ba34fe21db..43dfc76c4c9f5 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -34,7 +34,6 @@ use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind, Variant}; -use syntax::codemap::respan; use syntax::ext::base::SyntaxExtension; use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::hygiene::Mark; @@ -115,13 +114,13 @@ impl<'a> Resolver<'a> { let mut module_path: Vec<_> = prefix.segments.iter() .chain(path.segments.iter()) - .map(|seg| respan(seg.span, seg.ident)) + .map(|seg| seg.ident) .collect(); match use_tree.kind { ast::UseTreeKind::Simple(rename) => { let mut ident = use_tree.ident(); - let mut source = module_path.pop().unwrap().node; + let mut source = module_path.pop().unwrap(); let mut type_ns_only = false; if nested { @@ -130,7 +129,7 @@ impl<'a> Resolver<'a> { type_ns_only = true; let last_segment = *module_path.last().unwrap(); - if last_segment.node.name == keywords::CrateRoot.name() { + if last_segment.name == keywords::CrateRoot.name() { resolve_error( self, use_tree.span, @@ -142,9 +141,9 @@ impl<'a> Resolver<'a> { // Replace `use foo::self;` with `use foo;` let _ = module_path.pop(); - source = last_segment.node; + source = last_segment; if rename.is_none() { - ident = last_segment.node; + ident = last_segment; } } } else { @@ -195,8 +194,8 @@ impl<'a> Resolver<'a> { } ast::UseTreeKind::Nested(ref items) => { let prefix = ast::Path { - segments: module_path.iter() - .map(|s| ast::PathSegment::from_ident(s.node, s.span)) + segments: module_path.into_iter() + .map(|ident| ast::PathSegment::from_ident(ident, ident.span)) .collect(), span: path.span, }; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index cd06d431c78d1..a51b96acfbb5d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -41,9 +41,9 @@ use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; -use syntax::codemap::{dummy_spanned, respan, BytePos, CodeMap}; +use syntax::codemap::{BytePos, CodeMap}; use syntax::ext::hygiene::{Mark, MarkKind, SyntaxContext}; -use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy}; +use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::base::MacroKind; @@ -1653,8 +1653,8 @@ impl<'a> Resolver<'a> { { let namespace = if is_value { ValueNS } else { TypeNS }; let hir::Path { ref segments, span, ref mut def } = *path; - let path: Vec = segments.iter() - .map(|seg| respan(span, Ident::with_empty_ctxt(seg.name))) + let path: Vec = segments.iter() + .map(|seg| Ident::new(seg.name, span)) .collect(); match self.resolve_path(&path, Some(namespace), true, span) { PathResult::Module(module) => *def = module.def().unwrap(), @@ -2350,7 +2350,7 @@ impl<'a> Resolver<'a> { let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { let path: Vec<_> = trait_ref.path.segments.iter() - .map(|seg| respan(seg.span, seg.ident)) + .map(|seg| seg.ident) .collect(); let def = self.smart_resolve_path_fragment( trait_ref.ref_id, @@ -2499,7 +2499,7 @@ impl<'a> Resolver<'a> { _ => false, } { let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode }; - binding_map.insert(ident.node, binding_info); + binding_map.insert(ident, binding_info); } } true @@ -2639,7 +2639,7 @@ impl<'a> Resolver<'a> { } fn fresh_binding(&mut self, - ident: &SpannedIdent, + ident: Ident, pat_id: NodeId, outer_pat_id: NodeId, pat_src: PatternSource, @@ -2651,14 +2651,14 @@ impl<'a> Resolver<'a> { // because that breaks the assumptions later // passes make about or-patterns.) let mut def = Def::Local(pat_id); - match bindings.get(&ident.node).cloned() { + match bindings.get(&ident).cloned() { Some(id) if id == outer_pat_id => { // `Variant(a, a)`, error resolve_error( self, ident.span, ResolutionError::IdentifierBoundMoreThanOnceInSamePattern( - &ident.node.name.as_str()) + &ident.name.as_str()) ); } Some(..) if pat_src == PatternSource::FnParam => { @@ -2667,7 +2667,7 @@ impl<'a> Resolver<'a> { self, ident.span, ResolutionError::IdentifierBoundMoreThanOnceInParameterList( - &ident.node.name.as_str()) + &ident.name.as_str()) ); } Some(..) if pat_src == PatternSource::Match || @@ -2675,7 +2675,7 @@ impl<'a> Resolver<'a> { pat_src == PatternSource::WhileLet => { // `Variant1(a) | Variant2(a)`, ok // Reuse definition from the first `a`. - def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident.node]; + def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident]; } Some(..) => { span_bug!(ident.span, "two bindings with the same name from \ @@ -2683,9 +2683,9 @@ impl<'a> Resolver<'a> { } None => { // A completely fresh binding, add to the lists if it's valid. - if ident.node.name != keywords::Invalid.name() { - bindings.insert(ident.node, outer_pat_id); - self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident.node, def); + if ident.name != keywords::Invalid.name() { + bindings.insert(ident, outer_pat_id); + self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident, def); } } } @@ -2703,10 +2703,10 @@ impl<'a> Resolver<'a> { let outer_pat_id = pat.id; pat.walk(&mut |pat| { match pat.node { - PatKind::Ident(bmode, ref ident, ref opt_pat) => { + PatKind::Ident(bmode, ident, ref opt_pat) => { // First try to resolve the identifier as some existing // entity, then fall back to a fresh binding. - let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, + let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, false, pat.span) .and_then(LexicalScopeBinding::item); let resolution = binding.map(NameBinding::def).and_then(|def| { @@ -2718,7 +2718,7 @@ impl<'a> Resolver<'a> { Def::Const(..) if is_syntactic_ambiguity => { // Disambiguate in favor of a unit struct/variant // or constant pattern. - self.record_use(ident.node, ValueNS, binding.unwrap(), ident.span); + self.record_use(ident, ValueNS, binding.unwrap(), ident.span); Some(PathResolution::new(def)) } Def::StructCtor(..) | Def::VariantCtor(..) | @@ -2732,7 +2732,7 @@ impl<'a> Resolver<'a> { self, ident.span, ResolutionError::BindingShadowsSomethingUnacceptable( - pat_src.descr(), ident.node.name, binding.unwrap()) + pat_src.descr(), ident.name, binding.unwrap()) ); None } @@ -2785,7 +2785,7 @@ impl<'a> Resolver<'a> { source: PathSource) -> PathResolution { let segments = &path.segments.iter() - .map(|seg| respan(seg.span, seg.ident)) + .map(|seg| seg.ident) .collect::>(); self.smart_resolve_path_fragment(id, qself, segments, path.span, source) } @@ -2793,7 +2793,7 @@ impl<'a> Resolver<'a> { fn smart_resolve_path_fragment(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[SpannedIdent], + path: &[Ident], span: Span, source: PathSource) -> PathResolution { @@ -2813,11 +2813,11 @@ impl<'a> Resolver<'a> { format!("not a {}", expected), span) } else { - let item_str = path[path.len() - 1].node; + let item_str = path[path.len() - 1]; let item_span = path[path.len() - 1].span; let (mod_prefix, mod_str) = if path.len() == 1 { (format!(""), format!("this scope")) - } else if path.len() == 2 && path[0].node.name == keywords::CrateRoot.name() { + } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() { (format!(""), format!("the crate root")) } else { let mod_path = &path[..path.len() - 1]; @@ -2851,10 +2851,10 @@ impl<'a> Resolver<'a> { // Try to lookup the name in more relaxed fashion for better error reporting. let ident = *path.last().unwrap(); - let candidates = this.lookup_import_candidates(ident.node.name, ns, is_expected); + let candidates = this.lookup_import_candidates(ident.name, ns, is_expected); if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { let enum_candidates = - this.lookup_import_candidates(ident.node.name, ns, is_enum_variant); + this.lookup_import_candidates(ident.name, ns, is_enum_variant); let mut enum_candidates = enum_candidates.iter() .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::>(); enum_candidates.sort(); @@ -2872,8 +2872,8 @@ impl<'a> Resolver<'a> { } } if path.len() == 1 && this.self_type_is_available(span) { - if let Some(candidate) = this.lookup_assoc_candidate(ident.node, ns, is_expected) { - let self_is_available = this.self_value_is_available(path[0].node.span, span); + if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) { + let self_is_available = this.self_value_is_available(path[0].span, span); match candidate { AssocSuggestion::Field => { err.span_suggestion(span, "try", @@ -2918,7 +2918,7 @@ impl<'a> Resolver<'a> { (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node { ExprKind::Field(_, ident) => { err.span_label(parent.span, format!("did you mean `{}::{}`?", - path_str, ident.node)); + path_str, ident)); return (err, candidates); } ExprKind::MethodCall(ref segment, ..) => { @@ -3027,7 +3027,7 @@ impl<'a> Resolver<'a> { // or `::A::B`. If `B` should be resolved in value namespace then // it needs to be added to the trait map. if ns == ValueNS { - let item_name = path.last().unwrap().node; + let item_name = *path.last().unwrap(); let traits = self.get_traits_containing_item(item_name, ns); self.trait_map.insert(id, traits); } @@ -3094,7 +3094,7 @@ impl<'a> Resolver<'a> { fn resolve_qpath_anywhere(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[SpannedIdent], + path: &[Ident], primary_ns: Namespace, span: Span, defer_to_typeck: bool, @@ -3114,10 +3114,10 @@ impl<'a> Resolver<'a> { }; } } - let is_global = self.global_macros.get(&path[0].node.name).cloned() + let is_global = self.global_macros.get(&path[0].name).cloned() .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false); if primary_ns != MacroNS && (is_global || - self.macro_names.contains(&path[0].node.modern())) { + self.macro_names.contains(&path[0].modern())) { // Return some dummy definition, it's enough for error reporting. return Some( PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang)) @@ -3130,7 +3130,7 @@ impl<'a> Resolver<'a> { fn resolve_qpath(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[SpannedIdent], + path: &[Ident], ns: Namespace, span: Span, global_by_default: bool) @@ -3171,8 +3171,8 @@ impl<'a> Resolver<'a> { PathResult::Module(..) | PathResult::Failed(..) if (ns == TypeNS || path.len() > 1) && self.primitive_type_table.primitive_types - .contains_key(&path[0].node.name) => { - let prim = self.primitive_type_table.primitive_types[&path[0].node.name]; + .contains_key(&path[0].name) => { + let prim = self.primitive_type_table.primitive_types[&path[0].name]; PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) } PathResult::Module(module) => PathResolution::new(module.def().unwrap()), @@ -3185,8 +3185,8 @@ impl<'a> Resolver<'a> { }; if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path[0].node.name != keywords::CrateRoot.name() && - path[0].node.name != keywords::DollarCrate.name() { + path[0].name != keywords::CrateRoot.name() && + path[0].name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) { PathResult::NonModule(path_res) => path_res.base_def(), @@ -3204,7 +3204,7 @@ impl<'a> Resolver<'a> { } fn resolve_path(&mut self, - path: &[SpannedIdent], + path: &[Ident], opt_ns: Option, // `None` indicates a module path record_used: bool, path_span: Span) @@ -3216,14 +3216,14 @@ impl<'a> Resolver<'a> { debug!("resolve_path ident {} {:?}", i, ident); let is_last = i == path.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; - let name = ident.node.name; + let name = ident.name; if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() { - let mut ctxt = ident.node.span.ctxt().modern(); + let mut ctxt = ident.span.ctxt().modern(); module = Some(self.resolve_self(&mut ctxt, self.current_module)); continue } else if allow_super && ns == TypeNS && name == keywords::Super.name() { - let mut ctxt = ident.node.span.ctxt().modern(); + let mut ctxt = ident.span.ctxt().modern(); let self_module = match i { 0 => self.resolve_self(&mut ctxt, self.current_module), _ => module.unwrap(), @@ -3243,16 +3243,16 @@ impl<'a> Resolver<'a> { if ns == TypeNS { if (i == 0 && name == keywords::CrateRoot.name()) || (i == 1 && name == keywords::Crate.name() && - path[0].node.name == keywords::CrateRoot.name()) { + path[0].name == keywords::CrateRoot.name()) { // `::a::b` or `::crate::a::b` - module = Some(self.resolve_crate_root(ident.node.span.ctxt(), false)); + module = Some(self.resolve_crate_root(ident.span.ctxt(), false)); continue } else if i == 0 && name == keywords::DollarCrate.name() { // `$crate::a::b` - module = Some(self.resolve_crate_root(ident.node.span.ctxt(), true)); + module = Some(self.resolve_crate_root(ident.span.ctxt(), true)); continue - } else if i == 1 && !token::is_path_segment_keyword(ident.node) { - let prev_name = path[0].node.name; + } else if i == 1 && !token::is_path_segment_keyword(ident) { + let prev_name = path[0].name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() && self.session.features_untracked().extern_absolute_paths { @@ -3275,13 +3275,13 @@ impl<'a> Resolver<'a> { name == keywords::Super.name() && i != 0 || name == keywords::Extern.name() && i != 0 || name == keywords::Crate.name() && i != 1 && - path[0].node.name != keywords::CrateRoot.name() { + path[0].name != keywords::CrateRoot.name() { let name_str = if name == keywords::CrateRoot.name() { format!("crate root") } else { format!("`{}`", name) }; - let msg = if i == 1 && path[0].node.name == keywords::CrateRoot.name() { + let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() { format!("global paths cannot start with {}", name_str) } else if i == 0 && name == keywords::Crate.name() { format!("{} can only be used in absolute paths", name_str) @@ -3292,12 +3292,12 @@ impl<'a> Resolver<'a> { } let binding = if let Some(module) = module { - self.resolve_ident_in_module(module, ident.node, ns, false, record_used, path_span) + self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span) } else if opt_ns == Some(MacroNS) { - self.resolve_lexical_macro_path_segment(ident.node, ns, record_used, path_span) + self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span) .map(MacroBinding::binding) } else { - match self.resolve_ident_in_lexical_scope(ident.node, ns, record_used, path_span) { + match self.resolve_ident_in_lexical_scope(ident, ns, record_used, path_span) { Some(LexicalScopeBinding::Item(binding)) => Ok(binding), Some(LexicalScopeBinding::Def(def)) if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { @@ -3323,7 +3323,7 @@ impl<'a> Resolver<'a> { )); } else { return PathResult::Failed(ident.span, - format!("Not a module `{}`", ident.node), + format!("Not a module `{}`", ident), is_last); } } @@ -3344,12 +3344,12 @@ impl<'a> Resolver<'a> { if let Some(candidate) = candidates.get(0) { format!("Did you mean `{}`?", candidate.path) } else { - format!("Maybe a missing `extern crate {};`?", ident.node) + format!("Maybe a missing `extern crate {};`?", ident) } } else if i == 0 { - format!("Use of undeclared type or module `{}`", ident.node) + format!("Use of undeclared type or module `{}`", ident) } else { - format!("Could not find `{}` in `{}`", ident.node, path[i - 1].node) + format!("Could not find `{}` in `{}`", ident, path[i - 1]) }; return PathResult::Failed(ident.span, msg, is_last); } @@ -3515,7 +3515,7 @@ impl<'a> Resolver<'a> { } fn lookup_typo_candidate(&mut self, - path: &[SpannedIdent], + path: &[Ident], ns: Namespace, filter_fn: FilterFn, span: Span) @@ -3576,7 +3576,7 @@ impl<'a> Resolver<'a> { } } - let name = path[path.len() - 1].node.name; + let name = path[path.len() - 1].name; // Make sure error reporting is deterministic. names.sort_by_key(|name| name.as_str()); match find_best_match_for_name(names.iter(), &name.as_str(), None) { @@ -3738,12 +3738,12 @@ impl<'a> Resolver<'a> { fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) { match expr.node { - ExprKind::Field(_, name) => { + ExprKind::Field(_, ident) => { // FIXME(#6890): Even though you can't treat a method like a // field, we need to add any trait methods we find that match // the field name so that we can do some nice error reporting // later on in typeck. - let traits = self.get_traits_containing_item(name.node, ValueNS); + let traits = self.get_traits_containing_item(ident, ValueNS); self.trait_map.insert(expr.id, traits); } ExprKind::MethodCall(ref segment, ..) => { @@ -4243,30 +4243,30 @@ impl<'a> Resolver<'a> { } } -fn is_self_type(path: &[SpannedIdent], namespace: Namespace) -> bool { - namespace == TypeNS && path.len() == 1 && path[0].node.name == keywords::SelfType.name() +fn is_self_type(path: &[Ident], namespace: Namespace) -> bool { + namespace == TypeNS && path.len() == 1 && path[0].name == keywords::SelfType.name() } -fn is_self_value(path: &[SpannedIdent], namespace: Namespace) -> bool { - namespace == ValueNS && path.len() == 1 && path[0].node.name == keywords::SelfValue.name() +fn is_self_value(path: &[Ident], namespace: Namespace) -> bool { + namespace == ValueNS && path.len() == 1 && path[0].name == keywords::SelfValue.name() } -fn names_to_string(idents: &[SpannedIdent]) -> String { +fn names_to_string(idents: &[Ident]) -> String { let mut result = String::new(); for (i, ident) in idents.iter() - .filter(|i| i.node.name != keywords::CrateRoot.name()) + .filter(|ident| ident.name != keywords::CrateRoot.name()) .enumerate() { if i > 0 { result.push_str("::"); } - result.push_str(&ident.node.name.as_str()); + result.push_str(&ident.name.as_str()); } result } fn path_names_to_string(path: &Path) -> String { names_to_string(&path.segments.iter() - .map(|seg| respan(seg.span, seg.ident)) + .map(|seg| seg.ident) .collect::>()) } @@ -4355,7 +4355,6 @@ fn module_to_string(module: Module) -> Option { } Some(names_to_string(&names.into_iter() .rev() - .map(|n| dummy_spanned(n)) .collect::>())) } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index c65ee11e427fa..3b3bdfdba9ce2 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -20,7 +20,6 @@ use rustc::hir::map::{self, DefCollector}; use rustc::{ty, lint}; use syntax::ast::{self, Name, Ident}; use syntax::attr::{self, HasAttrs}; -use syntax::codemap::respan; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver}; @@ -413,7 +412,7 @@ impl<'a> Resolver<'a> { kind: MacroKind, force: bool) -> Result { let ast::Path { ref segments, span } = *path; - let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.ident)).collect(); + let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); let invocation = self.invocations[&scope]; let module = invocation.module.get(); self.current_module = if module.is_trait() { module.parent.unwrap() } else { module }; @@ -447,19 +446,16 @@ impl<'a> Resolver<'a> { Err(Determinacy::Determined) }, }; - let path = path.iter().map(|p| p.node).collect::>(); self.current_module.nearest_item_scope().macro_resolutions.borrow_mut() .push((path.into_boxed_slice(), span)); return def; } - let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, - path[0].node, - false); + let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, path[0], false); let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution { Ok(Def::Macro(binding.def_id, MacroKind::Bang)) } else { - match self.resolve_lexical_macro_path_segment(path[0].node, MacroNS, false, span) { + match self.resolve_lexical_macro_path_segment(path[0], MacroNS, false, span) { Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()), Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), Err(_) => { @@ -470,7 +466,7 @@ impl<'a> Resolver<'a> { }; self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut() - .push((scope, path[0].node, span, kind)); + .push((scope, path[0], span, kind)); result } @@ -608,7 +604,6 @@ impl<'a> Resolver<'a> { pub fn finalize_current_module_macro_resolutions(&mut self) { let module = self.current_module; for &(ref path, span) in module.macro_resolutions.borrow().iter() { - let path = path.iter().map(|p| respan(span, *p)).collect::>(); match self.resolve_path(&path, Some(MacroNS), true, span) { PathResult::NonModule(_) => {}, PathResult::Failed(span, msg, _) => { @@ -684,8 +679,8 @@ impl<'a> Resolver<'a> { false } }; - let ident = Ident::from_str(name); - self.lookup_typo_candidate(&vec![respan(span, ident)], MacroNS, is_macro, span) + let ident = Ident::new(Symbol::intern(name), span); + self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro, span) }); if let Some(suggestion) = suggestion { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 90a90d731534b..87738f7b79be5 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -24,7 +24,7 @@ use rustc::hir::def::*; use rustc::session::DiagnosticMessageId; use rustc::util::nodemap::{FxHashMap, FxHashSet}; -use syntax::ast::{Ident, Name, SpannedIdent, NodeId}; +use syntax::ast::{Ident, Name, NodeId}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::hygiene::Mark; use syntax::parse::token; @@ -58,7 +58,7 @@ pub enum ImportDirectiveSubclass<'a> { pub struct ImportDirective<'a> { pub id: NodeId, pub parent: Module<'a>, - pub module_path: Vec, + pub module_path: Vec, pub imported_module: Cell>>, // the resolution of `module_path` pub subclass: ImportDirectiveSubclass<'a>, pub span: Span, @@ -257,7 +257,7 @@ impl<'a> Resolver<'a> { // Add an import directive to the current module. pub fn add_import_directive(&mut self, - module_path: Vec, + module_path: Vec, subclass: ImportDirectiveSubclass<'a>, span: Span, id: NodeId, @@ -606,9 +606,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // FIXME: Last path segment is treated specially in import resolution, so extern crate // mode for absolute paths needs some special support for single-segment imports. - if module_path.len() == 1 && (module_path[0].node.name == keywords::CrateRoot.name() || - module_path[0].node.name == keywords::Extern.name()) { - let is_extern = module_path[0].node.name == keywords::Extern.name() || + if module_path.len() == 1 && (module_path[0].name == keywords::CrateRoot.name() || + module_path[0].name == keywords::Extern.name()) { + let is_extern = module_path[0].name == keywords::Extern.name() || self.session.features_untracked().extern_absolute_paths; match directive.subclass { GlobImport { .. } if is_extern => { @@ -617,7 +617,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } SingleImport { source, target, .. } => { let crate_root = if source.name == keywords::Crate.name() && - module_path[0].node.name != keywords::Extern.name() { + module_path[0].name != keywords::Extern.name() { if target.name == keywords::Crate.name() { return Some((directive.span, "crate root imports need to be explicitly named: \ @@ -669,9 +669,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let (mut self_path, mut self_result) = (module_path.clone(), None); let is_special = |ident| token::is_path_segment_keyword(ident) && ident.name != keywords::CrateRoot.name(); - if !self_path.is_empty() && !is_special(self_path[0].node) && - !(self_path.len() > 1 && is_special(self_path[1].node)) { - self_path[0].node.name = keywords::SelfValue.name(); + if !self_path.is_empty() && !is_special(self_path[0]) && + !(self_path.len() > 1 && is_special(self_path[1])) { + self_path[0].name = keywords::SelfValue.name(); self_result = Some(self.resolve_path(&self_path, None, false, span)); } return if let Some(PathResult::Module(..)) = self_result { @@ -957,7 +957,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { let resolutions = imported_module.parent.expect("parent should exist") .resolutions.borrow(); let enum_path_segment_index = directive.module_path.len() - 1; - let enum_ident = directive.module_path[enum_path_segment_index].node; + let enum_ident = directive.module_path[enum_path_segment_index]; let enum_resolution = resolutions.get(&(enum_ident, TypeNS)) .expect("resolution should exist"); @@ -1011,12 +1011,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { } } -fn import_path_to_string(names: &[SpannedIdent], +fn import_path_to_string(names: &[Ident], subclass: &ImportDirectiveSubclass, span: Span) -> String { let pos = names.iter() - .position(|p| span == p.span && p.node.name != keywords::CrateRoot.name()); - let global = !names.is_empty() && names[0].node.name == keywords::CrateRoot.name(); + .position(|p| span == p.span && p.name != keywords::CrateRoot.name()); + let global = !names.is_empty() && names[0].name == keywords::CrateRoot.name(); if let Some(pos) = pos { let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] }; names_to_string(names) diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 953747756517d..bc294de2ac11d 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -553,7 +553,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }; match self.tables.expr_ty_adjusted(&hir_node).sty { ty::TyAdt(def, _) if !def.is_enum() => { - let f = def.non_enum_variant().field_named(ident.node.name); + let f = def.non_enum_variant().field_named(ident.name); let sub_span = self.span_utils.span_for_last_ident(expr.span); filter!(self.span_utils, sub_span, expr.span, None); let span = self.span_from_span(sub_span.unwrap()); @@ -816,7 +816,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { field_ref: &ast::Field, variant: &ty::VariantDef, ) -> Option { - let f = variant.find_field_named(field_ref.ident.node.name)?; + let f = variant.find_field_named(field_ref.ident.name)?; // We don't really need a sub-span here, but no harm done let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span); filter!(self.span_utils, sub_span, field_ref.ident.span, None); @@ -981,12 +981,12 @@ impl<'l, 'a: 'l> Visitor<'a> for PathCollector<'l> { PatKind::TupleStruct(ref path, ..) | PatKind::Path(_, ref path) => { self.collected_paths.push((p.id, path)); } - PatKind::Ident(bm, ref path1, _) => { + PatKind::Ident(bm, ident, _) => { debug!( "PathCollector, visit ident in pat {}: {:?} {:?}", - path1.node, + ident, p.span, - path1.span + ident.span ); let immut = match bm { // Even if the ref is mut, you can't change the ref, only @@ -996,7 +996,7 @@ impl<'l, 'a: 'l> Visitor<'a> for PathCollector<'l> { ast::BindingMode::ByValue(mt) => mt, }; self.collected_idents - .push((p.id, path1.node, path1.span, immut)); + .push((p.id, ident, ident.span, immut)); } _ => {} } diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 0c890ce19d081..66a8449165cd1 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -671,7 +671,7 @@ impl Sig for ast::StructField { fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { let mut text = String::new(); let mut defs = None; - if let Some(ref ident) = self.ident { + if let Some(ident) = self.ident { text.push_str(&ident.to_string()); defs = Some(SigElement { id: id_from_node_id(self.id, scx), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 3f4cb52903c34..f93a586280d05 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -541,7 +541,7 @@ impl Pat { let node = match &self.node { PatKind::Wild => TyKind::Infer, PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) => - TyKind::Path(None, Path::from_ident(ident.span, ident.node)), + TyKind::Path(None, Path::from_ident(ident.span, *ident)), PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()), PatKind::Mac(mac) => TyKind::Mac(mac.clone()), PatKind::Ref(pat, mutbl) => @@ -638,7 +638,7 @@ pub enum PatKind { /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens /// during name resolution. - Ident(BindingMode, SpannedIdent, Option>), + Ident(BindingMode, Ident, Option>), /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`. /// The `bool` is `true` in the presence of a `..`. @@ -910,15 +910,13 @@ pub struct Arm { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Field { - pub ident: SpannedIdent, + pub ident: Ident, pub expr: P, pub span: Span, pub is_shorthand: bool, pub attrs: ThinVec, } -pub type SpannedIdent = Spanned; - #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum BlockCheckMode { Default, @@ -1144,7 +1142,7 @@ pub enum ExprKind { /// For example, `a += 1`. AssignOp(BinOp, P, P), /// Access of a named struct field (`obj.foo`) - Field(P, SpannedIdent), + Field(P, Ident), /// Access of an unnamed field of a struct or tuple-struct /// /// For example, `foo.0`. @@ -1689,7 +1687,7 @@ pub type ExplicitSelf = Spanned; impl Arg { pub fn to_self(&self) -> Option { if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node { - if ident.node.name == keywords::SelfValue.name() { + if ident.name == keywords::SelfValue.name() { return match self.ty.node { TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), TyKind::Rptr(lt, MutTy{ref ty, mutbl}) if ty.node == TyKind::ImplicitSelf => { @@ -1705,13 +1703,13 @@ impl Arg { pub fn is_self(&self) -> bool { if let PatKind::Ident(_, ident, _) = self.pat.node { - ident.node.name == keywords::SelfValue.name() + ident.name == keywords::SelfValue.name() } else { false } } - pub fn from_self(eself: ExplicitSelf, eself_ident: SpannedIdent) -> Arg { + pub fn from_self(eself: ExplicitSelf, eself_ident: Ident) -> Arg { let span = eself.span.to(eself_ident.span); let infer_ty = P(Ty { id: DUMMY_NODE_ID, diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 739679b71d5b1..541517b2bcbf3 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -1117,7 +1117,7 @@ impl MetaItem { let (span, name) = match tokens.next() { Some(TokenTree::Token(span, Token::Ident(ident, _))) => (span, ident.name), Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 { - token::Nonterminal::NtIdent(ident, _) => (ident.span, ident.node.name), + token::Nonterminal::NtIdent(ident, _) => (ident.span, ident.name), token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()), _ => return None, }, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index e64f97d58f449..11f7178f45bb2 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -239,7 +239,7 @@ impl TTMacroExpander for F if let tokenstream::TokenTree::Token(_, token::Interpolated(ref nt)) = tt { if let token::NtIdent(ident, is_raw) = nt.0 { return tokenstream::TokenTree::Token(ident.span, - token::Ident(ident.node, is_raw)); + token::Ident(ident, is_raw)); } } fold::noop_fold_tt(tt, self) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 8dabc03c2f95b..fc3000ea0b5f6 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -38,11 +38,11 @@ pub trait AstBuilder { fn qpath(&self, self_type: P, trait_path: ast::Path, - ident: ast::SpannedIdent) + ident: ast::Ident) -> (ast::QSelf, ast::Path); fn qpath_all(&self, self_type: P, trait_path: ast::Path, - ident: ast::SpannedIdent, + ident: ast::Ident, lifetimes: Vec, types: Vec>, bindings: Vec) @@ -344,7 +344,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn qpath(&self, self_type: P, trait_path: ast::Path, - ident: ast::SpannedIdent) + ident: ast::Ident) -> (ast::QSelf, ast::Path) { self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) } @@ -355,7 +355,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn qpath_all(&self, self_type: P, trait_path: ast::Path, - ident: ast::SpannedIdent, + ident: ast::Ident, lifetimes: Vec, types: Vec>, bindings: Vec) @@ -366,11 +366,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } else { None }; - path.segments.push(ast::PathSegment { - ident: ident.node, - span: ident.span, - parameters, - }); + path.segments.push(ast::PathSegment { ident, span: ident.span, parameters }); (ast::QSelf { ty: self_type, @@ -636,8 +632,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_field_access(&self, sp: Span, expr: P, ident: ast::Ident) -> P { - let id = Spanned { node: ident, span: sp }; - self.expr(sp, ast::ExprKind::Field(expr, id)) + self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp))) } fn expr_tup_field_access(&self, sp: Span, expr: P, idx: usize) -> P { let id = Spanned { node: idx, span: sp }; @@ -672,9 +667,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn expr_block(&self, b: P) -> P { self.expr(b.span, ast::ExprKind::Block(b)) } - fn field_imm(&self, span: Span, name: Ident, e: P) -> ast::Field { + fn field_imm(&self, span: Span, ident: Ident, e: P) -> ast::Field { ast::Field { - ident: respan(span, name), + ident: ident.with_span_pos(span), expr: e, span, is_shorthand: false, @@ -835,7 +830,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { span: Span, ident: ast::Ident, bm: ast::BindingMode) -> P { - let pat = PatKind::Ident(bm, Spanned{span: span, node: ident}, None); + let pat = PatKind::Ident(bm, ident.with_span_pos(span), None); self.pat(span, pat) } fn pat_path(&self, span: Span, path: ast::Path) -> P { diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index b412c2fbc7f7c..10dc17beb96ea 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -75,7 +75,7 @@ pub mod rt { impl ToTokens for ast::Ident { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, Token::from_ast_ident(*self))] + vec![TokenTree::Token(self.span, Token::from_ast_ident(*self))] } } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 8cb331c65da28..fdff17b13ed40 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -86,7 +86,6 @@ use self::TokenTreeOrTokenTreeVec::*; use ast::Ident; use syntax_pos::{self, BytePos, Span}; -use codemap::respan; use errors::FatalError; use ext::tt::quoted::{self, TokenTree}; use parse::{Directory, ParseSess}; @@ -824,9 +823,10 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { "expr" => token::NtExpr(panictry!(p.parse_expr())), "ty" => token::NtTy(panictry!(p.parse_ty())), // this could be handled like a token, since it is one - "ident" => if let Some((ident, is_raw)) = get_macro_ident(&p.token) { + "ident" => if let Some((ident, is_raw))) = get_macro_ident(&p.token) { + let span = p.span; p.bump(); - token::NtIdent(respan(p.prev_span, ident), is_raw) + token::NtIdent(Ident::new(ident.name, span), is_raw) } else { let token_str = pprust::token_to_string(&p.token); p.fatal(&format!("expected ident, found {}", &token_str)).emit(); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 06d0033000172..e7a5e57aed333 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -435,8 +435,8 @@ pub fn noop_fold_variant(v: Variant, fld: &mut T) -> Variant { } } -pub fn noop_fold_ident(i: Ident, _: &mut T) -> Ident { - i +pub fn noop_fold_ident(ident: Ident, fld: &mut T) -> Ident { + Ident::new(ident.name, fld.new_span(ident.span)) } pub fn noop_fold_usize(i: usize, _: &mut T) -> usize { @@ -630,8 +630,7 @@ pub fn noop_fold_interpolated(nt: token::Nonterminal, fld: &mut T) token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)), token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)), token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)), - token::NtIdent(id, is_raw) => - token::NtIdent(Spanned::{node: fld.fold_ident(id.node), ..id}, is_raw), + token::NtIdent(id, is_raw) => token::NtIdent(fld.fold_ident(id), is_raw), token::NtMeta(meta) => token::NtMeta(fld.fold_meta_item(meta)), token::NtPath(path) => token::NtPath(fld.fold_path(path)), token::NtTT(tt) => token::NtTT(fld.fold_tt(tt)), @@ -851,7 +850,7 @@ pub fn noop_fold_struct_field(f: StructField, fld: &mut T) -> StructF pub fn noop_fold_field(f: Field, folder: &mut T) -> Field { Field { - ident: respan(f.ident.span, folder.fold_ident(f.ident.node)), + ident: folder.fold_ident(f.ident), expr: folder.fold_expr(f.expr), span: folder.new_span(f.span), is_shorthand: f.is_shorthand, @@ -1105,11 +1104,10 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { id: folder.new_id(id), node: match node { PatKind::Wild => PatKind::Wild, - PatKind::Ident(binding_mode, pth1, sub) => { + PatKind::Ident(binding_mode, ident, sub) => { PatKind::Ident(binding_mode, - Spanned{span: folder.new_span(pth1.span), - node: folder.fold_ident(pth1.node)}, - sub.map(|x| folder.fold_pat(x))) + folder.fold_ident(ident), + sub.map(|x| folder.fold_pat(x))) } PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)), PatKind::TupleStruct(pth, pats, ddpos) => { @@ -1258,14 +1256,12 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu folder.fold_expr(er)) } ExprKind::Field(el, ident) => { - ExprKind::Field(folder.fold_expr(el), - respan(folder.new_span(ident.span), - folder.fold_ident(ident.node))) + ExprKind::Field(folder.fold_expr(el), folder.fold_ident(ident)) } - ExprKind::TupField(el, ident) => { + ExprKind::TupField(el, index) => { ExprKind::TupField(folder.fold_expr(el), - respan(folder.new_span(ident.span), - folder.fold_usize(ident.node))) + respan(folder.new_span(index.span), + folder.fold_usize(index.node))) } ExprKind::Index(el, er) => { ExprKind::Index(folder.fold_expr(el), folder.fold_expr(er)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2ddc54967b55c..3b5d514eb0552 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -512,13 +512,10 @@ impl From> for LhsExpr { /// Create a placeholder argument. fn dummy_arg(span: Span) -> Arg { - let spanned = Spanned { - span, - node: keywords::Invalid.ident() - }; + let ident = Ident::new(keywords::Invalid.name(), span); let pat = P(Pat { id: ast::DUMMY_NODE_ID, - node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), spanned, None), + node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None), span, }); let ty = Ty { @@ -778,7 +775,7 @@ impl<'a> Parser<'a> { fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> { match self.token { - token::Ident(i, _) => { + token::Ident(ident, _) => { if self.token.is_reserved_ident() { let mut err = self.expected_ident_found(); if recover { @@ -787,8 +784,9 @@ impl<'a> Parser<'a> { return Err(err); } } + let span = self.span; self.bump(); - Ok(i) + Ok(Ident::new(ident.name, span)) } _ => { Err(if self.prev_token_kind == PrevTokenKind::DocComment { @@ -1321,7 +1319,7 @@ impl<'a> Parser<'a> { fn eat_label(&mut self) -> Option(A); impl<#[may_dangle] A> Drop for Pt { //~^ ERROR may_dangle has unstable semantics and may be removed in the future diff --git a/src/test/ui/feature-gate-may-dangle.stderr b/src/test/ui/feature-gate-may-dangle.stderr index 85707f6e92127..aad725dfe65ec 100644 --- a/src/test/ui/feature-gate-may-dangle.stderr +++ b/src/test/ui/feature-gate-may-dangle.stderr @@ -1,5 +1,5 @@ error[E0658]: may_dangle has unstable semantics and may be removed in the future (see issue #34761) - --> $DIR/feature-gate-may-dangle.rs:18:6 + --> $DIR/feature-gate-may-dangle.rs:16:6 | LL | impl<#[may_dangle] A> Drop for Pt { | ^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gate-generic_param_attrs.rs b/src/test/ui/generic-param-attrs.rs similarity index 53% rename from src/test/ui/feature-gate-generic_param_attrs.rs rename to src/test/ui/generic-param-attrs.rs index 944802f450a6d..37fabcd7e1e90 100644 --- a/src/test/ui/feature-gate-generic_param_attrs.rs +++ b/src/test/ui/generic-param-attrs.rs @@ -8,69 +8,47 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// This test ensures that attributes on formals in generic parameter -// lists are rejected if feature(generic_param_attrs) is not enabled. +// This test previously ensured that attributes on formals in generic parameter +// lists are rejected without a feature gate. // // (We are prefixing all tested features with `rustc_`, to ensure that // the attributes themselves won't be rejected by the compiler when // using `rustc_attrs` feature. There is a separate compile-fail/ test // ensuring that the attribute feature-gating works in this context.) +// must-compile-successfully + #![feature(rustc_attrs)] #![allow(dead_code)] struct StLt<#[rustc_lt_struct] 'a>(&'a u32); -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) struct StTy<#[rustc_ty_struct] I>(I); -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) - enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B } -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) enum EnTy<#[rustc_ty_enum] J> { A(J), B } -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) - trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; } -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); } -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) - type TyLt<#[rustc_lt_type] 'd> = &'d u32; -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) type TyTy<#[rustc_ty_type] L> = (L, ); -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) impl<#[rustc_lt_inherent] 'e> StLt<'e> { } -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) impl<#[rustc_ty_inherent] M> StTy { } -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) - impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> { - //~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) fn foo(&self, _: &'f [u32]) -> &'f u32 { loop { } } } impl<#[rustc_ty_impl_for] N> TrTy for StTy { - //~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) fn foo(&self, _: N) { } } fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } } -//~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) fn f_ty<#[rustc_ty_fn] O>(_: O) { } -//~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) impl StTy { fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } } - //~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) fn m_ty<#[rustc_ty_meth] P>(_: P) { } - //~^ ERROR attributes on type parameter bindings are experimental (see issue #34761) } fn hof_lt(_: Q) where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32 - //~^ ERROR attributes on lifetime bindings are experimental (see issue #34761) -{ -} +{} -fn main() { - -} +fn main() {} diff --git a/src/test/ui/nll/drop-may-dangle.rs b/src/test/ui/nll/drop-may-dangle.rs index 2780b34746378..55c9f5de30205 100644 --- a/src/test/ui/nll/drop-may-dangle.rs +++ b/src/test/ui/nll/drop-may-dangle.rs @@ -17,7 +17,6 @@ #![allow(warnings)] #![feature(dropck_eyepatch)] -#![feature(generic_param_attrs)] fn use_x(_: usize) -> bool { true } diff --git a/src/test/ui/nll/drop-no-may-dangle.rs b/src/test/ui/nll/drop-no-may-dangle.rs index 3d9a5456cbb36..e5478e39fecca 100644 --- a/src/test/ui/nll/drop-no-may-dangle.rs +++ b/src/test/ui/nll/drop-no-may-dangle.rs @@ -17,7 +17,6 @@ #![allow(warnings)] #![feature(dropck_eyepatch)] -#![feature(generic_param_attrs)] fn use_x(_: usize) -> bool { true } diff --git a/src/test/ui/nll/drop-no-may-dangle.stderr b/src/test/ui/nll/drop-no-may-dangle.stderr index 6454413901bec..a35271bdcfeff 100644 --- a/src/test/ui/nll/drop-no-may-dangle.stderr +++ b/src/test/ui/nll/drop-no-may-dangle.stderr @@ -1,5 +1,5 @@ error[E0506]: cannot assign to `v[..]` because it is borrowed - --> $DIR/drop-no-may-dangle.rs:31:9 + --> $DIR/drop-no-may-dangle.rs:30:9 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; | ----- borrow of `v[..]` occurs here @@ -11,7 +11,7 @@ LL | } | - borrow later used here, when `p` is dropped error[E0506]: cannot assign to `v[..]` because it is borrowed - --> $DIR/drop-no-may-dangle.rs:34:5 + --> $DIR/drop-no-may-dangle.rs:33:5 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; | ----- borrow of `v[..]` occurs here